@develit-services/bank 0.8.2 → 0.8.3

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 +210 -42
  8. package/dist/export/worker.d.cts +23 -8
  9. package/dist/export/worker.d.mts +23 -8
  10. package/dist/export/worker.d.ts +23 -8
  11. package/dist/export/worker.mjs +201 -33
  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.cts → bank.BE9bK1n7.d.mts} +211 -1
  18. package/dist/shared/{bank.Bs7mkXbR.cjs → bank.BOnP9p9Y.cjs} +15 -2
  19. package/dist/shared/bank.C-T1FQxg.cjs +17 -0
  20. package/dist/shared/{bank.993UA65l.mjs → bank.C4VOdIx1.mjs} +57 -5
  21. package/dist/shared/{bank.BC06Rbrx.d.cts → bank.CQBfbG8u.d.cts} +0 -1
  22. package/dist/shared/{bank.BC06Rbrx.d.mts → bank.CQBfbG8u.d.mts} +0 -1
  23. package/dist/shared/{bank.BC06Rbrx.d.ts → bank.CQBfbG8u.d.ts} +0 -1
  24. package/dist/shared/{bank.Ce-NBBw1.cjs → bank.CQURey1E.cjs} +64 -7
  25. package/dist/shared/{bank.CGIeLo8U.mjs → bank.Cpy9PULF.mjs} +14 -3
  26. package/dist/shared/bank.DDHrdFgy.mjs +15 -0
  27. package/dist/shared/{bank.BJ7LqYtJ.d.cts → bank.DDveEfub.d.cts} +707 -126
  28. package/dist/shared/{bank.BJ7LqYtJ.d.mts → bank.DDveEfub.d.mts} +707 -126
  29. package/dist/shared/{bank.BJ7LqYtJ.d.ts → bank.DDveEfub.d.ts} +707 -126
  30. package/dist/shared/{bank.CeRbuycV.mjs → bank.DRrBrAdI.mjs} +62 -8
  31. package/dist/shared/{bank.IVhZ_RlH.cjs → bank.SQ4Mmr8u.cjs} +57 -3
  32. package/dist/shared/{bank.Du70-Kk_.d.mts → bank.gl4dlxWy.d.cts} +211 -1
  33. package/dist/shared/{bank.Du70-Kk_.d.ts → bank.pngKIcOl.d.ts} +211 -1
  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.DDveEfub.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.DDveEfub.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.DDveEfub.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) => {
@@ -249,6 +259,11 @@ const getOttQuery = async (db, { ott }) => {
249
259
  return await db.select().from(drizzle.tables.ott).where(drizzleOrm.eq(drizzle.tables.ott.oneTimeToken, ott)).get();
250
260
  };
251
261
 
262
+ const getPaymentRequestByIdQuery = async (db, { paymentId }) => {
263
+ const results = await db.select().from(drizzle.tables.paymentRequest).where(drizzleOrm.eq(drizzle.tables.paymentRequest.id, paymentId)).limit(1);
264
+ return results[0] ?? null;
265
+ };
266
+
252
267
  const seperateSupportedPayments = (incomingPayments, accounts) => {
253
268
  const [supportedPayments, unsupportedPayments] = incomingPayments.reduce(
254
269
  ([valid, invalid], payment) => {
@@ -274,10 +289,10 @@ const sendPaymentInputSchema = zod.z.object({
274
289
  correlationId: zod.z.string().min(1),
275
290
  refId: zod.z.string().optional(),
276
291
  amount: zod.z.number().positive(),
277
- paymentType: zod.z.enum(payment_schema.PAYMENT_TYPES),
278
- chargeBearer: zod.z.enum(payment_schema.CHARGE_BEARERS).optional(),
292
+ paymentType: zod.z.enum(paymentRequest_schema.PAYMENT_TYPES),
293
+ chargeBearer: zod.z.enum(paymentRequest_schema.CHARGE_BEARERS).optional(),
279
294
  executionDate: zod.z.string().optional(),
280
- instructionPriority: zod.z.enum(payment_schema.INSTRUCTION_PRIORITIES).optional(),
295
+ instructionPriority: zod.z.enum(paymentRequest_schema.INSTRUCTION_PRIORITIES).optional(),
281
296
  currency: zod.z.enum(generalCodes.CURRENCY_CODES),
282
297
  vs: zod.z.string().optional(),
283
298
  ss: zod.z.string().optional(),
@@ -290,7 +305,7 @@ const sendPaymentInputSchema = zod.z.object({
290
305
  });
291
306
 
292
307
  const getAuthUriInputSchema = zod.z.object({
293
- connectorKey: zod.z.enum(payment_schema.CONNECTOR_KEYS)
308
+ connectorKey: zod.z.enum(paymentRequest_schema.CONNECTOR_KEYS)
294
309
  });
295
310
 
296
311
  const authorizeAccountInputSchema = zod.z.object({
@@ -311,7 +326,7 @@ const simulateDepositInputSchema = zod.z.object({
311
326
  message: zod.z.string(),
312
327
  creditor: backendSdk.bankAccountMetadataSchema,
313
328
  debtor: backendSdk.bankAccountMetadataSchema,
314
- connectorKey: zod.z.enum(payment_schema.CONNECTOR_KEYS)
329
+ connectorKey: zod.z.enum(paymentRequest_schema.CONNECTOR_KEYS)
315
330
  });
316
331
 
317
332
  const ALLOWED_BATCH_FILTERS = {
@@ -326,7 +341,7 @@ const getBatchesInputSchema = zod.z.object({
326
341
  direction: zod.z.enum(["asc", "desc"])
327
342
  }),
328
343
  [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()
344
+ [ALLOWED_BATCH_FILTERS.STATUS]: zod.z.union([zod.z.enum(paymentRequest_schema.BATCH_STATUSES), zod.z.enum(paymentRequest_schema.BATCH_STATUSES).array()]).optional()
330
345
  });
331
346
 
332
347
  const processBatchInputSchema = zod.z.object({
@@ -381,10 +396,10 @@ const getPaymentsInputSchema = zod.z.object({
381
396
  [ALLOWED_PAYMENT_FILTERS.ACCOUNT_ID]: zod.z.union([zod.z.uuid(), zod.z.uuid().array()]).optional(),
382
397
  [ALLOWED_PAYMENT_FILTERS.AMOUNT]: zod.z.union([zod.z.number(), zod.z.number().array()]).optional(),
383
398
  [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(),
399
+ [ALLOWED_PAYMENT_FILTERS.DIRECTION]: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_DIRECTIONS), zod.z.enum(paymentRequest_schema.PAYMENT_DIRECTIONS).array()]).optional(),
385
400
  [ALLOWED_PAYMENT_FILTERS.FROM]: zod.z.date().optional(),
386
401
  [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()
402
+ [ALLOWED_PAYMENT_FILTERS.STATUS]: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES), zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES).array()]).optional()
388
403
  });
389
404
 
390
405
  const syncAccountInputSchema = zod.z.object({
@@ -419,7 +434,7 @@ zod.z.object({
419
434
  });
420
435
 
421
436
  const updateAccountInputSchema = zod.z.object({
422
- account: payment_schema.accountInsertSchema
437
+ account: paymentRequest_schema.accountInsertSchema
423
438
  });
424
439
 
425
440
  const getBankAccountsInputSchema = zod.z.object({
@@ -434,6 +449,13 @@ const disconnectAccountInputSchema = zod.z.object({
434
449
  accountId: zod.z.uuid()
435
450
  });
436
451
 
452
+ const handleAuthorizationCallbackInputSchema = zod.z.object({
453
+ paymentId: zod.z.string().uuid().optional(),
454
+ batchId: zod.z.string().uuid().optional()
455
+ }).refine((data) => data.paymentId || data.batchId, {
456
+ message: "Either paymentId or batchId is required"
457
+ });
458
+
437
459
  const sendPaymentSyncInputSchema = sendPaymentInputSchema;
438
460
 
439
461
  var __defProp = Object.defineProperty;
@@ -593,12 +615,45 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
593
615
  }).command.execute();
594
616
  statusChanged = true;
595
617
  }
618
+ if (statusChanged) {
619
+ const paymentRequests = await drizzle.getPaymentRequestsByBatchIdQuery(this.db, {
620
+ batchId: batch.id
621
+ });
622
+ const perPaymentStatuses = "payments" in apiResponse ? apiResponse.payments : null;
623
+ const batchStatusToPaymentStatus = {
624
+ SIGNED: "SIGNED",
625
+ COMPLETED: "COMPLETED",
626
+ FAILED: "FAILED",
627
+ SIGNATURE_FAILED: "FAILED"
628
+ };
629
+ for (const pr of paymentRequests) {
630
+ let newStatus = pr.status;
631
+ if (perPaymentStatuses) {
632
+ const match = perPaymentStatuses.find(
633
+ (p) => p.merchantTransactionId === pr.id
634
+ );
635
+ if (match) {
636
+ newStatus = mock_connector.mapFinbricksTransactionStatus(
637
+ match.resultCode
638
+ );
639
+ }
640
+ } else {
641
+ newStatus = batchStatusToPaymentStatus[currentStatus] ?? pr.status;
642
+ }
643
+ if (newStatus !== pr.status) {
644
+ await drizzle.updatePaymentRequestStatusCommand(this.db, {
645
+ id: pr.id,
646
+ status: newStatus,
647
+ processedAt: newStatus === "COMPLETED" || newStatus === "FAILED" ? /* @__PURE__ */ new Date() : void 0
648
+ }).command.execute();
649
+ }
650
+ }
651
+ }
596
652
  return {
597
653
  batchId: batch.id,
598
654
  previousStatus,
599
655
  currentStatus,
600
656
  statusChanged
601
- // eventSent,
602
657
  };
603
658
  }
604
659
  async updateBatchStatuses(input) {
@@ -670,6 +725,77 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
670
725
  }
671
726
  );
672
727
  }
728
+ async handleAuthorizationCallback(input) {
729
+ return this.handleAction(
730
+ { data: input, schema: handleAuthorizationCallbackInputSchema },
731
+ { successMessage: "Authorization callback processed" },
732
+ async ({ paymentId, batchId }) => {
733
+ let targetBatchId = null;
734
+ let paymentsUpdated = 0;
735
+ if (paymentId) {
736
+ const pr = await getPaymentRequestByIdQuery(this.db, { paymentId });
737
+ if (!pr) {
738
+ throw backendSdk.createInternalError(null, {
739
+ message: `Payment request not found: ${paymentId}`,
740
+ code: "DB-B-008",
741
+ status: 404
742
+ });
743
+ }
744
+ if (pr.status !== "SIGNED" && pr.status !== "COMPLETED") {
745
+ await drizzle.updatePaymentRequestStatusCommand(this.db, {
746
+ id: paymentId,
747
+ status: "SIGNED"
748
+ }).command.execute();
749
+ paymentsUpdated = 1;
750
+ }
751
+ targetBatchId = pr.batchId;
752
+ }
753
+ if (batchId) {
754
+ targetBatchId = batchId;
755
+ const batchPayments = await drizzle.getPaymentRequestsByBatchIdQuery(
756
+ this.db,
757
+ {
758
+ batchId
759
+ }
760
+ );
761
+ for (const pr of batchPayments) {
762
+ if (pr.status !== "SIGNED" && pr.status !== "COMPLETED") {
763
+ await drizzle.updatePaymentRequestStatusCommand(this.db, {
764
+ id: pr.id,
765
+ status: "SIGNED"
766
+ }).command.execute();
767
+ paymentsUpdated++;
768
+ }
769
+ }
770
+ }
771
+ let batchSigned = false;
772
+ if (targetBatchId) {
773
+ const allPayments = await drizzle.getPaymentRequestsByBatchIdQuery(this.db, {
774
+ batchId: targetBatchId
775
+ });
776
+ const allDone = allPayments.every(
777
+ (p) => p.status === "SIGNED" || p.status === "COMPLETED"
778
+ );
779
+ if (allDone) {
780
+ const batch = await drizzle.getBatchByIdQuery(this.db, {
781
+ batchId: targetBatchId
782
+ });
783
+ if (batch && batch.status !== "SIGNED") {
784
+ await drizzle.upsertBatchCommand(this.db, {
785
+ batch: { ...batch, status: "SIGNED" }
786
+ }).command.execute();
787
+ batchSigned = true;
788
+ }
789
+ }
790
+ }
791
+ return {
792
+ paymentsUpdated,
793
+ batchId: targetBatchId,
794
+ batchSigned
795
+ };
796
+ }
797
+ );
798
+ }
673
799
  async addPaymentsToBatch({
674
800
  paymentsToBatch
675
801
  }) {
@@ -715,21 +841,24 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
715
841
  (p) => p.sendAsSinglePayment !== true
716
842
  );
717
843
  for (const singlePayment of singlePayments) {
718
- const batchedPayment = mock_connector.toBatchedPayment(singlePayment);
719
- const { command } = drizzle.upsertBatchCommand(this.db, {
844
+ const batchId = backendSdk.uuidv4();
845
+ const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
720
846
  batch: {
721
- id: backendSdk.uuidv4(),
847
+ id: batchId,
722
848
  authorizationUrls: [],
723
849
  accountId: acc.id,
724
850
  paymentType: singlePayment.paymentType,
725
- payments: [batchedPayment],
726
851
  status: "OPEN",
727
- metadata: {
728
- sizeLimit: 1
729
- }
852
+ metadata: { sizeLimit: 1 }
730
853
  }
731
854
  });
732
- await command.execute();
855
+ const { command: insertPaymentRequest } = createPaymentRequestCommand(
856
+ this.db,
857
+ {
858
+ paymentRequest: mock_connector.toPaymentRequestInsert(singlePayment, batchId)
859
+ }
860
+ );
861
+ await this.db.batch([upsertBatch, insertPaymentRequest]);
733
862
  this.log({
734
863
  message: `\u2728 Created single payment batch (${singlePayment.paymentType}) for account ${acc.id}`
735
864
  });
@@ -744,30 +873,48 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
744
873
  accountId: acc.id,
745
874
  paymentType
746
875
  });
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(),
876
+ let batchId;
877
+ let availableCount = 0;
878
+ let availableBatch;
879
+ for (const ob of openBatches) {
880
+ const existingPayments = await drizzle.getPaymentRequestsByBatchIdQuery(
881
+ this.db,
882
+ { batchId: ob.id }
883
+ );
884
+ const limit = ob.metadata?.sizeLimit ?? acc.batchSizeLimit;
885
+ if (existingPayments.length < limit) {
886
+ availableBatch = ob;
887
+ availableCount = existingPayments.length;
888
+ break;
889
+ }
890
+ }
891
+ if (availableBatch) {
892
+ batchId = availableBatch.id;
893
+ this.log({
894
+ message: `\u{1F504} Found existing OPEN batch (${paymentType}) for account ${acc.id}, merging ${availableCount} existing + ${paymentsOfType.length} new payments`
895
+ });
896
+ } else {
897
+ batchId = backendSdk.uuidv4();
898
+ this.log({
899
+ message: `\u2728 Creating new batch (${paymentType}) for account ${acc.id} with ${paymentsOfType.length} payments`
900
+ });
901
+ }
902
+ const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
903
+ batch: availableBatch ? { ...availableBatch } : {
904
+ id: batchId,
760
905
  authorizationUrls: [],
761
906
  accountId: acc.id,
762
907
  paymentType,
763
- payments: batchedPayments,
764
908
  status: "OPEN",
765
- metadata: {
766
- sizeLimit: acc.batchSizeLimit
767
- }
909
+ metadata: { sizeLimit: acc.batchSizeLimit }
768
910
  }
769
911
  });
770
- await command.execute();
912
+ const paymentRequestCommands = paymentsOfType.map(
913
+ (p) => createPaymentRequestCommand(this.db, {
914
+ paymentRequest: mock_connector.toPaymentRequestInsert(p, batchId)
915
+ }).command
916
+ );
917
+ await this.db.batch([upsertBatch, ...paymentRequestCommands]);
771
918
  this.log({
772
919
  message: `\u2705 Batch (${paymentType}) upserted successfully for account ${acc.id}`
773
920
  });
@@ -1256,6 +1403,24 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1256
1403
  }
1257
1404
  );
1258
1405
  }
1406
+ async getFinbricksSupportedBanks() {
1407
+ const privateKeyPem = (await this.env.SECRETS_STORE.get({
1408
+ secretName: "BANK_SERVICE_FINBRICKS_PRIVATE_KEY_PEM"
1409
+ })).data?.secretValue || "";
1410
+ const client = new mock_connector.FinbricksClient(
1411
+ this.env.FINBRICKS_BASE_URI,
1412
+ this.env.FINBRICKS_MERCHANT_ID,
1413
+ privateKeyPem,
1414
+ this.env.REDIRECT_URI
1415
+ );
1416
+ return client.request({
1417
+ endpoint: mock_connector.FINBRICKS_ENDPOINTS.BANK_INFO,
1418
+ method: "GET",
1419
+ query: {
1420
+ merchantId: this.env.FINBRICKS_MERCHANT_ID
1421
+ }
1422
+ });
1423
+ }
1259
1424
  };
1260
1425
  __decorateClass([
1261
1426
  backendSdk.action("get-payments")
@@ -1272,6 +1437,9 @@ __decorateClass([
1272
1437
  __decorateClass([
1273
1438
  backendSdk.action("update-batch-statuses")
1274
1439
  ], BankServiceBase.prototype, "updateBatchStatuses", 1);
1440
+ __decorateClass([
1441
+ backendSdk.action("handle-authorization-callback")
1442
+ ], BankServiceBase.prototype, "handleAuthorizationCallback", 1);
1275
1443
  __decorateClass([
1276
1444
  backendSdk.action("add-payments-to-batch")
1277
1445
  ], BankServiceBase.prototype, "addPaymentsToBatch", 1);