From 57557e98c955f8b7f3db6a1c76f9641779e799d5 Mon Sep 17 00:00:00 2001 From: Lenno Nagel Date: Wed, 8 Jan 2025 09:41:45 +0200 Subject: [PATCH 1/6] Add support for LHV_LHVBEE22 --- src/app-gocardless/bank-factory.js | 2 ++ src/app-gocardless/banks/lhv-lhvbee22.js | 32 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/app-gocardless/banks/lhv-lhvbee22.js diff --git a/src/app-gocardless/bank-factory.js b/src/app-gocardless/bank-factory.js index e78069425..5a3fb7280 100644 --- a/src/app-gocardless/bank-factory.js +++ b/src/app-gocardless/bank-factory.js @@ -21,6 +21,7 @@ import IngPlIngbplpw from './banks/ing_pl_ingbplpw.js'; import IntegrationBank from './banks/integration-bank.js'; import IsyBankItbbitmm from './banks/isybank_itbbitmm.js'; import KbcKredbebb from './banks/kbc_kredbebb.js'; +import LhvLhvbee22 from './banks/lhv-lhvbee22.js'; import MbankRetailBrexplpw from './banks/mbank_retail_brexplpw.js'; import NationwideNaiagb21 from './banks/nationwide_naiagb21.js'; import NbgEthngraaxxx from './banks/nbg_ethngraaxxx.js'; @@ -60,6 +61,7 @@ export const banks = [ IngPlIngbplpw, IsyBankItbbitmm, KbcKredbebb, + LhvLhvbee22, MbankRetailBrexplpw, NationwideNaiagb21, NbgEthngraaxxx, diff --git a/src/app-gocardless/banks/lhv-lhvbee22.js b/src/app-gocardless/banks/lhv-lhvbee22.js new file mode 100644 index 000000000..188872cb3 --- /dev/null +++ b/src/app-gocardless/banks/lhv-lhvbee22.js @@ -0,0 +1,32 @@ +import Fallback from './integration-bank.js'; + +/** @type {import('./bank.interface.js').IBank} */ +export default { + ...Fallback, + + institutionIds: ['LHV_LHVBEE22'], + + accessValidForDays: 90, + + normalizeTransaction(transaction, booked) { + // extract bookingDate and creditorName for card transactions, e.g. + // (..1234) 2025-01-02 09:32 CrustumOU\Poordi 3\Tallinn\10156 ESTEST + // bookingDate: 2025-01-02 + // creditorName: CrustumOU + const cardTxRegex = + /^\(\.\.(\d{4})\) (\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}) (.+)$/g; + const cardTxMatch = cardTxRegex.exec( + transaction?.remittanceInformationUnstructured, + ); + + if (cardTxMatch) { + transaction = { + ...transaction, + bookingDate: cardTxMatch[2], + creditorName: cardTxMatch[4].split('\\')[0].trim(), + }; + } + + return Fallback.normalizeTransaction(transaction, booked); + }, +}; From 10bf54189bfda204e7a6e780472da56b3b026233 Mon Sep 17 00:00:00 2001 From: Lenno Nagel Date: Wed, 8 Jan 2025 09:50:31 +0200 Subject: [PATCH 2/6] Add upcoming-release-notes/542.md --- upcoming-release-notes/542.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 upcoming-release-notes/542.md diff --git a/upcoming-release-notes/542.md b/upcoming-release-notes/542.md new file mode 100644 index 000000000..8b20a730d --- /dev/null +++ b/upcoming-release-notes/542.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [lnagel] +--- + +Add GoCardless formatter for LHV Estonia (`LHV_LHVBEE22`). From 21557548b1ece1cd25af46a96096d44d39d722bb Mon Sep 17 00:00:00 2001 From: Lenno Nagel Date: Wed, 8 Jan 2025 11:45:55 +0200 Subject: [PATCH 3/6] Don't set bookingDate unless booked --- src/app-gocardless/banks/lhv-lhvbee22.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/app-gocardless/banks/lhv-lhvbee22.js b/src/app-gocardless/banks/lhv-lhvbee22.js index 188872cb3..43e7e075e 100644 --- a/src/app-gocardless/banks/lhv-lhvbee22.js +++ b/src/app-gocardless/banks/lhv-lhvbee22.js @@ -22,9 +22,15 @@ export default { if (cardTxMatch) { transaction = { ...transaction, - bookingDate: cardTxMatch[2], creditorName: cardTxMatch[4].split('\\')[0].trim(), }; + + if (booked) { + transaction = { + ...transaction, + bookingDate: cardTxMatch[2], + }; + } } return Fallback.normalizeTransaction(transaction, booked); From 0e0d3417335009b5700bd917f0a80fd47eb2f913 Mon Sep 17 00:00:00 2001 From: Lenno Nagel Date: Wed, 8 Jan 2025 11:46:34 +0200 Subject: [PATCH 4/6] Add a basic spec file --- .../banks/tests/lhv-lhvbee22.spec.js | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js diff --git a/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js b/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js new file mode 100644 index 000000000..571bdeb80 --- /dev/null +++ b/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js @@ -0,0 +1,79 @@ +import LhvLhvbee22 from '../lhv-lhvbee22.js'; + +describe('#normalizeTransaction', () => { + const bookedCardTransaction = { + transactionId: '2025010300000000-1', + bookingDate: '2025-01-03', + valueDate: '2025-01-03', + transactionAmount: { + amount: '-22.99', + currency: 'EUR', + }, + creditorName: null, + remittanceInformationUnstructured: + '(..1234) 2025-01-02 09:32 CrustumOU\\Poordi 3\\Tallinn\\10156 ESTEST', + bankTransactionCode: 'PMNT-CCRD-POSD', + internalTransactionId: 'fa000f86afb2cc7678bcff0000000000', + }; + + it('extracts booked card transaction creditor name', () => { + expect( + LhvLhvbee22.normalizeTransaction(bookedCardTransaction, true) + .creditorName, + ).toEqual('CrustumOU'); + }); + + it('extracts booked card transaction date', () => { + expect( + LhvLhvbee22.normalizeTransaction(bookedCardTransaction, true).bookingDate, + ).toEqual('2025-01-02'); + + expect( + LhvLhvbee22.normalizeTransaction(bookedCardTransaction, true).date, + ).toEqual('2025-01-02'); + }); + + it.each([ + ['regular text', 'Some info'], + ['partial card text', 'PIRKUMS xxx'], + ['null value', null], + ])('normalizes non-card transaction with %s', (_, remittanceInfo) => { + const transaction = { + ...bookedCardTransaction, + remittanceInformationUnstructured: remittanceInfo, + }; + const normalized = LhvLhvbee22.normalizeTransaction(transaction, true); + + expect(normalized.bookingDate).toEqual('2025-01-03'); + expect(normalized.date).toEqual('2025-01-03'); + }); + + const pendingCardTransaction = { + transactionId: '2025010300000000-1', + valueDate: '2025-01-03', + transactionAmount: { + amount: '-22.99', + currency: 'EUR', + }, + remittanceInformationUnstructured: + '(..1234) 2025-01-02 09:32 CrustumOU\\Poordi 3\\Tallinn\\10156 ESTEST', + }; + + it('extracts pending card transaction creditor name', () => { + expect( + LhvLhvbee22.normalizeTransaction(pendingCardTransaction, false) + .creditorName, + ).toEqual('CrustumOU'); + }); + + it('extracts pending card transaction date', () => { + expect( + LhvLhvbee22.normalizeTransaction(pendingCardTransaction, false) + .bookingDate, + ).toEqual(undefined); + + expect( + LhvLhvbee22.normalizeTransaction(pendingCardTransaction, false).date, + ).toEqual('2025-01-03'); + }); +}); From 05e8c52917b8af19ce913e180bcd269f89f180d2 Mon Sep 17 00:00:00 2001 From: Lenno Nagel Date: Thu, 9 Jan 2025 11:03:17 +0200 Subject: [PATCH 5/6] Add test case for invalid date and date validation to handle it --- src/app-gocardless/banks/lhv-lhvbee22.js | 8 ++++++-- src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/app-gocardless/banks/lhv-lhvbee22.js b/src/app-gocardless/banks/lhv-lhvbee22.js index 43e7e075e..f8d34bc28 100644 --- a/src/app-gocardless/banks/lhv-lhvbee22.js +++ b/src/app-gocardless/banks/lhv-lhvbee22.js @@ -1,3 +1,5 @@ +import d from 'date-fns'; + import Fallback from './integration-bank.js'; /** @type {import('./bank.interface.js').IBank} */ @@ -20,15 +22,17 @@ export default { ); if (cardTxMatch) { + const extractedDate = d.parse(cardTxMatch[2], 'yyyy-MM-dd', new Date()); + transaction = { ...transaction, creditorName: cardTxMatch[4].split('\\')[0].trim(), }; - if (booked) { + if (booked && d.isValid(extractedDate)) { transaction = { ...transaction, - bookingDate: cardTxMatch[2], + bookingDate: d.format(extractedDate, 'yyyy-MM-dd'), }; } } diff --git a/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js b/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js index 571bdeb80..72e61fb38 100644 --- a/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js +++ b/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js @@ -37,6 +37,7 @@ describe('#normalizeTransaction', () => { ['regular text', 'Some info'], ['partial card text', 'PIRKUMS xxx'], ['null value', null], + ['invalid date', '(..1234) 2025-13-45 09:32 Merchant\\Address'], ])('normalizes non-card transaction with %s', (_, remittanceInfo) => { const transaction = { ...bookedCardTransaction, From 7275d1f28210daad8ff18347cfe09e1ba5cfb3c4 Mon Sep 17 00:00:00 2001 From: Lenno Nagel Date: Wed, 22 Jan 2025 09:58:14 +0200 Subject: [PATCH 6/6] Remove accessValidForDays --- src/app-gocardless/banks/lhv-lhvbee22.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app-gocardless/banks/lhv-lhvbee22.js b/src/app-gocardless/banks/lhv-lhvbee22.js index f8d34bc28..8f948c650 100644 --- a/src/app-gocardless/banks/lhv-lhvbee22.js +++ b/src/app-gocardless/banks/lhv-lhvbee22.js @@ -8,8 +8,6 @@ export default { institutionIds: ['LHV_LHVBEE22'], - accessValidForDays: 90, - normalizeTransaction(transaction, booked) { // extract bookingDate and creditorName for card transactions, e.g. // (..1234) 2025-01-02 09:32 CrustumOU\Poordi 3\Tallinn\10156 ESTEST