Skip to content

Commit 23a63bc

Browse files
authored
Merge pull request #18 from as19git67:main
Allow multiple Ustrd when parsing remittanceInfo
2 parents 173f37d + 977199f commit 23a63bc

2 files changed

Lines changed: 199 additions & 0 deletions

File tree

src/camtParser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,9 @@ export class CamtParser {
352352
if (typeof current === 'string' || typeof current === 'number') {
353353
return String(current);
354354
}
355+
if (Array.isArray(current)) {
356+
return String(current.join(''));
357+
}
355358
if (current && typeof current === 'object' && current !== null && '#text' in current) {
356359
return String((current as { '#text': unknown })['#text']);
357360
}

src/tests/camtParser.test.ts

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,4 +728,200 @@ describe('CamtParser', () => {
728728
expect(transaction.purpose).toBe('Payment with party structure');
729729
expect(transaction.amount).toBe(200.0);
730730
});
731+
732+
it('should handle multiple entries in RmtInf (Ustrd)', () => {
733+
const camtXml = `<?xml version="1.0" encoding="ISO-8859-1"?>
734+
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08"
735+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
736+
xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08 camt.052.001.08.xsd">
737+
<BkToCstmrAcctRpt>
738+
<GrpHdr>
739+
<MsgId>52D20260106T1009246445830N000000000</MsgId>
740+
<CreDtTm>2026-01-06T10:09:24.0+01:00</CreDtTm>
741+
</GrpHdr>
742+
<Rpt>
743+
<Id>0752D522026010610092464000001000</Id>
744+
<RptPgntn>
745+
<PgNb>1</PgNb>
746+
<LastPgInd>true</LastPgInd>
747+
</RptPgntn>
748+
<ElctrncSeqNb>000000000</ElctrncSeqNb>
749+
<CreDtTm>2026-01-06T10:09:24.0+01:00</CreDtTm>
750+
<Acct>
751+
<Id>
752+
<IBAN>DE06940594210000027227</IBAN>
753+
</Id>
754+
<Ccy>EUR</Ccy>
755+
<Ownr>
756+
<Nm>John Doe</Nm>
757+
</Ownr>
758+
<Svcr>
759+
<FinInstnId>
760+
<BICFI>BANKABC1XXX</BICFI>
761+
<Nm>ABC Bank</Nm>
762+
<Othr>
763+
<Id>DE 123456789</Id>
764+
<Issr>UmsStId</Issr>
765+
</Othr>
766+
</FinInstnId>
767+
</Svcr>
768+
</Acct>
769+
<Bal>
770+
<Tp>
771+
<CdOrPrtry>
772+
<Cd>OPBD</Cd>
773+
</CdOrPrtry>
774+
</Tp>
775+
<Amt Ccy="EUR">27.31</Amt>
776+
<CdtDbtInd>DBIT</CdtDbtInd>
777+
<Dt>
778+
<Dt>2026-01-05</Dt>
779+
</Dt>
780+
</Bal>
781+
<Bal>
782+
<Tp>
783+
<CdOrPrtry>
784+
<Cd>CLBD</Cd>
785+
</CdOrPrtry>
786+
</Tp>
787+
<Amt Ccy="EUR">234.81</Amt>
788+
<CdtDbtInd>DBIT</CdtDbtInd>
789+
<Dt>
790+
<Dt>2026-01-05</Dt>
791+
</Dt>
792+
</Bal>
793+
<Ntry>
794+
<Amt Ccy="EUR">179.46</Amt>
795+
<CdtDbtInd>DBIT</CdtDbtInd>
796+
<Sts>
797+
<Cd>BOOK</Cd>
798+
</Sts>
799+
<BookgDt>
800+
<Dt>2026-01-05</Dt>
801+
</BookgDt>
802+
<ValDt>
803+
<Dt>2026-01-05</Dt>
804+
</ValDt>
805+
<AcctSvcrRef>TXN003</AcctSvcrRef>
806+
<BkTxCd>
807+
<Domn>
808+
<Cd>PMNT</Cd>
809+
<Fmly>
810+
<Cd>ICDT</Cd>
811+
<SubFmlyCd>ESCT</SubFmlyCd>
812+
</Fmly>
813+
</Domn>
814+
<Prtry>
815+
<Cd>NTRF+116+02089</Cd>
816+
<Issr>DK</Issr>
817+
</Prtry>
818+
</BkTxCd>
819+
<NtryDtls>
820+
<TxDtls>
821+
<Refs>
822+
<MsgId>test msgid</MsgId>
823+
<PmtInfId>VG 2025 QUARTAL IV 12345678</PmtInfId>
824+
<EndToEndId>VG 2025 QUARTAL IV</EndToEndId>
825+
</Refs>
826+
<Amt Ccy="EUR">179.46</Amt>
827+
<BkTxCd>
828+
<Domn>
829+
<Cd>PMNT</Cd>
830+
<Fmly>
831+
<Cd>ICDT</Cd>
832+
<SubFmlyCd>ESCT</SubFmlyCd>
833+
</Fmly>
834+
</Domn>
835+
<Prtry>
836+
<Cd>NTRF+116+02189</Cd>
837+
<Issr>DK</Issr>
838+
</Prtry>
839+
</BkTxCd>
840+
<RltdPties>
841+
<Dbtr>
842+
<Pty>
843+
<Nm>DOE</Nm>
844+
</Pty>
845+
</Dbtr>
846+
<DbtrAcct>
847+
<Id>
848+
<IBAN>DE12345678901234567890</IBAN>
849+
</Id>
850+
</DbtrAcct>
851+
<Cdtr>
852+
<Pty>
853+
<Nm>ABC Bank</Nm>
854+
</Pty>
855+
</Cdtr>
856+
<CdtrAcct>
857+
<Id>
858+
<IBAN>DE12345678901234567891</IBAN>
859+
</Id>
860+
</CdtrAcct>
861+
</RltdPties>
862+
<RltdAgts>
863+
<CdtrAgt>
864+
<FinInstnId>
865+
<BICFI>BANKABC1XXX</BICFI>
866+
</FinInstnId>
867+
</CdtrAgt>
868+
</RltdAgts>
869+
<RmtInf>
870+
<Ustrd>28,65EUR EREF: VG 2025 QUARTAL IV IBAN</Ustrd>
871+
<Ustrd>: DE12345678901234567891 BIC: BANKABC1XXX</Ustrd>
872+
</RmtInf>
873+
</TxDtls>
874+
</NtryDtls>
875+
<AddtlNtryInf>ENTGELT gem. Vereinbarung</AddtlNtryInf>
876+
</Ntry>
877+
</Rpt>
878+
</BkToCstmrAcctRpt>
879+
</Document>`;
880+
881+
const parser = new CamtParser(camtXml);
882+
const statements = parser.parse();
883+
884+
expect(statements).toHaveLength(1);
885+
const statement = statements[0];
886+
expect(statement.transactions).toHaveLength(1);
887+
888+
const transaction = statement.transactions[0];
889+
890+
// Check all Transaction fields filled by the parser
891+
expect(transaction.amount).toBe(-179.46);
892+
expect(transaction.customerReference).toBe('VG 2025 QUARTAL IV');
893+
expect(transaction.bankReference).toBe('TXN003');
894+
expect(transaction.purpose).toBe(
895+
'28,65EUR EREF: VG 2025 QUARTAL IV IBAN: DE12345678901234567891 BIC: BANKABC1XXX',
896+
);
897+
expect(transaction.remoteName).toBe('ABC Bank');
898+
expect(transaction.remoteAccountNumber).toBe('DE12345678901234567891');
899+
expect(transaction.remoteBankId).toBe('BANKABC1XXX');
900+
expect(transaction.e2eReference).toBe('VG 2025 QUARTAL IV');
901+
902+
// Check date fields
903+
expect(transaction.valueDate).toBeInstanceOf(Date);
904+
expect(transaction.valueDate.getFullYear()).toBe(2026);
905+
expect(transaction.valueDate.getMonth()).toBe(0); // November (0-based)
906+
expect(transaction.valueDate.getDate()).toBe(5);
907+
expect(transaction.entryDate).toBeInstanceOf(Date);
908+
expect(transaction.entryDate.getFullYear()).toBe(2026);
909+
expect(transaction.entryDate.getMonth()).toBe(0); // November (0-based)
910+
expect(transaction.entryDate.getDate()).toBe(5);
911+
912+
// Check transaction type and code fields
913+
expect(transaction.fundsCode).toBe('PMNT');
914+
expect(transaction.transactionType).toBe('ICDT');
915+
expect(transaction.transactionCode).toBe('ESCT');
916+
917+
// Check additional information fields
918+
expect(transaction.additionalInformation).toBe('ENTGELT gem. Vereinbarung');
919+
expect(transaction.bookingText).toBe('ENTGELT gem. Vereinbarung'); // Should match additionalInformation
920+
921+
// Verify optional fields not set in this test
922+
expect(transaction.primeNotesNr).toBeUndefined();
923+
expect(transaction.remoteIdentifier).toBeUndefined();
924+
expect(transaction.client).toBeUndefined();
925+
expect(transaction.textKeyExtension).toBeUndefined();
926+
});
731927
});

0 commit comments

Comments
 (0)