@develit-services/bank 0.3.60 → 0.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.
Files changed (45) hide show
  1. package/dist/database/schema.cjs +9 -9
  2. package/dist/database/schema.d.cts +4 -5
  3. package/dist/database/schema.d.mts +4 -5
  4. package/dist/database/schema.d.ts +4 -5
  5. package/dist/database/schema.mjs +3 -3
  6. package/dist/export/worker.cjs +91 -85
  7. package/dist/export/worker.d.cts +23 -766
  8. package/dist/export/worker.d.mts +23 -766
  9. package/dist/export/worker.d.ts +23 -766
  10. package/dist/export/worker.mjs +72 -66
  11. package/dist/export/workflows.cjs +215 -211
  12. package/dist/export/workflows.d.cts +4 -4
  13. package/dist/export/workflows.d.mts +4 -4
  14. package/dist/export/workflows.d.ts +4 -4
  15. package/dist/export/workflows.mjs +210 -206
  16. package/dist/export/wrangler.d.cts +3 -1
  17. package/dist/export/wrangler.d.mts +3 -1
  18. package/dist/export/wrangler.d.ts +3 -1
  19. package/dist/shared/bank.B51e8oDT.mjs +104 -0
  20. package/dist/shared/{bank.Dh_H_5rC.d.cts → bank.BJvgLwyZ.d.cts} +2 -0
  21. package/dist/shared/{bank.Dh_H_5rC.d.mts → bank.BJvgLwyZ.d.mts} +2 -0
  22. package/dist/shared/{bank.Dh_H_5rC.d.ts → bank.BJvgLwyZ.d.ts} +2 -0
  23. package/dist/shared/bank.BUSlmr6r.mjs +13 -0
  24. package/dist/shared/{bank.CMbfx0u7.cjs → bank.BeIpkWR-.cjs} +3 -14
  25. package/dist/shared/bank.Bg3Pdwm4.cjs +44 -0
  26. package/dist/shared/bank.CDoYUKBx.d.cts +748 -0
  27. package/dist/shared/bank.CDoYUKBx.d.mts +748 -0
  28. package/dist/shared/bank.CDoYUKBx.d.ts +748 -0
  29. package/dist/shared/{bank.CNEv3Rac.cjs → bank.CfSZTfWS.cjs} +634 -179
  30. package/dist/shared/{bank.XJJV8p4b.d.cts → bank.CsJuzqZH.d.cts} +2401 -2117
  31. package/dist/shared/{bank.XJJV8p4b.d.mts → bank.CsJuzqZH.d.mts} +2401 -2117
  32. package/dist/shared/{bank.XJJV8p4b.d.ts → bank.CsJuzqZH.d.ts} +2401 -2117
  33. package/dist/shared/bank.DEvSNsEs.cjs +114 -0
  34. package/dist/shared/{bank.DgGcjhmM.mjs → bank.DinCwx0P.mjs} +627 -179
  35. package/dist/shared/bank.Dpx6PvkA.mjs +33 -0
  36. package/dist/shared/bank.c38V_FCq.cjs +15 -0
  37. package/dist/shared/{bank.BqGzJNC6.mjs → bank.qc8ALZwm.mjs} +4 -14
  38. package/dist/types.cjs +51 -33
  39. package/dist/types.d.cts +164 -39
  40. package/dist/types.d.mts +164 -39
  41. package/dist/types.d.ts +164 -39
  42. package/dist/types.mjs +4 -3
  43. package/package.json +7 -10
  44. package/dist/shared/bank.CXpc8168.cjs +0 -212
  45. package/dist/shared/bank.DSsVeR3F.mjs +0 -202
@@ -1,36 +1,69 @@
1
1
  import { uuidv4, useResult, createInternalError } from '@develit-io/backend-sdk';
2
2
  import { format, parseISO } from 'date-fns';
3
- import { s as schema } from './bank.BqGzJNC6.mjs';
4
- import { and, eq } from 'drizzle-orm';
3
+ import { CURRENCY_CODES } from '@develit-io/general-codes';
4
+ import './bank.qc8ALZwm.mjs';
5
+ import 'drizzle-orm';
5
6
  import { importPKCS8, SignJWT } from 'jose';
6
- import '@develit-io/general-codes';
7
7
  import 'node:crypto';
8
8
 
9
9
  class IBankConnector {
10
10
  }
11
11
 
12
- const mapReferencesToPayment = (reference) => {
13
- const symbols = {
14
- vs: void 0,
15
- ss: void 0,
16
- ks: void 0
12
+ function toIncomingPayment(input) {
13
+ return {
14
+ id: uuidv4(),
15
+ correlationId: input.correlationId,
16
+ refId: input.refId,
17
+ amount: input.amount,
18
+ direction: "OUTGOING",
19
+ paymentType: input.paymentType,
20
+ currency: input.currency,
21
+ status: "CREATED",
22
+ statusReason: null,
23
+ batchId: null,
24
+ initiatedAt: null,
25
+ // Will be set in preparePayment when sent to bank
26
+ processedAt: null,
27
+ vs: input.vs || null,
28
+ ss: input.ss || null,
29
+ ks: input.ks || null,
30
+ message: input.message || null,
31
+ creditor: input.creditor,
32
+ creditorIban: input.creditor.iban || null,
33
+ debtor: input.debtor,
34
+ debtorIban: input.debtor.iban || null,
35
+ sendAsSinglePayment: input.sendAsSinglePayment
17
36
  };
18
- if (!reference) return symbols;
19
- if (Array.isArray(reference) && reference.length > 0) {
20
- symbols.vs = reference.find((ref) => ref.includes("VS")) || void 0;
21
- symbols.ss = reference.find((ref) => ref.includes("SS")) || void 0;
22
- symbols.ks = reference.find((ref) => ref.includes("KS")) || void 0;
23
- }
24
- if (typeof reference === "string") {
25
- const vsMatch = reference.match(/VS[:\s]*(\d+)/i);
26
- const ssMatch = reference.match(/SS[:\s]*(\d+)/i);
27
- const ksMatch = reference.match(/KS[:\s]*(\d+)/i);
28
- if (vsMatch) symbols.vs = vsMatch[1];
29
- if (ssMatch) symbols.ss = ssMatch[1];
30
- if (ksMatch) symbols.ks = ksMatch[1];
31
- }
32
- return symbols;
33
- };
37
+ }
38
+ function assignAccount(payment, account) {
39
+ return {
40
+ ...payment,
41
+ accountId: account.id,
42
+ connectorKey: account.connectorKey
43
+ };
44
+ }
45
+ function toBatchedPayment(payment) {
46
+ return payment;
47
+ }
48
+ function toPreparedPayment(payment, bankRefId, initiatedAt) {
49
+ return {
50
+ ...payment,
51
+ status: "PREPARED",
52
+ bankRefId,
53
+ initiatedAt: initiatedAt ?? /* @__PURE__ */ new Date()
54
+ };
55
+ }
56
+ function toCompletedPayment(payment, status, bankRefId, processedAt) {
57
+ return {
58
+ ...payment,
59
+ bankRefId,
60
+ status,
61
+ processedAt: processedAt ?? /* @__PURE__ */ new Date()
62
+ };
63
+ }
64
+ function batchTransform(payments, transformer) {
65
+ return payments.map(transformer);
66
+ }
34
67
 
35
68
  async function signFinbricksJws({
36
69
  privateKeyPem,
@@ -193,6 +226,29 @@ const mapFinbricksAccountInsert = ({
193
226
  iban: account.identification.iban
194
227
  });
195
228
 
229
+ const mapReferencesToPayment = (reference) => {
230
+ const symbols = {
231
+ vs: void 0,
232
+ ss: void 0,
233
+ ks: void 0
234
+ };
235
+ if (!reference) return symbols;
236
+ if (Array.isArray(reference) && reference.length > 0) {
237
+ symbols.vs = reference.find((ref) => ref.includes("VS")) || void 0;
238
+ symbols.ss = reference.find((ref) => ref.includes("SS")) || void 0;
239
+ symbols.ks = reference.find((ref) => ref.includes("KS")) || void 0;
240
+ }
241
+ if (typeof reference === "string") {
242
+ const vsMatch = reference.match(/VS[:\s]*(\d+)/i);
243
+ const ssMatch = reference.match(/SS[:\s]*(\d+)/i);
244
+ const ksMatch = reference.match(/KS[:\s]*(\d+)/i);
245
+ if (vsMatch) symbols.vs = vsMatch[1];
246
+ if (ssMatch) symbols.ss = ssMatch[1];
247
+ if (ksMatch) symbols.ks = ksMatch[1];
248
+ }
249
+ return symbols;
250
+ };
251
+
196
252
  const mapFinbricksTransactionToPayment = (tx, account) => {
197
253
  const isIncoming = tx.creditDebitIndicator === "CRDT";
198
254
  const related = tx.entryDetails?.transactionDetails?.relatedParties;
@@ -330,9 +386,6 @@ class FinbricksConnector extends IBankConnector {
330
386
  )
331
387
  };
332
388
  }
333
- async authenticate(code) {
334
- return "";
335
- }
336
389
  async revokeAuthentication(clientId) {
337
390
  const [_, error] = await useResult(
338
391
  this.finbricks.request({
@@ -399,45 +452,7 @@ class FinbricksConnector extends IBankConnector {
399
452
  }
400
453
  return response.accounts;
401
454
  }
402
- async listAccounts() {
403
- const accounts = (await Promise.all(
404
- this.connectedAccounts.map(
405
- (acc) => this.getAccountsForClient({ clientId: acc.token })
406
- )
407
- )).flat();
408
- const uniqueAccounts = Array.from(
409
- new Map(accounts.map((acc) => [acc.identification.iban, acc])).values()
410
- );
411
- return uniqueAccounts.map((acc) => ({
412
- connectorKey: this.connectorKey,
413
- bankRefId: acc.id,
414
- currency: acc.currency,
415
- sync: false,
416
- status: "AUTHORIZED",
417
- countryCode: acc.servicer.countryCode,
418
- bankCode: acc.servicer.bankCode,
419
- number: acc.identification.accountNumber.split("/")[0],
420
- name: acc.productName,
421
- iban: acc.identification.iban,
422
- holderName: acc.ownersNames.join(", ")
423
- }));
424
- }
425
- async preparePayment(payment) {
426
- return {
427
- ...payment,
428
- bankRefId: uuidv4(),
429
- // merchantTransactionId
430
- direction: "OUTGOING",
431
- paymentType: payment.paymentType,
432
- status: "PREPARED",
433
- initiatedAt: /* @__PURE__ */ new Date(),
434
- accountId: this.connectedAccounts.find(
435
- (acc) => acc.iban === payment.debtorIban
436
- ).id,
437
- connectorKey: this.PROVIDER
438
- };
439
- }
440
- async initiateBatchFromPayments({
455
+ async initiateBatch({
441
456
  batchId,
442
457
  payments
443
458
  }) {
@@ -461,7 +476,7 @@ class FinbricksConnector extends IBankConnector {
461
476
  merchantBatchId: batchId
462
477
  },
463
478
  payments: payments.map((p) => ({
464
- merchantTransactionId: p.bankRefId,
479
+ merchantTransactionId: p.id,
465
480
  creditorAccountIban: p.creditor.iban,
466
481
  amount: p.amount,
467
482
  variableSymbol: p.vs,
@@ -477,10 +492,13 @@ class FinbricksConnector extends IBankConnector {
477
492
  console.error("FINBRICKS BATCH ERROR", error);
478
493
  throw createInternalError(error);
479
494
  }
495
+ const initiatedAt = /* @__PURE__ */ new Date();
480
496
  return {
481
497
  id: batchId,
482
498
  authorizationUrls: [response.redirectUrl],
483
- payments: payments.map((p) => ({ ...p, status: "INITIALIZED" }))
499
+ payments: payments.map(
500
+ (p) => toPreparedPayment(p, void 0, initiatedAt)
501
+ )
484
502
  };
485
503
  }
486
504
  async initiateForeignPayment(payment) {
@@ -536,7 +554,8 @@ class FinbricksConnector extends IBankConnector {
536
554
  payment: {
537
555
  ...payment,
538
556
  bankRefId,
539
- status: "INITIALIZED",
557
+ status: "PREPARED",
558
+ initiatedAt: /* @__PURE__ */ new Date(),
540
559
  accountId: this.connectedAccounts.find(
541
560
  (acc) => acc.iban === payment.debtorIban
542
561
  ).id,
@@ -586,7 +605,8 @@ class FinbricksConnector extends IBankConnector {
586
605
  payment: {
587
606
  ...payment,
588
607
  bankRefId,
589
- status: "INITIALIZED",
608
+ status: "PREPARED",
609
+ initiatedAt: /* @__PURE__ */ new Date(),
590
610
  accountId: this.connectedAccounts.find(
591
611
  (acc) => acc.iban === payment.debtorIban
592
612
  ).id,
@@ -601,7 +621,7 @@ class FinbricksConnector extends IBankConnector {
601
621
  method: "POST",
602
622
  body: {
603
623
  merchantId: this.finbricks.MERCHANT_ID,
604
- merchantTransactionId: payment.bankRefId,
624
+ merchantTransactionId: payment.id,
605
625
  totalPrice: payment.amount,
606
626
  debtorAccountIban: payment.debtor.iban,
607
627
  creditorAccountIban: payment.creditor.iban,
@@ -622,7 +642,11 @@ class FinbricksConnector extends IBankConnector {
622
642
  }
623
643
  return {
624
644
  authorizationUrl: response.redirectUrl,
625
- payment: { ...payment, status: "INITIALIZED" }
645
+ payment: {
646
+ ...payment,
647
+ status: "PREPARED",
648
+ initiatedAt: /* @__PURE__ */ new Date()
649
+ }
626
650
  };
627
651
  }
628
652
  async getAllAccountPayments({
@@ -724,6 +748,36 @@ class FinbricksConnector extends IBankConnector {
724
748
  }
725
749
  }
726
750
 
751
+ class CreditasConnector extends FinbricksConnector {
752
+ constructor(config) {
753
+ super("CREDITAS", config);
754
+ }
755
+ }
756
+
757
+ class FioConnector extends FinbricksConnector {
758
+ constructor(config) {
759
+ super("FIO", config);
760
+ }
761
+ }
762
+
763
+ class AirBankConnector extends FinbricksConnector {
764
+ constructor(config) {
765
+ super("AIRBANK", config);
766
+ }
767
+ }
768
+
769
+ class CSASConnector extends FinbricksConnector {
770
+ constructor(config) {
771
+ super("CSAS", config);
772
+ }
773
+ }
774
+
775
+ class MonetaConnector extends FinbricksConnector {
776
+ constructor(config) {
777
+ super("MONETA", config);
778
+ }
779
+ }
780
+
727
781
  const isDeposit = (payment, creditorIban) => {
728
782
  return payment.creditor.iban === creditorIban;
729
783
  };
@@ -732,6 +786,414 @@ const getPaymentDirection = (payment, iban) => {
732
786
  return "OUTGOING";
733
787
  };
734
788
 
789
+ const initiateConnector = ({
790
+ bank,
791
+ env,
792
+ connectedAccounts
793
+ }) => {
794
+ switch (bank) {
795
+ case "ERSTE":
796
+ return new ErsteConnector({
797
+ API_KEY: env.ERSTE_API_KEY,
798
+ CLIENT_ID: env.ERSTE_CLIENT_ID,
799
+ CLIENT_SECRET: env.ERSTE_CLIENT_SECRET,
800
+ REDIRECT_URI: env.REDIRECT_URI,
801
+ AUTH_URI: env.ERSTE_AUTH_URI,
802
+ PAYMENTS_URI: env.ERSTE_PAYMENTS_URI,
803
+ ACCOUNTS_URI: env.ERSTE_ACCOUNTS_URI,
804
+ connectedAccounts
805
+ });
806
+ case "CREDITAS":
807
+ return new CreditasConnector({
808
+ BASE_URI: env.FINBRICKS_BASE_URI,
809
+ MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
810
+ PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
811
+ REDIRECT_URI: env.REDIRECT_URI,
812
+ connectedAccounts
813
+ });
814
+ case "MOCK_COBS":
815
+ return new MockCobsConnector({
816
+ BASE_URI: env.FINBRICKS_BASE_URI,
817
+ MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
818
+ PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
819
+ REDIRECT_URI: env.REDIRECT_URI,
820
+ connectedAccounts
821
+ });
822
+ case "FIO":
823
+ return new FioConnector({
824
+ BASE_URI: env.FINBRICKS_BASE_URI,
825
+ MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
826
+ PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
827
+ REDIRECT_URI: env.REDIRECT_URI,
828
+ connectedAccounts
829
+ });
830
+ case "MONETA":
831
+ return new MonetaConnector({
832
+ BASE_URI: env.FINBRICKS_BASE_URI,
833
+ MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
834
+ PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
835
+ REDIRECT_URI: env.REDIRECT_URI,
836
+ connectedAccounts
837
+ });
838
+ case "AIRBANK":
839
+ return new AirBankConnector({
840
+ BASE_URI: env.FINBRICKS_BASE_URI,
841
+ MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
842
+ PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
843
+ REDIRECT_URI: env.REDIRECT_URI,
844
+ connectedAccounts
845
+ });
846
+ case "CSAS":
847
+ return new CSASConnector({
848
+ BASE_URI: env.FINBRICKS_BASE_URI,
849
+ MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
850
+ PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
851
+ REDIRECT_URI: env.REDIRECT_URI,
852
+ connectedAccounts
853
+ });
854
+ case "DBU":
855
+ return new DbuConnector({
856
+ BASE_URL: env.DBUCS_BASE_URI,
857
+ USERNAME: env.DBUCS_USERNAME,
858
+ KV: env.BANK_KV
859
+ });
860
+ default:
861
+ const mockConnector = new MockConnector();
862
+ mockConnector.connectedAccounts = connectedAccounts;
863
+ return mockConnector;
864
+ }
865
+ };
866
+ function mod97(string) {
867
+ let checksum = string.slice(0, 2);
868
+ let fragment = "";
869
+ for (let offset = 2; offset < string.length; offset += 7) {
870
+ fragment = checksum + string.substring(offset, offset + 7);
871
+ checksum = (parseInt(fragment, 10) % 97).toString();
872
+ }
873
+ return parseInt(checksum, 10);
874
+ }
875
+ const calculateCzechIban = (accountNumber, bankCode) => {
876
+ const paddedBankCode = bankCode.padStart(4, "0");
877
+ let prefix = "";
878
+ let mainAccount = accountNumber;
879
+ if (accountNumber.includes("-")) {
880
+ const parts = accountNumber.split("-");
881
+ prefix = parts[0];
882
+ mainAccount = parts[1];
883
+ }
884
+ const paddedPrefix = prefix.padStart(6, "0");
885
+ const paddedAccount = mainAccount.padStart(10, "0");
886
+ const basicIban = paddedBankCode + paddedPrefix + paddedAccount;
887
+ const rearranged = basicIban + "1215";
888
+ const remainder = mod97(rearranged);
889
+ const checkDigits = (98 - remainder).toString().padStart(2, "0");
890
+ return `CZ${checkDigits}${basicIban}`;
891
+ };
892
+
893
+ class DbuConnector extends IBankConnector {
894
+ constructor({ BASE_URL, USERNAME, KV }) {
895
+ super();
896
+ this.connectorKey = "DBU";
897
+ this.connectedAccounts = [];
898
+ this.baseUrl = BASE_URL;
899
+ this.username = USERNAME;
900
+ this.kv = KV;
901
+ this.sessionId = uuidv4();
902
+ this.allowedPostEndpoints = ["/required-transactions", "/import/data"];
903
+ }
904
+ async makeRequest(endpoint, requestId, options = {}) {
905
+ const { method = "GET", headers = {}, query = {}, body } = options;
906
+ if (method === "POST" && !this.allowedPostEndpoints.includes(endpoint)) {
907
+ throw createInternalError(null, {
908
+ message: `DBU API endpoint ${endpoint} does not support POST method`,
909
+ code: "DBU_INVALID_METHOD"
910
+ });
911
+ }
912
+ const auth = btoa("devizova_burza:Fu7psMt7i59ct43D5Y3s");
913
+ const defaultHeaders = {
914
+ "x-dcs-username": this.username,
915
+ "x-dcs-session-id": `session-${this.sessionId}`,
916
+ "x-dcs-request-id": `request-${requestId}`,
917
+ "Content-Type": "application/json",
918
+ Authorization: `Basic ${auth}`,
919
+ ...headers
920
+ };
921
+ const baseUrl = this.baseUrl.endsWith("/") ? this.baseUrl.slice(0, -1) : this.baseUrl;
922
+ const cleanEndpoint = endpoint.startsWith("/") ? endpoint.slice(1) : endpoint;
923
+ const url = new URL(`${baseUrl}/${cleanEndpoint}`);
924
+ Object.entries(query).forEach(([key, value]) => {
925
+ if (value !== void 0 && value !== null) {
926
+ url.searchParams.append(key, value);
927
+ }
928
+ });
929
+ const fetchOptions = {
930
+ method,
931
+ headers: defaultHeaders
932
+ };
933
+ console.log("DBU Request:", url.toString(), fetchOptions);
934
+ if (body && method !== "GET") {
935
+ fetchOptions.body = JSON.stringify(body);
936
+ }
937
+ const response = await fetch(url.toString(), fetchOptions);
938
+ if (!response.ok) {
939
+ throw createInternalError(
940
+ new Error(`DBU API error: ${response.status}`),
941
+ {
942
+ message: `DBU request failed: ${response.statusText}`
943
+ }
944
+ );
945
+ }
946
+ return response.json();
947
+ }
948
+ mapDbuCurrencyCode(dbuCurrency) {
949
+ const currency = dbuCurrency.toUpperCase();
950
+ if (CURRENCY_CODES.includes(currency))
951
+ return currency;
952
+ throw createInternalError(null, {
953
+ message: `Unknown DBU currency code: ${dbuCurrency}`,
954
+ code: "DBU_UNKNOWN_CURRENCY"
955
+ });
956
+ }
957
+ mapDbuTransactionToPayment(transaction, account) {
958
+ const isIncoming = transaction.accountNumberCredit === account.number;
959
+ const direction = isIncoming ? "INCOMING" : "OUTGOING";
960
+ const creditorIban = calculateCzechIban(
961
+ transaction.accountNumberCredit,
962
+ transaction.bankCodeCredit
963
+ );
964
+ const debtorIban = calculateCzechIban(
965
+ transaction.accountNumberDebit,
966
+ transaction.bankCodeDebit
967
+ );
968
+ const parsed = {
969
+ id: uuidv4(),
970
+ correlationId: uuidv4(),
971
+ connectorKey: "DBU",
972
+ accountId: account.id,
973
+ bankRefId: transaction.idRequiredTransaction.toString(),
974
+ amount: transaction.realizedAmount || transaction.amount,
975
+ direction,
976
+ paymentType: "DOMESTIC",
977
+ //TODO: DBU handles domestic transactions only?
978
+ currency: this.mapDbuCurrencyCode(transaction.currencyCode),
979
+ status: this.mapDbuStatusToPaymentStatus(transaction.status),
980
+ initiatedAt: transaction.validFrom ? new Date(transaction.validFrom) : /* @__PURE__ */ new Date(),
981
+ processedAt: transaction.realizationDate ? new Date(transaction.realizationDate) : null,
982
+ vs: transaction.varSymbol,
983
+ ss: transaction.specSymbol,
984
+ ks: transaction.constSymbol,
985
+ message: transaction.textMessage,
986
+ creditor: {
987
+ number: transaction.accountNumberCredit,
988
+ bankCode: transaction.bankCodeCredit,
989
+ iban: creditorIban
990
+ },
991
+ debtor: {
992
+ number: transaction.accountNumberDebit,
993
+ bankCode: transaction.bankCodeDebit,
994
+ iban: debtorIban
995
+ },
996
+ debtorIban
997
+ };
998
+ return {
999
+ raw: transaction,
1000
+ parsed
1001
+ };
1002
+ }
1003
+ mapDbuStatusToPaymentStatus(dbuStatus) {
1004
+ const statusCode = dbuStatus.trim();
1005
+ switch (statusCode) {
1006
+ // COMPLETED - Transaction is fully realized
1007
+ case "3":
1008
+ return "COMPLETED";
1009
+ // PREPARED - Transaction is new and ready for processing
1010
+ case "0":
1011
+ return "PREPARED";
1012
+ // PENDING - Transaction is partially processed or on hold
1013
+ case "1":
1014
+ // RQT_STATUS_READY_FOR_REAL
1015
+ case "2":
1016
+ // RQT_STATUS_PARTIAL_REALIZED
1017
+ case "4":
1018
+ // RQT_STATUS_PARTIAL_HOLDED
1019
+ case "5":
1020
+ // RQT_STATUS_HOLDED
1021
+ case "6":
1022
+ // RQT_STATUS_WAIT_FOR_COT
1023
+ case "11":
1024
+ // RQT_STATUS_UNHOLDED
1025
+ case "30":
1026
+ // RQT_STATUS_RQ_TO_HD
1027
+ case "31":
1028
+ // RQT_STATUS_RQ_TO_HD_SENT
1029
+ case "32":
1030
+ // RQT_STATUS_WAIT_TO_HD_VERIFY
1031
+ case "34":
1032
+ // RQT_STATUS_HD_NEW_COLLECTION
1033
+ case "35":
1034
+ // RQT_STATUS_HD_RQ_COLLECTION
1035
+ case "40":
1036
+ // RQT_STATUS_SIPO_CHARGE
1037
+ case "50":
1038
+ // RQT_STATUS_4E
1039
+ case "51":
1040
+ // RQT_STATUS_4E_EDIT
1041
+ case "60":
1042
+ // RQT_STATUS_READY_TO_CANCELLED
1043
+ case "61":
1044
+ // RQT_STATUS_READY_TO_UNHOLDED
1045
+ case "63":
1046
+ // RQT_STATUS_READY_TO_REVERTED
1047
+ case "64":
1048
+ // RQT_STATUS_CC_CREATED
1049
+ case "65":
1050
+ // RQT_STATUS_CC_WAIT_FOR_RATE
1051
+ case "66":
1052
+ // RQT_STATUS_WAIT_FOR_DEBTOR
1053
+ case "70":
1054
+ // RQT_STATUS_RQ_TO_SEPA
1055
+ case "71":
1056
+ // RQT_STATUS_RQ_TO_SEPA_SENT
1057
+ case "72":
1058
+ // RQT_STATUS_RQ_TO_SEPA_CNC
1059
+ case "73":
1060
+ // RQT_STATUS_RQ_TO_SEPA_CNC_URG
1061
+ case "74":
1062
+ // RQT_STATUS_RQ_TO_SEPA_CNC_CLIENT
1063
+ case "75":
1064
+ // RQT_STATUS_RQ_TO_SEPA_056
1065
+ case "80":
1066
+ return "PENDING";
1067
+ // FAILED - Transaction is cancelled, rejected, reverted, suspended or expired
1068
+ case "10":
1069
+ // RQT_STATUS_CANCELLED
1070
+ case "12":
1071
+ // RQT_STATUS_SUSPENDED
1072
+ case "13":
1073
+ // RQT_STATUS_REVERTED
1074
+ case "14":
1075
+ // RQT_STATUS_EXPIRED
1076
+ case "15":
1077
+ // RQT_STATUS_REJECTED
1078
+ case "33":
1079
+ // RQT_STATUS_HD_CANCELLED
1080
+ case "39":
1081
+ return "FAILED";
1082
+ // Default to PENDING for unknown status codes
1083
+ default:
1084
+ return "PENDING";
1085
+ }
1086
+ }
1087
+ async getAuthUri({ ott }) {
1088
+ throw createInternalError(null, {
1089
+ message: "DBU connector does not require authorization",
1090
+ code: "DBU_NO_AUTH_REQUIRED"
1091
+ });
1092
+ }
1093
+ async authorizeAccount({ urlParams }) {
1094
+ return {
1095
+ credentials: [],
1096
+ accounts: []
1097
+ };
1098
+ }
1099
+ async listAccounts() {
1100
+ return [];
1101
+ }
1102
+ async initiateBatch({
1103
+ batchId,
1104
+ payments
1105
+ }) {
1106
+ throw createInternalError(null, {
1107
+ message: "DBU batch payments not implemented yet",
1108
+ code: "DBU_BATCH_NOT_IMPLEMENTED"
1109
+ });
1110
+ }
1111
+ async initiateSEPAPayment(payment) {
1112
+ throw createInternalError(null, {
1113
+ message: "DBU SEPA payment creation not implemented yet",
1114
+ code: "DBU_SEPA_PAYMENT_NOT_IMPLEMENTED"
1115
+ });
1116
+ }
1117
+ async initiateSinglePayment(payment) {
1118
+ throw createInternalError(null, {
1119
+ message: "DBU single payment creation not implemented yet",
1120
+ code: "DBU_PAYMENT_NOT_IMPLEMENTED"
1121
+ });
1122
+ }
1123
+ async getAllAccountPayments({
1124
+ account,
1125
+ filter
1126
+ }) {
1127
+ try {
1128
+ const dateFrom = format(filter.dateFrom, "yyyy-MM-dd");
1129
+ const dateTo = format(filter.dateTo || /* @__PURE__ */ new Date(), "yyyy-MM-dd");
1130
+ const allPayments = [];
1131
+ let offset = 0;
1132
+ const limit = 10;
1133
+ let hasMoreData = true;
1134
+ let pageNumber = 1;
1135
+ const baseRequestId = uuidv4();
1136
+ while (hasMoreData) {
1137
+ const response = await this.makeRequest(
1138
+ "/required-transactions",
1139
+ `${baseRequestId}_page${pageNumber}`,
1140
+ {
1141
+ method: "GET",
1142
+ query: {
1143
+ // Date filtering
1144
+ "filter.validFromStart": dateFrom,
1145
+ "filter.validFromEnd": dateTo,
1146
+ // Pagination parameters
1147
+ offset: offset.toString(),
1148
+ limit: limit.toString()
1149
+ }
1150
+ }
1151
+ );
1152
+ if (!response.transactions?.transaction || response.transactions.transaction.length === 0) {
1153
+ hasMoreData = false;
1154
+ break;
1155
+ }
1156
+ for (const transaction of response.transactions.transaction) {
1157
+ try {
1158
+ const payment = this.mapDbuTransactionToPayment(
1159
+ transaction,
1160
+ account
1161
+ );
1162
+ allPayments.push(payment);
1163
+ } catch (error) {
1164
+ console.error("Failed to map DBU transaction:", error, transaction);
1165
+ }
1166
+ }
1167
+ if (response.transactions.transaction.length < limit) {
1168
+ hasMoreData = false;
1169
+ } else {
1170
+ offset += limit;
1171
+ pageNumber += 1;
1172
+ }
1173
+ hasMoreData = false;
1174
+ }
1175
+ return allPayments;
1176
+ } catch (error) {
1177
+ throw createInternalError(error, {
1178
+ message: "Failed to fetch payments from DBU API"
1179
+ });
1180
+ }
1181
+ }
1182
+ async getPaymentStatus({
1183
+ paymentId
1184
+ }) {
1185
+ return "PENDING";
1186
+ }
1187
+ async getBatchStatus({
1188
+ batchId
1189
+ }) {
1190
+ return {
1191
+ status: "OPEN",
1192
+ apiResponse: {}
1193
+ };
1194
+ }
1195
+ }
1196
+
735
1197
  class ErsteConnector extends IBankConnector {
736
1198
  constructor(config) {
737
1199
  super();
@@ -780,40 +1242,49 @@ class ErsteConnector extends IBankConnector {
780
1242
  ]
781
1243
  };
782
1244
  }
783
- async authenticate(tokens) {
784
- const grantType = tokens?.refreshToken ? "refresh_token" : "authorization_code";
785
- let bodyParams = {
786
- client_id: this.CLIENT_ID,
787
- client_secret: this.CLIENT_SECRET,
788
- grant_type: grantType
789
- };
790
- if (tokens?.token) {
791
- bodyParams = {
792
- ...bodyParams,
793
- code: tokens.token,
794
- redirect_uri: this.REDIRECT_URI
795
- };
796
- }
797
- if (tokens?.refreshToken) bodyParams.refresh_token = tokens?.refreshToken;
798
- const body = new URLSearchParams(bodyParams);
799
- const result = await fetch(`${this.AUTH_URI}/token`, {
800
- method: "POST",
801
- body: body.toString(),
802
- headers: { "Content-Type": "application/x-www-form-urlencoded" }
803
- });
804
- if (result.status !== 200) {
805
- throw createInternalError(null, {
806
- message: await result.text()
807
- });
808
- }
809
- const json = await result.json();
810
- this.accessToken = json.access_token;
811
- return json.refresh_token || "";
812
- }
813
- listAccounts() {
814
- throw new Error("Method not implemented.");
815
- }
816
- async preparePayment(payment) {
1245
+ // async authenticate(tokens?: {
1246
+ // refreshToken?: string
1247
+ // token?: string
1248
+ // }): Promise<string> {
1249
+ // const grantType = tokens?.refreshToken
1250
+ // ? 'refresh_token'
1251
+ // : 'authorization_code'
1252
+ // let bodyParams: Record<string, string> = {
1253
+ // client_id: this.CLIENT_ID!,
1254
+ // client_secret: this.CLIENT_SECRET!,
1255
+ // grant_type: grantType,
1256
+ // }
1257
+ // if (tokens?.token) {
1258
+ // bodyParams = {
1259
+ // ...bodyParams,
1260
+ // code: tokens.token,
1261
+ // redirect_uri: this.REDIRECT_URI,
1262
+ // }
1263
+ // }
1264
+ // if (tokens?.refreshToken) bodyParams.refresh_token = tokens?.refreshToken
1265
+ // const body = new URLSearchParams(bodyParams)
1266
+ // const result = await fetch(`${this.AUTH_URI}/token`, {
1267
+ // method: 'POST',
1268
+ // body: body.toString(),
1269
+ // headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
1270
+ // })
1271
+ // if (result.status !== 200) {
1272
+ // throw createInternalError(null, {
1273
+ // message: await result.text(),
1274
+ // })
1275
+ // }
1276
+ // const json = (await result.json()) as {
1277
+ // access_token: string
1278
+ // refresh_token?: string
1279
+ // }
1280
+ // this.accessToken = json.access_token
1281
+ // return json.refresh_token || ''
1282
+ // }
1283
+ /**
1284
+ * Erste-specific: Prepare individual payment
1285
+ * This is an internal method used by initiateBatch
1286
+ */
1287
+ async prepareErstePayment(payment) {
817
1288
  if (!this.accessToken) {
818
1289
  throw createInternalError(null, {
819
1290
  message: "Internal authentication failed",
@@ -863,14 +1334,19 @@ class ErsteConnector extends IBankConnector {
863
1334
  connectorKey: "ERSTE"
864
1335
  };
865
1336
  }
866
- async initiateBatchFromPayments({
1337
+ async initiateBatch({
867
1338
  batchId,
868
1339
  payments
869
1340
  }) {
870
- const allRefIds = payments.map((payment) => payment.bankRefId);
1341
+ const preparedPayments = [];
1342
+ for (const payment of payments) {
1343
+ const prepared = await this.prepareErstePayment(payment);
1344
+ preparedPayments.push(prepared);
1345
+ }
1346
+ const allRefIds = preparedPayments.map((payment) => payment.bankRefId);
871
1347
  if (allRefIds.length === 0) {
872
1348
  throw createInternalError(null, {
873
- message: "No valid payments to include in batch",
1349
+ message: "No payments to include in batch",
874
1350
  status: 400
875
1351
  });
876
1352
  }
@@ -881,7 +1357,10 @@ class ErsteConnector extends IBankConnector {
881
1357
  throw createInternalError(signError);
882
1358
  }
883
1359
  const [authUri, authUriError] = await useResult(
884
- this.getBatchAuthorizationURI(signInfo)
1360
+ this.getBatchAuthorizationURI({
1361
+ signHash: signInfo.signHash,
1362
+ signId: signInfo.signId
1363
+ })
885
1364
  );
886
1365
  if (authUriError) {
887
1366
  throw createInternalError(authUriError);
@@ -889,14 +1368,11 @@ class ErsteConnector extends IBankConnector {
889
1368
  return {
890
1369
  id: batchId,
891
1370
  authorizationUrls: [authUri || ""],
892
- payments: payments.map((payment) => ({
893
- ...payment,
894
- status: "INITIALIZED"
895
- })),
1371
+ payments: preparedPayments,
896
1372
  metadata: signInfo
897
1373
  };
898
1374
  }
899
- initiateSinglePayment() {
1375
+ initiateSinglePayment(payment) {
900
1376
  throw new Error("Method not implemented.");
901
1377
  }
902
1378
  async sendBatchPaymentForAuthorization(paymentIds) {
@@ -1027,21 +1503,18 @@ class ErsteConnector extends IBankConnector {
1027
1503
  }
1028
1504
  }
1029
1505
 
1506
+ class MockCobsConnector extends FinbricksConnector {
1507
+ constructor(config) {
1508
+ super("MOCK_COBS", config);
1509
+ }
1510
+ }
1511
+
1030
1512
  class MockConnector extends IBankConnector {
1031
1513
  constructor() {
1032
1514
  super();
1033
1515
  this.connectorKey = "MOCK";
1034
1516
  this.connectedAccounts = [];
1035
1517
  }
1036
- initiateSEPAPayment(payment) {
1037
- throw new Error("Method not implemented.");
1038
- }
1039
- async authenticate() {
1040
- return "";
1041
- }
1042
- async listAccounts() {
1043
- return [];
1044
- }
1045
1518
  async getAuthUri({
1046
1519
  accountId
1047
1520
  }) {
@@ -1053,77 +1526,52 @@ class MockConnector extends IBankConnector {
1053
1526
  accounts: []
1054
1527
  };
1055
1528
  }
1056
- async preparePayment(payment) {
1057
- const bankRefId = uuidv4();
1058
- return {
1529
+ async initiateSinglePayment(payment) {
1530
+ const preparedPayment = {
1059
1531
  ...payment,
1060
- id: uuidv4(),
1061
- bankRefId,
1062
- direction: "OUTGOING",
1063
- paymentType: "DOMESTIC",
1532
+ bankRefId: uuidv4(),
1064
1533
  status: "PREPARED",
1065
- initiatedAt: /* @__PURE__ */ new Date(),
1066
- accountId: this.connectedAccounts.find(
1067
- (acc) => acc.iban === payment.debtor.iban
1068
- ).id,
1069
- connectorKey: "MOCK"
1534
+ initiatedAt: /* @__PURE__ */ new Date()
1070
1535
  };
1071
- }
1072
- async initiateSinglePayment(payment) {
1073
1536
  return {
1074
- payment: {
1075
- ...payment,
1076
- status: "INITIALIZED"
1077
- },
1078
- authorizationUrl: "http://mock.com"
1537
+ payment: preparedPayment,
1538
+ authorizationUrl: "http://mock.com/auto-approve"
1079
1539
  };
1080
1540
  }
1081
- async initiateBatchFromPayments({
1541
+ async initiateSEPAPayment(payment) {
1542
+ return this.initiateSinglePayment(payment);
1543
+ }
1544
+ async initiateBatch({
1082
1545
  batchId,
1083
1546
  payments
1084
1547
  }) {
1548
+ const preparedPayments = payments.map((payment) => ({
1549
+ ...payment,
1550
+ bankRefId: uuidv4(),
1551
+ status: "PREPARED",
1552
+ initiatedAt: /* @__PURE__ */ new Date()
1553
+ }));
1085
1554
  return {
1086
- id: uuidv4(),
1087
- authorizationUrls: ["http://mock.com"],
1088
- payments: payments.map(
1089
- (payment) => ({
1090
- ...payment,
1091
- status: "INITIALIZED"
1092
- })
1093
- )
1555
+ id: batchId,
1556
+ authorizationUrls: ["http://mock.com/auto-approve"],
1557
+ payments: preparedPayments
1094
1558
  };
1095
1559
  }
1096
1560
  async getAllAccountPayments({
1097
- db
1561
+ account,
1562
+ filter
1098
1563
  }) {
1099
- const payments = await db.select().from(tables.payment).where(
1100
- and(
1101
- eq(tables.payment.status, "INITIALIZED"),
1102
- eq(tables.payment.direction, "OUTGOING")
1103
- )
1104
- );
1105
- return payments.map((payment) => ({
1106
- raw: payment,
1107
- parsed: {
1108
- ...payment,
1109
- status: "COMPLETED"
1110
- }
1111
- }));
1112
- }
1113
- getPaymentStatus(_) {
1114
- throw new Error("Method not implemented.");
1564
+ return [];
1115
1565
  }
1116
- getBatchStatus(_) {
1117
- throw new Error("Method not implemented.");
1566
+ async getPaymentStatus(_) {
1567
+ return "COMPLETED";
1118
1568
  }
1119
- }
1120
-
1121
- class MockCobsConnector extends FinbricksConnector {
1122
- constructor(config) {
1123
- super("MOCK_COBS", config);
1569
+ async getBatchStatus(_) {
1570
+ return {
1571
+ status: "SIGNED",
1572
+ apiResponse: { mock: true }
1573
+ };
1124
1574
  }
1125
1575
  }
1126
1576
 
1127
- const tables = schema;
1128
-
1129
- export { ErsteConnector as E, FinbricksConnector as F, IBankConnector as I, MockConnector as M, MockCobsConnector as a, FinbricksClient as b, FINBRICKS_ENDPOINTS as c, signFinbricksJws as s, tables as t, useFinbricksFetch as u };
1577
+ export { DbuConnector as D, ErsteConnector as E, FinbricksConnector as F, IBankConnector as I, MockCobsConnector as M, MockConnector as a, FinbricksClient as b, FINBRICKS_ENDPOINTS as c, assignAccount as d, toBatchedPayment as e, toPreparedPayment as f, toCompletedPayment as g, batchTransform as h, initiateConnector as i, signFinbricksJws as s, toIncomingPayment as t, useFinbricksFetch as u };