@develit-services/bank 0.8.5 → 0.8.7

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 (32) hide show
  1. package/dist/database/schema.cjs +1 -1
  2. package/dist/database/schema.d.cts +1 -1
  3. package/dist/database/schema.d.mts +1 -1
  4. package/dist/database/schema.d.ts +1 -1
  5. package/dist/database/schema.mjs +1 -1
  6. package/dist/export/worker.cjs +583 -146
  7. package/dist/export/worker.d.cts +286 -44
  8. package/dist/export/worker.d.mts +286 -44
  9. package/dist/export/worker.d.ts +286 -44
  10. package/dist/export/worker.mjs +584 -147
  11. package/dist/export/workflows.cjs +132 -16
  12. package/dist/export/workflows.mjs +133 -17
  13. package/dist/shared/{bank.C-T1FQxg.cjs → bank.62VzK9Aj.cjs} +1 -1
  14. package/dist/shared/{bank.SQ4Mmr8u.cjs → bank.BS7fFjGA.cjs} +34 -4
  15. package/dist/shared/{bank.6faPHUEY.d.ts → bank.BYRq3yJf.d.ts} +81 -11
  16. package/dist/shared/{bank.C4VOdIx1.mjs → bank.C0UN6luZ.mjs} +34 -4
  17. package/dist/shared/{bank.DDHrdFgy.mjs → bank.CA5ytXxp.mjs} +1 -1
  18. package/dist/shared/{bank.BoWCMu5n.d.cts → bank.CO89tR9U.d.cts} +81 -11
  19. package/dist/shared/{bank.BaMRCHk-.d.ts → bank.Cns5ss41.d.cts} +55 -18
  20. package/dist/shared/{bank.BaMRCHk-.d.cts → bank.Cns5ss41.d.mts} +55 -18
  21. package/dist/shared/{bank.BaMRCHk-.d.mts → bank.Cns5ss41.d.ts} +55 -18
  22. package/dist/shared/{bank.DOL1uM4n.d.mts → bank.CreoSb2d.d.mts} +81 -11
  23. package/dist/shared/{bank.DRrBrAdI.mjs → bank.D1jqaHaF.mjs} +91 -31
  24. package/dist/shared/{bank.Cpy9PULF.mjs → bank.DEmzZGZW.mjs} +31 -5
  25. package/dist/shared/{bank.BOnP9p9Y.cjs → bank.Dm8GHThw.cjs} +31 -5
  26. package/dist/shared/{bank.CQURey1E.cjs → bank.DwyCCyd0.cjs} +90 -31
  27. package/dist/types.cjs +3 -4
  28. package/dist/types.d.cts +8 -16
  29. package/dist/types.d.mts +8 -16
  30. package/dist/types.d.ts +8 -16
  31. package/dist/types.mjs +3 -3
  32. package/package.json +2 -2
@@ -1,29 +1,29 @@
1
1
  'use strict';
2
2
 
3
3
  const backendSdk = require('@develit-io/backend-sdk');
4
- const drizzle = require('../shared/bank.BOnP9p9Y.cjs');
4
+ const drizzle = require('../shared/bank.Dm8GHThw.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');
7
+ const mock_connector = require('../shared/bank.DwyCCyd0.cjs');
8
8
  require('jose');
9
9
  const zod = require('zod');
10
- const paymentRequest_schema = require('../shared/bank.SQ4Mmr8u.cjs');
10
+ const paymentRequest_schema = require('../shared/bank.BS7fFjGA.cjs');
11
11
  const generalCodes = require('@develit-io/general-codes');
12
12
  require('date-fns');
13
13
  const drizzleOrm = require('drizzle-orm');
14
+ const sqliteCore = require('drizzle-orm/sqlite-core');
14
15
  require('node:crypto');
15
- require('../shared/bank.C-T1FQxg.cjs');
16
+ require('../shared/bank.62VzK9Aj.cjs');
16
17
  require('drizzle-orm/relations');
17
- require('drizzle-orm/sqlite-core');
18
18
  require('drizzle-zod');
19
19
 
20
20
  const upsertAccountCommand = (db, { account }) => {
21
21
  const id = account.id || backendSdk.uuidv4();
22
+ const { id: _id, ...accountWithoutId } = account;
22
23
  const command = db.insert(drizzle.tables.account).values({ ...account, id }).onConflictDoUpdate({
23
24
  target: drizzle.tables.account.iban,
24
- set: {
25
- ...account
26
- }
25
+ set: accountWithoutId
26
+ // preserve existing id on re-auth
27
27
  }).returning();
28
28
  return {
29
29
  id,
@@ -141,16 +141,25 @@ const getAllAccountsQuery = async (db, filters) => {
141
141
  filters?.filterBankRefIds
142
142
  )
143
143
  );
144
- const accountsWithExpiration = await db.select().from(drizzle.tables.account).leftJoin(
145
- drizzle.tables.accountCredentials,
146
- drizzleOrm.eq(drizzle.tables.accountCredentials.accountId, drizzle.tables.account.id)
147
- ).where(whereConditions);
148
- return accountsWithExpiration.map(({ account, account_credentials }) => {
149
- return {
150
- ...account,
151
- expiresAt: account_credentials?.expiresAt
152
- };
153
- });
144
+ const page = filters?.page ?? 1;
145
+ const limit = filters?.limit ?? 20;
146
+ const offset = (page - 1) * limit;
147
+ const [accountsWithExpiration, countResult] = await Promise.all([
148
+ db.select().from(drizzle.tables.account).leftJoin(
149
+ drizzle.tables.accountCredentials,
150
+ drizzleOrm.eq(drizzle.tables.accountCredentials.accountId, drizzle.tables.account.id)
151
+ ).where(whereConditions).limit(limit).offset(offset),
152
+ db.select({ count: drizzleOrm.sql`count(*)` }).from(drizzle.tables.account).where(whereConditions)
153
+ ]);
154
+ return {
155
+ accounts: accountsWithExpiration.map(
156
+ ({ account, account_credentials }) => ({
157
+ ...account,
158
+ expiresAt: account_credentials?.expiresAt
159
+ })
160
+ ),
161
+ totalCount: countResult[0]?.count ?? 0
162
+ };
154
163
  };
155
164
 
156
165
  const getAllPendingBatchesQuery = (db) => {
@@ -191,7 +200,17 @@ const getPaymentsWithPaginationQuery = async (db, {
191
200
  filterPaymentDateFrom,
192
201
  filterPaymentDateTo,
193
202
  filterPaymentStatus,
194
- filterPaymentyDirection
203
+ filterPaymentDirection,
204
+ filterPaymentType,
205
+ filterPaymentMinAmount,
206
+ filterPaymentMaxAmount,
207
+ filterPaymentVariableSymbol,
208
+ filterPaymentSpecificSymbol,
209
+ filterPaymentConstantSymbol,
210
+ filterPaymentMessage,
211
+ filterPaymentCreditorIban,
212
+ filterPaymentDebtorIban,
213
+ filterPaymentBatchId
195
214
  }) => {
196
215
  const whereConditions = drizzleOrm.and(
197
216
  buildMultiFilterConditions(
@@ -208,9 +227,22 @@ const getPaymentsWithPaginationQuery = async (db, {
208
227
  buildMultiFilterConditions(drizzle.tables.payment.status, filterPaymentStatus),
209
228
  buildMultiFilterConditions(
210
229
  drizzle.tables.payment.direction,
211
- filterPaymentyDirection
230
+ filterPaymentDirection
231
+ ),
232
+ buildMultiFilterConditions(drizzle.tables.payment.id, ids),
233
+ buildMultiFilterConditions(drizzle.tables.payment.paymentType, filterPaymentType),
234
+ buildRangeFilterConditions(
235
+ drizzle.tables.payment.amount,
236
+ filterPaymentMinAmount,
237
+ filterPaymentMaxAmount
212
238
  ),
213
- buildMultiFilterConditions(drizzle.tables.payment.id, ids)
239
+ filterPaymentVariableSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.vs, filterPaymentVariableSymbol) : void 0,
240
+ filterPaymentSpecificSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.ss, filterPaymentSpecificSymbol) : void 0,
241
+ filterPaymentConstantSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.ks, filterPaymentConstantSymbol) : void 0,
242
+ filterPaymentMessage !== void 0 ? drizzleOrm.like(drizzle.tables.payment.message, `%${filterPaymentMessage}%`) : void 0,
243
+ filterPaymentCreditorIban !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.creditorIban, filterPaymentCreditorIban) : void 0,
244
+ filterPaymentDebtorIban !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.debtorIban, filterPaymentDebtorIban) : void 0,
245
+ filterPaymentBatchId !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.batchId, filterPaymentBatchId) : void 0
214
246
  );
215
247
  const sortColumn = resolveColumn(drizzle.tables.payment, sort.column);
216
248
  const [{ totalCount }] = await db.select({
@@ -270,28 +302,261 @@ const getOttQuery = async (db, { ott }) => {
270
302
  };
271
303
 
272
304
  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;
305
+ const prResults = await db.select().from(drizzle.tables.paymentRequest).where(
306
+ drizzleOrm.and(
307
+ drizzleOrm.eq(drizzle.tables.paymentRequest.id, paymentId),
308
+ drizzleOrm.isNull(drizzle.tables.paymentRequest.deletedAt)
309
+ )
310
+ ).limit(1);
311
+ if (prResults[0]) return prResults[0];
312
+ const paymentResults = await db.select().from(drizzle.tables.payment).where(
313
+ drizzleOrm.or(
314
+ drizzleOrm.eq(drizzle.tables.payment.paymentRequestId, paymentId),
315
+ drizzleOrm.and(
316
+ drizzleOrm.isNull(drizzle.tables.payment.paymentRequestId),
317
+ drizzleOrm.eq(drizzle.tables.payment.id, paymentId)
318
+ )
319
+ )
320
+ ).limit(1);
321
+ if (!paymentResults[0]) return null;
322
+ const p = paymentResults[0];
323
+ return {
324
+ ...p,
325
+ id: p.paymentRequestId ?? p.id,
326
+ authorizationUrl: null,
327
+ sendAsSinglePayment: null,
328
+ direction: p.direction ?? "OUTGOING"
329
+ };
275
330
  };
276
331
 
277
- const seperateSupportedPayments = (incomingPayments, accounts) => {
278
- const [supportedPayments, unsupportedPayments] = incomingPayments.reduce(
279
- ([valid, invalid], payment) => {
280
- const isValid = accounts.some(
281
- (acc) => acc.iban === payment.debtorIban && acc.currency === payment.currency
282
- );
283
- if (isValid) {
284
- valid.push(payment);
285
- } else {
286
- invalid.push(payment);
287
- }
288
- return [valid, invalid];
289
- },
290
- [[], []]
332
+ function isCompletedOnly(filterStatus) {
333
+ if (!filterStatus) return false;
334
+ const statuses = Array.isArray(filterStatus) ? filterStatus : [filterStatus];
335
+ return statuses.length > 0 && statuses.every((s) => s === "COMPLETED");
336
+ }
337
+ function mapPaymentToPaymentRequest(p) {
338
+ return {
339
+ id: p.id,
340
+ createdAt: p.createdAt,
341
+ createdBy: p.createdBy,
342
+ updatedAt: p.updatedAt,
343
+ updatedBy: p.updatedBy,
344
+ deletedAt: p.deletedAt,
345
+ deletedBy: p.deletedBy,
346
+ batchId: p.batchId,
347
+ accountId: p.accountId,
348
+ correlationId: p.correlationId,
349
+ refId: p.refId,
350
+ bankRefId: p.bankRefId,
351
+ connectorKey: p.connectorKey,
352
+ amount: p.amount,
353
+ paymentType: p.paymentType,
354
+ currency: p.currency,
355
+ status: p.status,
356
+ statusReason: p.statusReason,
357
+ initiatedAt: p.initiatedAt,
358
+ processedAt: p.processedAt,
359
+ vs: p.vs,
360
+ ss: p.ss,
361
+ ks: p.ks,
362
+ message: p.message,
363
+ chargeBearer: p.chargeBearer,
364
+ instructionPriority: p.instructionPriority,
365
+ creditor: p.creditor,
366
+ creditorIban: p.creditorIban,
367
+ debtor: p.debtor,
368
+ debtorIban: p.debtorIban,
369
+ authorizationUrl: null,
370
+ sendAsSinglePayment: null
371
+ };
372
+ }
373
+ const getUnionColumns = () => ({
374
+ id: drizzle.tables.paymentRequest.id,
375
+ createdAt: drizzle.tables.paymentRequest.createdAt,
376
+ createdBy: drizzle.tables.paymentRequest.createdBy,
377
+ updatedAt: drizzle.tables.paymentRequest.updatedAt,
378
+ updatedBy: drizzle.tables.paymentRequest.updatedBy,
379
+ deletedAt: drizzle.tables.paymentRequest.deletedAt,
380
+ deletedBy: drizzle.tables.paymentRequest.deletedBy,
381
+ batchId: drizzle.tables.paymentRequest.batchId,
382
+ accountId: drizzle.tables.paymentRequest.accountId,
383
+ correlationId: drizzle.tables.paymentRequest.correlationId,
384
+ refId: drizzle.tables.paymentRequest.refId,
385
+ bankRefId: drizzle.tables.paymentRequest.bankRefId,
386
+ connectorKey: drizzle.tables.paymentRequest.connectorKey,
387
+ amount: drizzle.tables.paymentRequest.amount,
388
+ paymentType: drizzle.tables.paymentRequest.paymentType,
389
+ currency: drizzle.tables.paymentRequest.currency,
390
+ status: drizzle.tables.paymentRequest.status,
391
+ statusReason: drizzle.tables.paymentRequest.statusReason,
392
+ authorizationUrl: drizzle.tables.paymentRequest.authorizationUrl,
393
+ initiatedAt: drizzle.tables.paymentRequest.initiatedAt,
394
+ processedAt: drizzle.tables.paymentRequest.processedAt,
395
+ vs: drizzle.tables.paymentRequest.vs,
396
+ ss: drizzle.tables.paymentRequest.ss,
397
+ ks: drizzle.tables.paymentRequest.ks,
398
+ message: drizzle.tables.paymentRequest.message,
399
+ chargeBearer: drizzle.tables.paymentRequest.chargeBearer,
400
+ instructionPriority: drizzle.tables.paymentRequest.instructionPriority,
401
+ creditor: drizzle.tables.paymentRequest.creditor,
402
+ creditorIban: drizzle.tables.paymentRequest.creditorIban,
403
+ debtor: drizzle.tables.paymentRequest.debtor,
404
+ debtorIban: drizzle.tables.paymentRequest.debtorIban,
405
+ sendAsSinglePayment: drizzle.tables.paymentRequest.sendAsSinglePayment,
406
+ // payment_request je vždy OUTGOING — typ musí být kompatibilní s payment.direction
407
+ direction: drizzleOrm.sql`'OUTGOING'`.as("direction")
408
+ });
409
+ const getPaymentUnionColumns = () => ({
410
+ id: drizzleOrm.sql`COALESCE(${drizzle.tables.payment.paymentRequestId}, ${drizzle.tables.payment.id})`.as(
411
+ "id"
412
+ ),
413
+ createdAt: drizzle.tables.payment.createdAt,
414
+ createdBy: drizzle.tables.payment.createdBy,
415
+ updatedAt: drizzle.tables.payment.updatedAt,
416
+ updatedBy: drizzle.tables.payment.updatedBy,
417
+ deletedAt: drizzle.tables.payment.deletedAt,
418
+ deletedBy: drizzle.tables.payment.deletedBy,
419
+ batchId: drizzle.tables.payment.batchId,
420
+ accountId: drizzle.tables.payment.accountId,
421
+ correlationId: drizzle.tables.payment.correlationId,
422
+ refId: drizzle.tables.payment.refId,
423
+ bankRefId: drizzle.tables.payment.bankRefId,
424
+ connectorKey: drizzle.tables.payment.connectorKey,
425
+ amount: drizzle.tables.payment.amount,
426
+ paymentType: drizzle.tables.payment.paymentType,
427
+ currency: drizzle.tables.payment.currency,
428
+ status: drizzle.tables.payment.status,
429
+ statusReason: drizzle.tables.payment.statusReason,
430
+ authorizationUrl: drizzleOrm.sql`NULL`.as("authorization_url"),
431
+ initiatedAt: drizzle.tables.payment.initiatedAt,
432
+ processedAt: drizzle.tables.payment.processedAt,
433
+ vs: drizzle.tables.payment.vs,
434
+ ss: drizzle.tables.payment.ss,
435
+ ks: drizzle.tables.payment.ks,
436
+ message: drizzle.tables.payment.message,
437
+ chargeBearer: drizzle.tables.payment.chargeBearer,
438
+ instructionPriority: drizzle.tables.payment.instructionPriority,
439
+ creditor: drizzle.tables.payment.creditor,
440
+ creditorIban: drizzle.tables.payment.creditorIban,
441
+ debtor: drizzle.tables.payment.debtor,
442
+ debtorIban: drizzle.tables.payment.debtorIban,
443
+ sendAsSinglePayment: drizzleOrm.sql`NULL`.as("send_as_single_payment"),
444
+ direction: drizzle.tables.payment.direction
445
+ });
446
+ const getPaymentRequestsWithPaginationQuery = async (db, {
447
+ limit,
448
+ page,
449
+ sort,
450
+ filterAccountId,
451
+ filterStatus,
452
+ filterPaymentType,
453
+ filterCurrency,
454
+ filterMinAmount,
455
+ filterMaxAmount,
456
+ filterBatchId,
457
+ filterCreditorIban,
458
+ filterDebtorIban,
459
+ filterDateFrom,
460
+ filterDateTo,
461
+ filterVariableSymbol,
462
+ filterSpecificSymbol,
463
+ filterConstantSymbol,
464
+ filterMessage,
465
+ filterBankRefId,
466
+ filterPaymentId,
467
+ filterDirection,
468
+ filterSource
469
+ }) => {
470
+ const offset = (page - 1) * limit;
471
+ const buildPrWhereConditions = () => drizzleOrm.and(
472
+ drizzleOrm.isNull(drizzle.tables.paymentRequest.deletedAt),
473
+ buildMultiFilterConditions(
474
+ drizzle.tables.paymentRequest.accountId,
475
+ filterAccountId
476
+ ),
477
+ buildMultiFilterConditions(drizzle.tables.paymentRequest.status, filterStatus),
478
+ buildMultiFilterConditions(
479
+ drizzle.tables.paymentRequest.paymentType,
480
+ filterPaymentType
481
+ ),
482
+ buildMultiFilterConditions(
483
+ drizzle.tables.paymentRequest.currency,
484
+ filterCurrency
485
+ ),
486
+ buildRangeFilterConditions(
487
+ drizzle.tables.paymentRequest.amount,
488
+ filterMinAmount,
489
+ filterMaxAmount
490
+ ),
491
+ filterBatchId !== void 0 ? drizzleOrm.eq(drizzle.tables.paymentRequest.batchId, filterBatchId) : void 0,
492
+ filterCreditorIban !== void 0 ? drizzleOrm.eq(drizzle.tables.paymentRequest.creditorIban, filterCreditorIban) : void 0,
493
+ filterDebtorIban !== void 0 ? drizzleOrm.eq(drizzle.tables.paymentRequest.debtorIban, filterDebtorIban) : void 0,
494
+ filterDateFrom !== void 0 ? drizzleOrm.gte(drizzle.tables.paymentRequest.createdAt, filterDateFrom) : void 0,
495
+ filterDateTo !== void 0 ? drizzleOrm.lte(drizzle.tables.paymentRequest.createdAt, filterDateTo) : void 0,
496
+ filterVariableSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.paymentRequest.vs, filterVariableSymbol) : void 0,
497
+ filterSpecificSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.paymentRequest.ss, filterSpecificSymbol) : void 0,
498
+ filterConstantSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.paymentRequest.ks, filterConstantSymbol) : void 0,
499
+ filterMessage !== void 0 ? drizzleOrm.like(drizzle.tables.paymentRequest.message, `%${filterMessage}%`) : void 0,
500
+ filterBankRefId !== void 0 ? drizzleOrm.eq(drizzle.tables.paymentRequest.bankRefId, filterBankRefId) : void 0,
501
+ filterPaymentId !== void 0 ? drizzleOrm.eq(drizzle.tables.paymentRequest.id, filterPaymentId) : void 0,
502
+ // payment_request is always OUTGOING — exclude branch entirely when filtering INCOMING
503
+ filterDirection === "INCOMING" ? drizzleOrm.sql`0` : void 0,
504
+ // payment_request is always API (has no bank-synced payments)
505
+ filterSource === "BANK" ? drizzleOrm.sql`0` : void 0
291
506
  );
507
+ const buildPaymentWhereConditions = () => drizzleOrm.and(
508
+ drizzleOrm.isNull(drizzle.tables.payment.deletedAt),
509
+ buildMultiFilterConditions(drizzle.tables.payment.accountId, filterAccountId),
510
+ buildMultiFilterConditions(drizzle.tables.payment.status, filterStatus),
511
+ buildMultiFilterConditions(drizzle.tables.payment.paymentType, filterPaymentType),
512
+ buildMultiFilterConditions(drizzle.tables.payment.currency, filterCurrency),
513
+ buildRangeFilterConditions(
514
+ drizzle.tables.payment.amount,
515
+ filterMinAmount,
516
+ filterMaxAmount
517
+ ),
518
+ filterBatchId !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.batchId, filterBatchId) : void 0,
519
+ filterCreditorIban !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.creditorIban, filterCreditorIban) : void 0,
520
+ filterDebtorIban !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.debtorIban, filterDebtorIban) : void 0,
521
+ filterDateFrom !== void 0 ? drizzleOrm.gte(drizzle.tables.payment.createdAt, filterDateFrom) : void 0,
522
+ filterDateTo !== void 0 ? drizzleOrm.lte(drizzle.tables.payment.createdAt, filterDateTo) : void 0,
523
+ filterVariableSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.vs, filterVariableSymbol) : void 0,
524
+ filterSpecificSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.ss, filterSpecificSymbol) : void 0,
525
+ filterConstantSymbol !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.ks, filterConstantSymbol) : void 0,
526
+ filterMessage !== void 0 ? drizzleOrm.like(drizzle.tables.payment.message, `%${filterMessage}%`) : void 0,
527
+ filterBankRefId !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.bankRefId, filterBankRefId) : void 0,
528
+ filterPaymentId !== void 0 ? drizzleOrm.sql`COALESCE(${drizzle.tables.payment.paymentRequestId}, ${drizzle.tables.payment.id}) = ${filterPaymentId}` : void 0,
529
+ filterDirection !== void 0 ? drizzleOrm.eq(drizzle.tables.payment.direction, filterDirection) : void 0,
530
+ filterSource === "BANK" ? drizzleOrm.isNull(drizzle.tables.payment.paymentRequestId) : filterSource === "API" ? drizzleOrm.isNotNull(drizzle.tables.payment.paymentRequestId) : void 0
531
+ );
532
+ const queryInFlight = !isCompletedOnly(filterStatus);
533
+ const queryCompleted = true;
534
+ if (!queryInFlight && queryCompleted) {
535
+ const whereConditions = buildPaymentWhereConditions();
536
+ const sortColumn = resolveColumn(drizzle.tables.payment, sort.column);
537
+ const [{ totalCount }] = await db.select({ totalCount: drizzleOrm.sql`count(*)` }).from(drizzle.tables.payment).where(whereConditions);
538
+ const payments = await db.select().from(drizzle.tables.payment).where(whereConditions).limit(limit).offset(offset).orderBy(sort.direction === "asc" ? drizzleOrm.asc(sortColumn) : drizzleOrm.desc(sortColumn));
539
+ return {
540
+ paymentRequests: payments.map(mapPaymentToPaymentRequest),
541
+ totalCount
542
+ };
543
+ }
544
+ const prWhereConditions = buildPrWhereConditions();
545
+ const paymentWhereConditions = buildPaymentWhereConditions();
546
+ const unionColumns = getUnionColumns();
547
+ const paymentUnionColumns = getPaymentUnionColumns();
548
+ const sortColObj = sort.column in unionColumns ? unionColumns[sort.column] : unionColumns.updatedAt;
549
+ const [{ totalCount: countPR }, { totalCount: countP }] = await Promise.all([
550
+ db.select({ totalCount: drizzleOrm.sql`count(*)` }).from(drizzle.tables.paymentRequest).where(prWhereConditions).then(([row]) => row),
551
+ db.select({ totalCount: drizzleOrm.sql`count(*)` }).from(drizzle.tables.payment).where(paymentWhereConditions).then(([row]) => row)
552
+ ]);
553
+ const paymentRequests = await sqliteCore.unionAll(
554
+ db.select(unionColumns).from(drizzle.tables.paymentRequest).where(prWhereConditions),
555
+ db.select(paymentUnionColumns).from(drizzle.tables.payment).where(paymentWhereConditions)
556
+ ).orderBy(sort.direction === "asc" ? drizzleOrm.asc(sortColObj) : drizzleOrm.desc(sortColObj)).limit(limit).offset(offset);
292
557
  return {
293
- supportedPayments,
294
- unsupportedPayments
558
+ paymentRequests,
559
+ totalCount: countPR + countP
295
560
  };
296
561
  };
297
562
 
@@ -301,7 +566,6 @@ const sendPaymentInputSchema = zod.z.object({
301
566
  amount: zod.z.number().positive(),
302
567
  paymentType: zod.z.enum(paymentRequest_schema.PAYMENT_TYPES),
303
568
  chargeBearer: zod.z.enum(paymentRequest_schema.CHARGE_BEARERS).optional(),
304
- executionDate: zod.z.string().optional(),
305
569
  instructionPriority: zod.z.enum(paymentRequest_schema.INSTRUCTION_PRIORITIES).optional(),
306
570
  currency: zod.z.enum(generalCodes.CURRENCY_CODES),
307
571
  vs: zod.z.string().optional(),
@@ -310,7 +574,6 @@ const sendPaymentInputSchema = zod.z.object({
310
574
  message: zod.z.string().optional(),
311
575
  creditor: backendSdk.bankAccountMetadataSchema,
312
576
  debtor: backendSdk.bankAccountMetadataSchema,
313
- purpose: zod.z.string().optional(),
314
577
  sendAsSinglePayment: zod.z.boolean().optional()
315
578
  });
316
579
 
@@ -390,10 +653,20 @@ const ALLOWED_PAYMENT_FILTERS = {
390
653
  ACCOUNT_ID: "filterPaymentAccountId",
391
654
  AMOUNT: "filterPaymentAmount",
392
655
  CURRENCY: "filterPaymentCurrency",
393
- DIRECTION: "filterPaymentyDirection",
656
+ DIRECTION: "filterPaymentDirection",
394
657
  FROM: "filterPaymentDateFrom",
395
658
  TO: "filterPaymentDateTo",
396
- STATUS: "filterPaymentStatus"
659
+ STATUS: "filterPaymentStatus",
660
+ PAYMENT_TYPE: "filterPaymentType",
661
+ MIN_AMOUNT: "filterPaymentMinAmount",
662
+ MAX_AMOUNT: "filterPaymentMaxAmount",
663
+ VARIABLE_SYMBOL: "filterPaymentVariableSymbol",
664
+ SPECIFIC_SYMBOL: "filterPaymentSpecificSymbol",
665
+ CONSTANT_SYMBOL: "filterPaymentConstantSymbol",
666
+ MESSAGE: "filterPaymentMessage",
667
+ CREDITOR_IBAN: "filterPaymentCreditorIban",
668
+ DEBTOR_IBAN: "filterPaymentDebtorIban",
669
+ BATCH_ID: "filterPaymentBatchId"
397
670
  };
398
671
  const getPaymentsInputSchema = zod.z.object({
399
672
  page: zod.z.number().positive(),
@@ -409,7 +682,17 @@ const getPaymentsInputSchema = zod.z.object({
409
682
  [ALLOWED_PAYMENT_FILTERS.DIRECTION]: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_DIRECTIONS), zod.z.enum(paymentRequest_schema.PAYMENT_DIRECTIONS).array()]).optional(),
410
683
  [ALLOWED_PAYMENT_FILTERS.FROM]: zod.z.date().optional(),
411
684
  [ALLOWED_PAYMENT_FILTERS.TO]: zod.z.date().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()
685
+ [ALLOWED_PAYMENT_FILTERS.STATUS]: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES), zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES).array()]).optional(),
686
+ [ALLOWED_PAYMENT_FILTERS.PAYMENT_TYPE]: zod.z.enum(paymentRequest_schema.PAYMENT_TYPES).optional(),
687
+ [ALLOWED_PAYMENT_FILTERS.MIN_AMOUNT]: zod.z.number().positive().optional(),
688
+ [ALLOWED_PAYMENT_FILTERS.MAX_AMOUNT]: zod.z.number().positive().optional(),
689
+ [ALLOWED_PAYMENT_FILTERS.VARIABLE_SYMBOL]: zod.z.string().regex(/^\d{1,10}$/).optional(),
690
+ [ALLOWED_PAYMENT_FILTERS.SPECIFIC_SYMBOL]: zod.z.string().regex(/^\d{1,10}$/).optional(),
691
+ [ALLOWED_PAYMENT_FILTERS.CONSTANT_SYMBOL]: zod.z.string().regex(/^\d{4}$/).optional(),
692
+ [ALLOWED_PAYMENT_FILTERS.MESSAGE]: zod.z.string().optional(),
693
+ [ALLOWED_PAYMENT_FILTERS.CREDITOR_IBAN]: zod.z.string().optional(),
694
+ [ALLOWED_PAYMENT_FILTERS.DEBTOR_IBAN]: zod.z.string().optional(),
695
+ [ALLOWED_PAYMENT_FILTERS.BATCH_ID]: zod.z.uuid().optional()
413
696
  });
414
697
 
415
698
  const syncAccountInputSchema = zod.z.object({
@@ -448,6 +731,8 @@ const updateAccountInputSchema = zod.z.object({
448
731
  });
449
732
 
450
733
  const getBankAccountsInputSchema = zod.z.object({
734
+ page: zod.z.number().positive().optional(),
735
+ limit: zod.z.number().positive().optional(),
451
736
  includeWorkflow: zod.z.boolean().optional(),
452
737
  includeBatchCounts: zod.z.boolean().optional(),
453
738
  filterIbans: zod.z.array(zod.z.string()).optional(),
@@ -468,6 +753,34 @@ const handleAuthorizationCallbackInputSchema = zod.z.object({
468
753
 
469
754
  const sendPaymentSyncInputSchema = sendPaymentInputSchema;
470
755
 
756
+ const getPaymentRequestsInputSchema = zod.z.object({
757
+ page: zod.z.number().positive(),
758
+ limit: zod.z.number().positive(),
759
+ sort: zod.z.object({
760
+ column: zod.z.enum(["createdAt", "updatedAt", "amount"]),
761
+ direction: zod.z.enum(["asc", "desc"])
762
+ }),
763
+ filterAccountId: zod.z.union([zod.z.uuid(), zod.z.uuid().array()]).optional(),
764
+ filterStatus: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES), zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES).array()]).optional(),
765
+ filterPaymentType: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_TYPES), zod.z.enum(paymentRequest_schema.PAYMENT_TYPES).array()]).optional(),
766
+ filterCurrency: zod.z.union([zod.z.enum(generalCodes.CURRENCY_CODES), zod.z.enum(generalCodes.CURRENCY_CODES).array()]).optional(),
767
+ filterMinAmount: zod.z.number().positive().optional(),
768
+ filterMaxAmount: zod.z.number().positive().optional(),
769
+ filterBatchId: zod.z.uuid().optional(),
770
+ filterCreditorIban: zod.z.string().optional(),
771
+ filterDebtorIban: zod.z.string().optional(),
772
+ filterDateFrom: zod.z.date().optional(),
773
+ filterDateTo: zod.z.date().optional(),
774
+ filterVariableSymbol: zod.z.string().optional(),
775
+ filterSpecificSymbol: zod.z.string().optional(),
776
+ filterConstantSymbol: zod.z.string().optional(),
777
+ filterMessage: zod.z.string().optional(),
778
+ filterBankRefId: zod.z.string().optional(),
779
+ filterPaymentId: zod.z.uuid().optional(),
780
+ filterDirection: zod.z.enum(["INCOMING", "OUTGOING"]).optional(),
781
+ filterSource: zod.z.enum(["API", "BANK"]).optional()
782
+ });
783
+
471
784
  var __defProp = Object.defineProperty;
472
785
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
473
786
  var __decorateClass = (decorators, target, key, kind) => {
@@ -489,7 +802,9 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
489
802
  return await getAllAccountsQuery(this.db, filters);
490
803
  }
491
804
  async _getConnectedAccounts() {
492
- const accounts = await this._getAccounts();
805
+ const { accounts } = await this._getAccounts({
806
+ limit: Number.MAX_SAFE_INTEGER
807
+ });
493
808
  return accounts.filter((acc) => acc.status !== "DISABLED");
494
809
  }
495
810
  async _initiateBankConnector({
@@ -523,6 +838,27 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
523
838
  env: this.env
524
839
  });
525
840
  }
841
+ _validatePaymentTypeAndCurrency(paymentType, currency, creditor) {
842
+ const PAYMENT_TYPE_CURRENCY_MAP = {
843
+ DOMESTIC: ["CZK"],
844
+ SEPA: ["EUR"]
845
+ };
846
+ const allowedCurrencies = PAYMENT_TYPE_CURRENCY_MAP[paymentType];
847
+ if (allowedCurrencies && !allowedCurrencies.includes(currency)) {
848
+ throw backendSdk.createInternalError(null, {
849
+ message: `Payment type ${paymentType} requires currency ${allowedCurrencies.join(" or ")}, got ${currency}`,
850
+ code: "VALID-B-008",
851
+ status: 422
852
+ });
853
+ }
854
+ if (paymentType === "SEPA" && !creditor.iban) {
855
+ throw backendSdk.createInternalError(null, {
856
+ message: "SEPA payments require creditor IBAN",
857
+ code: "VALID-B-009",
858
+ status: 422
859
+ });
860
+ }
861
+ }
526
862
  async getPayments(input) {
527
863
  return this.handleAction(
528
864
  { data: input, schema: getPaymentsInputSchema },
@@ -806,50 +1142,49 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
806
1142
  }
807
1143
  );
808
1144
  }
809
- async addPaymentsToBatch({
810
- paymentsToBatch
811
- }) {
1145
+ async addPaymentsToBatch({ paymentIds }) {
812
1146
  return this.handleAction(null, {}, async () => {
813
- this.logInput({ paymentsToBatch });
814
- const incomingPayments = paymentsToBatch.map(mock_connector.toIncomingPayment);
815
- const accounts = await this._getAccounts();
816
- const { supportedPayments, unsupportedPayments } = seperateSupportedPayments(incomingPayments, accounts);
817
- if (unsupportedPayments.length > 0) {
818
- this.logError({ unsupportedPayments });
819
- await this.pushToQueue(
820
- this.env.QUEUE_BUS_QUEUE,
821
- unsupportedPayments.map((unsupported) => ({
822
- eventType: "BANK_PAYMENT",
823
- eventSignal: "paymentFailed",
824
- bankPayment: {
825
- ...unsupported,
826
- status: "FAILED",
827
- statusReason: "UNSUPPORTED_ACCOUNT"
828
- },
829
- metadata: {
830
- correlationId: unsupported.correlationId,
831
- entityId: unsupported.id,
832
- timestamp: (/* @__PURE__ */ new Date()).toDateString()
833
- }
834
- }))
835
- );
1147
+ this.logInput({ paymentIds });
1148
+ const paymentRequests = (await Promise.all(
1149
+ paymentIds.map(
1150
+ (id) => getPaymentRequestByIdQuery(this.db, { paymentId: id })
1151
+ )
1152
+ )).filter((p) => p !== null);
1153
+ const foundIds = new Set(paymentRequests.map((p) => p.id));
1154
+ const missingIds = paymentIds.filter((id) => !foundIds.has(id));
1155
+ if (missingIds.length > 0) {
1156
+ this.logError({ missingIds });
836
1157
  }
837
- for (const acc of accounts) {
838
- const accountAssignedPayments = supportedPayments.filter(
839
- (payment) => payment.debtorIban === acc.iban && payment.currency === acc.currency
840
- ).map((payment) => mock_connector.assignAccount(payment, acc));
841
- if (accountAssignedPayments.length === 0) {
1158
+ const byAccount = Map.groupBy(
1159
+ paymentRequests,
1160
+ (p) => `${p.accountId}:${p.paymentType}`
1161
+ );
1162
+ const { accounts } = await this._getAccounts();
1163
+ for (const [, paymentsOfType] of byAccount) {
1164
+ const first2 = paymentsOfType[0];
1165
+ const acc = accounts.find((a) => a.id === first2.accountId);
1166
+ if (!acc) {
1167
+ this.logError({ message: `Account not found: ${first2.accountId}` });
1168
+ await Promise.all(
1169
+ paymentsOfType.map(
1170
+ (p) => drizzle.updatePaymentRequestStatusCommand(this.db, {
1171
+ id: p.id,
1172
+ status: "FAILED",
1173
+ statusReason: "ACCOUNT_NOT_FOUND"
1174
+ }).command.execute()
1175
+ )
1176
+ );
842
1177
  continue;
843
1178
  }
844
- this.log({
845
- message: `\u{1F4B0} Processing ${accountAssignedPayments.length} payments for account (${acc.iban}, ${acc.currency})`
846
- });
847
- const singlePayments = accountAssignedPayments.filter(
1179
+ const singlePayments = paymentsOfType.filter(
848
1180
  (p) => p.sendAsSinglePayment === true
849
1181
  );
850
- const regularPayments = accountAssignedPayments.filter(
1182
+ const regularPayments = paymentsOfType.filter(
851
1183
  (p) => p.sendAsSinglePayment !== true
852
1184
  );
1185
+ this.log({
1186
+ message: `\u{1F4B0} Processing ${paymentsOfType.length} payments for account (${acc.iban}, ${acc.currency})`
1187
+ });
853
1188
  for (const singlePayment of singlePayments) {
854
1189
  const batchId = backendSdk.uuidv4();
855
1190
  const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
@@ -862,73 +1197,67 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
862
1197
  metadata: { sizeLimit: 1 }
863
1198
  }
864
1199
  });
865
- const { command: insertPaymentRequest } = createPaymentRequestCommand(
1200
+ const { command: updateRequest } = drizzle.updatePaymentRequestStatusCommand(
866
1201
  this.db,
867
- {
868
- paymentRequest: mock_connector.toPaymentRequestInsert(singlePayment, batchId)
869
- }
1202
+ { id: singlePayment.id, status: "CREATED", batchId }
870
1203
  );
871
- await this.db.batch([upsertBatch, insertPaymentRequest]);
1204
+ await this.db.batch([upsertBatch, updateRequest]);
872
1205
  this.log({
873
1206
  message: `\u2728 Created single payment batch (${singlePayment.paymentType}) for account ${acc.id}`
874
1207
  });
875
1208
  }
876
1209
  if (regularPayments.length > 0) {
877
- const paymentsByType = Map.groupBy(
878
- regularPayments,
879
- (p) => p.paymentType
880
- );
881
- for (const [paymentType, paymentsOfType] of paymentsByType) {
882
- const openBatches = await getAccountOpenBatchesQuery(this.db, {
883
- accountId: acc.id,
884
- paymentType
885
- });
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
- });
1210
+ const openBatches = await getAccountOpenBatchesQuery(this.db, {
1211
+ accountId: acc.id,
1212
+ paymentType: first2.paymentType
1213
+ });
1214
+ let batchId;
1215
+ let availableCount = 0;
1216
+ let availableBatch;
1217
+ for (const ob of openBatches) {
1218
+ const existingPayments = await drizzle.getPaymentRequestsByBatchIdQuery(
1219
+ this.db,
1220
+ { batchId: ob.id }
1221
+ );
1222
+ const limit = ob.metadata?.sizeLimit ?? acc.batchSizeLimit;
1223
+ if (existingPayments.length < limit) {
1224
+ availableBatch = ob;
1225
+ availableCount = existingPayments.length;
1226
+ break;
911
1227
  }
912
- const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
913
- batch: availableBatch ? { ...availableBatch } : {
914
- id: batchId,
915
- authorizationUrls: [],
916
- accountId: acc.id,
917
- paymentType,
918
- status: "OPEN",
919
- metadata: { sizeLimit: acc.batchSizeLimit }
920
- }
1228
+ }
1229
+ if (availableBatch) {
1230
+ batchId = availableBatch.id;
1231
+ this.log({
1232
+ message: `\u{1F504} Found existing OPEN batch (${first2.paymentType}) for account ${acc.id}, merging ${availableCount} existing + ${regularPayments.length} new payments`
921
1233
  });
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]);
1234
+ } else {
1235
+ batchId = backendSdk.uuidv4();
928
1236
  this.log({
929
- message: `\u2705 Batch (${paymentType}) upserted successfully for account ${acc.id}`
1237
+ message: `\u2728 Creating new batch (${first2.paymentType}) for account ${acc.id} with ${regularPayments.length} payments`
930
1238
  });
931
1239
  }
1240
+ const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
1241
+ batch: availableBatch ? { ...availableBatch } : {
1242
+ id: batchId,
1243
+ authorizationUrls: [],
1244
+ accountId: acc.id,
1245
+ paymentType: first2.paymentType,
1246
+ status: "OPEN",
1247
+ metadata: { sizeLimit: acc.batchSizeLimit }
1248
+ }
1249
+ });
1250
+ const updateCommands = regularPayments.map(
1251
+ (p) => drizzle.updatePaymentRequestStatusCommand(this.db, {
1252
+ id: p.id,
1253
+ status: "CREATED",
1254
+ batchId
1255
+ }).command
1256
+ );
1257
+ await this.db.batch([upsertBatch, ...updateCommands]);
1258
+ this.log({
1259
+ message: `\u2705 Batch (${first2.paymentType}) upserted successfully for account ${acc.id}`
1260
+ });
932
1261
  }
933
1262
  }
934
1263
  });
@@ -985,7 +1314,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
985
1314
  async () => {
986
1315
  this.logQueuePull(b);
987
1316
  const queueHandlerResponse = await this.addPaymentsToBatch({
988
- paymentsToBatch: b.messages.map(({ body }) => body)
1317
+ paymentIds: b.messages.map(({ body }) => body.paymentId)
989
1318
  });
990
1319
  this.logOutput(queueHandlerResponse);
991
1320
  }
@@ -1051,7 +1380,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1051
1380
  const { credentials, accounts } = await connector.authorizeAccount({
1052
1381
  urlParams
1053
1382
  });
1054
- const alreadyExistingAccounts = (await this._getAccounts()).filter(
1383
+ const alreadyExistingAccounts = (await this._getAccounts()).accounts.filter(
1055
1384
  (acc) => acc.connectorKey === ottRow.refId && accounts.map((item) => item.iban).includes(acc.iban)
1056
1385
  );
1057
1386
  const upsertAccounts = accounts.map((acc) => {
@@ -1099,7 +1428,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1099
1428
  ...upsertAccounts,
1100
1429
  ...createAccountCredentials
1101
1430
  ]);
1102
- const fetchedAccounts = await this._getAccounts();
1431
+ const { accounts: fetchedAccounts } = await this._getAccounts();
1103
1432
  if (!fetchedAccounts)
1104
1433
  throw backendSdk.createInternalError(null, {
1105
1434
  message: "Account not found",
@@ -1107,7 +1436,11 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1107
1436
  status: 404
1108
1437
  });
1109
1438
  if (startSync) {
1110
- for (const account of fetchedAccounts) {
1439
+ const newAccountIbans = new Set(accounts.map((a) => a.iban));
1440
+ const accountsToSync = fetchedAccounts.filter(
1441
+ (a) => newAccountIbans.has(a.iban)
1442
+ );
1443
+ for (const account of accountsToSync) {
1111
1444
  const { error } = await this.syncAccount({
1112
1445
  accountId: account.id
1113
1446
  });
@@ -1149,12 +1482,18 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1149
1482
  code: "VALID-B-003",
1150
1483
  status: 422
1151
1484
  });
1485
+ if (account.connectorKey !== connectorKey)
1486
+ throw backendSdk.createInternalError(null, {
1487
+ message: `Connector key mismatch: account uses ${account.connectorKey}, got ${connectorKey}`,
1488
+ code: "VALID-B-010",
1489
+ status: 422
1490
+ });
1152
1491
  const payment = {
1153
1492
  id: backendSdk.uuidv4(),
1154
1493
  bankRefId: backendSdk.uuidv4(),
1155
1494
  correlationId: backendSdk.uuidv4(),
1156
1495
  amount,
1157
- connectorKey,
1496
+ connectorKey: account.connectorKey,
1158
1497
  accountId: account.id,
1159
1498
  direction: "INCOMING",
1160
1499
  paymentType: "DOMESTIC",
@@ -1194,10 +1533,51 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1194
1533
  { data: input, schema: sendPaymentInputSchema },
1195
1534
  { successMessage: "Payment queued successfully" },
1196
1535
  async (data) => {
1536
+ const incomingPayment = mock_connector.toIncomingPayment(data);
1537
+ const { accounts } = await this._getAccounts();
1538
+ const account = accounts.find(
1539
+ (acc) => acc.iban === incomingPayment.debtorIban && acc.currency === incomingPayment.currency
1540
+ );
1541
+ if (!account) {
1542
+ throw backendSdk.createInternalError(null, {
1543
+ message: `No account found for IBAN ${incomingPayment.debtorIban} with currency ${incomingPayment.currency}`,
1544
+ code: "VALID-B-004",
1545
+ status: 422
1546
+ });
1547
+ }
1548
+ if (account.status !== "AUTHORIZED") {
1549
+ throw backendSdk.createInternalError(null, {
1550
+ message: `Account ${account.iban} is not authorized (status: ${account.status})`,
1551
+ code: "VALID-B-007",
1552
+ status: 422
1553
+ });
1554
+ }
1555
+ const connector = await this._initiateBankConnector({
1556
+ connectorKey: account.connectorKey
1557
+ });
1558
+ if (!connector.supportsPaymentType(data.paymentType)) {
1559
+ throw backendSdk.createInternalError(null, {
1560
+ message: `Connector ${account.connectorKey} does not support ${data.paymentType} payments yet`,
1561
+ code: "VALID-B-006",
1562
+ status: 422
1563
+ });
1564
+ }
1565
+ this._validatePaymentTypeAndCurrency(
1566
+ data.paymentType,
1567
+ data.currency,
1568
+ data.creditor
1569
+ );
1570
+ const accountAssigned = mock_connector.assignAccount(incomingPayment, account);
1571
+ const { command: insertPaymentRequest } = createPaymentRequestCommand(
1572
+ this.db,
1573
+ { paymentRequest: mock_connector.toPaymentRequestInsert(accountAssigned, null) }
1574
+ );
1575
+ await insertPaymentRequest.execute();
1197
1576
  await this.pushToQueue(
1198
1577
  this.env.PAYMENTS_READY_TO_BATCH_QUEUE,
1199
- data
1578
+ { paymentId: incomingPayment.id }
1200
1579
  );
1580
+ return { paymentId: incomingPayment.id };
1201
1581
  }
1202
1582
  );
1203
1583
  }
@@ -1207,7 +1587,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1207
1587
  { successMessage: "Payment initiated successfully" },
1208
1588
  async (data) => {
1209
1589
  const incomingPayment = mock_connector.toIncomingPayment(data);
1210
- const accounts = await this._getAccounts();
1590
+ const { accounts } = await this._getAccounts();
1211
1591
  const account = accounts.find(
1212
1592
  (acc) => acc.iban === incomingPayment.debtorIban && acc.currency === incomingPayment.currency
1213
1593
  );
@@ -1218,12 +1598,31 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1218
1598
  status: 422
1219
1599
  });
1220
1600
  }
1601
+ if (account.status !== "AUTHORIZED") {
1602
+ throw backendSdk.createInternalError(null, {
1603
+ message: `Account ${account.iban} is not authorized (status: ${account.status})`,
1604
+ code: "VALID-B-007",
1605
+ status: 422
1606
+ });
1607
+ }
1221
1608
  const batchedPayment = mock_connector.toBatchedPayment(
1222
1609
  mock_connector.assignAccount(incomingPayment, account)
1223
1610
  );
1224
1611
  const connector = await this._initiateBankConnector({
1225
1612
  connectorKey: account.connectorKey
1226
1613
  });
1614
+ if (!connector.supportsPaymentType(data.paymentType)) {
1615
+ throw backendSdk.createInternalError(null, {
1616
+ message: `Connector ${account.connectorKey} does not support ${data.paymentType} payments yet`,
1617
+ code: "VALID-B-006",
1618
+ status: 422
1619
+ });
1620
+ }
1621
+ this._validatePaymentTypeAndCurrency(
1622
+ data.paymentType,
1623
+ data.currency,
1624
+ data.creditor
1625
+ );
1227
1626
  const initiate = () => {
1228
1627
  switch (data.paymentType) {
1229
1628
  case "DOMESTIC":
@@ -1252,16 +1651,20 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1252
1651
  { data: input, schema: getBankAccountsInputSchema },
1253
1652
  { successMessage: "Bank accounts retrieved successfully" },
1254
1653
  async ({
1654
+ page,
1655
+ limit,
1255
1656
  includeWorkflow,
1256
1657
  includeBatchCounts,
1257
1658
  filterIbans,
1258
1659
  filterCurrencies,
1259
1660
  filterBankRefIds
1260
1661
  }) => {
1261
- const accounts = await this._getAccounts({
1662
+ const { accounts, totalCount } = await this._getAccounts({
1262
1663
  filterIbans,
1263
1664
  filterCurrencies,
1264
- filterBankRefIds
1665
+ filterBankRefIds,
1666
+ page,
1667
+ limit
1265
1668
  });
1266
1669
  const accountsWithOptionalFields = await Promise.all(
1267
1670
  accounts.map(async (a) => {
@@ -1295,7 +1698,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1295
1698
  );
1296
1699
  return {
1297
1700
  accounts: accountsWithOptionalFields,
1298
- totalCount: accounts.length
1701
+ totalCount
1299
1702
  };
1300
1703
  }
1301
1704
  );
@@ -1413,6 +1816,34 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1413
1816
  }
1414
1817
  );
1415
1818
  }
1819
+ async getPaymentRequests(input) {
1820
+ return this.handleAction(
1821
+ { data: input, schema: getPaymentRequestsInputSchema },
1822
+ { successMessage: "Payment requests fetched successfully" },
1823
+ async (params) => {
1824
+ return await getPaymentRequestsWithPaginationQuery(this.db, params);
1825
+ }
1826
+ );
1827
+ }
1828
+ async getPaymentRequest(input) {
1829
+ return this.handleAction(
1830
+ null,
1831
+ { successMessage: "Payment request fetched successfully" },
1832
+ async () => {
1833
+ const paymentRequest = await getPaymentRequestByIdQuery(this.db, {
1834
+ paymentId: input.paymentId
1835
+ });
1836
+ if (!paymentRequest) {
1837
+ throw backendSdk.createInternalError(null, {
1838
+ message: `Payment request not found: ${input.paymentId}`,
1839
+ code: "NOT-FOUND-B-001",
1840
+ status: 404
1841
+ });
1842
+ }
1843
+ return { paymentRequest };
1844
+ }
1845
+ );
1846
+ }
1416
1847
  async getFinbricksSupportedBanks() {
1417
1848
  const privateKeyPem = (await this.env.SECRETS_STORE.get({
1418
1849
  secretName: "BANK_SERVICE_FINBRICKS_PRIVATE_KEY_PEM"
@@ -1486,6 +1917,12 @@ __decorateClass([
1486
1917
  __decorateClass([
1487
1918
  backendSdk.action("getBatches")
1488
1919
  ], BankServiceBase.prototype, "getBatches", 1);
1920
+ __decorateClass([
1921
+ backendSdk.action("get-payment-requests")
1922
+ ], BankServiceBase.prototype, "getPaymentRequests", 1);
1923
+ __decorateClass([
1924
+ backendSdk.action("get-payment-request")
1925
+ ], BankServiceBase.prototype, "getPaymentRequest", 1);
1489
1926
  BankServiceBase = __decorateClass([
1490
1927
  backendSdk.service("bank")
1491
1928
  ], BankServiceBase);