@develit-services/bank 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +381 -0
- package/dist/database/schema.cjs +1 -1
- package/dist/database/schema.d.cts +1 -1
- package/dist/database/schema.d.mts +1 -1
- package/dist/database/schema.d.ts +1 -1
- package/dist/database/schema.mjs +1 -1
- package/dist/export/worker.cjs +47 -36
- package/dist/export/worker.d.cts +378 -77
- package/dist/export/worker.d.mts +378 -77
- package/dist/export/worker.d.ts +378 -77
- package/dist/export/worker.mjs +47 -36
- package/dist/export/workflows.cjs +24 -9
- package/dist/export/workflows.mjs +24 -9
- package/dist/export/wrangler.cjs +7 -0
- package/dist/export/wrangler.d.cts +7 -1
- package/dist/export/wrangler.d.mts +7 -1
- package/dist/export/wrangler.d.ts +7 -1
- package/dist/export/wrangler.mjs +7 -0
- package/dist/shared/{bank.Coi0lSqK.d.cts → bank.BC06Rbrx.d.cts} +1 -0
- package/dist/shared/{bank.Coi0lSqK.d.mts → bank.BC06Rbrx.d.mts} +1 -0
- package/dist/shared/{bank.Coi0lSqK.d.ts → bank.BC06Rbrx.d.ts} +1 -0
- package/dist/shared/{bank.DLWegh_f.mjs → bank.BnIYdBEF.mjs} +9 -0
- package/dist/shared/bank.C6_7Rch8.d.cts +4755 -0
- package/dist/shared/bank.C6_7Rch8.d.mts +4755 -0
- package/dist/shared/bank.C6_7Rch8.d.ts +4755 -0
- package/dist/shared/{bank.DEvSNsEs.cjs → bank.CTqIXnHg.cjs} +2 -2
- package/dist/shared/{bank.DFIwAQqg.mjs → bank.CTtFAN03.mjs} +1 -1
- package/dist/shared/{bank.Dq27-5wD.mjs → bank.CkUMU1sJ.mjs} +365 -50
- package/dist/shared/{bank.BeIpkWR-.cjs → bank.D7kwLMqF.cjs} +9 -0
- package/dist/shared/{bank.c38V_FCq.cjs → bank.DlW1XNug.cjs} +1 -1
- package/dist/shared/{bank.pd7-Rbo-.mjs → bank.e8T8fQDG.mjs} +2 -2
- package/dist/shared/{bank.DNHA-HFP.cjs → bank.iEgK7rge.cjs} +365 -50
- package/dist/types.cjs +2 -2
- package/dist/types.d.cts +452 -40
- package/dist/types.d.mts +452 -40
- package/dist/types.d.ts +452 -40
- package/dist/types.mjs +2 -2
- package/package.json +1 -1
- package/dist/shared/bank.Vj1x4v-K.d.cts +0 -2515
- package/dist/shared/bank.Vj1x4v-K.d.mts +0 -2515
- package/dist/shared/bank.Vj1x4v-K.d.ts +0 -2515
package/README.md
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# Bank Service
|
|
2
|
+
|
|
3
|
+
Microsluzba pro spravu bankovnich uctu, zpracovani plateb a synchronizaci transakci. Postavena na Cloudflare Workers s D1 databazi.
|
|
4
|
+
|
|
5
|
+
## Obsah
|
|
6
|
+
|
|
7
|
+
- [Architektura](#architektura)
|
|
8
|
+
- [Zivotni cyklus platby](#zivotni-cyklus-platby)
|
|
9
|
+
- [Batch processing](#batch-processing)
|
|
10
|
+
- [Synchronizace uctu](#synchronizace-uctu)
|
|
11
|
+
- [Bankovni konektory](#bankovni-konektory)
|
|
12
|
+
- [RPC akce](#rpc-akce)
|
|
13
|
+
- [Event system](#event-system)
|
|
14
|
+
- [Databazove schema](#databazove-schema)
|
|
15
|
+
|
|
16
|
+
## Architektura
|
|
17
|
+
|
|
18
|
+
Sluzba se sklada z:
|
|
19
|
+
|
|
20
|
+
- **Akce (Actions)** - API endpointy pro spravu uctu, plateb a batchu
|
|
21
|
+
- **Workflows** - Cloudflare Durable Objects pro asynchronni zpracovani (sync uctu, process batch)
|
|
22
|
+
- **Konektory** - Abstrakce nad API jednotlivych bank (Erste, Fio, Moneta, ...)
|
|
23
|
+
- **Queue handlery** - Zpracovani front pro batchovani plateb a CRON ulohy
|
|
24
|
+
|
|
25
|
+
## Zivotni cyklus platby
|
|
26
|
+
|
|
27
|
+
Platba prochazi 5 fazemi s explicitnimi typy:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
SendPaymentInput (API vstup)
|
|
31
|
+
│
|
|
32
|
+
▼
|
|
33
|
+
┌─────────────────────────────────────────────┐
|
|
34
|
+
│ 1. IncomingPayment status: CREATED │
|
|
35
|
+
│ Nova platba z API, zatim bez uctu │
|
|
36
|
+
└──────────────────┬──────────────────────────┘
|
|
37
|
+
│ prirazeni uctu + konektoru
|
|
38
|
+
▼
|
|
39
|
+
┌─────────────────────────────────────────────┐
|
|
40
|
+
│ 2. AccountAssignedPayment status: CREATED │
|
|
41
|
+
│ Platba prirazena k bankovnimu uctu │
|
|
42
|
+
│ a konektoru (accountId, connectorKey) │
|
|
43
|
+
└──────────────────┬──────────────────────────┘
|
|
44
|
+
│ vlozeni do batche
|
|
45
|
+
▼
|
|
46
|
+
┌─────────────────────────────────────────────┐
|
|
47
|
+
│ 3. BatchedPayment status: CREATED │
|
|
48
|
+
│ Platba je soucasti batche, ceka na │
|
|
49
|
+
│ odeslani do banky │
|
|
50
|
+
└──────────────────┬──────────────────────────┘
|
|
51
|
+
│ connector.initiate*Batch()
|
|
52
|
+
▼
|
|
53
|
+
┌─────────────────────────────────────────────┐
|
|
54
|
+
│ 4. PreparedPayment status: PREPARED │
|
|
55
|
+
│ Odeslana do banky, ceka na autorizaci │
|
|
56
|
+
│ (muze jiz mit bankRefId) │
|
|
57
|
+
└──────────────────┬──────────────────────────┘
|
|
58
|
+
│ autorizace + zpracovani bankou
|
|
59
|
+
▼
|
|
60
|
+
┌─────────────────────────────────────────────┐
|
|
61
|
+
│ 5. CompletedPayment status: COMPLETED│
|
|
62
|
+
│ Zpracovana bankou, ma bankRefId │
|
|
63
|
+
│ a processedAt timestamp │
|
|
64
|
+
│ (pripadne FAILED / PENDING) │
|
|
65
|
+
└─────────────────────────────────────────────┘
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Stavy platby
|
|
69
|
+
|
|
70
|
+
| Status | Popis |
|
|
71
|
+
|--------|-------|
|
|
72
|
+
| `CREATED` | Platba vytvorena, ceka na zpracovani |
|
|
73
|
+
| `PREPARED` | Odeslana do banky, ceka na autorizaci |
|
|
74
|
+
| `PENDING` | Banka zpracovava |
|
|
75
|
+
| `COMPLETED` | Uspesne dokoncena |
|
|
76
|
+
| `FAILED` | Selhala |
|
|
77
|
+
|
|
78
|
+
### Typy plateb
|
|
79
|
+
|
|
80
|
+
- `SEPA` - SEPA prevod
|
|
81
|
+
- `SWIFT` - SWIFT prevod
|
|
82
|
+
- `DOMESTIC` - Tuzemsky prevod
|
|
83
|
+
- `UNKNOWN` - Nezname
|
|
84
|
+
|
|
85
|
+
### Smer platby
|
|
86
|
+
|
|
87
|
+
- `INCOMING` - Prichozi platba
|
|
88
|
+
- `OUTGOING` - Odchozi platba
|
|
89
|
+
|
|
90
|
+
## Batch processing
|
|
91
|
+
|
|
92
|
+
Platby se neodesilaji do banky jednotlive, ale seskupuji se do **batchu** (davek). Kazdy ucet ma nastaveny `batchSizeLimit` (vychozi: 50 plateb na batch).
|
|
93
|
+
|
|
94
|
+
Kazdy batch obsahuje pouze platby **jednoho typu** (SEPA, DOMESTIC nebo SWIFT). Ruzne typy plateb nelze odeslat do banky v jednom batchi.
|
|
95
|
+
|
|
96
|
+
### Jak to funguje
|
|
97
|
+
|
|
98
|
+
1. Volani `send-payment` vlozi platbu do fronty `PAYMENTS_READY_TO_BATCH_QUEUE`
|
|
99
|
+
2. Queue handler spusti akci `add-payments-to-batch`, ktera:
|
|
100
|
+
- Filtruje platby podle podpory uctu
|
|
101
|
+
- Prirazuje platby k uctum a konektorum
|
|
102
|
+
- **Seskupi platby podle `paymentType`** (SEPA, DOMESTIC, SWIFT) - kazdy typ ma vlastni batch
|
|
103
|
+
- Hleda existujici OPEN batch pro dany ucet a typ platby, nebo vytvori novy
|
|
104
|
+
- Respektuje `batchSizeLimit` - pokud je batch plny, vytvori dalsi
|
|
105
|
+
- Platby s flagou `sendAsSinglePayment` jdou do samostatneho batche
|
|
106
|
+
3. Batch je pripraven ke zpracovani
|
|
107
|
+
|
|
108
|
+
### Zivotni cyklus batche
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
┌─────────────────────────────────────┐
|
|
112
|
+
│ OPEN │
|
|
113
|
+
│ Batch prijima platby, neni plny │
|
|
114
|
+
└──────────────┬──────────────────────┘
|
|
115
|
+
│ spusteni process-batch
|
|
116
|
+
▼
|
|
117
|
+
┌─────────────────────────────────────┐
|
|
118
|
+
│ PROCESSING │
|
|
119
|
+
│ Zamceny, probiha komunikace s bankou│
|
|
120
|
+
│ (checksum validace proti zmenam) │
|
|
121
|
+
└──────────────┬──────────────────────┘
|
|
122
|
+
│ connector.initiate*Batch()
|
|
123
|
+
▼
|
|
124
|
+
┌─────────────────────────────────────┐
|
|
125
|
+
│ READY_TO_SIGN │
|
|
126
|
+
│ Ceka na autorizaci uzivatelem │
|
|
127
|
+
│ (obsahuje auth URL z banky) │
|
|
128
|
+
└──────────────┬──────────────────────┘
|
|
129
|
+
│ uzivatel autorizuje
|
|
130
|
+
▼
|
|
131
|
+
┌─────────────────────────────────────┐
|
|
132
|
+
│ SIGNED │
|
|
133
|
+
│ Autorizovany, banka zpracovava │
|
|
134
|
+
└──────────────┬──────────────────────┘
|
|
135
|
+
│ banka dokonci
|
|
136
|
+
▼
|
|
137
|
+
┌─────────────────────────────────────┐
|
|
138
|
+
│ COMPLETED / FAILED / │
|
|
139
|
+
│ SIGNATURE_FAILED │
|
|
140
|
+
│ Konecny stav │
|
|
141
|
+
└─────────────────────────────────────┘
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### ProcessBatch workflow
|
|
145
|
+
|
|
146
|
+
Workflow (Cloudflare Durable Object) ridi zpracovani batche:
|
|
147
|
+
|
|
148
|
+
1. Nacte a validuje batch (nesmi byt SIGNED/PROCESSING)
|
|
149
|
+
2. Zamkne batch (nastavi PROCESSING, overi checksum)
|
|
150
|
+
3. Iniciuje batch u banky pres konektor podle typu platby (`connector.initiateDomesticBatch()` / `initiateSEPABatch()` / `initiateForeignBatch()`)
|
|
151
|
+
4. Aktualizuje batch na READY_TO_SIGN s autorizacnimi URL
|
|
152
|
+
5. Odesle email s odkazem na autorizaci
|
|
153
|
+
6. Ceka na autorizaci uzivatelem
|
|
154
|
+
|
|
155
|
+
### CRON kontrola stavu
|
|
156
|
+
|
|
157
|
+
Planovana uloha (`CRON_BATCH_STATUSES`) pravidelne vola `update-batch-statuses`, ktera:
|
|
158
|
+
- Nacte vsechny pending batche (READY_TO_SIGN, SIGNED)
|
|
159
|
+
- Seskupi je podle konektoru
|
|
160
|
+
- Zavola `connector.getBatchStatus()` pro kazdy batch
|
|
161
|
+
- Aktualizuje stavy batchu a jednotlivych plateb
|
|
162
|
+
- Emituje eventy pro zmenene platby
|
|
163
|
+
|
|
164
|
+
## Synchronizace uctu
|
|
165
|
+
|
|
166
|
+
Kazdy pripojeny ucet ma workflow `SyncAccountPayments`, ktery bezi v nekonecne smycce:
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
┌──→ Nacti konfiguraci uctu
|
|
170
|
+
│ │
|
|
171
|
+
│ ▼
|
|
172
|
+
│ Stahni platby z banky (connector.getAllAccountPayments)
|
|
173
|
+
│ │ (az 5 pokusu, 2s delay mezi nimi)
|
|
174
|
+
│ ▼
|
|
175
|
+
│ Filtruj dokoncene platby
|
|
176
|
+
│ │
|
|
177
|
+
│ ▼
|
|
178
|
+
│ Vloz nove platby do DB (deduplikace pres bankRefId)
|
|
179
|
+
│ │
|
|
180
|
+
│ ▼
|
|
181
|
+
│ Emituj BANK_PAYMENT eventy
|
|
182
|
+
│ │
|
|
183
|
+
│ ▼
|
|
184
|
+
│ Aktualizuj lastSyncAt + metadata
|
|
185
|
+
│ │
|
|
186
|
+
│ ▼
|
|
187
|
+
│ Spi syncIntervalS sekund (vychozi: 600s)
|
|
188
|
+
│ │
|
|
189
|
+
└────┘
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Deduplikace: Workflow si pamatuje `lastSyncBankRefIds` z posledni synchronizace, aby nevkladal duplicity.
|
|
193
|
+
|
|
194
|
+
## Bankovni konektory
|
|
195
|
+
|
|
196
|
+
Vsechny konektory dedi z abstraktni tridy `IBankConnector`, ktera poskytuje spolecnou logiku vcetne batch fallbacku.
|
|
197
|
+
|
|
198
|
+
### Prehled konektoru
|
|
199
|
+
|
|
200
|
+
| Konektor | Klic | Batch podpora | Poznamka |
|
|
201
|
+
|----------|------|---------------|----------|
|
|
202
|
+
| Erste Bank | `ERSTE` | DOMESTIC | Vlastni API |
|
|
203
|
+
| Finbricks | `FINBRICKS` | DOMESTIC | Platforma pro vice bank (bazova trida) |
|
|
204
|
+
| Moneta | `MONETA` | DOMESTIC | Pres Finbricks |
|
|
205
|
+
| Creditas | `CREDITAS` | Zadna | Pres Finbricks |
|
|
206
|
+
| Fio | `FIO` | DOMESTIC | Pres Finbricks |
|
|
207
|
+
| DBU | `DBU` | Zadna | Pres Finbricks |
|
|
208
|
+
| CSAS | `CSAS` | DOMESTIC | Pres Finbricks |
|
|
209
|
+
| AirBank | `AIRBANK` | DOMESTIC | Pres Finbricks |
|
|
210
|
+
| Mock | `MOCK` | Vsechny typy | Testovaci, automaticky dokoncuje platby |
|
|
211
|
+
| Mock COBS | `MOCK_COBS` | Vsechny typy | Testovaci COBS konektor |
|
|
212
|
+
|
|
213
|
+
### Metody konektoru
|
|
214
|
+
|
|
215
|
+
Kazdy konektor implementuje nasledujici metody (nebo vraci `Not implemented`):
|
|
216
|
+
|
|
217
|
+
**Sprava uctu:**
|
|
218
|
+
- `getAuthUri()` - Ziskat autorizacni URL
|
|
219
|
+
- `authorizeAccount()` - Dokoncit autorizaci uctu
|
|
220
|
+
|
|
221
|
+
**Single platby (per typ):**
|
|
222
|
+
- `initiateDomesticPayment()` - Tuzemska platba
|
|
223
|
+
- `initiateSEPAPayment()` - SEPA platba
|
|
224
|
+
- `initiateForeignPayment()` - Zahranicni (SWIFT) platba
|
|
225
|
+
|
|
226
|
+
**Batch platby (per typ):**
|
|
227
|
+
- `initiateDomesticBatch()` - Batch tuzemskych plateb
|
|
228
|
+
- `initiateSEPABatch()` - Batch SEPA plateb
|
|
229
|
+
- `initiateForeignBatch()` - Batch zahranicnich plateb
|
|
230
|
+
|
|
231
|
+
**Synchronizace a stavy:**
|
|
232
|
+
- `getAllAccountPayments()` - Stahnout transakce uctu
|
|
233
|
+
- `getBatchStatus()` - Zjistit stav batche
|
|
234
|
+
- `getPaymentStatus()` - Zjistit stav platby
|
|
235
|
+
|
|
236
|
+
### Abstrakce a batch fallback
|
|
237
|
+
|
|
238
|
+
Bazova trida `IBankConnector` implementuje **template method pattern** pro batch operace. Kazdy konektor deklaruje, ktere typy plateb podporuje v batchi pres metodu `supportsBatch(paymentType)`.
|
|
239
|
+
|
|
240
|
+
Pokud konektor **nepodporuje** batch pro dany typ platby, bazova trida automaticky provede fallback - rozlozi batch na jednotlive platby a odesle je sekvencne pres prislusnou single payment metodu:
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
initiateDomesticBatch()
|
|
244
|
+
│
|
|
245
|
+
├─ supportsBatch('DOMESTIC') === true
|
|
246
|
+
│ └─► initiateDomesticBatchImpl() // nativni batch API banky
|
|
247
|
+
│
|
|
248
|
+
└─ supportsBatch('DOMESTIC') === false
|
|
249
|
+
└─► for each payment: // fallback na single platby
|
|
250
|
+
initiateDomesticPayment()
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Stejny pattern plati pro `initiateSEPABatch()` a `initiateForeignBatch()`.
|
|
254
|
+
|
|
255
|
+
**Implementace v konektoru:**
|
|
256
|
+
- `supportsBatch(paymentType)` - Vraci `true`/`false` podle podpory banky
|
|
257
|
+
- `initiate*BatchImpl()` - Chranene (protected) metody s nativni batch implementaci, volane pouze kdyz `supportsBatch()` vraci `true`
|
|
258
|
+
|
|
259
|
+
Vysledek je vzdy jednotny typ `InitiatedBatch` (obsahuje `authorizationUrls`, `payments` a volitelne `metadata`), bez ohledu na to, zda byl pouzit nativni batch nebo fallback.
|
|
260
|
+
|
|
261
|
+
### Charge Bearer
|
|
262
|
+
|
|
263
|
+
Platby mohou specifikovat `chargeBearer` (nositel poplatku):
|
|
264
|
+
- `SHA` - Sdilene poplatky (vychozi)
|
|
265
|
+
- `OUR` - Poplatky plati odesilatel
|
|
266
|
+
- `BEN` - Poplatky plati prijemce
|
|
267
|
+
|
|
268
|
+
Hodnota se cte primo z platby a predava konektoru (pouzivano napr. ve Finbricks).
|
|
269
|
+
|
|
270
|
+
## RPC akce
|
|
271
|
+
|
|
272
|
+
Bank service je **RPC worker** - nema vlastni verejne HTTP endpointy. Vsechny akce jsou dostupne pouze pres Cloudflare Worker binding. Verejne endpointy vystavuje az **gateway**, ktera tento worker binduje a zpristupnuje prislusne akce.
|
|
273
|
+
|
|
274
|
+
### Sprava uctu
|
|
275
|
+
|
|
276
|
+
| Akce | Popis |
|
|
277
|
+
|------|-------|
|
|
278
|
+
| `get-auth-uri` | Ziska autorizacni URL pro pripojeni uctu |
|
|
279
|
+
| `authorize-account` | Dokonci autorizaci uctu (ulozi kredencialy, spusti sync) |
|
|
280
|
+
| `disconnect-account` | Odpoji ucet (smaze kredencialy, platby, zastavi workflow) |
|
|
281
|
+
| `get-bank-accounts` | Seznam uctu (volitelne vcetne workflow stavu a batch statistik) |
|
|
282
|
+
| `update-account` | Aktualizace nastaveni uctu |
|
|
283
|
+
|
|
284
|
+
### Platby
|
|
285
|
+
|
|
286
|
+
| Akce | Popis |
|
|
287
|
+
|------|-------|
|
|
288
|
+
| `send-payment` | Odesle platbu (vlozi do fronty pro batchovani) |
|
|
289
|
+
| `get-payments` | Seznam plateb s paginaci a filtry (ucet, castka, mena, smer, datum, stav) |
|
|
290
|
+
| `simulate-deposit` | Testovaci: vytvori prichozi platbu ve stavu COMPLETED |
|
|
291
|
+
|
|
292
|
+
### Batch operace
|
|
293
|
+
|
|
294
|
+
| Akce | Popis |
|
|
295
|
+
|------|-------|
|
|
296
|
+
| `process-batch` | Spusti zpracovani batche (workflow) |
|
|
297
|
+
| `process-batch-status` | Stav zpracovani batche |
|
|
298
|
+
| `process-batch-restart` | Restart selhaneho batch workflow |
|
|
299
|
+
| `get-batches` | Seznam batchu s paginaci a filtry |
|
|
300
|
+
| `update-batch-statuses` | Aktualizuje stavy batchu z banky (CRON) |
|
|
301
|
+
|
|
302
|
+
### Synchronizace
|
|
303
|
+
|
|
304
|
+
| Akce | Popis |
|
|
305
|
+
|------|-------|
|
|
306
|
+
| `sync-account` | Spusti synchronizaci uctu (workflow) |
|
|
307
|
+
| `sync-account-status` | Stav synchronizacniho workflow |
|
|
308
|
+
| `sync-account-restart` | Restart synchronizace |
|
|
309
|
+
| `sync-account-terminate` | Zastaveni synchronizace |
|
|
310
|
+
|
|
311
|
+
## Event system
|
|
312
|
+
|
|
313
|
+
Sluzba emituje `BankPaymentEvent` do `QUEUE_BUS_QUEUE` pro konzumaci ostatnimi sluzbami:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
type BankPaymentEvent = {
|
|
317
|
+
eventType: 'BANK_PAYMENT'
|
|
318
|
+
eventSignal: 'paymentCreated' | 'paymentCompleted' | 'paymentFailed' | 'paymentUpdated'
|
|
319
|
+
bankPayment: Partial<PaymentSelectType>
|
|
320
|
+
metadata: {
|
|
321
|
+
correlationId: string
|
|
322
|
+
entityId: string
|
|
323
|
+
timestamp: string
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
| Signal | Kdy se emituje |
|
|
329
|
+
|--------|---------------|
|
|
330
|
+
| `paymentCreated` | Nova platba synchronizovana z banky |
|
|
331
|
+
| `paymentCompleted` | Platba uspesne dokoncena |
|
|
332
|
+
| `paymentFailed` | Platba selhala |
|
|
333
|
+
| `paymentUpdated` | Zmena stavu platby |
|
|
334
|
+
|
|
335
|
+
## Databazove schema
|
|
336
|
+
|
|
337
|
+
### payment
|
|
338
|
+
|
|
339
|
+
Hlavni tabulka plateb s vazbou na ucet a batch.
|
|
340
|
+
|
|
341
|
+
Klicove sloupce: `correlationId`, `refId`, `bankRefId`, `amount`, `currency`, `direction`, `paymentType`, `status`, `accountId`, `connectorKey`, `vs`/`ss`/`ks`, `message`, `creditor`, `debtor`, `batchId`, `initiatedAt`, `processedAt`.
|
|
342
|
+
|
|
343
|
+
Unikatni omezeni: `(connectorKey, bankRefId)`.
|
|
344
|
+
|
|
345
|
+
### batch
|
|
346
|
+
|
|
347
|
+
Batch plateb s JSON polem plateb a stavovymi informacemi.
|
|
348
|
+
|
|
349
|
+
Klicove sloupce: `status`, `payments` (JSON), `authorizationUrl`, `signHash`, `signId`, `sizeLimit`, `accountId`.
|
|
350
|
+
|
|
351
|
+
### account
|
|
352
|
+
|
|
353
|
+
Bankovni ucet s konfiguraci synchronizace.
|
|
354
|
+
|
|
355
|
+
Klicove sloupce: `iban` (unikatni), `number`, `bankCode`, `connectorKey`, `currency`, `batchSizeLimit`, `syncIntervalS`, `lastSyncAt`, `status` (`AUTHORIZED` / `DISABLED` / `EXPIRED`).
|
|
356
|
+
|
|
357
|
+
### account_credentials
|
|
358
|
+
|
|
359
|
+
Sifrovane bankovni tokeny (AES). Typy: `AUTH_TOKEN`, `REFRESH_TOKEN`, `CLIENT_ID`, `API_KEY`.
|
|
360
|
+
|
|
361
|
+
### ott (One-Time Token)
|
|
362
|
+
|
|
363
|
+
Jednorazove tokeny pro autorizacni flow uctu.
|
|
364
|
+
|
|
365
|
+
## Error Codes
|
|
366
|
+
|
|
367
|
+
Format: `{CATEGORY}-B-{NUMBER}`
|
|
368
|
+
|
|
369
|
+
| Code | Status | Description |
|
|
370
|
+
|------|--------|-------------|
|
|
371
|
+
| `DB-B-001` | 404 | No credentials found for account |
|
|
372
|
+
| `DB-B-002` | 404 | One-time token not found |
|
|
373
|
+
| `DB-B-003` | 404 | Account not found (authorize) |
|
|
374
|
+
| `DB-B-004` | 404 | Account not found (update) |
|
|
375
|
+
| `DB-B-005` | 404 | Account not found (disconnect) |
|
|
376
|
+
| `DB-B-006` | 500 | Account not updated (disconnect) |
|
|
377
|
+
| `DB-B-007` | 404 | Batch not found |
|
|
378
|
+
| `VALID-B-001` | 400 | Invalid connector key |
|
|
379
|
+
| `VALID-B-002` | 400 | One-time token expired |
|
|
380
|
+
| `VALID-B-003` | 422 | Unsupported account |
|
|
381
|
+
| `SYS-B-001` | 501 | Not implemented |
|
package/dist/database/schema.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ao as account, ap as accountCredentials, aq as batch, ar as ott, as as payment, at as paymentRelations } from '../shared/bank.
|
|
1
|
+
export { ao as account, ap as accountCredentials, aq as batch, ar as ott, as as payment, at as paymentRelations } from '../shared/bank.C6_7Rch8.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 { ao as account, ap as accountCredentials, aq as batch, ar as ott, as as payment, at as paymentRelations } from '../shared/bank.
|
|
1
|
+
export { ao as account, ap as accountCredentials, aq as batch, ar as ott, as as payment, at as paymentRelations } from '../shared/bank.C6_7Rch8.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 { ao as account, ap as accountCredentials, aq as batch, ar as ott, as as payment, at as paymentRelations } from '../shared/bank.
|
|
1
|
+
export { ao as account, ap as accountCredentials, aq as batch, ar as ott, as as payment, at as paymentRelations } from '../shared/bank.C6_7Rch8.js';
|
|
2
2
|
import 'drizzle-orm/sqlite-core';
|
|
3
3
|
import 'drizzle-orm';
|
|
4
4
|
import '@develit-io/backend-sdk';
|
package/dist/database/schema.mjs
CHANGED
|
@@ -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.
|
|
1
|
+
export { n as account, p as accountCredentials, q as batch, r as ott, s as payment, t as paymentRelations } from '../shared/bank.BnIYdBEF.mjs';
|
|
2
2
|
import '@develit-io/backend-sdk';
|
|
3
3
|
import 'drizzle-orm/relations';
|
|
4
4
|
import 'drizzle-orm/sqlite-core';
|
package/dist/export/worker.cjs
CHANGED
|
@@ -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.
|
|
4
|
+
const drizzle = require('../shared/bank.CTqIXnHg.cjs');
|
|
5
5
|
const cloudflare_workers = require('cloudflare:workers');
|
|
6
6
|
const d1 = require('drizzle-orm/d1');
|
|
7
7
|
const zod = require('zod');
|
|
8
|
-
const payment_schema = require('../shared/bank.
|
|
8
|
+
const payment_schema = require('../shared/bank.D7kwLMqF.cjs');
|
|
9
9
|
const generalCodes = require('@develit-io/general-codes');
|
|
10
10
|
require('date-fns');
|
|
11
11
|
require('jose');
|
|
12
12
|
const drizzleOrm = require('drizzle-orm');
|
|
13
13
|
require('node:crypto');
|
|
14
|
-
const mock_connector = require('../shared/bank.
|
|
15
|
-
require('../shared/bank.
|
|
14
|
+
const mock_connector = require('../shared/bank.iEgK7rge.cjs');
|
|
15
|
+
require('../shared/bank.DlW1XNug.cjs');
|
|
16
16
|
require('drizzle-orm/relations');
|
|
17
17
|
require('drizzle-orm/sqlite-core');
|
|
18
18
|
require('drizzle-zod');
|
|
@@ -224,11 +224,12 @@ const getBatchesQuery = async (db, {
|
|
|
224
224
|
};
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
const getAccountOpenBatchesQuery = async (db, { accountId }) => {
|
|
227
|
+
const getAccountOpenBatchesQuery = async (db, { accountId, paymentType }) => {
|
|
228
228
|
return await db.select().from(drizzle.tables.batch).where(
|
|
229
229
|
drizzleOrm.and(
|
|
230
230
|
drizzleOrm.eq(drizzle.tables.batch.accountId, accountId),
|
|
231
|
-
drizzleOrm.eq(drizzle.tables.batch.status, "OPEN")
|
|
231
|
+
drizzleOrm.eq(drizzle.tables.batch.status, "OPEN"),
|
|
232
|
+
paymentType ? drizzleOrm.eq(drizzle.tables.batch.paymentType, paymentType) : void 0
|
|
232
233
|
)
|
|
233
234
|
);
|
|
234
235
|
};
|
|
@@ -485,7 +486,8 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
485
486
|
iban: acc.iban,
|
|
486
487
|
token: credentials.value,
|
|
487
488
|
id: acc.id,
|
|
488
|
-
connectorKey: acc.connectorKey
|
|
489
|
+
connectorKey: acc.connectorKey,
|
|
490
|
+
bankRefId: acc.bankRefId
|
|
489
491
|
};
|
|
490
492
|
})
|
|
491
493
|
);
|
|
@@ -727,6 +729,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
727
729
|
id: backendSdk.uuidv4(),
|
|
728
730
|
authorizationUrls: [],
|
|
729
731
|
accountId: acc.id,
|
|
732
|
+
paymentType: singlePayment.paymentType,
|
|
730
733
|
payments: [batchedPayment],
|
|
731
734
|
status: "OPEN",
|
|
732
735
|
metadata: {
|
|
@@ -736,40 +739,47 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
736
739
|
});
|
|
737
740
|
await command.execute();
|
|
738
741
|
this.log({
|
|
739
|
-
message: `\u2728 Created single payment batch for account ${acc.id}`
|
|
742
|
+
message: `\u2728 Created single payment batch (${singlePayment.paymentType}) for account ${acc.id}`
|
|
740
743
|
});
|
|
741
744
|
}
|
|
742
745
|
if (regularPayments.length > 0) {
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
const availableBatch = openBatches.find(
|
|
747
|
-
(batch) => batch.payments.length < (batch.metadata?.sizeLimit ?? acc.batchSizeLimit)
|
|
746
|
+
const paymentsByType = Map.groupBy(
|
|
747
|
+
regularPayments,
|
|
748
|
+
(p) => p.paymentType
|
|
748
749
|
);
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
});
|
|
752
|
-
const batchedPayments = regularPayments.map(mock_connector.toBatchedPayment);
|
|
753
|
-
const { command } = drizzle.upsertBatchCommand(this.db, {
|
|
754
|
-
batch: availableBatch ? {
|
|
755
|
-
...availableBatch,
|
|
756
|
-
payments: [...availableBatch.payments, ...batchedPayments]
|
|
757
|
-
} : {
|
|
758
|
-
id: backendSdk.uuidv4(),
|
|
759
|
-
authorizationUrls: [],
|
|
750
|
+
for (const [paymentType, paymentsOfType] of paymentsByType) {
|
|
751
|
+
const openBatches = await getAccountOpenBatchesQuery(this.db, {
|
|
760
752
|
accountId: acc.id,
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
753
|
+
paymentType
|
|
754
|
+
});
|
|
755
|
+
const availableBatch = openBatches.find(
|
|
756
|
+
(batch) => batch.payments.length < (batch.metadata?.sizeLimit ?? acc.batchSizeLimit)
|
|
757
|
+
);
|
|
758
|
+
this.log({
|
|
759
|
+
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`
|
|
760
|
+
});
|
|
761
|
+
const batchedPayments = paymentsOfType.map(mock_connector.toBatchedPayment);
|
|
762
|
+
const { command } = drizzle.upsertBatchCommand(this.db, {
|
|
763
|
+
batch: availableBatch ? {
|
|
764
|
+
...availableBatch,
|
|
765
|
+
payments: [...availableBatch.payments, ...batchedPayments]
|
|
766
|
+
} : {
|
|
767
|
+
id: backendSdk.uuidv4(),
|
|
768
|
+
authorizationUrls: [],
|
|
769
|
+
accountId: acc.id,
|
|
770
|
+
paymentType,
|
|
771
|
+
payments: batchedPayments,
|
|
772
|
+
status: "OPEN",
|
|
773
|
+
metadata: {
|
|
774
|
+
sizeLimit: acc.batchSizeLimit
|
|
775
|
+
}
|
|
765
776
|
}
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
}
|
|
772
|
-
return upsertedBatch;
|
|
777
|
+
});
|
|
778
|
+
await command.execute();
|
|
779
|
+
this.log({
|
|
780
|
+
message: `\u2705 Batch (${paymentType}) upserted successfully for account ${acc.id}`
|
|
781
|
+
});
|
|
782
|
+
}
|
|
773
783
|
}
|
|
774
784
|
}
|
|
775
785
|
});
|
|
@@ -879,7 +889,8 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
879
889
|
});
|
|
880
890
|
}
|
|
881
891
|
const connector = await this._initiateBankConnector({
|
|
882
|
-
connectorKey: ottRow.refId
|
|
892
|
+
connectorKey: ottRow.refId,
|
|
893
|
+
skipAccounts: true
|
|
883
894
|
});
|
|
884
895
|
const { credentials, accounts } = await connector.authorizeAccount({
|
|
885
896
|
urlParams
|