diff --git a/src/app-gocardless/bank-factory.js b/src/app-gocardless/bank-factory.js index 0f6e7fa08..ebbb58df7 100644 --- a/src/app-gocardless/bank-factory.js +++ b/src/app-gocardless/bank-factory.js @@ -5,6 +5,7 @@ import BankinterBkbkesmm from './banks/bankinter-bkbkesmm.js'; import Belfius from './banks/belfius_gkccbebb.js'; import Berliner_Sparkasse_beladebexxx from './banks/berliner_sparkasse_beladebexxx.js'; import BnpBeGebabebb from './banks/bnp-be-gebabebb.js'; +import CBCcregbebb from './banks/cbc_cregbebb.js'; import DanskeBankDabNO22 from './banks/danskebank-dabno22.js'; import EasybankBawaatww from './banks/easybank-bawaatww.js'; import Fortuneo from './banks/FORTUNEO_FTNOFRP1XXX.js'; @@ -33,6 +34,7 @@ export const banks = [ Belfius, Berliner_Sparkasse_beladebexxx, BnpBeGebabebb, + CBCcregbebb, DanskeBankDabNO22, EasybankBawaatww, Fortuneo, diff --git a/src/app-gocardless/banks/cbc_cregbebb.js b/src/app-gocardless/banks/cbc_cregbebb.js new file mode 100644 index 000000000..bf881dacf --- /dev/null +++ b/src/app-gocardless/banks/cbc_cregbebb.js @@ -0,0 +1,36 @@ +import { extractPayeeNameFromRemittanceInfo } from './util/extract-payeeName-from-remittanceInfo.js'; +import Fallback from './integration-bank.js'; + +/** @type {import('./bank.interface.js').IBank} */ +export default { + ...Fallback, + + institutionIds: ['CBC_CREGBEBB'], + + /** + * For negative amounts, the only payee information we have is returned in + * remittanceInformationUnstructured. + */ + normalizeTransaction(transaction, _booked) { + if (Number(transaction.transactionAmount.amount) > 0) { + return { + ...transaction, + payeeName: + transaction.debtorName || + transaction.remittanceInformationUnstructured, + date: transaction.bookingDate || transaction.valueDate, + }; + } + + return { + ...transaction, + payeeName: + transaction.creditorName || + extractPayeeNameFromRemittanceInfo( + transaction.remittanceInformationUnstructured, + ['Paiement', 'Domiciliation', 'Transfert', 'Ordre permanent'], + ), + date: transaction.bookingDate || transaction.valueDate, + }; + }, +}; diff --git a/src/app-gocardless/banks/kbc_kredbebb.js b/src/app-gocardless/banks/kbc_kredbebb.js index 089c4deca..f2c7a725e 100644 --- a/src/app-gocardless/banks/kbc_kredbebb.js +++ b/src/app-gocardless/banks/kbc_kredbebb.js @@ -1,24 +1,6 @@ +import { extractPayeeNameFromRemittanceInfo } from './util/extract-payeeName-from-remittanceInfo.js'; import Fallback from './integration-bank.js'; -/** - * The remittance information contains creditorName, payments method, dates, etc. - * This function makes sure to only extract the creditorName based on the different indicators like "Betaling met". - * f.e. Proxy Poel BE Gent Betaling met Apple Pay via Maestro 23-08-2024 om 14.03 uur XXXX XXXX XXXX XXXX -> Proxy Poel BE Gent - */ -function extractPayeeName(remittanceInformationUnstructured) { - const indices = [ - remittanceInformationUnstructured.lastIndexOf(' Betaling met'), - remittanceInformationUnstructured.lastIndexOf(' Domiciliëring'), - remittanceInformationUnstructured.lastIndexOf(' Overschrijving'), - ]; - - const indexForRemoval = Math.max(...indices); - - return indexForRemoval > -1 - ? remittanceInformationUnstructured.substring(0, indexForRemoval) - : remittanceInformationUnstructured; -} - /** @type {import('./bank.interface.js').IBank} */ export default { ...Fallback, @@ -44,7 +26,10 @@ export default { ...transaction, payeeName: transaction.creditorName || - extractPayeeName(transaction.remittanceInformationUnstructured), + extractPayeeNameFromRemittanceInfo( + transaction.remittanceInformationUnstructured, + ['Betaling met', 'Domiciliëring', 'Overschrijving'], + ), date: transaction.bookingDate || transaction.valueDate, }; }, diff --git a/src/app-gocardless/banks/tests/cbc_cregbebb.spec.js b/src/app-gocardless/banks/tests/cbc_cregbebb.spec.js new file mode 100644 index 000000000..4114ac494 --- /dev/null +++ b/src/app-gocardless/banks/tests/cbc_cregbebb.spec.js @@ -0,0 +1,32 @@ +import CBCcregbebb from '../cbc_cregbebb.js'; + +describe('cbc_cregbebb', () => { + describe('#normalizeTransaction', () => { + it('returns the remittanceInformationUnstructured as payeeName when the amount is negative', () => { + const transaction = { + remittanceInformationUnstructured: + 'ONKART FR Viry Paiement Maestro par Carte de débit CBC 05-09-2024 à 15.43 heures 6703 19XX XXXX X201 5 JOHN DOE', + transactionAmount: { amount: '-45.00', currency: 'EUR' }, + }; + const normalizedTransaction = CBCcregbebb.normalizeTransaction( + transaction, + true, + ); + expect(normalizedTransaction.payeeName).toEqual('ONKART FR Viry'); + }); + + it('returns the debtorName as payeeName when the amount is positive', () => { + const transaction = { + debtorName: 'ONKART FR Viry', + remittanceInformationUnstructured: + 'ONKART FR Viry Paiement Maestro par Carte de débit CBC 05-09-2024 à 15.43 heures 6703 19XX XXXX X201 5 JOHN DOE', + transactionAmount: { amount: '10.99', currency: 'EUR' }, + }; + const normalizedTransaction = CBCcregbebb.normalizeTransaction( + transaction, + true, + ); + expect(normalizedTransaction.payeeName).toEqual('ONKART FR Viry'); + }); + }); +}); diff --git a/src/app-gocardless/banks/util/extract-payeeName-from-remittanceInfo.js b/src/app-gocardless/banks/util/extract-payeeName-from-remittanceInfo.js new file mode 100644 index 000000000..4dcb7fa2d --- /dev/null +++ b/src/app-gocardless/banks/util/extract-payeeName-from-remittanceInfo.js @@ -0,0 +1,36 @@ +/** +/** + * Extracts the payee name from the unstructured remittance information string based on pattern detection. + * + * This function scans the `remittanceInformationUnstructured` string for the presence of + * any of the specified patterns and removes the substring from the position of the last + * occurrence of the most relevant pattern. If no patterns are found, it returns the original string. + * + * @param {string} [remittanceInformationUnstructured=''] - The unstructured remittance information from which to extract the payee name. + * @param {string[]} [patterns=[]] - An array of patterns to look for within the remittance information. + * These patterns are used to identify and remove unwanted parts of the remittance information. + * @returns {string} - The extracted payee name, cleaned of any matched patterns, or the original + * remittance information if no patterns are found. + * + * @example + * const remittanceInfo = 'John Doe Paiement Maestro par Carte de débit CBC 05-09-2024 à 15.43 heures 6703 19XX XXXX X...'; + * const patterns = ['Paiement', 'Domiciliation', 'Transfert', 'Ordre permanent']; + * const payeeName = extractPayeeNameFromRemittanceInfo(remittanceInfo, patterns); // --> 'John Doe' + */ +export function extractPayeeNameFromRemittanceInfo( + remittanceInformationUnstructured, + patterns, +) { + if (!remittanceInformationUnstructured || !patterns.length) { + return remittanceInformationUnstructured; + } + + const indexForRemoval = patterns.reduce((maxIndex, pattern) => { + const index = remittanceInformationUnstructured.lastIndexOf(pattern); + return index > maxIndex ? index : maxIndex; + }, -1); + + return indexForRemoval > -1 + ? remittanceInformationUnstructured.substring(0, indexForRemoval).trim() + : remittanceInformationUnstructured; +} diff --git a/upcoming-release-notes/451.md b/upcoming-release-notes/451.md new file mode 100644 index 000000000..a6b2e9491 --- /dev/null +++ b/upcoming-release-notes/451.md @@ -0,0 +1,6 @@ +--- +category: Bugfix +authors: [MMichotte] +--- + +Fix wrong payeeName used for CBC_CREGBEBB \ No newline at end of file