@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.
- 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 +583 -146
- package/dist/export/worker.d.cts +286 -44
- package/dist/export/worker.d.mts +286 -44
- package/dist/export/worker.d.ts +286 -44
- package/dist/export/worker.mjs +584 -147
- package/dist/export/workflows.cjs +132 -16
- package/dist/export/workflows.mjs +133 -17
- package/dist/shared/{bank.C-T1FQxg.cjs → bank.62VzK9Aj.cjs} +1 -1
- package/dist/shared/{bank.SQ4Mmr8u.cjs → bank.BS7fFjGA.cjs} +34 -4
- package/dist/shared/{bank.6faPHUEY.d.ts → bank.BYRq3yJf.d.ts} +81 -11
- package/dist/shared/{bank.C4VOdIx1.mjs → bank.C0UN6luZ.mjs} +34 -4
- package/dist/shared/{bank.DDHrdFgy.mjs → bank.CA5ytXxp.mjs} +1 -1
- package/dist/shared/{bank.BoWCMu5n.d.cts → bank.CO89tR9U.d.cts} +81 -11
- package/dist/shared/{bank.BaMRCHk-.d.ts → bank.Cns5ss41.d.cts} +55 -18
- package/dist/shared/{bank.BaMRCHk-.d.cts → bank.Cns5ss41.d.mts} +55 -18
- package/dist/shared/{bank.BaMRCHk-.d.mts → bank.Cns5ss41.d.ts} +55 -18
- package/dist/shared/{bank.DOL1uM4n.d.mts → bank.CreoSb2d.d.mts} +81 -11
- package/dist/shared/{bank.DRrBrAdI.mjs → bank.D1jqaHaF.mjs} +91 -31
- package/dist/shared/{bank.Cpy9PULF.mjs → bank.DEmzZGZW.mjs} +31 -5
- package/dist/shared/{bank.BOnP9p9Y.cjs → bank.Dm8GHThw.cjs} +31 -5
- package/dist/shared/{bank.CQURey1E.cjs → bank.DwyCCyd0.cjs} +90 -31
- package/dist/types.cjs +3 -4
- package/dist/types.d.cts +8 -16
- package/dist/types.d.mts +8 -16
- package/dist/types.d.ts +8 -16
- package/dist/types.mjs +3 -3
- package/package.json +2 -2
package/dist/export/worker.cjs
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
274
|
-
|
|
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
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
-
|
|
294
|
-
|
|
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: "
|
|
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({
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
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
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
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
|
-
|
|
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 =
|
|
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:
|
|
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,
|
|
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
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
);
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
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
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
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
|
-
|
|
923
|
-
|
|
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: `\
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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);
|