mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-22 00:13:45 -05:00
Fix Boursorama GoCardless transaction ordering (#5344)
I wrongly thought that all the card transactions will always have their first line with the `CARTE` identifier. But as I have seen recently, it's not the case, and we shouldn't rely on the ordering of the array returned by the Boursorama GoCardless integration. Thus, check for transaction patterns in all of the lines of the unstructured array. This addresses a true case (added in test) where the payee name was wrongly extracted as being `110,04 Gbp / 1 Euro = 0,860763454`
This commit is contained in:
committed by
GitHub
parent
5db7026435
commit
76de8bf67f
@@ -30,61 +30,62 @@ export default {
|
||||
.filter(line => line.startsWith('Réf : ') === false);
|
||||
|
||||
const infoArray = editedTrans.remittanceInformationUnstructuredArray;
|
||||
const firstLine = infoArray[0];
|
||||
|
||||
let match;
|
||||
|
||||
/*
|
||||
* Some transactions always have their identifier in the first line (e.g. card),
|
||||
* while others have it **randomly** in any of the lines (e.g. transfers).
|
||||
*/
|
||||
|
||||
// Check the first line for specific patterns
|
||||
if ((match = firstLine.match(regexCard))) {
|
||||
// Transactions can have their identifier in any line, as the order of lines is not guaranteed.
|
||||
// This is why we check all lines for specific patterns.
|
||||
if ((match = infoArray.find(line => regexCard.test(line)))) {
|
||||
// Card transaction
|
||||
const payeeName = match.groups.payeeName;
|
||||
editedTrans.payeeName = title(payeeName);
|
||||
editedTrans.notes = `Carte ${match.groups.date}`;
|
||||
const cardMatch = match.match(regexCard);
|
||||
editedTrans.payeeName = title(cardMatch.groups.payeeName);
|
||||
editedTrans.notes = `Carte ${cardMatch.groups.date}`;
|
||||
if (infoArray.length > 1) {
|
||||
editedTrans.notes += ' ' + infoArray.slice(1).join(' ');
|
||||
editedTrans.notes += ' ' + infoArray.filter(l => l !== match).join(' ');
|
||||
}
|
||||
} else if ((match = firstLine.match(regexLoan))) {
|
||||
} else if ((match = infoArray.find(line => regexLoan.test(line)))) {
|
||||
// Loan
|
||||
editedTrans.payeeName = 'Prêt bancaire';
|
||||
editedTrans.notes = firstLine;
|
||||
} else if ((match = firstLine.match(regexAtmWithdrawal))) {
|
||||
editedTrans.notes = match;
|
||||
} else if (
|
||||
(match = infoArray.find(line => regexAtmWithdrawal.test(line)))
|
||||
) {
|
||||
// ATM withdrawal
|
||||
const atmMatch = match.match(regexAtmWithdrawal);
|
||||
editedTrans.payeeName = 'Retrait DAB';
|
||||
editedTrans.notes = `Retrait ${match.groups.date} ${match.groups.locationName}`;
|
||||
editedTrans.notes = `Retrait ${atmMatch.groups.date} ${atmMatch.groups.locationName}`;
|
||||
if (infoArray.length > 1) {
|
||||
editedTrans.notes += ' ' + infoArray.slice(1).join(' ');
|
||||
editedTrans.notes += ' ' + infoArray.filter(l => l !== match).join(' ');
|
||||
}
|
||||
} else if ((match = firstLine.match(regexCreditNote))) {
|
||||
} else if ((match = infoArray.find(line => regexCreditNote.test(line)))) {
|
||||
// Credit note (refund)
|
||||
editedTrans.payeeName = title(match.groups.payeeName);
|
||||
editedTrans.notes = `Avoir ${match.groups.date}`;
|
||||
} else {
|
||||
// For the next patterns, we need to check all lines as the identifier can be anywhere
|
||||
if ((match = infoArray.find(line => regexInstantTransfer.test(line)))) {
|
||||
// Instant transfer
|
||||
editedTrans.payeeName = title(match.replace(regexInstantTransfer, ''));
|
||||
editedTrans.notes = infoArray.filter(l => l !== match).join(' ');
|
||||
} else if ((match = infoArray.find(line => regexSepa.test(line)))) {
|
||||
// SEPA transfer
|
||||
editedTrans.payeeName = title(match.replace(regexSepa, ''));
|
||||
editedTrans.notes = infoArray.filter(l => l !== match).join(' ');
|
||||
} else if ((match = infoArray.find(line => regexTransfer.test(line)))) {
|
||||
// Other transfer
|
||||
// Must be evaluated after the other transfers as they're more specific
|
||||
// (here VIR only)
|
||||
const infoArrayWithoutLine = infoArray.filter(l => l !== match);
|
||||
editedTrans.payeeName = title(infoArrayWithoutLine.join(' '));
|
||||
editedTrans.notes = match.replace(regexTransfer, '');
|
||||
} else {
|
||||
// Unknown transaction type
|
||||
editedTrans.payeeName = title(firstLine.replace(/ \d+$/, ''));
|
||||
editedTrans.notes = infoArray.slice(1).join(' ');
|
||||
const creditMatch = match.match(regexCreditNote);
|
||||
editedTrans.payeeName = title(creditMatch.groups.payeeName);
|
||||
editedTrans.notes = `Avoir ${creditMatch.groups.date}`;
|
||||
if (infoArray.length > 1) {
|
||||
editedTrans.notes += ' ' + infoArray.filter(l => l !== match).join(' ');
|
||||
}
|
||||
} else if (
|
||||
(match = infoArray.find(line => regexInstantTransfer.test(line)))
|
||||
) {
|
||||
// Instant transfer
|
||||
editedTrans.payeeName = title(match.replace(regexInstantTransfer, ''));
|
||||
editedTrans.notes = infoArray.filter(l => l !== match).join(' ');
|
||||
} else if ((match = infoArray.find(line => regexSepa.test(line)))) {
|
||||
// SEPA transfer
|
||||
editedTrans.payeeName = title(match.replace(regexSepa, ''));
|
||||
editedTrans.notes = infoArray.filter(l => l !== match).join(' ');
|
||||
} else if ((match = infoArray.find(line => regexTransfer.test(line)))) {
|
||||
// Other transfer
|
||||
// Must be evaluated after the other transfers as they're more specific
|
||||
// (here VIR only)
|
||||
const infoArrayWithoutLine = infoArray.filter(l => l !== match);
|
||||
editedTrans.payeeName = title(infoArrayWithoutLine.join(' '));
|
||||
editedTrans.notes = match.replace(regexTransfer, '');
|
||||
} else {
|
||||
// Unknown transaction type
|
||||
editedTrans.payeeName = title(infoArray[0].replace(/ \d+$/, ''));
|
||||
editedTrans.notes = infoArray.slice(1).join(' ');
|
||||
}
|
||||
|
||||
return Fallback.normalizeTransaction(transaction, booked, editedTrans);
|
||||
|
||||
@@ -19,6 +19,19 @@ describe('BoursoBank', () => {
|
||||
'Payee Name',
|
||||
'Carte 03/02/25 2,80 NZD / 1 euro = 1,818181818',
|
||||
],
|
||||
[
|
||||
[
|
||||
'2,80 NZD / 1 euro = 1,818181818',
|
||||
'CARTE 03/02/25 PAYEE NAME CB*1234',
|
||||
],
|
||||
'Payee Name',
|
||||
'Carte 03/02/25 2,80 NZD / 1 euro = 1,818181818',
|
||||
],
|
||||
[
|
||||
['110,04 GBP / 1 euro = 0,860763454', 'CARTE 13/07/25 PAYEE NAME'],
|
||||
'Payee Name',
|
||||
'Carte 13/07/25 110,04 GBP / 1 euro = 0,860763454',
|
||||
],
|
||||
[
|
||||
['RETRAIT DAB 01/03/25 My location CB*9876'],
|
||||
'Retrait DAB',
|
||||
@@ -32,6 +45,14 @@ describe('BoursoBank', () => {
|
||||
'Retrait DAB',
|
||||
'Retrait 01/03/25 My location 2,80 NZD / 1 euro = 1,818181818',
|
||||
],
|
||||
[
|
||||
[
|
||||
'2,80 NZD / 1 euro = 1,818181818',
|
||||
'RETRAIT DAB 01/03/25 My location CB*9876',
|
||||
],
|
||||
'Retrait DAB',
|
||||
'Retrait 01/03/25 My location 2,80 NZD / 1 euro = 1,818181818',
|
||||
],
|
||||
[
|
||||
['VIR Text put by the sender', 'PAYEE NAME'],
|
||||
'Payee Name',
|
||||
|
||||
Reference in New Issue
Block a user