diff --git a/cypress/e2e/transaction-import.cy.ts b/cypress/e2e/transaction-import.cy.ts index 62de218d..c94a1655 100644 --- a/cypress/e2e/transaction-import.cy.ts +++ b/cypress/e2e/transaction-import.cy.ts @@ -154,7 +154,7 @@ describe('Transaction Import', () => { // Now at the last transaction, import this too cy.contains('5 of 5') - cy.getInputFor('Available From').should('have.value', '2023-06-01') + cy.getInputFor('Available From').should('have.value', '2023-07-01') cy.get('button').contains('Import').click() // Now back at the second transactions since we skipped it diff --git a/cypress/e2e/transactions.cy.ts b/cypress/e2e/transactions.cy.ts index 227e561b..127a5f91 100644 --- a/cypress/e2e/transactions.cy.ts +++ b/cypress/e2e/transactions.cy.ts @@ -6,15 +6,13 @@ import { createTransactions, } from '../support/setup' import { Budget, Account, Envelope } from '../../src/types' -import { dateFromIsoString } from '../../src/lib/dates' +import { dateFromIsoString, setToFirstOfNextMonth } from '../../src/lib/dates' describe('Transactions', () => { const date = new Date() // Get the current month in YYYY-MM-01 format - const currentMonth = `${new Date(Date.now()) - .toISOString() - .substring(0, 7)}-01` + const currentMonth = `${date.toISOString().substring(0, 7)}-01` beforeEach(() => { // prepare a budget with two internal & one external accounts @@ -112,6 +110,11 @@ describe('Transactions', () => { cy.getAutocompleteFor('Destination').type('Bank ac') cy.contains('Bank account').click() + cy.getInputFor('Available From').should( + 'have.value', + setToFirstOfNextMonth(dateFromIsoString(date.toISOString())) + ) + cy.getInputFor('Available From').type(currentMonth) cy.getInputFor('Available From').should('have.value', currentMonth) diff --git a/src/components/TransactionForm.tsx b/src/components/TransactionForm.tsx index d9a63450..af1737e5 100644 --- a/src/components/TransactionForm.tsx +++ b/src/components/TransactionForm.tsx @@ -9,6 +9,7 @@ import { dateToIsoString, monthYearFromDate, setToFirstOfTheMonth, + setToFirstOfNextMonth, } from '../lib/dates' import { safeName } from '../lib/name-helper' import { @@ -117,6 +118,18 @@ const TransactionForm = ({ budget, setNotification }: Props) => { setTransaction({ ...transaction, [key]: value }) } + const updateValues = ( + values: { key: keyof UnpersistedTransaction; value: any }[] + ) => { + const newTransaction = { ...transaction } + values.forEach( + (value: { key: keyof UnpersistedTransaction; value: any }) => { + newTransaction[value.key] = value.value + } + ) + setTransaction(newTransaction) + } + const createNewResources = async () => { const promises = [] let { sourceAccountId, destinationAccountId } = transaction @@ -394,7 +407,15 @@ const TransactionForm = ({ budget, setNotification }: Props) => { onChange={e => { // value is empty string for invalid dates (e.g. when prefixing month with 0 while typing) – we want to ignore that and keep the previous input if (e.target.value) { - updateValue('date', dateToIsoString(e.target.value)) + updateValues([ + { key: 'date', value: dateToIsoString(e.target.value) }, + { + key: 'availableFrom', + value: dateToIsoString( + setToFirstOfNextMonth(e.target.value) + ), + }, + ]) } }} options={{ disabled: transaction.reconciled || false }} @@ -412,11 +433,12 @@ const TransactionForm = ({ budget, setNotification }: Props) => { }`} value={(isSupported.inputTypeMonth() ? (date: string) => monthYearFromDate(new Date(date)) - : (date: string) => - setToFirstOfTheMonth(dateFromIsoString(date)))( - transaction.availableFrom || - transaction.date || - new Date().toISOString() + : (date: string) => date)( + dateFromIsoString(transaction.availableFrom || '') || + setToFirstOfNextMonth( + dateFromIsoString(transaction.date || '') || + new Date().toISOString() + ) )} onChange={e => { // value is empty string for invalid dates (e.g. when prefixing month with 0 while typing) – we want to ignore that and keep the previous input diff --git a/src/components/TransactionImport/Result.tsx b/src/components/TransactionImport/Result.tsx index 2f957ffe..50e46731 100644 --- a/src/components/TransactionImport/Result.tsx +++ b/src/components/TransactionImport/Result.tsx @@ -22,6 +22,7 @@ import { dateToIsoString, monthYearFromDate, setToFirstOfTheMonth, + setToFirstOfNextMonth, } from '../../lib/dates' import { api } from '../../lib/api/base' import { safeName } from '../../lib/name-helper' @@ -436,7 +437,7 @@ const Result = (props: Props) => { value={(isSupported.inputTypeMonth() ? (date: string) => monthYearFromDate(new Date(date)) : (date: string) => - setToFirstOfTheMonth(dateFromIsoString(date)))( + setToFirstOfNextMonth(dateFromIsoString(date)))( currentTransaction().availableFrom || currentTransaction().date || new Date().toISOString() diff --git a/src/lib/dates.ts b/src/lib/dates.ts index 4c5557f4..19c06a8d 100644 --- a/src/lib/dates.ts +++ b/src/lib/dates.ts @@ -28,12 +28,22 @@ const setToFirstOfTheMonth = (date: string) => { return `${year}-${month}-01` } +const setToFirstOfNextMonth = (date: string) => { + const d = new Date(date) + d.setDate(1) + d.setMonth(d.getMonth() + 1) + + // Return date in YYYY-MM-DD format + return dateFromIsoString(d.toISOString()) +} + export { dateFromIsoString, dateToIsoString, monthYearFromDate, dateFromMonthYear, setToFirstOfTheMonth, + setToFirstOfNextMonth, translatedMonthFormat, shortTranslatedMonthFormat, }