@develit-services/bank 0.8.2 → 0.8.4

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 (41) hide show
  1. package/README.md +82 -6
  2. package/dist/database/schema.cjs +9 -7
  3. package/dist/database/schema.d.cts +1 -1
  4. package/dist/database/schema.d.mts +1 -1
  5. package/dist/database/schema.d.ts +1 -1
  6. package/dist/database/schema.mjs +1 -1
  7. package/dist/export/worker.cjs +221 -43
  8. package/dist/export/worker.d.cts +24 -8
  9. package/dist/export/worker.d.mts +24 -8
  10. package/dist/export/worker.d.ts +24 -8
  11. package/dist/export/worker.mjs +212 -34
  12. package/dist/export/workflows.cjs +71 -52
  13. package/dist/export/workflows.mjs +71 -52
  14. package/dist/export/wrangler.d.cts +1 -2
  15. package/dist/export/wrangler.d.mts +1 -2
  16. package/dist/export/wrangler.d.ts +1 -2
  17. package/dist/shared/{bank.Du70-Kk_.d.ts → bank.6faPHUEY.d.ts} +211 -1
  18. package/dist/shared/{bank.Bs7mkXbR.cjs → bank.BOnP9p9Y.cjs} +15 -2
  19. package/dist/shared/{bank.BJ7LqYtJ.d.cts → bank.BaMRCHk-.d.cts} +707 -126
  20. package/dist/shared/{bank.BJ7LqYtJ.d.mts → bank.BaMRCHk-.d.mts} +707 -126
  21. package/dist/shared/{bank.BJ7LqYtJ.d.ts → bank.BaMRCHk-.d.ts} +707 -126
  22. package/dist/shared/{bank.Du70-Kk_.d.cts → bank.BoWCMu5n.d.cts} +211 -1
  23. package/dist/shared/bank.C-T1FQxg.cjs +17 -0
  24. package/dist/shared/{bank.993UA65l.mjs → bank.C4VOdIx1.mjs} +57 -5
  25. package/dist/shared/{bank.BC06Rbrx.d.cts → bank.CQBfbG8u.d.cts} +0 -1
  26. package/dist/shared/{bank.BC06Rbrx.d.mts → bank.CQBfbG8u.d.mts} +0 -1
  27. package/dist/shared/{bank.BC06Rbrx.d.ts → bank.CQBfbG8u.d.ts} +0 -1
  28. package/dist/shared/{bank.Ce-NBBw1.cjs → bank.CQURey1E.cjs} +64 -7
  29. package/dist/shared/{bank.CGIeLo8U.mjs → bank.Cpy9PULF.mjs} +14 -3
  30. package/dist/shared/bank.DDHrdFgy.mjs +15 -0
  31. package/dist/shared/{bank.Du70-Kk_.d.mts → bank.DOL1uM4n.d.mts} +211 -1
  32. package/dist/shared/{bank.CeRbuycV.mjs → bank.DRrBrAdI.mjs} +62 -8
  33. package/dist/shared/{bank.IVhZ_RlH.cjs → bank.SQ4Mmr8u.cjs} +57 -3
  34. package/dist/types.cjs +25 -23
  35. package/dist/types.d.cts +29 -180
  36. package/dist/types.d.mts +29 -180
  37. package/dist/types.d.ts +29 -180
  38. package/dist/types.mjs +2 -2
  39. package/package.json +1 -1
  40. package/dist/shared/bank.Cp0yvOdq.cjs +0 -15
  41. package/dist/shared/bank.fIGTiPnp.mjs +0 -13
package/README.md CHANGED
@@ -24,7 +24,7 @@ Sluzba se sklada z:
24
24
 
25
25
  ## Zivotni cyklus platby
26
26
 
27
- Platba prochazi 5 fazemi s explicitnimi typy:
27
+ Platba prochazi 6 fazemi s explicitnimi typy:
28
28
 
29
29
  ```
30
30
  SendPaymentInput (API vstup)
@@ -55,10 +55,17 @@ SendPaymentInput (API vstup)
55
55
  │ Odeslana do banky, ceka na autorizaci │
56
56
  │ (muze jiz mit bankRefId) │
57
57
  └──────────────────┬──────────────────────────┘
58
- autorizace + zpracovani bankou
58
+ uzivatel autorizuje (callback)
59
59
 
60
60
  ┌─────────────────────────────────────────────┐
61
- │ 5. CompletedPayment status: COMPLETED
61
+ │ 5. SignedPayment status: SIGNED
62
+ │ Autorizovana uzivatelem, banka │
63
+ │ zpracovava │
64
+ └──────────────────┬──────────────────────────┘
65
+ │ banka dokonci zpracovani
66
+
67
+ ┌─────────────────────────────────────────────┐
68
+ │ 6. CompletedPayment status: COMPLETED│
62
69
  │ Zpracovana bankou, ma bankRefId │
63
70
  │ a processedAt timestamp │
64
71
  │ (pripadne FAILED / PENDING) │
@@ -71,6 +78,7 @@ SendPaymentInput (API vstup)
71
78
  |--------|-------|
72
79
  | `CREATED` | Platba vytvorena, ceka na zpracovani |
73
80
  | `PREPARED` | Odeslana do banky, ceka na autorizaci |
81
+ | `SIGNED` | Autorizovana uzivatelem, banka zpracovava |
74
82
  | `PENDING` | Banka zpracovava |
75
83
  | `COMPLETED` | Uspesne dokoncena |
76
84
  | `FAILED` | Selhala |
@@ -146,11 +154,14 @@ Kazdy batch obsahuje pouze platby **jednoho typu** (SEPA, DOMESTIC nebo SWIFT).
146
154
  Workflow (Cloudflare Durable Object) ridi zpracovani batche:
147
155
 
148
156
  1. Nacte a validuje batch (nesmi byt SIGNED/PROCESSING)
157
+ 1b. Nacte payment requesty pro batch z `payment_request` tabulky
149
158
  2. Zamkne batch (nastavi PROCESSING, overi checksum)
150
159
  3. Iniciuje batch u banky pres konektor podle typu platby (`connector.initiateDomesticBatch()` / `initiateSEPABatch()` / `initiateForeignBatch()`)
160
+ 3b. Aktualizuje singlePayments na PREPARED (bankRefId, initiatedAt, authorizationUrl)
151
161
  4. Aktualizuje batch na READY_TO_SIGN s autorizacnimi URL
162
+ 4a. MOCK konektor: preskoci autorizaci, rovnou oznaci singlePayments jako COMPLETED a batch jako SIGNED
152
163
  5. Odesle email s odkazem na autorizaci
153
- 6. Ceka na autorizaci uzivatelem
164
+ 6. (TBD) Ceka na autorizaci uzivatelem (waitForEvent)
154
165
 
155
166
  ### CRON kontrola stavu
156
167
 
@@ -241,6 +252,64 @@ Vsechny konektory dedi z abstraktni tridy `IBankConnector`, ktera poskytuje spol
241
252
  | Mock | `MOCK` | Vsechny typy | Testovaci, automaticky dokoncuje platby |
242
253
  | Mock COBS | `MOCK_COBS` | Vsechny typy | Testovaci COBS konektor |
243
254
 
255
+ ### Podporovane sluzby dle bank (Finbricks, CZ)
256
+
257
+ > Data ze sandbox prostredi Finbricks (`/status/bankInfo`). Aktualizovano: 2026-02-23.
258
+
259
+ #### Platby
260
+
261
+ | Banka | Provider | Domestic | SEPA | Foreign | Batch | Recurring | Pairing | Settled |
262
+ |-------|----------|:--------:|:----:|:-------:|:-----:|:---------:|:-------:|:-------:|
263
+ | MONETA Money Bank | `MONETA` | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
264
+ | Mock Cobs banka | `MOCK_COBS` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
265
+ | Air Bank | `AIRBANK` | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
266
+ | J&T Banka | `JTB` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
267
+ | mBank | `MBANK` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
268
+ | Raiffeisen | `RAIFFEISEN` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
269
+ | Fio banka | `FIO` | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
270
+ | CSOB | `CSOB` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
271
+ | Komercni banka | `KB` | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ |
272
+ | UniCredit | `UNICREDIT` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
273
+ | Ceska sporitelna | `CSAS` | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
274
+ | Partners Banka | `PARTNERS` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
275
+ | Banka CREDITAS | `CREDITAS` | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
276
+
277
+ #### Ucty (informace)
278
+
279
+ | Banka | Provider | Info | Zustatek | Transakce |
280
+ |-------|----------|:----:|:--------:|:---------:|
281
+ | MONETA Money Bank | `MONETA` | ✅ | ✅ | ✅ |
282
+ | Mock Cobs banka | `MOCK_COBS` | ✅ | ✅ | ✅ |
283
+ | Air Bank | `AIRBANK` | ✅ | ✅ | ✅ |
284
+ | J&T Banka | `JTB` | ✅ | ✅ | ✅ |
285
+ | mBank | `MBANK` | ✅ | ✅ | ✅ |
286
+ | Raiffeisen | `RAIFFEISEN` | ✅ | ✅ | ✅ |
287
+ | Fio banka | `FIO` | ✅ | ✅ | ✅ |
288
+ | CSOB | `CSOB` | ✅ | ✅ | ✅ |
289
+ | Komercni banka | `KB` | ✅ | ✅ | ✅ |
290
+ | UniCredit | `UNICREDIT` | ✅ | ✅ | ✅ |
291
+ | Ceska sporitelna | `CSAS` | ✅ | ✅ | ✅ |
292
+ | Partners Banka | `PARTNERS` | ✅ | ✅ | ✅ |
293
+ | Banka CREDITAS | `CREDITAS` | ✅ | ✅ | ✅ |
294
+
295
+ #### Instant platby
296
+
297
+ | Banka | Provider | Domestic Creditor | Domestic Debtor | SEPA Creditor | SEPA Debtor |
298
+ |-------|----------|:-----------------:|:---------------:|:-------------:|:-----------:|
299
+ | MONETA Money Bank | `MONETA` | ✅ | ✅ | ❌ | ❌ |
300
+ | Mock Cobs banka | `MOCK_COBS` | ✅ | ✅ | ✅ | ❌ |
301
+ | Air Bank | `AIRBANK` | ✅ | ✅ | ✅ | ✅ |
302
+ | J&T Banka | `JTB` | ✅ | ✅ | ✅ | ✅ |
303
+ | mBank | `MBANK` | ✅ | ✅ | ❌ | ❌ |
304
+ | Raiffeisen | `RAIFFEISEN` | ✅ | ✅ | ❌ | ❌ |
305
+ | Fio banka | `FIO` | ✅ | ✅ | ❌ | ✅ |
306
+ | CSOB | `CSOB` | ✅ | ✅ | ❌ | ❌ |
307
+ | Komercni banka | `KB` | ✅ | ✅ | ❌ | ❌ |
308
+ | UniCredit | `UNICREDIT` | ✅ | ✅ | ❌ | ❌ |
309
+ | Ceska sporitelna | `CSAS` | ✅ | ✅ | ❌ | ❌ |
310
+ | Partners Banka | `PARTNERS` | ✅ | ✅ | ❌ | ❌ |
311
+ | Banka CREDITAS | `CREDITAS` | ✅ | ✅ | ❌ | ❌ |
312
+
244
313
  ### Metody konektoru
245
314
 
246
315
  Kazdy konektor implementuje nasledujici metody (nebo vraci `Not implemented`):
@@ -319,6 +388,7 @@ Bank service je **RPC worker** - nema vlastni verejne HTTP endpointy. Vsechny ak
319
388
  | `send-payment` | Odesle platbu (vlozi do fronty pro batchovani) |
320
389
  | `send-payment-sync` | Odesle platbu synchronne primo do banky, vrati `authorizationUrl` (bez queue/batch/DB) |
321
390
  | `get-payments` | Seznam plateb s paginaci a filtry (ucet, castka, mena, smer, datum, stav) |
391
+ | `handle-authorization-callback` | Zpracuje callback po autorizaci platby/batche (aktualizuje singlePayment + batch status) |
322
392
  | `simulate-deposit` | Testovaci: vytvori prichozi platbu ve stavu COMPLETED |
323
393
 
324
394
  ### Batch operace
@@ -374,11 +444,17 @@ Klicove sloupce: `correlationId`, `refId`, `bankRefId`, `amount`, `currency`, `d
374
444
 
375
445
  Unikatni omezeni: `(connectorKey, bankRefId)`.
376
446
 
447
+ ### payment_request
448
+
449
+ Odchozi platby v prubehu zpracovani (in-flight). Kazda platba v batchi ma vlastni radek se stavem.
450
+
451
+ Klicove sloupce: `batchId`, `status`, `bankRefId`, `amount`, `currency`, `paymentType`, `creditorIban`, `debtorIban`, `accountId`, `connectorKey`, `authorizationUrl`, `initiatedAt`, `processedAt`, `statusReason`.
452
+
377
453
  ### batch
378
454
 
379
- Batch plateb s JSON polem plateb a stavovymi informacemi.
455
+ Batch plateb se stavovymi informacemi. Platby jsou v tabulce `payment_request` (vazba pres `batchId`).
380
456
 
381
- Klicove sloupce: `status`, `payments` (JSON), `authorizationUrl`, `signHash`, `signId`, `sizeLimit`, `accountId`.
457
+ Klicove sloupce: `status`, `authorizationUrls`, `paymentsChecksum`, `metadata`, `sizeLimit`, `accountId`, `paymentType`.
382
458
 
383
459
  ### account
384
460
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const payment_schema = require('../shared/bank.IVhZ_RlH.cjs');
3
+ const paymentRequest_schema = require('../shared/bank.SQ4Mmr8u.cjs');
4
4
  require('@develit-io/backend-sdk');
5
5
  require('drizzle-orm/relations');
6
6
  require('drizzle-orm/sqlite-core');
@@ -13,9 +13,11 @@ require('drizzle-zod');
13
13
 
14
14
 
15
15
 
16
- exports.account = payment_schema.account;
17
- exports.accountCredentials = payment_schema.accountCredentials;
18
- exports.batch = payment_schema.batch;
19
- exports.ott = payment_schema.ott;
20
- exports.payment = payment_schema.payment;
21
- exports.paymentRelations = payment_schema.paymentRelations;
16
+ exports.account = paymentRequest_schema.account;
17
+ exports.accountCredentials = paymentRequest_schema.accountCredentials;
18
+ exports.batch = paymentRequest_schema.batch;
19
+ exports.ott = paymentRequest_schema.ott;
20
+ exports.payment = paymentRequest_schema.payment;
21
+ exports.paymentRelations = paymentRequest_schema.paymentRelations;
22
+ exports.paymentRequest = paymentRequest_schema.paymentRequest;
23
+ exports.paymentRequestRelations = paymentRequest_schema.paymentRequestRelations;
@@ -1,4 +1,4 @@
1
- export { aq as account, ar as accountCredentials, as as batch, at as ott, au as payment, av as paymentRelations } from '../shared/bank.BJ7LqYtJ.cjs';
1
+ export { as as account, at as accountCredentials, au as batch, av as ott, aw as payment, ax as paymentRelations, ay as paymentRequest, az as paymentRequestRelations } from '../shared/bank.BaMRCHk-.cjs';
2
2
  import 'drizzle-orm/sqlite-core';
3
3
  import 'drizzle-orm';
4
4
  import '@develit-io/backend-sdk';
@@ -1,4 +1,4 @@
1
- export { aq as account, ar as accountCredentials, as as batch, at as ott, au as payment, av as paymentRelations } from '../shared/bank.BJ7LqYtJ.mjs';
1
+ export { as as account, at as accountCredentials, au as batch, av as ott, aw as payment, ax as paymentRelations, ay as paymentRequest, az as paymentRequestRelations } from '../shared/bank.BaMRCHk-.mjs';
2
2
  import 'drizzle-orm/sqlite-core';
3
3
  import 'drizzle-orm';
4
4
  import '@develit-io/backend-sdk';
@@ -1,4 +1,4 @@
1
- export { aq as account, ar as accountCredentials, as as batch, at as ott, au as payment, av as paymentRelations } from '../shared/bank.BJ7LqYtJ.js';
1
+ export { as as account, at as accountCredentials, au as batch, av as ott, aw as payment, ax as paymentRelations, ay as paymentRequest, az as paymentRequestRelations } from '../shared/bank.BaMRCHk-.js';
2
2
  import 'drizzle-orm/sqlite-core';
3
3
  import 'drizzle-orm';
4
4
  import '@develit-io/backend-sdk';
@@ -1,4 +1,4 @@
1
- export { n as account, p as accountCredentials, q as batch, r as ott, s as payment, t as paymentRelations } from '../shared/bank.993UA65l.mjs';
1
+ export { n as account, p as accountCredentials, q as batch, r as ott, s as payment, t as paymentRelations, u as paymentRequest, v as paymentRequestRelations } from '../shared/bank.C4VOdIx1.mjs';
2
2
  import '@develit-io/backend-sdk';
3
3
  import 'drizzle-orm/relations';
4
4
  import 'drizzle-orm/sqlite-core';
@@ -1,18 +1,18 @@
1
1
  'use strict';
2
2
 
3
3
  const backendSdk = require('@develit-io/backend-sdk');
4
- const drizzle = require('../shared/bank.Bs7mkXbR.cjs');
4
+ const drizzle = require('../shared/bank.BOnP9p9Y.cjs');
5
5
  const cloudflare_workers = require('cloudflare:workers');
6
6
  const d1 = require('drizzle-orm/d1');
7
+ const mock_connector = require('../shared/bank.CQURey1E.cjs');
8
+ require('jose');
7
9
  const zod = require('zod');
8
- const payment_schema = require('../shared/bank.IVhZ_RlH.cjs');
10
+ const paymentRequest_schema = require('../shared/bank.SQ4Mmr8u.cjs');
9
11
  const generalCodes = require('@develit-io/general-codes');
10
12
  require('date-fns');
11
- require('jose');
12
13
  const drizzleOrm = require('drizzle-orm');
13
14
  require('node:crypto');
14
- const mock_connector = require('../shared/bank.Ce-NBBw1.cjs');
15
- require('../shared/bank.Cp0yvOdq.cjs');
15
+ require('../shared/bank.C-T1FQxg.cjs');
16
16
  require('drizzle-orm/relations');
17
17
  require('drizzle-orm/sqlite-core');
18
18
  require('drizzle-zod');
@@ -94,6 +94,16 @@ const deletePaymentsByAccountCommand = (db, { accountId }) => {
94
94
  };
95
95
  };
96
96
 
97
+ const createPaymentRequestCommand = (db, { paymentRequest }) => {
98
+ return {
99
+ command: db.insert(drizzle.tables.paymentRequest).values({
100
+ ...paymentRequest,
101
+ creditorIban: paymentRequest.creditor.iban,
102
+ debtorIban: paymentRequest.debtor.iban
103
+ }).returning()
104
+ };
105
+ };
106
+
97
107
  const getAccountBatchCountsQuery = async (db, { accountId }) => {
98
108
  const result = await db.select({
99
109
  totalCount: drizzleOrm.sql`COUNT(*)`.as("totalCount"),
@@ -144,7 +154,7 @@ const getAllAccountsQuery = async (db, filters) => {
144
154
  };
145
155
 
146
156
  const getAllPendingBatchesQuery = (db) => {
147
- return db.select().from(drizzle.tables.batch).where(drizzleOrm.inArray(drizzle.tables.batch.status, ["READY_TO_SIGN"]));
157
+ return db.select().from(drizzle.tables.batch).where(drizzleOrm.inArray(drizzle.tables.batch.status, ["READY_TO_SIGN", "SIGNED"]));
148
158
  };
149
159
 
150
160
  const buildMultiFilterConditions = (column, value) => {
@@ -229,8 +239,18 @@ const getBatchesQuery = async (db, {
229
239
  totalCount: drizzleOrm.sql`count(*)`
230
240
  }).from(drizzle.tables.batch).where(whereConditions);
231
241
  const batches = await db.select().from(drizzle.tables.batch).where(whereConditions).limit(limit).offset((page - 1) * limit).orderBy(sort.direction === "asc" ? drizzleOrm.asc(sortColumn) : drizzleOrm.desc(sortColumn));
242
+ const batchIds = batches.map((b) => b.id);
243
+ const paymentRequests = batchIds.length > 0 ? await db.select().from(drizzle.tables.paymentRequest).where(drizzleOrm.inArray(drizzle.tables.paymentRequest.batchId, batchIds)) : [];
244
+ const paymentRequestsByBatchId = Map.groupBy(
245
+ paymentRequests,
246
+ (pr) => pr.batchId
247
+ );
248
+ const batchesWithPaymentRequests = batches.map((batch) => ({
249
+ ...batch,
250
+ paymentRequests: paymentRequestsByBatchId.get(batch.id) ?? []
251
+ }));
232
252
  return {
233
- batches,
253
+ batches: batchesWithPaymentRequests,
234
254
  totalCount
235
255
  };
236
256
  };
@@ -249,6 +269,11 @@ const getOttQuery = async (db, { ott }) => {
249
269
  return await db.select().from(drizzle.tables.ott).where(drizzleOrm.eq(drizzle.tables.ott.oneTimeToken, ott)).get();
250
270
  };
251
271
 
272
+ const getPaymentRequestByIdQuery = async (db, { paymentId }) => {
273
+ const results = await db.select().from(drizzle.tables.paymentRequest).where(drizzleOrm.eq(drizzle.tables.paymentRequest.id, paymentId)).limit(1);
274
+ return results[0] ?? null;
275
+ };
276
+
252
277
  const seperateSupportedPayments = (incomingPayments, accounts) => {
253
278
  const [supportedPayments, unsupportedPayments] = incomingPayments.reduce(
254
279
  ([valid, invalid], payment) => {
@@ -274,10 +299,10 @@ const sendPaymentInputSchema = zod.z.object({
274
299
  correlationId: zod.z.string().min(1),
275
300
  refId: zod.z.string().optional(),
276
301
  amount: zod.z.number().positive(),
277
- paymentType: zod.z.enum(payment_schema.PAYMENT_TYPES),
278
- chargeBearer: zod.z.enum(payment_schema.CHARGE_BEARERS).optional(),
302
+ paymentType: zod.z.enum(paymentRequest_schema.PAYMENT_TYPES),
303
+ chargeBearer: zod.z.enum(paymentRequest_schema.CHARGE_BEARERS).optional(),
279
304
  executionDate: zod.z.string().optional(),
280
- instructionPriority: zod.z.enum(payment_schema.INSTRUCTION_PRIORITIES).optional(),
305
+ instructionPriority: zod.z.enum(paymentRequest_schema.INSTRUCTION_PRIORITIES).optional(),
281
306
  currency: zod.z.enum(generalCodes.CURRENCY_CODES),
282
307
  vs: zod.z.string().optional(),
283
308
  ss: zod.z.string().optional(),
@@ -290,7 +315,7 @@ const sendPaymentInputSchema = zod.z.object({
290
315
  });
291
316
 
292
317
  const getAuthUriInputSchema = zod.z.object({
293
- connectorKey: zod.z.enum(payment_schema.CONNECTOR_KEYS)
318
+ connectorKey: zod.z.enum(paymentRequest_schema.CONNECTOR_KEYS)
294
319
  });
295
320
 
296
321
  const authorizeAccountInputSchema = zod.z.object({
@@ -311,7 +336,7 @@ const simulateDepositInputSchema = zod.z.object({
311
336
  message: zod.z.string(),
312
337
  creditor: backendSdk.bankAccountMetadataSchema,
313
338
  debtor: backendSdk.bankAccountMetadataSchema,
314
- connectorKey: zod.z.enum(payment_schema.CONNECTOR_KEYS)
339
+ connectorKey: zod.z.enum(paymentRequest_schema.CONNECTOR_KEYS)
315
340
  });
316
341
 
317
342
  const ALLOWED_BATCH_FILTERS = {
@@ -326,7 +351,7 @@ const getBatchesInputSchema = zod.z.object({
326
351
  direction: zod.z.enum(["asc", "desc"])
327
352
  }),
328
353
  [ALLOWED_BATCH_FILTERS.ACCOUNT_ID]: zod.z.union([zod.z.uuid(), zod.z.uuid().array()]).optional(),
329
- [ALLOWED_BATCH_FILTERS.STATUS]: zod.z.union([zod.z.enum(payment_schema.BATCH_STATUSES), zod.z.enum(payment_schema.BATCH_STATUSES).array()]).optional()
354
+ [ALLOWED_BATCH_FILTERS.STATUS]: zod.z.union([zod.z.enum(paymentRequest_schema.BATCH_STATUSES), zod.z.enum(paymentRequest_schema.BATCH_STATUSES).array()]).optional()
330
355
  });
331
356
 
332
357
  const processBatchInputSchema = zod.z.object({
@@ -381,10 +406,10 @@ const getPaymentsInputSchema = zod.z.object({
381
406
  [ALLOWED_PAYMENT_FILTERS.ACCOUNT_ID]: zod.z.union([zod.z.uuid(), zod.z.uuid().array()]).optional(),
382
407
  [ALLOWED_PAYMENT_FILTERS.AMOUNT]: zod.z.union([zod.z.number(), zod.z.number().array()]).optional(),
383
408
  [ALLOWED_PAYMENT_FILTERS.CURRENCY]: zod.z.union([zod.z.enum(generalCodes.CURRENCY_CODES), zod.z.enum(generalCodes.CURRENCY_CODES).array()]).optional(),
384
- [ALLOWED_PAYMENT_FILTERS.DIRECTION]: zod.z.union([zod.z.enum(payment_schema.PAYMENT_DIRECTIONS), zod.z.enum(payment_schema.PAYMENT_DIRECTIONS).array()]).optional(),
409
+ [ALLOWED_PAYMENT_FILTERS.DIRECTION]: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_DIRECTIONS), zod.z.enum(paymentRequest_schema.PAYMENT_DIRECTIONS).array()]).optional(),
385
410
  [ALLOWED_PAYMENT_FILTERS.FROM]: zod.z.date().optional(),
386
411
  [ALLOWED_PAYMENT_FILTERS.TO]: zod.z.date().optional(),
387
- [ALLOWED_PAYMENT_FILTERS.STATUS]: zod.z.union([zod.z.enum(payment_schema.PAYMENT_STATUSES), zod.z.enum(payment_schema.PAYMENT_STATUSES).array()]).optional()
412
+ [ALLOWED_PAYMENT_FILTERS.STATUS]: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES), zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES).array()]).optional()
388
413
  });
389
414
 
390
415
  const syncAccountInputSchema = zod.z.object({
@@ -419,7 +444,7 @@ zod.z.object({
419
444
  });
420
445
 
421
446
  const updateAccountInputSchema = zod.z.object({
422
- account: payment_schema.accountInsertSchema
447
+ account: paymentRequest_schema.accountInsertSchema
423
448
  });
424
449
 
425
450
  const getBankAccountsInputSchema = zod.z.object({
@@ -434,6 +459,13 @@ const disconnectAccountInputSchema = zod.z.object({
434
459
  accountId: zod.z.uuid()
435
460
  });
436
461
 
462
+ const handleAuthorizationCallbackInputSchema = zod.z.object({
463
+ paymentId: zod.z.string().uuid().optional(),
464
+ batchId: zod.z.string().uuid().optional()
465
+ }).refine((data) => data.paymentId || data.batchId, {
466
+ message: "Either paymentId or batchId is required"
467
+ });
468
+
437
469
  const sendPaymentSyncInputSchema = sendPaymentInputSchema;
438
470
 
439
471
  var __defProp = Object.defineProperty;
@@ -593,12 +625,45 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
593
625
  }).command.execute();
594
626
  statusChanged = true;
595
627
  }
628
+ if (statusChanged) {
629
+ const paymentRequests = await drizzle.getPaymentRequestsByBatchIdQuery(this.db, {
630
+ batchId: batch.id
631
+ });
632
+ const perPaymentStatuses = "payments" in apiResponse ? apiResponse.payments : null;
633
+ const batchStatusToPaymentStatus = {
634
+ SIGNED: "SIGNED",
635
+ COMPLETED: "COMPLETED",
636
+ FAILED: "FAILED",
637
+ SIGNATURE_FAILED: "FAILED"
638
+ };
639
+ for (const pr of paymentRequests) {
640
+ let newStatus = pr.status;
641
+ if (perPaymentStatuses) {
642
+ const match = perPaymentStatuses.find(
643
+ (p) => p.merchantTransactionId === pr.id
644
+ );
645
+ if (match) {
646
+ newStatus = mock_connector.mapFinbricksTransactionStatus(
647
+ match.resultCode
648
+ );
649
+ }
650
+ } else {
651
+ newStatus = batchStatusToPaymentStatus[currentStatus] ?? pr.status;
652
+ }
653
+ if (newStatus !== pr.status) {
654
+ await drizzle.updatePaymentRequestStatusCommand(this.db, {
655
+ id: pr.id,
656
+ status: newStatus,
657
+ processedAt: newStatus === "COMPLETED" || newStatus === "FAILED" ? /* @__PURE__ */ new Date() : void 0
658
+ }).command.execute();
659
+ }
660
+ }
661
+ }
596
662
  return {
597
663
  batchId: batch.id,
598
664
  previousStatus,
599
665
  currentStatus,
600
666
  statusChanged
601
- // eventSent,
602
667
  };
603
668
  }
604
669
  async updateBatchStatuses(input) {
@@ -670,6 +735,77 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
670
735
  }
671
736
  );
672
737
  }
738
+ async handleAuthorizationCallback(input) {
739
+ return this.handleAction(
740
+ { data: input, schema: handleAuthorizationCallbackInputSchema },
741
+ { successMessage: "Authorization callback processed" },
742
+ async ({ paymentId, batchId }) => {
743
+ let targetBatchId = null;
744
+ let paymentsUpdated = 0;
745
+ if (paymentId) {
746
+ const pr = await getPaymentRequestByIdQuery(this.db, { paymentId });
747
+ if (!pr) {
748
+ throw backendSdk.createInternalError(null, {
749
+ message: `Payment request not found: ${paymentId}`,
750
+ code: "DB-B-008",
751
+ status: 404
752
+ });
753
+ }
754
+ if (pr.status !== "SIGNED" && pr.status !== "COMPLETED") {
755
+ await drizzle.updatePaymentRequestStatusCommand(this.db, {
756
+ id: paymentId,
757
+ status: "SIGNED"
758
+ }).command.execute();
759
+ paymentsUpdated = 1;
760
+ }
761
+ targetBatchId = pr.batchId;
762
+ }
763
+ if (batchId) {
764
+ targetBatchId = batchId;
765
+ const batchPayments = await drizzle.getPaymentRequestsByBatchIdQuery(
766
+ this.db,
767
+ {
768
+ batchId
769
+ }
770
+ );
771
+ for (const pr of batchPayments) {
772
+ if (pr.status !== "SIGNED" && pr.status !== "COMPLETED") {
773
+ await drizzle.updatePaymentRequestStatusCommand(this.db, {
774
+ id: pr.id,
775
+ status: "SIGNED"
776
+ }).command.execute();
777
+ paymentsUpdated++;
778
+ }
779
+ }
780
+ }
781
+ let batchSigned = false;
782
+ if (targetBatchId) {
783
+ const allPayments = await drizzle.getPaymentRequestsByBatchIdQuery(this.db, {
784
+ batchId: targetBatchId
785
+ });
786
+ const allDone = allPayments.every(
787
+ (p) => p.status === "SIGNED" || p.status === "COMPLETED"
788
+ );
789
+ if (allDone) {
790
+ const batch = await drizzle.getBatchByIdQuery(this.db, {
791
+ batchId: targetBatchId
792
+ });
793
+ if (batch && batch.status !== "SIGNED") {
794
+ await drizzle.upsertBatchCommand(this.db, {
795
+ batch: { ...batch, status: "SIGNED" }
796
+ }).command.execute();
797
+ batchSigned = true;
798
+ }
799
+ }
800
+ }
801
+ return {
802
+ paymentsUpdated,
803
+ batchId: targetBatchId,
804
+ batchSigned
805
+ };
806
+ }
807
+ );
808
+ }
673
809
  async addPaymentsToBatch({
674
810
  paymentsToBatch
675
811
  }) {
@@ -715,21 +851,24 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
715
851
  (p) => p.sendAsSinglePayment !== true
716
852
  );
717
853
  for (const singlePayment of singlePayments) {
718
- const batchedPayment = mock_connector.toBatchedPayment(singlePayment);
719
- const { command } = drizzle.upsertBatchCommand(this.db, {
854
+ const batchId = backendSdk.uuidv4();
855
+ const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
720
856
  batch: {
721
- id: backendSdk.uuidv4(),
857
+ id: batchId,
722
858
  authorizationUrls: [],
723
859
  accountId: acc.id,
724
860
  paymentType: singlePayment.paymentType,
725
- payments: [batchedPayment],
726
861
  status: "OPEN",
727
- metadata: {
728
- sizeLimit: 1
729
- }
862
+ metadata: { sizeLimit: 1 }
730
863
  }
731
864
  });
732
- await command.execute();
865
+ const { command: insertPaymentRequest } = createPaymentRequestCommand(
866
+ this.db,
867
+ {
868
+ paymentRequest: mock_connector.toPaymentRequestInsert(singlePayment, batchId)
869
+ }
870
+ );
871
+ await this.db.batch([upsertBatch, insertPaymentRequest]);
733
872
  this.log({
734
873
  message: `\u2728 Created single payment batch (${singlePayment.paymentType}) for account ${acc.id}`
735
874
  });
@@ -744,30 +883,48 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
744
883
  accountId: acc.id,
745
884
  paymentType
746
885
  });
747
- const availableBatch = openBatches.find(
748
- (batch) => batch.payments.length < (batch.metadata?.sizeLimit ?? acc.batchSizeLimit)
749
- );
750
- this.log({
751
- message: availableBatch ? `\u{1F504} Found existing OPEN batch (${paymentType}) for account ${acc.id}, merging ${availableBatch.payments.length} existing + ${paymentsOfType.length} new payments` : `\u2728 Creating new batch (${paymentType}) for account ${acc.id} with ${paymentsOfType.length} payments`
752
- });
753
- const batchedPayments = paymentsOfType.map(mock_connector.toBatchedPayment);
754
- const { command } = drizzle.upsertBatchCommand(this.db, {
755
- batch: availableBatch ? {
756
- ...availableBatch,
757
- payments: [...availableBatch.payments, ...batchedPayments]
758
- } : {
759
- id: backendSdk.uuidv4(),
886
+ let batchId;
887
+ let availableCount = 0;
888
+ let availableBatch;
889
+ for (const ob of openBatches) {
890
+ const existingPayments = await drizzle.getPaymentRequestsByBatchIdQuery(
891
+ this.db,
892
+ { batchId: ob.id }
893
+ );
894
+ const limit = ob.metadata?.sizeLimit ?? acc.batchSizeLimit;
895
+ if (existingPayments.length < limit) {
896
+ availableBatch = ob;
897
+ availableCount = existingPayments.length;
898
+ break;
899
+ }
900
+ }
901
+ if (availableBatch) {
902
+ batchId = availableBatch.id;
903
+ this.log({
904
+ message: `\u{1F504} Found existing OPEN batch (${paymentType}) for account ${acc.id}, merging ${availableCount} existing + ${paymentsOfType.length} new payments`
905
+ });
906
+ } else {
907
+ batchId = backendSdk.uuidv4();
908
+ this.log({
909
+ message: `\u2728 Creating new batch (${paymentType}) for account ${acc.id} with ${paymentsOfType.length} payments`
910
+ });
911
+ }
912
+ const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
913
+ batch: availableBatch ? { ...availableBatch } : {
914
+ id: batchId,
760
915
  authorizationUrls: [],
761
916
  accountId: acc.id,
762
917
  paymentType,
763
- payments: batchedPayments,
764
918
  status: "OPEN",
765
- metadata: {
766
- sizeLimit: acc.batchSizeLimit
767
- }
919
+ metadata: { sizeLimit: acc.batchSizeLimit }
768
920
  }
769
921
  });
770
- await command.execute();
922
+ const paymentRequestCommands = paymentsOfType.map(
923
+ (p) => createPaymentRequestCommand(this.db, {
924
+ paymentRequest: mock_connector.toPaymentRequestInsert(p, batchId)
925
+ }).command
926
+ );
927
+ await this.db.batch([upsertBatch, ...paymentRequestCommands]);
771
928
  this.log({
772
929
  message: `\u2705 Batch (${paymentType}) upserted successfully for account ${acc.id}`
773
930
  });
@@ -1256,6 +1413,24 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1256
1413
  }
1257
1414
  );
1258
1415
  }
1416
+ async getFinbricksSupportedBanks() {
1417
+ const privateKeyPem = (await this.env.SECRETS_STORE.get({
1418
+ secretName: "BANK_SERVICE_FINBRICKS_PRIVATE_KEY_PEM"
1419
+ })).data?.secretValue || "";
1420
+ const client = new mock_connector.FinbricksClient(
1421
+ this.env.FINBRICKS_BASE_URI,
1422
+ this.env.FINBRICKS_MERCHANT_ID,
1423
+ privateKeyPem,
1424
+ this.env.REDIRECT_URI
1425
+ );
1426
+ return client.request({
1427
+ endpoint: mock_connector.FINBRICKS_ENDPOINTS.BANK_INFO,
1428
+ method: "GET",
1429
+ query: {
1430
+ merchantId: this.env.FINBRICKS_MERCHANT_ID
1431
+ }
1432
+ });
1433
+ }
1259
1434
  };
1260
1435
  __decorateClass([
1261
1436
  backendSdk.action("get-payments")
@@ -1272,6 +1447,9 @@ __decorateClass([
1272
1447
  __decorateClass([
1273
1448
  backendSdk.action("update-batch-statuses")
1274
1449
  ], BankServiceBase.prototype, "updateBatchStatuses", 1);
1450
+ __decorateClass([
1451
+ backendSdk.action("handle-authorization-callback")
1452
+ ], BankServiceBase.prototype, "handleAuthorizationCallback", 1);
1275
1453
  __decorateClass([
1276
1454
  backendSdk.action("add-payments-to-batch")
1277
1455
  ], BankServiceBase.prototype, "addPaymentsToBatch", 1);