lib-fints 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -40
- package/dist/camtParser.js +412 -0
- package/dist/client.js +58 -80
- package/dist/dataGroups/SepaAccount.js +17 -0
- package/dist/dataGroups/SepaAccountParameters.js +16 -0
- package/dist/dialog.js +126 -108
- package/dist/httpClient.js +17 -3
- package/dist/index.js +1 -0
- package/dist/interactions/balanceInteraction.js +1 -1
- package/dist/interactions/customerInteraction.js +6 -3
- package/dist/interactions/endDialogInteraction.js +17 -0
- package/dist/interactions/initDialogInteraction.js +18 -8
- package/dist/interactions/sepaAccountInteraction.js +48 -0
- package/dist/interactions/statementInteractionCAMT.js +54 -0
- package/dist/interactions/{statementInteraction.js → statementInteractionMT940.js} +11 -8
- package/dist/interactions/tanMediaInteraction.js +4 -0
- package/dist/segments/HICAZ.js +22 -0
- package/dist/segments/HICAZS.js +19 -0
- package/dist/segments/HISPA.js +14 -0
- package/dist/segments/HISPAS.js +14 -0
- package/dist/segments/HKCAZ.js +28 -0
- package/dist/segments/HKSPA.js +21 -0
- package/dist/segments/registry.js +16 -2
- package/dist/statement.js +1 -0
- package/dist/tests/HICAZS.test.js +18 -0
- package/dist/tests/HKCAZ.test.js +47 -0
- package/dist/tests/camtParser.test.js +673 -0
- package/dist/tests/client.test.js +21 -16
- package/dist/tests/dialog.test.js +234 -0
- package/dist/types/bankAccount.d.ts +2 -3
- package/dist/types/bankAccount.d.ts.map +1 -1
- package/dist/types/camtParser.d.ts +31 -0
- package/dist/types/camtParser.d.ts.map +1 -0
- package/dist/types/client.d.ts +4 -4
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/config.d.ts +2 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/dataGroups/SepaAccount.d.ts +11 -0
- package/dist/types/dataGroups/SepaAccount.d.ts.map +1 -0
- package/dist/types/dataGroups/SepaAccountParameters.d.ts +13 -0
- package/dist/types/dataGroups/SepaAccountParameters.d.ts.map +1 -0
- package/dist/types/dialog.d.ts +12 -8
- package/dist/types/dialog.d.ts.map +1 -1
- package/dist/types/httpClient.d.ts +2 -1
- package/dist/types/httpClient.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/interactions/customerInteraction.d.ts +7 -3
- package/dist/types/interactions/customerInteraction.d.ts.map +1 -1
- package/dist/types/interactions/endDialogInteraction.d.ts +13 -0
- package/dist/types/interactions/endDialogInteraction.d.ts.map +1 -0
- package/dist/types/interactions/initDialogInteraction.d.ts +2 -3
- package/dist/types/interactions/initDialogInteraction.d.ts.map +1 -1
- package/dist/types/interactions/sepaAccountInteraction.d.ts +17 -0
- package/dist/types/interactions/sepaAccountInteraction.d.ts.map +1 -0
- package/dist/types/interactions/{statementInteraction.d.ts → statementInteractionCAMT.d.ts} +4 -7
- package/dist/types/interactions/statementInteractionCAMT.d.ts.map +1 -0
- package/dist/types/interactions/statementInteractionMT940.d.ts +13 -0
- package/dist/types/interactions/statementInteractionMT940.d.ts.map +1 -0
- package/dist/types/interactions/tanMediaInteraction.d.ts.map +1 -1
- package/dist/types/mt940parser.d.ts +2 -38
- package/dist/types/mt940parser.d.ts.map +1 -1
- package/dist/types/segments/HICAZ.d.ts +22 -0
- package/dist/types/segments/HICAZ.d.ts.map +1 -0
- package/dist/types/segments/HICAZS.d.ts +17 -0
- package/dist/types/segments/HICAZS.d.ts.map +1 -0
- package/dist/types/segments/HISPA.d.ts +17 -0
- package/dist/types/segments/HISPA.d.ts.map +1 -0
- package/dist/types/segments/HISPAS.d.ts +14 -0
- package/dist/types/segments/HISPAS.d.ts.map +1 -0
- package/dist/types/segments/HKCAZ.d.ts +27 -0
- package/dist/types/segments/HKCAZ.d.ts.map +1 -0
- package/dist/types/segments/HKKAZ.d.ts +1 -1
- package/dist/types/segments/HKSAL.d.ts +1 -1
- package/dist/types/segments/HKSPA.d.ts +21 -0
- package/dist/types/segments/HKSPA.d.ts.map +1 -0
- package/dist/types/segments/HKTAN.d.ts +1 -1
- package/dist/types/segments/registry.d.ts.map +1 -1
- package/dist/types/statement.d.ts +39 -0
- package/dist/types/statement.d.ts.map +1 -0
- package/dist/types/tests/HICAZS.test.d.ts +2 -0
- package/dist/types/tests/HICAZS.test.d.ts.map +1 -0
- package/dist/types/tests/HKCAZ.test.d.ts +2 -0
- package/dist/types/tests/HKCAZ.test.d.ts.map +1 -0
- package/dist/types/tests/camtParser.test.d.ts +2 -0
- package/dist/types/tests/camtParser.test.d.ts.map +1 -0
- package/dist/types/tests/dialog.test.d.ts +2 -0
- package/dist/types/tests/dialog.test.d.ts.map +1 -0
- package/package.json +4 -1
- package/dist/types/interactions/statementInteraction.d.ts.map +0 -1
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CamtParser } from '../camtParser.js';
|
|
3
|
+
describe('CamtParser', () => {
|
|
4
|
+
it('should parse CAMT.052 XML with balances and transactions', () => {
|
|
5
|
+
const camtXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
6
|
+
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08">
|
|
7
|
+
<BkToCstmrAcctRpt>
|
|
8
|
+
<GrpHdr>
|
|
9
|
+
<MsgId>camt52_20131118101510__ONLINEBA</MsgId>
|
|
10
|
+
<CreDtTm>2013-11-18T10:15:10+01:00</CreDtTm>
|
|
11
|
+
</GrpHdr>
|
|
12
|
+
<Rpt>
|
|
13
|
+
<Id>camt052_ONLINEBA</Id>
|
|
14
|
+
<ElctrncSeqNb>00001</ElctrncSeqNb>
|
|
15
|
+
<CreDtTm>2013-11-18T10:15:10+01:00</CreDtTm>
|
|
16
|
+
<Acct>
|
|
17
|
+
<Id>
|
|
18
|
+
<IBAN>DE06940594210000027227</IBAN>
|
|
19
|
+
</Id>
|
|
20
|
+
<Ccy>EUR</Ccy>
|
|
21
|
+
</Acct>
|
|
22
|
+
<Bal>
|
|
23
|
+
<Tp>
|
|
24
|
+
<CdOrPrtry>
|
|
25
|
+
<Cd>PRCD</Cd>
|
|
26
|
+
</CdOrPrtry>
|
|
27
|
+
</Tp>
|
|
28
|
+
<Amt Ccy="EUR">1000.00</Amt>
|
|
29
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
30
|
+
<Dt>
|
|
31
|
+
<Dt>2013-10-31</Dt>
|
|
32
|
+
</Dt>
|
|
33
|
+
</Bal>
|
|
34
|
+
<Bal>
|
|
35
|
+
<Tp>
|
|
36
|
+
<CdOrPrtry>
|
|
37
|
+
<Cd>CLBD</Cd>
|
|
38
|
+
</CdOrPrtry>
|
|
39
|
+
</Tp>
|
|
40
|
+
<Amt Ccy="EUR">1500.00</Amt>
|
|
41
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
42
|
+
<Dt>
|
|
43
|
+
<Dt>2013-11-04</Dt>
|
|
44
|
+
</Dt>
|
|
45
|
+
</Bal>
|
|
46
|
+
<Ntry>
|
|
47
|
+
<Amt>500.00</Amt>
|
|
48
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
49
|
+
<BookgDt>
|
|
50
|
+
<Dt>2013-11-01</Dt>
|
|
51
|
+
</BookgDt>
|
|
52
|
+
<ValDt>
|
|
53
|
+
<Dt>2013-11-01</Dt>
|
|
54
|
+
</ValDt>
|
|
55
|
+
<AcctSvcrRef>TXN001</AcctSvcrRef>
|
|
56
|
+
<BkTxCd>
|
|
57
|
+
<Prtry>
|
|
58
|
+
<Cd>TRF</Cd>
|
|
59
|
+
</Prtry>
|
|
60
|
+
</BkTxCd>
|
|
61
|
+
<NtryDtls>
|
|
62
|
+
<TxDtls>
|
|
63
|
+
<Refs>
|
|
64
|
+
<EndToEndId>E2E123</EndToEndId>
|
|
65
|
+
<MndtId>MANDT001</MndtId>
|
|
66
|
+
</Refs>
|
|
67
|
+
<RmtInf>
|
|
68
|
+
<Ustrd>Test payment</Ustrd>
|
|
69
|
+
</RmtInf>
|
|
70
|
+
<RltdPties>
|
|
71
|
+
<Dbtr>
|
|
72
|
+
<Nm>John Doe</Nm>
|
|
73
|
+
</Dbtr>
|
|
74
|
+
<DbtrAcct>
|
|
75
|
+
<Id>
|
|
76
|
+
<IBAN>DE12345678901234567890</IBAN>
|
|
77
|
+
</Id>
|
|
78
|
+
</DbtrAcct>
|
|
79
|
+
<Cdtr>
|
|
80
|
+
<Nm>Jane Doe</Nm>
|
|
81
|
+
</Cdtr>
|
|
82
|
+
<CdtrAcct>
|
|
83
|
+
<Id>
|
|
84
|
+
<IBAN>DE12345678901234567891</IBAN>
|
|
85
|
+
</Id>
|
|
86
|
+
</CdtrAcct>
|
|
87
|
+
</RltdPties>
|
|
88
|
+
<RltdAgts>
|
|
89
|
+
<DbtrAgt>
|
|
90
|
+
<FinInstnId>
|
|
91
|
+
<BIC>BYLADEM1001</BIC>
|
|
92
|
+
</FinInstnId>
|
|
93
|
+
</DbtrAgt>
|
|
94
|
+
<CdtrAgt>
|
|
95
|
+
<FinInstnId>
|
|
96
|
+
<BIC>DEUTDEFF</BIC>
|
|
97
|
+
</FinInstnId>
|
|
98
|
+
</CdtrAgt>
|
|
99
|
+
</RltdAgts>
|
|
100
|
+
</TxDtls>
|
|
101
|
+
</NtryDtls>
|
|
102
|
+
</Ntry>
|
|
103
|
+
</Rpt>
|
|
104
|
+
</BkToCstmrAcctRpt>
|
|
105
|
+
</Document>`;
|
|
106
|
+
const parser = new CamtParser(camtXml);
|
|
107
|
+
const statements = parser.parse();
|
|
108
|
+
expect(statements).toHaveLength(1);
|
|
109
|
+
const statement = statements[0];
|
|
110
|
+
// Check all Statement fields
|
|
111
|
+
expect(statement.account).toBe('DE06940594210000027227');
|
|
112
|
+
expect(statement.number).toBe('camt052_ONLINEBA');
|
|
113
|
+
expect(statement.transactionReference).toBe('00001');
|
|
114
|
+
// Verify optional fields that are not set
|
|
115
|
+
expect(statement.relatedReference).toBeUndefined();
|
|
116
|
+
expect(statement.availableBalance).toBeUndefined();
|
|
117
|
+
expect(statement.forwardBalances).toBeUndefined();
|
|
118
|
+
// Check balances with all fields
|
|
119
|
+
expect(statement.openingBalance).toBeDefined();
|
|
120
|
+
expect(statement.openingBalance.value).toBe(1000.0);
|
|
121
|
+
expect(statement.openingBalance.currency).toBe('EUR');
|
|
122
|
+
expect(statement.openingBalance.date).toBeInstanceOf(Date);
|
|
123
|
+
expect(statement.openingBalance.date.getFullYear()).toBe(2013);
|
|
124
|
+
expect(statement.openingBalance.date.getMonth()).toBe(9); // October (0-based)
|
|
125
|
+
expect(statement.openingBalance.date.getDate()).toBe(31);
|
|
126
|
+
expect(statement.closingBalance).toBeDefined();
|
|
127
|
+
expect(statement.closingBalance.value).toBe(1500.0);
|
|
128
|
+
expect(statement.closingBalance.currency).toBe('EUR');
|
|
129
|
+
expect(statement.closingBalance.date).toBeInstanceOf(Date);
|
|
130
|
+
expect(statement.closingBalance.date.getFullYear()).toBe(2013);
|
|
131
|
+
expect(statement.closingBalance.date.getMonth()).toBe(10); // November (0-based)
|
|
132
|
+
expect(statement.closingBalance.date.getDate()).toBe(4);
|
|
133
|
+
// Check transactions
|
|
134
|
+
expect(statement.transactions).toHaveLength(1);
|
|
135
|
+
const transaction = statement.transactions[0];
|
|
136
|
+
// Check all Transaction fields filled by the parser
|
|
137
|
+
expect(transaction.amount).toBe(500.0);
|
|
138
|
+
expect(transaction.customerReference).toBe('E2E123');
|
|
139
|
+
expect(transaction.bankReference).toBe('TXN001');
|
|
140
|
+
expect(transaction.purpose).toBe('Test payment');
|
|
141
|
+
expect(transaction.remoteName).toBe('John Doe');
|
|
142
|
+
expect(transaction.remoteAccountNumber).toBe('DE12345678901234567890');
|
|
143
|
+
expect(transaction.remoteBankId).toBe('BYLADEM1001'); // Credit transaction uses DbtrAgt BIC
|
|
144
|
+
expect(transaction.e2eReference).toBe('E2E123');
|
|
145
|
+
expect(transaction.mandateReference).toBe('MANDT001');
|
|
146
|
+
// Check date fields
|
|
147
|
+
expect(transaction.valueDate).toBeInstanceOf(Date);
|
|
148
|
+
expect(transaction.valueDate.getFullYear()).toBe(2013);
|
|
149
|
+
expect(transaction.valueDate.getMonth()).toBe(10); // November (0-based)
|
|
150
|
+
expect(transaction.valueDate.getDate()).toBe(1);
|
|
151
|
+
expect(transaction.entryDate).toBeInstanceOf(Date);
|
|
152
|
+
expect(transaction.entryDate.getFullYear()).toBe(2013);
|
|
153
|
+
expect(transaction.entryDate.getMonth()).toBe(10); // November (0-based)
|
|
154
|
+
expect(transaction.entryDate.getDate()).toBe(1);
|
|
155
|
+
// Check transaction type and code fields
|
|
156
|
+
expect(transaction.fundsCode).toBe('CRDT'); // Credit/debit indicator
|
|
157
|
+
expect(transaction.transactionType).toBe(''); // Should be empty as no family code in BkTxCd
|
|
158
|
+
expect(transaction.transactionCode).toBe(''); // Parser only handles structured BkTxCd, not Prtry format
|
|
159
|
+
// Check additional information fields
|
|
160
|
+
expect(transaction.additionalInformation).toBe(''); // No AddtlNtryInf in this test
|
|
161
|
+
expect(transaction.bookingText).toBe(''); // Should match additionalInformation
|
|
162
|
+
// Verify optional fields not set in this test
|
|
163
|
+
expect(transaction.primeNotesNr).toBeUndefined();
|
|
164
|
+
expect(transaction.remoteIdentifier).toBeUndefined();
|
|
165
|
+
expect(transaction.client).toBeUndefined();
|
|
166
|
+
expect(transaction.textKeyExtension).toBeUndefined();
|
|
167
|
+
});
|
|
168
|
+
it('should handle debit transactions correctly', () => {
|
|
169
|
+
const camtXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
170
|
+
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08">
|
|
171
|
+
<BkToCstmrAcctRpt>
|
|
172
|
+
<Rpt>
|
|
173
|
+
<Id>test</Id>
|
|
174
|
+
<Acct>
|
|
175
|
+
<Id>
|
|
176
|
+
<IBAN>DE06940594210000027227</IBAN>
|
|
177
|
+
</Id>
|
|
178
|
+
</Acct>
|
|
179
|
+
<Bal>
|
|
180
|
+
<Tp><CdOrPrtry><Cd>PRCD</Cd></CdOrPrtry></Tp>
|
|
181
|
+
<Amt Ccy="EUR">1000.00</Amt>
|
|
182
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
183
|
+
<Dt><Dt>2013-10-31</Dt></Dt>
|
|
184
|
+
</Bal>
|
|
185
|
+
<Bal>
|
|
186
|
+
<Tp><CdOrPrtry><Cd>CLBD</Cd></CdOrPrtry></Tp>
|
|
187
|
+
<Amt Ccy="EUR">800.00</Amt>
|
|
188
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
189
|
+
<Dt><Dt>2013-11-01</Dt></Dt>
|
|
190
|
+
</Bal>
|
|
191
|
+
<Ntry>
|
|
192
|
+
<Amt>200.00</Amt>
|
|
193
|
+
<CdtDbtInd>DBIT</CdtDbtInd>
|
|
194
|
+
<BookgDt><Dt>2013-11-01</Dt></BookgDt>
|
|
195
|
+
<ValDt><Dt>2013-11-01</Dt></ValDt>
|
|
196
|
+
<AcctSvcrRef>TXN002</AcctSvcrRef>
|
|
197
|
+
<NtryDtls>
|
|
198
|
+
<TxDtls>
|
|
199
|
+
<Refs>
|
|
200
|
+
<EndToEndId>485315597247918</EndToEndId>
|
|
201
|
+
</Refs>
|
|
202
|
+
<AmtDtls>
|
|
203
|
+
<TxAmt>
|
|
204
|
+
<Amt Ccy="EUR">5.83</Amt>
|
|
205
|
+
</TxAmt>
|
|
206
|
+
</AmtDtls>
|
|
207
|
+
<RltdPties>
|
|
208
|
+
<Dbtr>
|
|
209
|
+
<Nm>Jane Doe</Nm>
|
|
210
|
+
</Dbtr>
|
|
211
|
+
<DbtrAcct>
|
|
212
|
+
<Id>
|
|
213
|
+
<IBAN>DE12345678901234567891</IBAN>
|
|
214
|
+
</Id>
|
|
215
|
+
</DbtrAcct>
|
|
216
|
+
<Cdtr>
|
|
217
|
+
<Nm>John Doe</Nm>
|
|
218
|
+
</Cdtr>
|
|
219
|
+
<CdtrAcct>
|
|
220
|
+
<Id>
|
|
221
|
+
<IBAN>DE12345678901234567890</IBAN>
|
|
222
|
+
</Id>
|
|
223
|
+
</CdtrAcct>
|
|
224
|
+
</RltdPties>
|
|
225
|
+
<RltdAgts>
|
|
226
|
+
<DbtrAgt>
|
|
227
|
+
<FinInstnId>
|
|
228
|
+
<BIC>SOGEDEFF</BIC>
|
|
229
|
+
</FinInstnId>
|
|
230
|
+
</DbtrAgt>
|
|
231
|
+
<CdtrAgt>
|
|
232
|
+
<FinInstnId>
|
|
233
|
+
<BIC>DEUTDEFF</BIC>
|
|
234
|
+
</FinInstnId>
|
|
235
|
+
</CdtrAgt>
|
|
236
|
+
</RltdAgts>
|
|
237
|
+
<Purp>
|
|
238
|
+
<Cd>IDCP</Cd>
|
|
239
|
+
</Purp>
|
|
240
|
+
<RmtInf>
|
|
241
|
+
<Ustrd>Test payment</Ustrd>
|
|
242
|
+
</RmtInf>
|
|
243
|
+
</TxDtls>
|
|
244
|
+
</NtryDtls>
|
|
245
|
+
<AddtlNtryInf>Additional Info</AddtlNtryInf>
|
|
246
|
+
</Ntry>
|
|
247
|
+
</Rpt>
|
|
248
|
+
</BkToCstmrAcctRpt>
|
|
249
|
+
</Document>`;
|
|
250
|
+
const parser = new CamtParser(camtXml);
|
|
251
|
+
const statements = parser.parse();
|
|
252
|
+
expect(statements).toHaveLength(1);
|
|
253
|
+
expect(statements[0].transactions).toHaveLength(1);
|
|
254
|
+
expect(statements[0].transactions[0].amount).toBe(-200.0); // Should be negative for debit
|
|
255
|
+
const transaction = statements[0].transactions[0];
|
|
256
|
+
// Comprehensive Transaction field checks for debit transaction
|
|
257
|
+
expect(transaction.purpose).toBe('Test payment');
|
|
258
|
+
expect(transaction.remoteName).toBe('John Doe');
|
|
259
|
+
expect(transaction.remoteAccountNumber).toBe('DE12345678901234567890');
|
|
260
|
+
expect(transaction.remoteBankId).toBe('DEUTDEFF'); // Debit transaction uses CdtrAgt BIC
|
|
261
|
+
// Check all other fields for debit transaction
|
|
262
|
+
expect(transaction.customerReference).toBe('485315597247918');
|
|
263
|
+
expect(transaction.bankReference).toBe('TXN002');
|
|
264
|
+
expect(transaction.e2eReference).toBe('485315597247918');
|
|
265
|
+
expect(transaction.mandateReference).toBe(''); // No MndtId in this test
|
|
266
|
+
// Date fields
|
|
267
|
+
expect(transaction.valueDate).toBeInstanceOf(Date);
|
|
268
|
+
expect(transaction.valueDate.getFullYear()).toBe(2013);
|
|
269
|
+
expect(transaction.entryDate).toBeInstanceOf(Date);
|
|
270
|
+
expect(transaction.entryDate.getFullYear()).toBe(2013);
|
|
271
|
+
// Transaction type indicators
|
|
272
|
+
expect(transaction.fundsCode).toBe('DBIT'); // Debit indicator
|
|
273
|
+
expect(transaction.transactionType).toBe(''); // No family code
|
|
274
|
+
expect(transaction.transactionCode).toBe(''); // No BkTxCd in this test
|
|
275
|
+
// Additional info fields
|
|
276
|
+
expect(transaction.additionalInformation).toBe('Additional Info');
|
|
277
|
+
expect(transaction.bookingText).toBe('Additional Info');
|
|
278
|
+
});
|
|
279
|
+
it('should handle empty or invalid XML gracefully', () => {
|
|
280
|
+
const parser = new CamtParser('invalid xml');
|
|
281
|
+
expect(() => parser.parse()).toThrow(); // Should throw error for invalid XML
|
|
282
|
+
});
|
|
283
|
+
it('should handle multiple reports', () => {
|
|
284
|
+
const camtXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
285
|
+
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08">
|
|
286
|
+
<BkToCstmrAcctRpt>
|
|
287
|
+
<Rpt>
|
|
288
|
+
<Id>report1</Id>
|
|
289
|
+
<Acct><Id><IBAN>DE11111111111111111111</IBAN></Id></Acct>
|
|
290
|
+
<Bal><Tp><CdOrPrtry><Cd>PRCD</Cd></CdOrPrtry></Tp><Amt Ccy="EUR">100.00</Amt><CdtDbtInd>CRDT</CdtDbtInd><Dt><Dt>2023-01-01</Dt></Dt></Bal>
|
|
291
|
+
<Bal><Tp><CdOrPrtry><Cd>CLBD</Cd></CdOrPrtry></Tp><Amt Ccy="EUR">200.00</Amt><CdtDbtInd>CRDT</CdtDbtInd><Dt><Dt>2023-01-01</Dt></Dt></Bal>
|
|
292
|
+
</Rpt>
|
|
293
|
+
<Rpt>
|
|
294
|
+
<Id>report2</Id>
|
|
295
|
+
<Acct><Id><IBAN>DE22222222222222222222</IBAN></Id></Acct>
|
|
296
|
+
<Bal><Tp><CdOrPrtry><Cd>PRCD</Cd></CdOrPrtry></Tp><Amt Ccy="EUR">300.00</Amt><CdtDbtInd>CRDT</CdtDbtInd><Dt><Dt>2023-01-01</Dt></Dt></Bal>
|
|
297
|
+
<Bal><Tp><CdOrPrtry><Cd>CLBD</Cd></CdOrPrtry></Tp><Amt Ccy="EUR">400.00</Amt><CdtDbtInd>CRDT</CdtDbtInd><Dt><Dt>2023-01-01</Dt></Dt></Bal>
|
|
298
|
+
</Rpt>
|
|
299
|
+
</BkToCstmrAcctRpt>
|
|
300
|
+
</Document>`;
|
|
301
|
+
const parser = new CamtParser(camtXml);
|
|
302
|
+
const statements = parser.parse();
|
|
303
|
+
expect(statements).toHaveLength(2);
|
|
304
|
+
expect(statements[0].account).toBe('DE11111111111111111111');
|
|
305
|
+
expect(statements[1].account).toBe('DE22222222222222222222');
|
|
306
|
+
});
|
|
307
|
+
it('should parse comprehensive CAMT XML with all possible fields and bank transaction codes', () => {
|
|
308
|
+
const camtXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
309
|
+
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08">
|
|
310
|
+
<BkToCstmrAcctRpt>
|
|
311
|
+
<GrpHdr>
|
|
312
|
+
<MsgId>comprehensive_test</MsgId>
|
|
313
|
+
<CreDtTm>2023-12-22T14:30:00+01:00</CreDtTm>
|
|
314
|
+
</GrpHdr>
|
|
315
|
+
<Rpt>
|
|
316
|
+
<Id>COMPREHENSIVE_TEST</Id>
|
|
317
|
+
<ElctrncSeqNb>987654321</ElctrncSeqNb>
|
|
318
|
+
<CreDtTm>2023-12-22T14:30:00+01:00</CreDtTm>
|
|
319
|
+
<Acct>
|
|
320
|
+
<Id>
|
|
321
|
+
<IBAN>DE89370400440532013000</IBAN>
|
|
322
|
+
</Id>
|
|
323
|
+
<Ccy>EUR</Ccy>
|
|
324
|
+
</Acct>
|
|
325
|
+
<Bal>
|
|
326
|
+
<Tp>
|
|
327
|
+
<CdOrPrtry>
|
|
328
|
+
<Cd>PRCD</Cd>
|
|
329
|
+
</CdOrPrtry>
|
|
330
|
+
</Tp>
|
|
331
|
+
<Amt Ccy="EUR">5000.50</Amt>
|
|
332
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
333
|
+
<Dt>
|
|
334
|
+
<Dt>2023-12-21</Dt>
|
|
335
|
+
</Dt>
|
|
336
|
+
</Bal>
|
|
337
|
+
<Bal>
|
|
338
|
+
<Tp>
|
|
339
|
+
<CdOrPrtry>
|
|
340
|
+
<Cd>CLBD</Cd>
|
|
341
|
+
</CdOrPrtry>
|
|
342
|
+
</Tp>
|
|
343
|
+
<Amt Ccy="EUR">4750.75</Amt>
|
|
344
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
345
|
+
<Dt>
|
|
346
|
+
<Dt>2023-12-22</Dt>
|
|
347
|
+
</Dt>
|
|
348
|
+
</Bal>
|
|
349
|
+
<Bal>
|
|
350
|
+
<Tp>
|
|
351
|
+
<CdOrPrtry>
|
|
352
|
+
<Cd>ITBD</Cd>
|
|
353
|
+
</CdOrPrtry>
|
|
354
|
+
</Tp>
|
|
355
|
+
<Amt Ccy="EUR">4500.00</Amt>
|
|
356
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
357
|
+
<Dt>
|
|
358
|
+
<Dt>2023-12-22</Dt>
|
|
359
|
+
</Dt>
|
|
360
|
+
</Bal>
|
|
361
|
+
<Ntry>
|
|
362
|
+
<Amt>249.75</Amt>
|
|
363
|
+
<CdtDbtInd>DBIT</CdtDbtInd>
|
|
364
|
+
<BookgDt>
|
|
365
|
+
<Dt>2023-12-22</Dt>
|
|
366
|
+
</BookgDt>
|
|
367
|
+
<ValDt>
|
|
368
|
+
<Dt>2023-12-22</Dt>
|
|
369
|
+
</ValDt>
|
|
370
|
+
<AcctSvcrRef>BANK-REF-123456</AcctSvcrRef>
|
|
371
|
+
<BkTxCd>
|
|
372
|
+
<Domn>
|
|
373
|
+
<Cd>PMNT</Cd>
|
|
374
|
+
<Fmly>
|
|
375
|
+
<Cd>ICDT</Cd>
|
|
376
|
+
<SubFmlyCd>ESCT</SubFmlyCd>
|
|
377
|
+
</Fmly>
|
|
378
|
+
</Domn>
|
|
379
|
+
</BkTxCd>
|
|
380
|
+
<NtryDtls>
|
|
381
|
+
<TxDtls>
|
|
382
|
+
<Refs>
|
|
383
|
+
<EndToEndId>NOTPROVIDED</EndToEndId>
|
|
384
|
+
<TxId>TXN-ID-789</TxId>
|
|
385
|
+
<MndtId>MANDATE-REF-456</MndtId>
|
|
386
|
+
</Refs>
|
|
387
|
+
<AmtDtls>
|
|
388
|
+
<TxAmt>
|
|
389
|
+
<Amt Ccy="EUR">249.75</Amt>
|
|
390
|
+
</TxAmt>
|
|
391
|
+
</AmtDtls>
|
|
392
|
+
<RmtInf>
|
|
393
|
+
<Ustrd>SEPA Instant Transfer Payment Reference Text</Ustrd>
|
|
394
|
+
</RmtInf>
|
|
395
|
+
<RltdPties>
|
|
396
|
+
<Dbtr>
|
|
397
|
+
<Nm>Max Mustermann</Nm>
|
|
398
|
+
</Dbtr>
|
|
399
|
+
<DbtrAcct>
|
|
400
|
+
<Id>
|
|
401
|
+
<IBAN>DE89370400440532013000</IBAN>
|
|
402
|
+
</Id>
|
|
403
|
+
</DbtrAcct>
|
|
404
|
+
<Cdtr>
|
|
405
|
+
<Nm>Erika Musterfrau</Nm>
|
|
406
|
+
</Cdtr>
|
|
407
|
+
<CdtrAcct>
|
|
408
|
+
<Id>
|
|
409
|
+
<IBAN>DE12500105170648489890</IBAN>
|
|
410
|
+
</Id>
|
|
411
|
+
</CdtrAcct>
|
|
412
|
+
</RltdPties>
|
|
413
|
+
<RltdAgts>
|
|
414
|
+
<DbtrAgt>
|
|
415
|
+
<FinInstnId>
|
|
416
|
+
<BIC>COBADEFFXXX</BIC>
|
|
417
|
+
</FinInstnId>
|
|
418
|
+
</DbtrAgt>
|
|
419
|
+
<CdtrAgt>
|
|
420
|
+
<FinInstnId>
|
|
421
|
+
<BIC>INGDDEFFXXX</BIC>
|
|
422
|
+
</FinInstnId>
|
|
423
|
+
</CdtrAgt>
|
|
424
|
+
</RltdAgts>
|
|
425
|
+
<Purp>
|
|
426
|
+
<Cd>CBFF</Cd>
|
|
427
|
+
</Purp>
|
|
428
|
+
</TxDtls>
|
|
429
|
+
</NtryDtls>
|
|
430
|
+
<AddtlNtryInf>Additional payment information from bank</AddtlNtryInf>
|
|
431
|
+
</Ntry>
|
|
432
|
+
</Rpt>
|
|
433
|
+
</BkToCstmrAcctRpt>
|
|
434
|
+
</Document>`;
|
|
435
|
+
const parser = new CamtParser(camtXml);
|
|
436
|
+
const statements = parser.parse();
|
|
437
|
+
expect(statements).toHaveLength(1);
|
|
438
|
+
const statement = statements[0];
|
|
439
|
+
// Test all Statement fields with comprehensive data
|
|
440
|
+
expect(statement.account).toBe('DE89370400440532013000');
|
|
441
|
+
expect(statement.number).toBe('COMPREHENSIVE_TEST');
|
|
442
|
+
expect(statement.transactionReference).toBe('987654321');
|
|
443
|
+
expect(statement.relatedReference).toBeUndefined();
|
|
444
|
+
expect(statement.forwardBalances).toBeUndefined();
|
|
445
|
+
// Test opening balance with exact date parsing
|
|
446
|
+
expect(statement.openingBalance).toBeDefined();
|
|
447
|
+
expect(statement.openingBalance.value).toBe(5000.5);
|
|
448
|
+
expect(statement.openingBalance.currency).toBe('EUR');
|
|
449
|
+
expect(statement.openingBalance.date.getFullYear()).toBe(2023);
|
|
450
|
+
expect(statement.openingBalance.date.getMonth()).toBe(11); // December (0-based)
|
|
451
|
+
expect(statement.openingBalance.date.getDate()).toBe(21);
|
|
452
|
+
// Test closing balance
|
|
453
|
+
expect(statement.closingBalance).toBeDefined();
|
|
454
|
+
expect(statement.closingBalance.value).toBe(4750.75);
|
|
455
|
+
expect(statement.closingBalance.currency).toBe('EUR');
|
|
456
|
+
expect(statement.closingBalance.date.getFullYear()).toBe(2023);
|
|
457
|
+
expect(statement.closingBalance.date.getMonth()).toBe(11); // December (0-based)
|
|
458
|
+
expect(statement.closingBalance.date.getDate()).toBe(22);
|
|
459
|
+
// Test available balance (ITBD)
|
|
460
|
+
expect(statement.availableBalance).toBeDefined();
|
|
461
|
+
expect(statement.availableBalance.value).toBe(4500.0);
|
|
462
|
+
expect(statement.availableBalance.currency).toBe('EUR');
|
|
463
|
+
// Test transaction with comprehensive fields
|
|
464
|
+
expect(statement.transactions).toHaveLength(1);
|
|
465
|
+
const transaction = statement.transactions[0];
|
|
466
|
+
// Amount and basic fields
|
|
467
|
+
expect(transaction.amount).toBe(-249.75); // Negative for debit
|
|
468
|
+
expect(transaction.customerReference).toBe('NOTPROVIDED');
|
|
469
|
+
expect(transaction.bankReference).toBe('BANK-REF-123456');
|
|
470
|
+
expect(transaction.purpose).toBe('SEPA Instant Transfer Payment Reference Text');
|
|
471
|
+
// Party information (debit transaction - creditor is remote party)
|
|
472
|
+
expect(transaction.remoteName).toBe('Erika Musterfrau');
|
|
473
|
+
expect(transaction.remoteAccountNumber).toBe('DE12500105170648489890');
|
|
474
|
+
expect(transaction.remoteBankId).toBe('INGDDEFFXXX'); // CdtrAgt BIC for debit
|
|
475
|
+
// Reference fields
|
|
476
|
+
expect(transaction.e2eReference).toBe('NOTPROVIDED');
|
|
477
|
+
expect(transaction.mandateReference).toBe('MANDATE-REF-456');
|
|
478
|
+
// Date fields with exact verification
|
|
479
|
+
expect(transaction.valueDate).toBeInstanceOf(Date);
|
|
480
|
+
expect(transaction.valueDate.getFullYear()).toBe(2023);
|
|
481
|
+
expect(transaction.valueDate.getMonth()).toBe(11); // December
|
|
482
|
+
expect(transaction.valueDate.getDate()).toBe(22);
|
|
483
|
+
expect(transaction.entryDate).toBeInstanceOf(Date);
|
|
484
|
+
expect(transaction.entryDate.getFullYear()).toBe(2023);
|
|
485
|
+
expect(transaction.entryDate.getMonth()).toBe(11);
|
|
486
|
+
expect(transaction.entryDate.getDate()).toBe(22);
|
|
487
|
+
// Bank transaction code structure
|
|
488
|
+
expect(transaction.fundsCode).toBe('PMNT'); // Domain code
|
|
489
|
+
expect(transaction.transactionType).toBe('ICDT'); // Family code
|
|
490
|
+
expect(transaction.transactionCode).toBe('ESCT'); // SubFamily code
|
|
491
|
+
// Additional information
|
|
492
|
+
expect(transaction.additionalInformation).toBe('Additional payment information from bank');
|
|
493
|
+
expect(transaction.bookingText).toBe('Additional payment information from bank');
|
|
494
|
+
// Verify undefined optional fields
|
|
495
|
+
expect(transaction.primeNotesNr).toBeUndefined();
|
|
496
|
+
expect(transaction.remoteIdentifier).toBeUndefined();
|
|
497
|
+
expect(transaction.client).toBeUndefined();
|
|
498
|
+
expect(transaction.textKeyExtension).toBeUndefined();
|
|
499
|
+
});
|
|
500
|
+
it('should handle edge cases and missing optional fields correctly', () => {
|
|
501
|
+
const camtXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
502
|
+
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08">
|
|
503
|
+
<BkToCstmrAcctRpt>
|
|
504
|
+
<Rpt>
|
|
505
|
+
<Id>edge-case-test</Id>
|
|
506
|
+
<Acct>
|
|
507
|
+
<Id>
|
|
508
|
+
<IBAN>DE99999999999999999999</IBAN>
|
|
509
|
+
</Id>
|
|
510
|
+
<Ccy>USD</Ccy>
|
|
511
|
+
</Acct>
|
|
512
|
+
<Bal>
|
|
513
|
+
<Tp><CdOrPrtry><Cd>PRCD</Cd></CdOrPrtry></Tp>
|
|
514
|
+
<Amt Ccy="USD">0.01</Amt>
|
|
515
|
+
<CdtDbtInd>DBIT</CdtDbtInd>
|
|
516
|
+
<Dt><Dt>20231222</Dt></Dt>
|
|
517
|
+
</Bal>
|
|
518
|
+
<Bal>
|
|
519
|
+
<Tp><CdOrPrtry><Cd>CLBD</Cd></CdOrPrtry></Tp>
|
|
520
|
+
<Amt Ccy="USD">999.99</Amt>
|
|
521
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
522
|
+
<Dt><Dt>20231222</Dt></Dt>
|
|
523
|
+
</Bal>
|
|
524
|
+
<Ntry>
|
|
525
|
+
<Amt>1000.00</Amt>
|
|
526
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
527
|
+
<BookgDt><Dt>20231222</Dt></BookgDt>
|
|
528
|
+
<ValDt><Dt>20231221</Dt></ValDt>
|
|
529
|
+
<AcctSvcrRef></AcctSvcrRef>
|
|
530
|
+
<NtryDtls>
|
|
531
|
+
<TxDtls>
|
|
532
|
+
<Refs>
|
|
533
|
+
<EndToEndId></EndToEndId>
|
|
534
|
+
</Refs>
|
|
535
|
+
<RmtInf>
|
|
536
|
+
<Ustrd></Ustrd>
|
|
537
|
+
</RmtInf>
|
|
538
|
+
<RltdPties>
|
|
539
|
+
<Dbtr>
|
|
540
|
+
<Nm></Nm>
|
|
541
|
+
</Dbtr>
|
|
542
|
+
</RltdPties>
|
|
543
|
+
</TxDtls>
|
|
544
|
+
</NtryDtls>
|
|
545
|
+
</Ntry>
|
|
546
|
+
</Rpt>
|
|
547
|
+
</BkToCstmrAcctRpt>
|
|
548
|
+
</Document>`;
|
|
549
|
+
const parser = new CamtParser(camtXml);
|
|
550
|
+
const statements = parser.parse();
|
|
551
|
+
expect(statements).toHaveLength(1);
|
|
552
|
+
const statement = statements[0];
|
|
553
|
+
// Test edge case balances
|
|
554
|
+
expect(statement.openingBalance.value).toBe(-0.01); // Negative due to DBIT indicator
|
|
555
|
+
expect(statement.openingBalance.currency).toBe('USD');
|
|
556
|
+
expect(statement.closingBalance.value).toBe(999.99);
|
|
557
|
+
expect(statement.closingBalance.currency).toBe('USD');
|
|
558
|
+
// Test date parsing from YYYYMMDD format
|
|
559
|
+
expect(statement.openingBalance.date.getFullYear()).toBe(2023);
|
|
560
|
+
expect(statement.openingBalance.date.getMonth()).toBe(11); // December
|
|
561
|
+
expect(statement.openingBalance.date.getDate()).toBe(22);
|
|
562
|
+
// Test transaction with mostly empty/missing fields
|
|
563
|
+
expect(statement.transactions).toHaveLength(1);
|
|
564
|
+
const transaction = statement.transactions[0];
|
|
565
|
+
expect(transaction.amount).toBe(1000.0);
|
|
566
|
+
expect(transaction.customerReference).toBe(''); // Empty EndToEndId
|
|
567
|
+
expect(transaction.bankReference).toBe(''); // Empty AcctSvcrRef
|
|
568
|
+
expect(transaction.purpose).toBe(''); // Empty Ustrd
|
|
569
|
+
expect(transaction.remoteName).toBe(''); // Empty Nm
|
|
570
|
+
expect(transaction.remoteAccountNumber).toBe(''); // No IBAN provided
|
|
571
|
+
expect(transaction.remoteBankId).toBe(''); // No BIC provided
|
|
572
|
+
expect(transaction.e2eReference).toBe(''); // Empty EndToEndId
|
|
573
|
+
expect(transaction.mandateReference).toBe(''); // No MndtId
|
|
574
|
+
// Test date parsing consistency
|
|
575
|
+
expect(transaction.valueDate.getDate()).toBe(21); // Different from entry date
|
|
576
|
+
expect(transaction.entryDate.getDate()).toBe(22);
|
|
577
|
+
// Test transaction type fields with no BkTxCd
|
|
578
|
+
expect(transaction.fundsCode).toBe('CRDT');
|
|
579
|
+
expect(transaction.transactionType).toBe('');
|
|
580
|
+
expect(transaction.transactionCode).toBe('');
|
|
581
|
+
expect(transaction.additionalInformation).toBe('');
|
|
582
|
+
expect(transaction.bookingText).toBe('');
|
|
583
|
+
});
|
|
584
|
+
it('should handle party structure variations in XML (Dbtr.Pty.Nm format)', () => {
|
|
585
|
+
const camtXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
586
|
+
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.052.001.08">
|
|
587
|
+
<BkToCstmrAcctRpt>
|
|
588
|
+
<Rpt>
|
|
589
|
+
<Id>party-structure-test</Id>
|
|
590
|
+
<Acct>
|
|
591
|
+
<Id>
|
|
592
|
+
<IBAN>DE06940594210000027227</IBAN>
|
|
593
|
+
</Id>
|
|
594
|
+
</Acct>
|
|
595
|
+
<Bal>
|
|
596
|
+
<Tp><CdOrPrtry><Cd>PRCD</Cd></CdOrPrtry></Tp>
|
|
597
|
+
<Amt Ccy="EUR">1000.00</Amt>
|
|
598
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
599
|
+
<Dt><Dt>2013-10-31</Dt></Dt>
|
|
600
|
+
</Bal>
|
|
601
|
+
<Bal>
|
|
602
|
+
<Tp><CdOrPrtry><Cd>CLBD</Cd></CdOrPrtry></Tp>
|
|
603
|
+
<Amt Ccy="EUR">1200.00</Amt>
|
|
604
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
605
|
+
<Dt><Dt>2013-11-01</Dt></Dt>
|
|
606
|
+
</Bal>
|
|
607
|
+
<Ntry>
|
|
608
|
+
<Amt>200.00</Amt>
|
|
609
|
+
<CdtDbtInd>CRDT</CdtDbtInd>
|
|
610
|
+
<BookgDt><Dt>2013-11-01</Dt></BookgDt>
|
|
611
|
+
<ValDt><Dt>2013-11-01</Dt></ValDt>
|
|
612
|
+
<AcctSvcrRef>TXN003</AcctSvcrRef>
|
|
613
|
+
<NtryDtls>
|
|
614
|
+
<TxDtls>
|
|
615
|
+
<Refs>
|
|
616
|
+
<EndToEndId>PARTY-TEST-123</EndToEndId>
|
|
617
|
+
</Refs>
|
|
618
|
+
<RmtInf>
|
|
619
|
+
<Ustrd>Payment with party structure</Ustrd>
|
|
620
|
+
</RmtInf>
|
|
621
|
+
<RltdPties>
|
|
622
|
+
<Dbtr>
|
|
623
|
+
<Pty>
|
|
624
|
+
<Nm>John Smith Bank Format</Nm>
|
|
625
|
+
</Pty>
|
|
626
|
+
</Dbtr>
|
|
627
|
+
<DbtrAcct>
|
|
628
|
+
<Id>
|
|
629
|
+
<IBAN>DE12345678901234567890</IBAN>
|
|
630
|
+
</Id>
|
|
631
|
+
</DbtrAcct>
|
|
632
|
+
<Cdtr>
|
|
633
|
+
<Pty>
|
|
634
|
+
<Nm>Jane Smith Bank Format</Nm>
|
|
635
|
+
</Pty>
|
|
636
|
+
</Cdtr>
|
|
637
|
+
<CdtrAcct>
|
|
638
|
+
<Id>
|
|
639
|
+
<IBAN>DE12345678901234567891</IBAN>
|
|
640
|
+
</Id>
|
|
641
|
+
</CdtrAcct>
|
|
642
|
+
</RltdPties>
|
|
643
|
+
<RltdAgts>
|
|
644
|
+
<DbtrAgt>
|
|
645
|
+
<FinInstnId>
|
|
646
|
+
<BICFI>BANKABC1XXX</BICFI>
|
|
647
|
+
</FinInstnId>
|
|
648
|
+
</DbtrAgt>
|
|
649
|
+
<CdtrAgt>
|
|
650
|
+
<FinInstnId>
|
|
651
|
+
<BICFI>BANKDEF2XXX</BICFI>
|
|
652
|
+
</FinInstnId>
|
|
653
|
+
</CdtrAgt>
|
|
654
|
+
</RltdAgts>
|
|
655
|
+
</TxDtls>
|
|
656
|
+
</NtryDtls>
|
|
657
|
+
</Ntry>
|
|
658
|
+
</Rpt>
|
|
659
|
+
</BkToCstmrAcctRpt>
|
|
660
|
+
</Document>`;
|
|
661
|
+
const parser = new CamtParser(camtXml);
|
|
662
|
+
const statements = parser.parse();
|
|
663
|
+
expect(statements).toHaveLength(1);
|
|
664
|
+
expect(statements[0].transactions).toHaveLength(1);
|
|
665
|
+
const transaction = statements[0].transactions[0];
|
|
666
|
+
// Verify that the party name is correctly extracted from Dbtr.Pty.Nm structure
|
|
667
|
+
expect(transaction.remoteName).toBe('John Smith Bank Format');
|
|
668
|
+
expect(transaction.remoteAccountNumber).toBe('DE12345678901234567890');
|
|
669
|
+
expect(transaction.remoteBankId).toBe('BANKABC1XXX'); // Credit transaction uses DbtrAgt BIC
|
|
670
|
+
expect(transaction.purpose).toBe('Payment with party structure');
|
|
671
|
+
expect(transaction.amount).toBe(200.0);
|
|
672
|
+
});
|
|
673
|
+
});
|