Skip to content
This repository has been archived by the owner on Feb 10, 2025. It is now read-only.

Commit

Permalink
Add GoCardless integration for COMMERZBANK_COBADEFF
Browse files Browse the repository at this point in the history
  • Loading branch information
nsulzer committed Jan 5, 2025
1 parent 2005c1b commit 5c23963
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/app-gocardless/bank-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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 CommerzbankCobadeff from './banks/commerzbank_cobadeff.js';
import DanskeBankDabNO22 from './banks/danskebank-dabno22.js';
import EasybankBawaatww from './banks/easybank-bawaatww.js';
import EntercardSwednokk from './banks/entercard-swednokk.js';
Expand Down Expand Up @@ -44,6 +45,7 @@ export const banks = [
Berliner_Sparkasse_beladebexxx,
BnpBeGebabebb,
CBCcregbebb,
CommerzbankCobadeff,
DanskeBankDabNO22,
EasybankBawaatww,
EntercardSwednokk,
Expand Down
87 changes: 87 additions & 0 deletions src/app-gocardless/banks/commerzbank_cobadeff.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import Fallback from './integration-bank.js';
import { amountToInteger, printIban } from '../utils.js';
import { formatPayeeName } from '../../util/payee-name.js';

/** @type {import('./bank.interface.js').IBank} */
export default {
...Fallback,

institutionIds: ['COMMERZBANK_COBADEFF'],

accessValidForDays: 179,

normalizeAccount(account) {
return {
account_id: account.id,
institution: account.institution,
mask: account.iban.slice(-4),
iban: account.iban,
name: [account.name, printIban(account)].join(' '),
official_name: account.product,
type: 'checking',
};
},

normalizeTransaction(transaction, _booked) {
// remittanceInformationUnstructured is limited to 140 chars thus ...
// ... missing information form remittanceInformationUnstructuredArray ...
// ... so we recreate it.
transaction.remittanceInformationUnstructured =
transaction.remittanceInformationUnstructuredArray.join(' ');

// The limitations of remittanceInformationUnstructuredArray ...
// ... can result in split keywords. We fix these. Other ...
// ... splits will need to be fixed by user with rules.
const keywords = [
'End-to-End-Ref.:',
'Mandatsref:',
'Gläubiger-ID:',
'SEPA-BASISLASTSCHRIFT',
'Kartenzahlung',
'Dauerauftrag',
];
keywords.forEach((keyword) => {
transaction.remittanceInformationUnstructured =
transaction.remittanceInformationUnstructured.replace(
RegExp(keyword.split('').join('\\s*'), 'gi'),
', ' + keyword + ' ',
);
});

// Clean up remittanceInformation, deduplicate payee (removing slashes ...
// ... that are added to the remittanceInformation field), and ...
// ... remove clutter like "End-to-End-Ref.: NOTPROVIDED"
const payee = transaction.creditorName || transaction.debtorName || '';
transaction.remittanceInformationUnstructured =
transaction.remittanceInformationUnstructured
.replace(/\s*(,)?\s+/g, '$1 ')
.replace(RegExp(payee.split(' ').join('(/*| )'), 'gi'), ' ')
.replace(', End-to-End-Ref.: NOTPROVIDED', '')
.trim();

return {
...transaction,
payeeName: formatPayeeName(transaction),
date: transaction.bookingDate,
};
},

/**
* For COMMERZBANK_COBADEFF we don't know what balance was
* after each transaction so we have to calculate it by getting
* current balance from the account and subtract all the transactions
*
* As a current balance we use `expected` balance type because it
* corresponds to the current running balance, whereas `interimAvailable`
* holds the remaining credit limit.
*/
calculateStartingBalance(sortedTransactions = [], balances = []) {
const currentBalance = balances.find(
(balance) => 'expected' === balance.balanceType,
);

return sortedTransactions.reduce((total, trans) => {
return total - amountToInteger(trans.transactionAmount.amount);
}, amountToInteger(currentBalance.balanceAmount.amount));
},
};
110 changes: 110 additions & 0 deletions src/app-gocardless/banks/tests/commerzbank_cobadeff.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import CommerzbankCobadeff from '../commerzbank_cobadeff.js';

describe('CommerzbankCobadeff', () => {
describe('#normalizeTransaction', () => {
it('correctly formats remittanceInformationUnstructured', () => {
const transaction = {
endToEndId: '1234567890',
mandateId: '321654',
bookingDate: '2024-12-20',
valueDate: '2024-12-20',
transactionAmount: {
amount: '-12.34',
currency: 'EUR',
},
creditorName: 'SHOP NAME CITY DE',
remittanceInformationUnstructured:
'SHOP NAME//CITY/DE\n2024-12-19T15:34:31 KFN 1 AB 1234\nKartenzahlung',
remittanceInformationUnstructuredArray: [
'SHOP NAME//CITY/DE',
'2024-12-19T15:34:31 KFN 1 AB 1234',
'Kartenzahlung',
],
remittanceInformationStructured:
'SHOP NAME//CITY/DE 2024-12-19T15:34:31 KFN 1 AB 1234 Kartenzahlung',
internalTransactionId: '3815213adb654baeadfb231c853',
};
const normalizedTransaction = CommerzbankCobadeff.normalizeTransaction(
transaction,
false,
);
expect(normalizedTransaction.remittanceInformationUnstructured).toEqual(
'2024-12-19T15:34:31 KFN 1 AB 1234, Kartenzahlung',
);
});

it('correctly formats remittanceInformationUnstructured; repair split keyword', () => {
const transaction = {
endToEndId: '901234567890',
mandateId: 'ABC123DEF456',
bookingDate: '2024-10-11',
valueDate: '2024-10-11',
transactionAmount: {
amount: '-56.78',
currency: 'EUR',
},
creditorName: 'Long payee name that is eaxtly 35ch',
remittanceInformationUnstructured:
'Long payee name that is eaxtly 35ch\n901234567890/. Long description tha\nt gets cut and is very long, did I\nmention it is long\nEnd-to-En',
remittanceInformationUnstructuredArray: [
'Long payee name that is eaxtly 35ch',
'901234567890/. Long description tha',
't gets cut and is very long, did I',
'mention it is long',
'End-to-En',
'd-Ref.: 901234567890',
'Mandatsref: ABC123DEF456',
'Gläubiger-ID:',
'AB12CDE0000000000000000012',
'SEPA-BASISLASTSCHRIFT wiederholend',
],
remittanceInformationStructured:
'Long payee name that is eaxtly 35ch 901234567890/. Long description tha t gets cut and is very long, did I mention it is long End-to-En',
internalTransactionId: '812354cfdea36465asdfe',
};
const normalizedTransaction = CommerzbankCobadeff.normalizeTransaction(
transaction,
false,
);
expect(normalizedTransaction.remittanceInformationUnstructured).toEqual(
'901234567890/. Long description tha t gets cut and is very long, did I mention it is long, End-to-End-Ref.: 901234567890, Mandatsref: ABC123DEF456, Gläubiger-ID: AB12CDE0000000000000000012, SEPA-BASISLASTSCHRIFT wiederholend',
);
});

it('correctly formats remittanceInformationUnstructured; removing NOTPROVIDED', () => {
const transaction = {
endToEndId: 'NOTPROVIDED',
bookingDate: '2024-12-02',
valueDate: '2024-12-02',
transactionAmount: {
amount: '-9',
currency: 'EUR',
},
creditorName: 'CREDITOR NAME',
creditorAccount: {
iban: 'CREDITOR000IBAN',
},
remittanceInformationUnstructured:
'CREDITOR NAME\nCREDITOR00BIC\nCREDITOR000IBAN\nDESCRIPTION\nEnd-to-End-Ref.: NOTPROVIDED\nDauerauftrag',
remittanceInformationUnstructuredArray: [
'CREDITOR NAME',
'CREDITOR00BIC',
'CREDITOR000IBAN',
'DESCRIPTION',
'End-to-End-Ref.: NOTPROVIDED',
'Dauerauftrag',
],
remittanceInformationStructured:
'CREDITOR NAME CREDITOR00BIC CREDITOR000IBAN DESCRIPTION End-to-End-Ref.: NOTPROVIDED Dauerauftrag',
internalTransactionId: 'f617dc31ab77622bf13d6c95d6dd8b4a',
};
const normalizedTransaction = CommerzbankCobadeff.normalizeTransaction(
transaction,

Check failure on line 102 in src/app-gocardless/banks/tests/commerzbank_cobadeff.spec.js

View workflow job for this annotation

GitHub Actions / build

Argument of type '{ endToEndId: string; bookingDate: string; valueDate: string; transactionAmount: { amount: string; currency: string; }; creditorName: string; creditorAccount: { iban: string; }; remittanceInformationUnstructured: string; remittanceInformationUnstructuredArray: string[]; remittanceInformationStructured: string; inter...' is not assignable to parameter of type 'Transaction'.
false,
);
expect(normalizedTransaction.remittanceInformationUnstructured).toEqual(
'CREDITOR00BIC CREDITOR000IBAN DESCRIPTION, Dauerauftrag',
);
});
});
});
6 changes: 6 additions & 0 deletions upcoming-release-notes/537.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [nsulzer]
---

Add GoCardless integration for COMMERZBANK_COBADEFF

0 comments on commit 5c23963

Please sign in to comment.