@actual-app/sync-server 25.4.0-alpha.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.
Files changed (137) hide show
  1. package/.dockerignore +12 -0
  2. package/README.md +19 -0
  3. package/app.js +11 -0
  4. package/babel.config.json +3 -0
  5. package/bin/@actual-app/sync-server +55 -0
  6. package/docker/alpine.Dockerfile +62 -0
  7. package/docker/ubuntu.Dockerfile +63 -0
  8. package/docker-compose.yml +29 -0
  9. package/jest.config.json +19 -0
  10. package/jest.global-setup.js +101 -0
  11. package/jest.global-teardown.js +6 -0
  12. package/migrations/1694360000000-create-folders.js +25 -0
  13. package/migrations/1694360479680-create-account-db.js +30 -0
  14. package/migrations/1694362247011-create-secret-table.js +16 -0
  15. package/migrations/1702667624000-rename-nordigen-secrets.js +19 -0
  16. package/migrations/1718889148000-openid.js +41 -0
  17. package/migrations/1719409568000-multiuser.js +116 -0
  18. package/package.json +64 -0
  19. package/src/account-db.js +239 -0
  20. package/src/accounts/openid.js +361 -0
  21. package/src/accounts/password.js +149 -0
  22. package/src/app-account.js +155 -0
  23. package/src/app-admin.js +410 -0
  24. package/src/app-admin.test.js +381 -0
  25. package/src/app-gocardless/README.md +198 -0
  26. package/src/app-gocardless/app-gocardless.js +274 -0
  27. package/src/app-gocardless/bank-factory.js +91 -0
  28. package/src/app-gocardless/banks/abanca_caglesmm.js +22 -0
  29. package/src/app-gocardless/banks/abnamro_abnanl2a.js +57 -0
  30. package/src/app-gocardless/banks/american_express_aesudef1.js +40 -0
  31. package/src/app-gocardless/banks/bancsabadell_bsabesbbb.js +31 -0
  32. package/src/app-gocardless/banks/bank.interface.ts +51 -0
  33. package/src/app-gocardless/banks/bank_of_ireland_b365_bofiie2d.js +39 -0
  34. package/src/app-gocardless/banks/bankinter_bkbkesmm.js +24 -0
  35. package/src/app-gocardless/banks/belfius_gkccbebb.js +17 -0
  36. package/src/app-gocardless/banks/berliner_sparkasse_beladebexxx.js +61 -0
  37. package/src/app-gocardless/banks/bnp_be_gebabebb.js +73 -0
  38. package/src/app-gocardless/banks/cbc_cregbebb.js +34 -0
  39. package/src/app-gocardless/banks/commerzbank_cobadeff.js +51 -0
  40. package/src/app-gocardless/banks/danskebank_dabno22.js +39 -0
  41. package/src/app-gocardless/banks/direkt_heladef1822.js +18 -0
  42. package/src/app-gocardless/banks/easybank_bawaatww.js +50 -0
  43. package/src/app-gocardless/banks/entercard_swednokk.js +40 -0
  44. package/src/app-gocardless/banks/fortuneo_ftnofrp1xxx.js +46 -0
  45. package/src/app-gocardless/banks/hype_hyeeit22.js +74 -0
  46. package/src/app-gocardless/banks/ing_ingbrobu.js +70 -0
  47. package/src/app-gocardless/banks/ing_ingddeff.js +47 -0
  48. package/src/app-gocardless/banks/ing_pl_ingbplpw.js +46 -0
  49. package/src/app-gocardless/banks/integration-bank.js +115 -0
  50. package/src/app-gocardless/banks/isybank_itbbitmm.js +18 -0
  51. package/src/app-gocardless/banks/kbc_kredbebb.js +33 -0
  52. package/src/app-gocardless/banks/lhv-lhvbee22.js +36 -0
  53. package/src/app-gocardless/banks/mbank_retail_brexplpw.js +56 -0
  54. package/src/app-gocardless/banks/nationwide_naiagb21.js +46 -0
  55. package/src/app-gocardless/banks/nbg_ethngraaxxx.js +51 -0
  56. package/src/app-gocardless/banks/norwegian_xx_norwnok1.js +74 -0
  57. package/src/app-gocardless/banks/revolut_revolt21.js +37 -0
  58. package/src/app-gocardless/banks/sandboxfinance_sfin0000.js +28 -0
  59. package/src/app-gocardless/banks/seb_kort_bank_ab.js +58 -0
  60. package/src/app-gocardless/banks/seb_privat.js +29 -0
  61. package/src/app-gocardless/banks/sparnord_spnodk22.js +24 -0
  62. package/src/app-gocardless/banks/spk_karlsruhe_karsde66.js +61 -0
  63. package/src/app-gocardless/banks/spk_marburg_biedenkopf_heladef1mar.js +30 -0
  64. package/src/app-gocardless/banks/spk_worms_alzey_ried_malade51wor.js +19 -0
  65. package/src/app-gocardless/banks/ssk_dusseldorf_dussdeddxxx.js +50 -0
  66. package/src/app-gocardless/banks/swedbank_habalv22.js +47 -0
  67. package/src/app-gocardless/banks/tests/abanca_caglesmm.spec.js +21 -0
  68. package/src/app-gocardless/banks/tests/abnamro_abnanl2a.spec.js +61 -0
  69. package/src/app-gocardless/banks/tests/bancsabadell_bsabesbbb.spec.js +53 -0
  70. package/src/app-gocardless/banks/tests/belfius_gkccbebb.spec.js +22 -0
  71. package/src/app-gocardless/banks/tests/cbc_cregbebb.spec.js +34 -0
  72. package/src/app-gocardless/banks/tests/commerzbank_cobadeff.spec.js +110 -0
  73. package/src/app-gocardless/banks/tests/easybank_bawaatww.spec.js +54 -0
  74. package/src/app-gocardless/banks/tests/fortuneo_ftnofrp1xxx.spec.js +206 -0
  75. package/src/app-gocardless/banks/tests/ing_ingddeff.spec.js +302 -0
  76. package/src/app-gocardless/banks/tests/ing_pl_ingbplpw.spec.js +202 -0
  77. package/src/app-gocardless/banks/tests/integration_bank.spec.js +158 -0
  78. package/src/app-gocardless/banks/tests/kbc_kredbebb.spec.js +38 -0
  79. package/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js +68 -0
  80. package/src/app-gocardless/banks/tests/mbank_retail_brexplpw.spec.js +171 -0
  81. package/src/app-gocardless/banks/tests/nationwide_naiagb21.spec.js +105 -0
  82. package/src/app-gocardless/banks/tests/nbg_ethngraaxxx.spec.js +48 -0
  83. package/src/app-gocardless/banks/tests/revolut_revolt21.spec.js +42 -0
  84. package/src/app-gocardless/banks/tests/sandboxfinance_sfin0000.spec.js +133 -0
  85. package/src/app-gocardless/banks/tests/spk_marburg_biedenkopf_heladef1mar.spec.js +256 -0
  86. package/src/app-gocardless/banks/tests/ssk_dusseldorf_dussdeddxxx.spec.js +102 -0
  87. package/src/app-gocardless/banks/tests/swedbank_habalv22.spec.js +57 -0
  88. package/src/app-gocardless/banks/tests/virgin_nrnbgb22.spec.js +54 -0
  89. package/src/app-gocardless/banks/util/extract-payeeName-from-remittanceInfo.js +36 -0
  90. package/src/app-gocardless/banks/virgin_nrnbgb22.js +39 -0
  91. package/src/app-gocardless/errors.js +84 -0
  92. package/src/app-gocardless/gocardless-node.types.ts +497 -0
  93. package/src/app-gocardless/gocardless.types.ts +93 -0
  94. package/src/app-gocardless/link.html +18 -0
  95. package/src/app-gocardless/services/gocardless-service.js +620 -0
  96. package/src/app-gocardless/services/tests/fixtures.js +181 -0
  97. package/src/app-gocardless/services/tests/gocardless-service.spec.js +537 -0
  98. package/src/app-gocardless/tests/bank-factory.spec.js +20 -0
  99. package/src/app-gocardless/tests/utils.spec.js +162 -0
  100. package/src/app-gocardless/util/handle-error.js +16 -0
  101. package/src/app-gocardless/utils.js +45 -0
  102. package/src/app-openid.js +108 -0
  103. package/src/app-pluggyai/app-pluggyai.js +215 -0
  104. package/src/app-pluggyai/pluggyai-service.js +120 -0
  105. package/src/app-secrets.js +61 -0
  106. package/src/app-simplefin/app-simplefin.js +418 -0
  107. package/src/app-sync/errors.js +13 -0
  108. package/src/app-sync/services/files-service.js +243 -0
  109. package/src/app-sync/tests/services/files-service.test.js +250 -0
  110. package/src/app-sync/validation.js +77 -0
  111. package/src/app-sync.js +391 -0
  112. package/src/app-sync.test.js +877 -0
  113. package/src/app.js +145 -0
  114. package/src/config-types.ts +44 -0
  115. package/src/db.js +58 -0
  116. package/src/load-config.js +307 -0
  117. package/src/migrations.js +36 -0
  118. package/src/run-migrations.js +8 -0
  119. package/src/scripts/disable-openid.js +44 -0
  120. package/src/scripts/enable-openid.js +53 -0
  121. package/src/scripts/health-check.js +23 -0
  122. package/src/scripts/reset-password.js +51 -0
  123. package/src/secrets.test.js +83 -0
  124. package/src/services/secrets-service.js +94 -0
  125. package/src/services/user-service.js +272 -0
  126. package/src/sql/messages.sql +9 -0
  127. package/src/sync-simple.js +95 -0
  128. package/src/util/hash.js +5 -0
  129. package/src/util/middlewares.js +62 -0
  130. package/src/util/paths.js +13 -0
  131. package/src/util/payee-name.js +45 -0
  132. package/src/util/prompt.js +88 -0
  133. package/src/util/title/index.js +59 -0
  134. package/src/util/title/lower-case.js +93 -0
  135. package/src/util/title/specials.js +21 -0
  136. package/src/util/validate-user.js +68 -0
  137. package/tsconfig.json +21 -0
@@ -0,0 +1,206 @@
1
+ import Fortuneo from '../fortuneo_ftnofrp1xxx.js';
2
+
3
+ describe('Fortuneo', () => {
4
+ describe('#normalizeTransaction', () => {
5
+ const transactionsRaw = [
6
+ {
7
+ bookingDate: '2024-07-05',
8
+ valueDate: '2024-07-05',
9
+ transactionAmount: {
10
+ amount: '-12.0',
11
+ currency: 'EUR',
12
+ },
13
+ remittanceInformationUnstructuredArray: ['PRLV ONG'],
14
+ internalTransactionId: '674323725470140d5caaf7b85a135817',
15
+ date: '2024-07-05',
16
+ },
17
+ {
18
+ bookingDate: '2024-07-04',
19
+ valueDate: '2024-07-04',
20
+ transactionAmount: {
21
+ amount: '-7.72',
22
+ currency: 'EUR',
23
+ },
24
+ remittanceInformationUnstructuredArray: [
25
+ 'PRLV PRIXTEL SCOR/53766825A',
26
+ ],
27
+ internalTransactionId: 'e8365f68077f2be249f8dfa9183296e4',
28
+ date: '2024-07-04',
29
+ },
30
+ {
31
+ bookingDate: '2024-07-04',
32
+ valueDate: '2024-07-04',
33
+ transactionAmount: {
34
+ amount: '-500.0',
35
+ currency: 'EUR',
36
+ },
37
+ remittanceInformationUnstructuredArray: ['VIR XXXYYYYZZZ'],
38
+ internalTransactionId: '0c12be495b71a63d14e46c43bfcb12f6',
39
+ date: '2024-07-04',
40
+ },
41
+ {
42
+ bookingDate: '2024-07-04',
43
+ valueDate: '2024-07-04',
44
+ transactionAmount: {
45
+ amount: '-10.49',
46
+ currency: 'EUR',
47
+ },
48
+ remittanceInformationUnstructuredArray: [
49
+ 'CARTE 04/07 Google Payment I Dublin',
50
+ ],
51
+ internalTransactionId: 'b09df9be4711cb06bdd2a53aef5423cc',
52
+ date: '2024-07-04',
53
+ },
54
+ {
55
+ bookingDate: '2024-07-04',
56
+ valueDate: '2024-07-04',
57
+ transactionAmount: {
58
+ amount: '-6.38',
59
+ currency: 'EUR',
60
+ },
61
+ remittanceInformationUnstructuredArray: ['CARTE 03/07 SPORT MARKET'],
62
+ internalTransactionId: '67552cc7782c742f1df8297e614470ea',
63
+ date: '2024-07-04',
64
+ },
65
+ {
66
+ bookingDate: '2024-07-04',
67
+ valueDate: '2024-07-04',
68
+ transactionAmount: {
69
+ amount: '26.52',
70
+ currency: 'EUR',
71
+ },
72
+ remittanceInformationUnstructuredArray: [
73
+ 'ANN CARTE WEEZEVENT SOMEPLACE',
74
+ ],
75
+ internalTransactionId: 'c0bed1b61806bd45fd07732e5dfb1f11',
76
+ date: '2024-07-04',
77
+ },
78
+ {
79
+ bookingDate: '2024-07-03',
80
+ valueDate: '2024-07-03',
81
+ transactionAmount: {
82
+ amount: '-104.9',
83
+ currency: 'EUR',
84
+ },
85
+ remittanceInformationUnstructuredArray: [
86
+ "CARTE 02/07 HPY*L'APPAC - Sport JANDA",
87
+ ],
88
+ internalTransactionId: '7716b23b56cda848efd788a0d8c79d12',
89
+ date: '2024-07-03',
90
+ },
91
+ {
92
+ bookingDate: '2024-07-03',
93
+ valueDate: '2024-07-02',
94
+ transactionAmount: {
95
+ amount: '-22.95',
96
+ currency: 'EUR',
97
+ },
98
+ remittanceInformationUnstructuredArray: [
99
+ 'VIR INST Leclerc XXXX Leclerc XXXX 44321IXCRT211141232',
100
+ ],
101
+ internalTransactionId: 'e75304593c9557f20014904f90eb23a2',
102
+ date: '2024-07-03',
103
+ },
104
+ {
105
+ bookingDate: '2024-07-02',
106
+ valueDate: '2024-07-02',
107
+ transactionAmount: {
108
+ amount: '-8.9',
109
+ currency: 'EUR',
110
+ },
111
+ remittanceInformationUnstructuredArray: ['CARTE 01/07 CHIK CHAK'],
112
+ internalTransactionId: 'e9811e50c8d7453c459f4e42453cf07c',
113
+ date: '2024-07-02',
114
+ },
115
+ {
116
+ bookingDate: '2024-07-02',
117
+ valueDate: '2024-07-02',
118
+ transactionAmount: {
119
+ amount: '-8.0',
120
+ currency: 'EUR',
121
+ },
122
+ remittanceInformationUnstructuredArray: [
123
+ 'CARTE 01/07 SERVICE 1228 GENEV 8,00 EUR',
124
+ ],
125
+ internalTransactionId: '354a49232bd05de583a3d2ab834e20cd',
126
+ date: '2024-07-02',
127
+ },
128
+ ];
129
+
130
+ it('sets debtor and creditor name according to amount', () => {
131
+ const creditorTransaction = transactionsRaw[0];
132
+ const debtorTransaction = transactionsRaw[5];
133
+
134
+ const normalizedCreditorTransaction = Fortuneo.normalizeTransaction(
135
+ creditorTransaction,
136
+ true,
137
+ );
138
+ const normalizedDebtorTransaction = Fortuneo.normalizeTransaction(
139
+ debtorTransaction,
140
+ true,
141
+ );
142
+
143
+ expect(normalizedCreditorTransaction.payeeName).toBeDefined();
144
+ expect(
145
+ parseFloat(normalizedCreditorTransaction.transactionAmount.amount),
146
+ ).toBeLessThan(0);
147
+
148
+ expect(normalizedDebtorTransaction.payeeName).toBeDefined();
149
+ expect(
150
+ parseFloat(normalizedDebtorTransaction.transactionAmount.amount),
151
+ ).toBeGreaterThan(0);
152
+ });
153
+
154
+ it('extracts payee name from remittanceInformationUnstructured', () => {
155
+ const transaction0 = transactionsRaw[0];
156
+ const normalizedTransaction = Fortuneo.normalizeTransaction(
157
+ transaction0,
158
+ true,
159
+ );
160
+
161
+ expect(normalizedTransaction.payeeName).toBe('Ong');
162
+
163
+ const transaction2 = transactionsRaw[2];
164
+ const normalizedTransaction2 = Fortuneo.normalizeTransaction(
165
+ transaction2,
166
+ true,
167
+ );
168
+
169
+ expect(normalizedTransaction2.payeeName).toBe('Xxxyyyyzzz');
170
+
171
+ const transaction3 = transactionsRaw[3];
172
+ const normalizedTransaction3 = Fortuneo.normalizeTransaction(
173
+ transaction3,
174
+ true,
175
+ );
176
+
177
+ expect(normalizedTransaction3.payeeName).toBe('Google Payment I Dublin');
178
+
179
+ const transaction4 = transactionsRaw[4];
180
+ const normalizedTransaction4 = Fortuneo.normalizeTransaction(
181
+ transaction4,
182
+ true,
183
+ );
184
+
185
+ expect(normalizedTransaction4.payeeName).toBe('Sport Market');
186
+
187
+ const transaction5 = transactionsRaw[5];
188
+ const normalizedTransaction5 = Fortuneo.normalizeTransaction(
189
+ transaction5,
190
+ true,
191
+ );
192
+
193
+ expect(normalizedTransaction5.payeeName).toBe('Weezevent Someplace');
194
+
195
+ const transaction7 = transactionsRaw[7];
196
+ const normalizedTransaction7 = Fortuneo.normalizeTransaction(
197
+ transaction7,
198
+ true,
199
+ );
200
+
201
+ expect(normalizedTransaction7.payeeName).toBe(
202
+ 'Leclerc Xxxx Leclerc Xxxx 44321ixcrt211141232',
203
+ );
204
+ });
205
+ });
206
+ });
@@ -0,0 +1,302 @@
1
+ import IngIngddeff from '../ing_ingddeff.js';
2
+
3
+ describe('IngIngddeff', () => {
4
+ describe('#normalizeAccount', () => {
5
+ /** @type {import('../../gocardless.types.js').DetailedAccountWithInstitution} */
6
+ const accountRaw = {
7
+ resourceId: 'e896eec6-6096-4efc-a941-756bd9d74765',
8
+ iban: 'DE02500105170137075030',
9
+ currency: 'EUR',
10
+ ownerName: 'Jane Doe',
11
+ product: 'Girokonto',
12
+ id: 'a787ba27-02ee-4fd6-be86-73831adc5498',
13
+ created: '2023-12-29T14:17:11.630352Z',
14
+ last_accessed: '2023-12-29T14:19:42.709478Z',
15
+ institution_id: 'ING_INGDDEFF',
16
+ status: 'READY',
17
+ owner_name: 'Jane Doe',
18
+ institution: {
19
+ id: 'ING_INGDDEFF',
20
+ name: 'ING',
21
+ bic: 'INGDDEFFXXX',
22
+ transaction_total_days: '390',
23
+ max_access_valid_for_days: '90',
24
+ countries: ['DE'],
25
+ logo: 'https://storage.googleapis.com/gc-prd-institution_icons-production/DE/PNG/ing.png',
26
+ supported_payments: {
27
+ 'single-payment': ['SCT'],
28
+ },
29
+ supported_features: [
30
+ 'account_selection',
31
+ 'business_accounts',
32
+ 'corporate_accounts',
33
+ 'payments',
34
+ 'pending_transactions',
35
+ 'private_accounts',
36
+ ],
37
+ /*identification_codes: [],*/
38
+ },
39
+ };
40
+
41
+ it('returns normalized account data returned to Frontend', () => {
42
+ expect(IngIngddeff.normalizeAccount(accountRaw)).toEqual({
43
+ account_id: 'a787ba27-02ee-4fd6-be86-73831adc5498',
44
+ iban: 'DE02500105170137075030',
45
+ institution: {
46
+ bic: 'INGDDEFFXXX',
47
+ countries: ['DE'],
48
+ id: 'ING_INGDDEFF',
49
+ logo: 'https://storage.googleapis.com/gc-prd-institution_icons-production/DE/PNG/ing.png',
50
+ name: 'ING',
51
+ supported_features: [
52
+ 'account_selection',
53
+ 'business_accounts',
54
+ 'corporate_accounts',
55
+ 'payments',
56
+ 'pending_transactions',
57
+ 'private_accounts',
58
+ ],
59
+ supported_payments: {
60
+ 'single-payment': ['SCT'],
61
+ },
62
+ transaction_total_days: '390',
63
+ max_access_valid_for_days: '90',
64
+ },
65
+ mask: '5030',
66
+ name: 'Girokonto (XXX 5030) EUR',
67
+ official_name: 'Girokonto',
68
+ type: 'checking',
69
+ });
70
+ });
71
+ });
72
+
73
+ const transactionsRaw = [
74
+ {
75
+ transactionId: '000010348081381',
76
+ endToEndId: 'NOTPROVIDED',
77
+ bookingDate: '2023-12-29',
78
+ valueDate: '2023-12-29',
79
+ transactionAmount: {
80
+ amount: '-4.00',
81
+ currency: 'EUR',
82
+ },
83
+ creditorName: 'VISA XXXXXXXXXXXXXXXXXXXX ',
84
+ remittanceInformationUnstructured:
85
+ 'mandatereference:,creditorid:,remittanceinformation:NR XXXX 63053 51590342815 KAUFUMSATZ 24.90 2311825 ARN044873748454374484719431 Google Pay ',
86
+ proprietaryBankTransactionCode: 'Lastschrifteinzug',
87
+ internalTransactionId: '085179a2e5fa34b0ff71b3f2c9f4876f',
88
+ date: '2023-12-29',
89
+ },
90
+ {
91
+ transactionId: '000010348081380',
92
+ endToEndId: 'NOTPROVIDED',
93
+ bookingDate: '2023-12-29',
94
+ valueDate: '2023-12-29',
95
+ transactionAmount: {
96
+ amount: '-2.00',
97
+ currency: 'EUR',
98
+ },
99
+ creditorName: 'VISA XXXXXXXXXXXXXXXXXXXX ',
100
+ remittanceInformationUnstructured:
101
+ 'mandatereference:,creditorid:,remittanceinformation:NR XXXX 8987 90671935362 KAUFUMSATZ 94.81 929614 ARN54795476045598005130492 Google Pay ',
102
+ proprietaryBankTransactionCode: 'Lastschrifteinzug',
103
+ internalTransactionId: '0707bbe2de27e5aabfd5dc614c584951',
104
+ date: '2023-12-29',
105
+ },
106
+ {
107
+ transactionId: '000010348081379',
108
+ endToEndId: 'NOTPROVIDED',
109
+ bookingDate: '2023-12-29',
110
+ valueDate: '2023-12-29',
111
+ transactionAmount: {
112
+ amount: '-6.00',
113
+ currency: 'EUR',
114
+ },
115
+ creditorName: 'VISA XXXXXXXXXXXXXXXXXXXX ',
116
+ remittanceInformationUnstructured:
117
+ 'mandatereference:,creditorid:,remittanceinformation:NR XXXX 2206 17679024325 KAUFUMSATZ 55.25 819456 ARN08595270353806495555431 Google Pay ',
118
+ proprietaryBankTransactionCode: 'Lastschrifteinzug',
119
+ internalTransactionId: '4b15b590652c9ebdc3f974591b15b250',
120
+ date: '2023-12-29',
121
+ },
122
+ {
123
+ transactionId: '000010348081378',
124
+ endToEndId: 'NOTPROVIDED',
125
+ bookingDate: '2023-12-29',
126
+ valueDate: '2023-12-29',
127
+ transactionAmount: {
128
+ amount: '-12.99',
129
+ currency: 'EUR',
130
+ },
131
+ creditorName: 'VISA XXXXXXXXXXXXXXXXXXXX ',
132
+ remittanceInformationUnstructured:
133
+ 'mandatereference:,creditorid:,remittanceinformation:NR XXXX 9437 535-182-825 LU KAUFUMSATZ 43.79 665448 ARN86236748928277201384604 ',
134
+ proprietaryBankTransactionCode: 'Lastschrifteinzug',
135
+ internalTransactionId: 'f930f8c153f3e37fb9906e4b3a2b4552',
136
+ date: '2023-12-29',
137
+ },
138
+ {
139
+ transactionId: '000010348081377',
140
+ endToEndId: 'NOTPROVIDED',
141
+ bookingDate: '2023-12-29',
142
+ valueDate: '2023-12-29',
143
+ transactionAmount: {
144
+ amount: '-9.00',
145
+ currency: 'EUR',
146
+ },
147
+ creditorName: 'VISA XXXXXXXXXXXXXXXXXXXX ',
148
+ remittanceInformationUnstructured:
149
+ 'mandatereference:,creditorid:,remittanceinformation:NR XXXX 3582 98236826123 KAUFUMSATZ 88.90 477561 ARN64452564252952225664357 Google Pay ',
150
+ proprietaryBankTransactionCode: 'Lastschrifteinzug',
151
+ internalTransactionId: '1ce866282deb78cc4ff4cd108e11b8cc',
152
+ date: '2023-12-29',
153
+ },
154
+ {
155
+ transactionId: '000010347374680',
156
+ endToEndId: '9212020-0900000070-2023121711315956',
157
+ bookingDate: '2023-12-29',
158
+ valueDate: '2023-12-29',
159
+ transactionAmount: {
160
+ amount: '2892.61',
161
+ currency: 'EUR',
162
+ },
163
+ debtorName: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
164
+ remittanceInformationUnstructured:
165
+ 'mandatereference:,creditorid:,remittanceinformation:F22685813 Gehalt 80/6586',
166
+ proprietaryBankTransactionCode: 'Gehalt/Rente',
167
+ internalTransactionId: 'e731d8eb47f1ae96ccc11e1fb8b76a60',
168
+ date: '2023-12-29',
169
+ },
170
+ {
171
+ transactionId: '000010336959253',
172
+ endToEndId: 'NOTPROVIDED',
173
+ bookingDate: '2023-12-28',
174
+ valueDate: '2023-12-28',
175
+ transactionAmount: {
176
+ amount: '-85.80',
177
+ currency: 'EUR',
178
+ },
179
+ creditorName: 'VISA XXXXXXXXXXXXXXXXXXXX ',
180
+ remittanceInformationUnstructured:
181
+ 'mandatereference:,creditorid:,remittanceinformation:NR XXXX 7082 FAUCOGNEY E FR KAUFUMSATZ 38.20 265113 ARN47998616225906149245029 ',
182
+ proprietaryBankTransactionCode: 'Lastschrifteinzug',
183
+ internalTransactionId: '2bbc054ae7ba299482a7849fded864f3',
184
+ date: '2023-12-28',
185
+ },
186
+ {
187
+ transactionId: '000010350537843',
188
+ endToEndId: 'NOTPROVIDED',
189
+ bookingDate: '2023-12-29',
190
+ valueDate: '2023-12-27',
191
+ transactionAmount: {
192
+ amount: '2.79',
193
+ currency: 'EUR',
194
+ },
195
+ debtorName: ' ',
196
+ remittanceInformationUnstructured:
197
+ 'mandatereference:,creditorid:,remittanceinformation: Zins/Dividende ISIN IE36B9RBWM04 VANG.FTSE',
198
+ proprietaryBankTransactionCode: 'Zins / Dividende WP',
199
+ internalTransactionId: '3bb7c58199d3fa5a44e85871d9001798',
200
+ date: '2023-12-29',
201
+ },
202
+ {
203
+ transactionId: '000010341786083',
204
+ endToEndId: 'NOTPROVIDED',
205
+ bookingDate: '2023-12-28',
206
+ valueDate: '2023-12-27',
207
+ transactionAmount: {
208
+ amount: '79.80',
209
+ currency: 'EUR',
210
+ },
211
+ debtorName: 'VISA XXXXXXXXXXXXXXXXXXXX ',
212
+ remittanceInformationUnstructured:
213
+ 'mandatereference:,creditorid:,remittanceinformation:NR XXXX 4619 GUTSCHRIFTSBELEG 03.91 134870 ',
214
+ proprietaryBankTransactionCode: 'Gutschrift',
215
+ internalTransactionId: '5570eefb7213e39153a6c7fb97d7dc6f',
216
+ date: '2023-12-28',
217
+ },
218
+ {
219
+ transactionId: '000010328399902',
220
+ endToEndId: 'NOTPROVIDED',
221
+ bookingDate: '2023-12-27',
222
+ valueDate: '2023-12-27',
223
+ transactionAmount: {
224
+ amount: '-10.90',
225
+ currency: 'EUR',
226
+ },
227
+ debtorName: 'VISA XXXXXXXXXXXXXXXXXXXX ',
228
+ remittanceInformationUnstructured:
229
+ 'mandatereference:,creditorid:,remittanceinformation:NR XXXX 3465 XXXXXXXXX KAUFUMSATZ 90.40 505416 ARN63639757770303957985044 Google Pay ',
230
+ proprietaryBankTransactionCode: 'Lastschrifteinzug',
231
+ internalTransactionId: '1b1bf30b23afb56ba4d41b9c65cf0efa',
232
+ date: '2023-12-27',
233
+ },
234
+ ];
235
+
236
+ describe('#sortTransactions', () => {
237
+ it('handles empty arrays', () => {
238
+ const transactions = [];
239
+ const sortedTransactions = IngIngddeff.sortTransactions(transactions);
240
+ expect(sortedTransactions).toEqual([]);
241
+ });
242
+
243
+ it('returns empty array for undefined input', () => {
244
+ const sortedTransactions = IngIngddeff.sortTransactions(undefined);
245
+ expect(sortedTransactions).toEqual([]);
246
+ });
247
+
248
+ it('returns sorted array for unsorted inputs', () => {
249
+ const normalizeTransactions = transactionsRaw.map(tx =>
250
+ IngIngddeff.normalizeTransaction(tx, true),
251
+ );
252
+ const originalOrder = Array.from(normalizeTransactions);
253
+ const swap = (a, b) => {
254
+ const swap = normalizeTransactions[a];
255
+ normalizeTransactions[a] = normalizeTransactions[b];
256
+ normalizeTransactions[b] = swap;
257
+ };
258
+ swap(1, 4);
259
+ swap(3, 6);
260
+ swap(0, 7);
261
+ const sortedTransactions = IngIngddeff.sortTransactions(
262
+ normalizeTransactions,
263
+ );
264
+ expect(sortedTransactions).toEqual(originalOrder);
265
+ });
266
+ });
267
+
268
+ describe('#countStartingBalance', () => {
269
+ /** @type {import('../../gocardless-node.types.js').Balance[]} */
270
+ const balances = [
271
+ {
272
+ balanceAmount: { amount: '3596.87', currency: 'EUR' },
273
+ balanceType: 'interimBooked',
274
+ lastChangeDateTime: '2023-12-29T16:44:06.479Z',
275
+ },
276
+ ];
277
+
278
+ it('should calculate the starting balance correctly', () => {
279
+ const normalizeTransactions = transactionsRaw.map(tx =>
280
+ IngIngddeff.normalizeTransaction(tx, true),
281
+ );
282
+ const sortedTransactions = IngIngddeff.sortTransactions(
283
+ normalizeTransactions,
284
+ );
285
+
286
+ const startingBalance = IngIngddeff.calculateStartingBalance(
287
+ sortedTransactions,
288
+ balances,
289
+ );
290
+
291
+ expect(startingBalance).toEqual(75236);
292
+ });
293
+
294
+ it('returns the same balance amount when no transactions', () => {
295
+ const transactions = [];
296
+
297
+ expect(
298
+ IngIngddeff.calculateStartingBalance(transactions, balances),
299
+ ).toEqual(359687);
300
+ });
301
+ });
302
+ });