diff --git a/src/app-gocardless/tests/utils.spec.js b/src/app-gocardless/tests/utils.spec.js index 352525b9d..b30e95a26 100644 --- a/src/app-gocardless/tests/utils.spec.js +++ b/src/app-gocardless/tests/utils.spec.js @@ -33,5 +33,130 @@ describe('utils', () => { }, ]); }); + + it('should sort by valueDate if bookingDate is missing', () => { + const transactions = [ + { + valueDate: '2023-01-01', + transactionAmount: mockTransactionAmount, + }, + { + valueDate: '2023-01-20', + transactionAmount: mockTransactionAmount, + }, + { + valueDate: '2023-01-10', + transactionAmount: mockTransactionAmount, + }, + ]; + expect(sortByBookingDateOrValueDate(transactions)).toEqual([ + { + valueDate: '2023-01-20', + transactionAmount: mockTransactionAmount, + }, + { + valueDate: '2023-01-10', + transactionAmount: mockTransactionAmount, + }, + { + valueDate: '2023-01-01', + transactionAmount: mockTransactionAmount, + }, + ]); + }); + + it('should use multiple fields in sort', () => { + const transactions = [ + { + bookingDate: '2023-01-01', + bookingDateTime: '2023-01-01T00:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-10', + bookingDateTime: '2023-01-01T12:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-01', + bookingDateTime: '2023-01-01T12:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-10', + bookingDateTime: '2023-01-01T00:00:00Z', + transactionAmount: mockTransactionAmount, + }, + ]; + expect(sortByBookingDateOrValueDate(transactions)).toEqual([ + { + bookingDate: '2023-01-10', + bookingDateTime: '2023-01-01T12:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-10', + bookingDateTime: '2023-01-01T00:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-01', + bookingDateTime: '2023-01-01T12:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-01', + bookingDateTime: '2023-01-01T00:00:00Z', + transactionAmount: mockTransactionAmount, + }, + ]); + }); + + it('should sort on booking date if value date is widely off', () => { + const transactions = [ + { + bookingDate: '2023-01-01', + valueDateTime: '2023-01-31T00:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-02', + valueDateTime: '2023-01-02T12:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-30', + valueDateTime: '2023-01-01T12:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-30', + valueDateTime: '2023-01-01T00:00:00Z', + transactionAmount: mockTransactionAmount, + }, + ]; + expect(sortByBookingDateOrValueDate(transactions)).toEqual([ + { + bookingDate: '2023-01-30', + valueDateTime: '2023-01-01T12:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-30', + valueDateTime: '2023-01-01T00:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-02', + valueDateTime: '2023-01-02T12:00:00Z', + transactionAmount: mockTransactionAmount, + }, + { + bookingDate: '2023-01-01', + valueDateTime: '2023-01-31T00:00:00Z', + transactionAmount: mockTransactionAmount, + }, + ]); + }); }); }); diff --git a/src/app-gocardless/utils.js b/src/app-gocardless/utils.js index 7a3987b77..1c7e0f69a 100644 --- a/src/app-gocardless/utils.js +++ b/src/app-gocardless/utils.js @@ -6,11 +6,35 @@ export const printIban = (account) => { } }; +const compareDates = ( + /** @type {string | number | Date | undefined} */ a, + /** @type {string | number | Date | undefined} */ b, +) => { + if (!a || !b) { + return 0; + } + return +new Date(a) - +new Date(b); +}; + +/** + * @type {(function(*, *): number)[]} + */ +const compareFunctions = [ + (a, b) => compareDates(a.bookingDate, b.bookingDate), + (a, b) => compareDates(a.bookingDateTime, b.bookingDateTime), + (a, b) => compareDates(a.valueDate, b.valueDate), + (a, b) => compareDates(a.valueDateTime, b.valueDateTime), +]; + export const sortByBookingDateOrValueDate = (transactions = []) => - transactions.sort( - (a, b) => - +new Date(b.bookingDate || b.valueDate) - - +new Date(a.bookingDate || a.valueDate), - ); + transactions.sort((a, b) => { + for (const sortFunction of compareFunctions) { + const result = sortFunction(b, a); + if (result !== 0) { + return result; + } + } + return 0; + }); export const amountToInteger = (n) => Math.round(n * 100);