@develit-services/bank 0.8.6 → 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 +251 -39
- package/dist/export/worker.d.mts +251 -39
- package/dist/export/worker.d.ts +251 -39
- 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.B6U8sUZn.d.mts → bank.BYRq3yJf.d.ts} +17 -7
- 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.BoMDujsl.d.ts → bank.CO89tR9U.d.cts} +17 -7
- package/dist/shared/{bank.BliD3oCT.d.ts → bank.Cns5ss41.d.cts} +47 -10
- package/dist/shared/{bank.BliD3oCT.d.cts → bank.Cns5ss41.d.mts} +47 -10
- package/dist/shared/{bank.BliD3oCT.d.mts → bank.Cns5ss41.d.ts} +47 -10
- package/dist/shared/{bank.lbzMqyr3.d.cts → bank.CreoSb2d.d.mts} +17 -7
- 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
|
@@ -1,22 +1,22 @@
|
|
|
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 batchLifecycle = require('../shared/bank.Bg3Pdwm4.cjs');
|
|
6
|
-
const mock_connector = require('../shared/bank.
|
|
6
|
+
const mock_connector = require('../shared/bank.DwyCCyd0.cjs');
|
|
7
7
|
const drizzleOrm = require('drizzle-orm');
|
|
8
|
+
require('drizzle-orm/sqlite-core');
|
|
8
9
|
const cloudflare_workers = require('cloudflare:workers');
|
|
9
10
|
const cloudflare_workflows = require('cloudflare:workflows');
|
|
10
11
|
const d1 = require('drizzle-orm/d1');
|
|
11
12
|
require('node:crypto');
|
|
12
|
-
require('../shared/bank.
|
|
13
|
+
require('../shared/bank.BS7fFjGA.cjs');
|
|
13
14
|
require('drizzle-orm/relations');
|
|
14
|
-
require('drizzle-orm/sqlite-core');
|
|
15
15
|
require('date-fns');
|
|
16
16
|
require('jose');
|
|
17
17
|
require('@develit-io/general-codes');
|
|
18
18
|
require('drizzle-zod');
|
|
19
|
-
require('../shared/bank.
|
|
19
|
+
require('../shared/bank.62VzK9Aj.cjs');
|
|
20
20
|
|
|
21
21
|
const updateAccountLastSyncCommand = (db, {
|
|
22
22
|
lastSyncAt,
|
|
@@ -92,13 +92,18 @@ class BankProcessBatch extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
92
92
|
const batchedPayments = paymentRequests.map(
|
|
93
93
|
mock_connector.toBatchedPaymentFromPaymentRequest
|
|
94
94
|
);
|
|
95
|
-
|
|
95
|
+
const currentBatch = await drizzle.getBatchByIdQuery(db, { batchId });
|
|
96
|
+
if (currentBatch?.batchPaymentInitiatedAt) {
|
|
96
97
|
return {
|
|
97
|
-
authorizationUrls:
|
|
98
|
+
authorizationUrls: currentBatch.authorizationUrls,
|
|
98
99
|
preparedPayments: batchedPayments.map(
|
|
99
|
-
(p) => mock_connector.toPreparedPayment(
|
|
100
|
+
(p) => mock_connector.toPreparedPayment(
|
|
101
|
+
p,
|
|
102
|
+
void 0,
|
|
103
|
+
currentBatch.batchPaymentInitiatedAt
|
|
104
|
+
)
|
|
100
105
|
),
|
|
101
|
-
metadata:
|
|
106
|
+
metadata: currentBatch.metadata
|
|
102
107
|
};
|
|
103
108
|
}
|
|
104
109
|
const account = await drizzle.getAccountByIdQuery(db, {
|
|
@@ -138,6 +143,17 @@ class BankProcessBatch extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
138
143
|
const message = err instanceof Error ? err.message : typeof err === "object" && err !== null && "message" in err ? String(err.message) : String(err);
|
|
139
144
|
const status = typeof err === "object" && err !== null && "status" in err ? Number(err.status) : 0;
|
|
140
145
|
if (status >= 400 && status < 500) {
|
|
146
|
+
const updateCommands = paymentRequests.map(
|
|
147
|
+
(p) => drizzle.updatePaymentRequestStatusCommand(db, {
|
|
148
|
+
id: p.id,
|
|
149
|
+
status: "FAILED",
|
|
150
|
+
statusReason: message,
|
|
151
|
+
processedAt: /* @__PURE__ */ new Date()
|
|
152
|
+
}).command
|
|
153
|
+
);
|
|
154
|
+
if (updateCommands.length > 0) {
|
|
155
|
+
await db.batch(updateCommands);
|
|
156
|
+
}
|
|
141
157
|
throw new cloudflare_workflows.NonRetryableError(message);
|
|
142
158
|
}
|
|
143
159
|
throw new Error(message);
|
|
@@ -201,7 +217,8 @@ class BankProcessBatch extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
201
217
|
id: p.id,
|
|
202
218
|
status: "COMPLETED",
|
|
203
219
|
bankRefId: `MOCK-${backendSdk.uuidv4()}`,
|
|
204
|
-
processedAt
|
|
220
|
+
processedAt,
|
|
221
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
205
222
|
}).command
|
|
206
223
|
);
|
|
207
224
|
const updateBatchCommand = drizzle.upsertBatchCommand(db, {
|
|
@@ -330,11 +347,87 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
330
347
|
"process new payments and update lastSyncAt",
|
|
331
348
|
async () => {
|
|
332
349
|
const eventsToEmit = [];
|
|
333
|
-
const
|
|
350
|
+
const prIds = paymentsToInsert.map((p) => p.parsed.paymentRequestId).filter((id) => id != null);
|
|
351
|
+
const bankRefIds = paymentsToInsert.filter((p) => p.parsed.paymentRequestId == null).map((p) => p.parsed.bankRefId);
|
|
352
|
+
const [matchingByPrId, matchingByBankRefId] = await Promise.all([
|
|
353
|
+
prIds.length > 0 ? db.select().from(drizzle.tables.paymentRequest).where(drizzleOrm.inArray(drizzle.tables.paymentRequest.id, prIds)) : Promise.resolve([]),
|
|
354
|
+
bankRefIds.length > 0 ? db.select().from(drizzle.tables.paymentRequest).where(
|
|
355
|
+
drizzleOrm.and(
|
|
356
|
+
drizzleOrm.inArray(drizzle.tables.paymentRequest.bankRefId, bankRefIds),
|
|
357
|
+
drizzleOrm.eq(drizzle.tables.paymentRequest.accountId, account.id),
|
|
358
|
+
drizzleOrm.eq(
|
|
359
|
+
drizzle.tables.paymentRequest.connectorKey,
|
|
360
|
+
account.connectorKey
|
|
361
|
+
),
|
|
362
|
+
drizzleOrm.isNull(drizzle.tables.paymentRequest.deletedAt)
|
|
363
|
+
)
|
|
364
|
+
) : Promise.resolve([])
|
|
365
|
+
]);
|
|
366
|
+
const requestById = Object.fromEntries(
|
|
367
|
+
matchingByPrId.map((r) => [r.id, r])
|
|
368
|
+
);
|
|
369
|
+
const requestByBankRefId = Object.fromEntries(
|
|
370
|
+
matchingByBankRefId.map((r) => [r.bankRefId, r])
|
|
371
|
+
);
|
|
372
|
+
const enrichedPayments = paymentsToInsert.map((p) => {
|
|
373
|
+
const req = p.parsed.paymentRequestId ? requestById[p.parsed.paymentRequestId] : requestByBankRefId[p.parsed.bankRefId];
|
|
374
|
+
if (!req) return p;
|
|
375
|
+
return {
|
|
376
|
+
...p,
|
|
377
|
+
parsed: {
|
|
378
|
+
...p.parsed,
|
|
379
|
+
// Set paymentRequestId if missing (bankRefId fallback match)
|
|
380
|
+
paymentRequestId: p.parsed.paymentRequestId ?? req.id,
|
|
381
|
+
createdAt: req.createdAt ?? p.parsed.createdAt,
|
|
382
|
+
batchId: p.parsed.batchId ?? req.batchId,
|
|
383
|
+
refId: p.parsed.refId ?? req.refId,
|
|
384
|
+
chargeBearer: p.parsed.chargeBearer ?? req.chargeBearer,
|
|
385
|
+
instructionPriority: p.parsed.instructionPriority ?? req.instructionPriority,
|
|
386
|
+
message: p.parsed.message ?? req.message,
|
|
387
|
+
vs: p.parsed.vs ?? req.vs,
|
|
388
|
+
ss: p.parsed.ss ?? req.ss,
|
|
389
|
+
ks: p.parsed.ks ?? req.ks,
|
|
390
|
+
creditor: {
|
|
391
|
+
...p.parsed.creditor,
|
|
392
|
+
holderName: p.parsed.creditor?.holderName ?? req.creditor?.holderName,
|
|
393
|
+
address: p.parsed.creditor?.address ?? req.creditor?.address,
|
|
394
|
+
swiftBic: p.parsed.creditor?.swiftBic ?? req.creditor?.swiftBic
|
|
395
|
+
},
|
|
396
|
+
debtor: {
|
|
397
|
+
...p.parsed.debtor,
|
|
398
|
+
holderName: p.parsed.debtor?.holderName ?? req.debtor?.holderName
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
});
|
|
403
|
+
const createCommands = enrichedPayments.map(
|
|
334
404
|
(p) => drizzle.createPaymentCommand(db, { payment: p.parsed }).command
|
|
335
405
|
);
|
|
406
|
+
const softDeleteCommands = enrichedPayments.map(
|
|
407
|
+
(p) => db.update(drizzle.tables.paymentRequest).set({
|
|
408
|
+
deletedAt: now,
|
|
409
|
+
status: p.parsed.status,
|
|
410
|
+
statusReason: p.parsed.statusReason ?? null
|
|
411
|
+
}).where(
|
|
412
|
+
drizzleOrm.or(
|
|
413
|
+
// Primary: match via paymentRequestId (our ID echoed back by bank)
|
|
414
|
+
p.parsed.paymentRequestId ? drizzleOrm.eq(drizzle.tables.paymentRequest.id, p.parsed.paymentRequestId) : void 0,
|
|
415
|
+
// Fallback: match via bankRefId (set during processBatch)
|
|
416
|
+
drizzleOrm.and(
|
|
417
|
+
drizzleOrm.isNotNull(drizzle.tables.paymentRequest.bankRefId),
|
|
418
|
+
drizzleOrm.eq(drizzle.tables.paymentRequest.bankRefId, p.parsed.bankRefId),
|
|
419
|
+
drizzleOrm.eq(drizzle.tables.paymentRequest.accountId, account.id),
|
|
420
|
+
drizzleOrm.eq(
|
|
421
|
+
drizzle.tables.paymentRequest.connectorKey,
|
|
422
|
+
account.connectorKey
|
|
423
|
+
),
|
|
424
|
+
drizzleOrm.isNull(drizzle.tables.paymentRequest.deletedAt)
|
|
425
|
+
)
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
);
|
|
336
429
|
eventsToEmit.push(
|
|
337
|
-
...
|
|
430
|
+
...enrichedPayments.map((p) => ({
|
|
338
431
|
eventType: "BANK_PAYMENT",
|
|
339
432
|
eventSignal: "paymentCreated",
|
|
340
433
|
bankPayment: p.parsed,
|
|
@@ -349,9 +442,7 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
349
442
|
payments: payments.length,
|
|
350
443
|
paymentsToProcess: paymentsToProcess.length,
|
|
351
444
|
paymentsInserted: paymentsToInsert.length,
|
|
352
|
-
lastSyncBankRefIds: paymentsToProcess.map(
|
|
353
|
-
(p) => p.parsed.bankRefId
|
|
354
|
-
),
|
|
445
|
+
lastSyncBankRefIds: paymentsToProcess.filter((p) => p.parsed.status === "COMPLETED").map((p) => p.parsed.bankRefId),
|
|
355
446
|
lastSyncPayments: lastSyncBankRefIds.length,
|
|
356
447
|
eventsEmitted: eventsToEmit.length
|
|
357
448
|
};
|
|
@@ -362,13 +453,38 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
362
453
|
}).command;
|
|
363
454
|
if (eventsToEmit.length) {
|
|
364
455
|
await db.batch(
|
|
365
|
-
backendSdk.asNonEmpty([
|
|
456
|
+
backendSdk.asNonEmpty([
|
|
457
|
+
updateLastSyncCommand,
|
|
458
|
+
...createCommands,
|
|
459
|
+
...softDeleteCommands
|
|
460
|
+
])
|
|
366
461
|
);
|
|
367
462
|
await pushToQueue(
|
|
368
463
|
this.env.QUEUE_BUS_QUEUE,
|
|
369
464
|
eventsToEmit
|
|
370
465
|
);
|
|
371
466
|
}
|
|
467
|
+
const paymentRequestIds = enrichedPayments.map((p) => p.parsed.paymentRequestId).filter((id) => id != null);
|
|
468
|
+
if (paymentRequestIds.length > 0) {
|
|
469
|
+
const processedPRs = await db.select({ batchId: drizzle.tables.paymentRequest.batchId }).from(drizzle.tables.paymentRequest).where(drizzleOrm.inArray(drizzle.tables.paymentRequest.id, paymentRequestIds));
|
|
470
|
+
const batchIds = [
|
|
471
|
+
...new Set(
|
|
472
|
+
processedPRs.map((pr) => pr.batchId).filter((id) => id != null)
|
|
473
|
+
)
|
|
474
|
+
];
|
|
475
|
+
for (const batchId of batchIds) {
|
|
476
|
+
const allPRsInBatch = await db.select({ deletedAt: drizzle.tables.paymentRequest.deletedAt }).from(drizzle.tables.paymentRequest).where(drizzleOrm.eq(drizzle.tables.paymentRequest.batchId, batchId));
|
|
477
|
+
const allDone = allPRsInBatch.length > 0 && allPRsInBatch.every((pr) => pr.deletedAt != null);
|
|
478
|
+
if (allDone) {
|
|
479
|
+
const batch = await drizzle.getBatchByIdQuery(db, { batchId });
|
|
480
|
+
if (batch && batch.status !== "COMPLETED" && batch.status !== "FAILED") {
|
|
481
|
+
await drizzle.upsertBatchCommand(db, {
|
|
482
|
+
batch: { ...batch, status: "COMPLETED" }
|
|
483
|
+
}).command.execute();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
372
488
|
return {
|
|
373
489
|
...lastSyncMetadata,
|
|
374
490
|
newLastSyncAt: now
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { first, uuidv4, asNonEmpty } from '@develit-io/backend-sdk';
|
|
2
|
-
import { t as tables, g as getBatchByIdQuery, a as getPaymentRequestsByBatchIdQuery, c as checksum, u as upsertBatchCommand, b as getAccountByIdQuery, d as createCredentialsResolver, e as updatePaymentRequestStatusCommand, f as createPaymentCommand } from '../shared/bank.
|
|
2
|
+
import { t as tables, g as getBatchByIdQuery, a as getPaymentRequestsByBatchIdQuery, c as checksum, u as upsertBatchCommand, b as getAccountByIdQuery, d as createCredentialsResolver, e as updatePaymentRequestStatusCommand, f as createPaymentCommand } from '../shared/bank.DEmzZGZW.mjs';
|
|
3
3
|
import { f as isBatchSigned, a as isBatchFailed, c as isBatchOpen, g as isPaymentCompleted } from '../shared/bank.CbAwwIhZ.mjs';
|
|
4
|
-
import {
|
|
5
|
-
import { eq } from 'drizzle-orm';
|
|
4
|
+
import { e as toBatchedPaymentFromPaymentRequest, i as toPreparedPayment, j as initiateConnector } from '../shared/bank.D1jqaHaF.mjs';
|
|
5
|
+
import { eq, inArray, and, isNull, or, isNotNull } from 'drizzle-orm';
|
|
6
|
+
import 'drizzle-orm/sqlite-core';
|
|
6
7
|
import { WorkflowEntrypoint } from 'cloudflare:workers';
|
|
7
8
|
import { NonRetryableError } from 'cloudflare:workflows';
|
|
8
9
|
import { drizzle } from 'drizzle-orm/d1';
|
|
9
10
|
import 'node:crypto';
|
|
10
|
-
import '../shared/bank.
|
|
11
|
+
import '../shared/bank.C0UN6luZ.mjs';
|
|
11
12
|
import 'drizzle-orm/relations';
|
|
12
|
-
import 'drizzle-orm/sqlite-core';
|
|
13
13
|
import 'date-fns';
|
|
14
14
|
import 'jose';
|
|
15
15
|
import '@develit-io/general-codes';
|
|
16
16
|
import 'drizzle-zod';
|
|
17
|
-
import '../shared/bank.
|
|
17
|
+
import '../shared/bank.CA5ytXxp.mjs';
|
|
18
18
|
|
|
19
19
|
const updateAccountLastSyncCommand = (db, {
|
|
20
20
|
lastSyncAt,
|
|
@@ -90,13 +90,18 @@ class BankProcessBatch extends WorkflowEntrypoint {
|
|
|
90
90
|
const batchedPayments = paymentRequests.map(
|
|
91
91
|
toBatchedPaymentFromPaymentRequest
|
|
92
92
|
);
|
|
93
|
-
|
|
93
|
+
const currentBatch = await getBatchByIdQuery(db, { batchId });
|
|
94
|
+
if (currentBatch?.batchPaymentInitiatedAt) {
|
|
94
95
|
return {
|
|
95
|
-
authorizationUrls:
|
|
96
|
+
authorizationUrls: currentBatch.authorizationUrls,
|
|
96
97
|
preparedPayments: batchedPayments.map(
|
|
97
|
-
(p) => toPreparedPayment(
|
|
98
|
+
(p) => toPreparedPayment(
|
|
99
|
+
p,
|
|
100
|
+
void 0,
|
|
101
|
+
currentBatch.batchPaymentInitiatedAt
|
|
102
|
+
)
|
|
98
103
|
),
|
|
99
|
-
metadata:
|
|
104
|
+
metadata: currentBatch.metadata
|
|
100
105
|
};
|
|
101
106
|
}
|
|
102
107
|
const account = await getAccountByIdQuery(db, {
|
|
@@ -136,6 +141,17 @@ class BankProcessBatch extends WorkflowEntrypoint {
|
|
|
136
141
|
const message = err instanceof Error ? err.message : typeof err === "object" && err !== null && "message" in err ? String(err.message) : String(err);
|
|
137
142
|
const status = typeof err === "object" && err !== null && "status" in err ? Number(err.status) : 0;
|
|
138
143
|
if (status >= 400 && status < 500) {
|
|
144
|
+
const updateCommands = paymentRequests.map(
|
|
145
|
+
(p) => updatePaymentRequestStatusCommand(db, {
|
|
146
|
+
id: p.id,
|
|
147
|
+
status: "FAILED",
|
|
148
|
+
statusReason: message,
|
|
149
|
+
processedAt: /* @__PURE__ */ new Date()
|
|
150
|
+
}).command
|
|
151
|
+
);
|
|
152
|
+
if (updateCommands.length > 0) {
|
|
153
|
+
await db.batch(updateCommands);
|
|
154
|
+
}
|
|
139
155
|
throw new NonRetryableError(message);
|
|
140
156
|
}
|
|
141
157
|
throw new Error(message);
|
|
@@ -199,7 +215,8 @@ class BankProcessBatch extends WorkflowEntrypoint {
|
|
|
199
215
|
id: p.id,
|
|
200
216
|
status: "COMPLETED",
|
|
201
217
|
bankRefId: `MOCK-${uuidv4()}`,
|
|
202
|
-
processedAt
|
|
218
|
+
processedAt,
|
|
219
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
203
220
|
}).command
|
|
204
221
|
);
|
|
205
222
|
const updateBatchCommand = upsertBatchCommand(db, {
|
|
@@ -328,11 +345,87 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
328
345
|
"process new payments and update lastSyncAt",
|
|
329
346
|
async () => {
|
|
330
347
|
const eventsToEmit = [];
|
|
331
|
-
const
|
|
348
|
+
const prIds = paymentsToInsert.map((p) => p.parsed.paymentRequestId).filter((id) => id != null);
|
|
349
|
+
const bankRefIds = paymentsToInsert.filter((p) => p.parsed.paymentRequestId == null).map((p) => p.parsed.bankRefId);
|
|
350
|
+
const [matchingByPrId, matchingByBankRefId] = await Promise.all([
|
|
351
|
+
prIds.length > 0 ? db.select().from(tables.paymentRequest).where(inArray(tables.paymentRequest.id, prIds)) : Promise.resolve([]),
|
|
352
|
+
bankRefIds.length > 0 ? db.select().from(tables.paymentRequest).where(
|
|
353
|
+
and(
|
|
354
|
+
inArray(tables.paymentRequest.bankRefId, bankRefIds),
|
|
355
|
+
eq(tables.paymentRequest.accountId, account.id),
|
|
356
|
+
eq(
|
|
357
|
+
tables.paymentRequest.connectorKey,
|
|
358
|
+
account.connectorKey
|
|
359
|
+
),
|
|
360
|
+
isNull(tables.paymentRequest.deletedAt)
|
|
361
|
+
)
|
|
362
|
+
) : Promise.resolve([])
|
|
363
|
+
]);
|
|
364
|
+
const requestById = Object.fromEntries(
|
|
365
|
+
matchingByPrId.map((r) => [r.id, r])
|
|
366
|
+
);
|
|
367
|
+
const requestByBankRefId = Object.fromEntries(
|
|
368
|
+
matchingByBankRefId.map((r) => [r.bankRefId, r])
|
|
369
|
+
);
|
|
370
|
+
const enrichedPayments = paymentsToInsert.map((p) => {
|
|
371
|
+
const req = p.parsed.paymentRequestId ? requestById[p.parsed.paymentRequestId] : requestByBankRefId[p.parsed.bankRefId];
|
|
372
|
+
if (!req) return p;
|
|
373
|
+
return {
|
|
374
|
+
...p,
|
|
375
|
+
parsed: {
|
|
376
|
+
...p.parsed,
|
|
377
|
+
// Set paymentRequestId if missing (bankRefId fallback match)
|
|
378
|
+
paymentRequestId: p.parsed.paymentRequestId ?? req.id,
|
|
379
|
+
createdAt: req.createdAt ?? p.parsed.createdAt,
|
|
380
|
+
batchId: p.parsed.batchId ?? req.batchId,
|
|
381
|
+
refId: p.parsed.refId ?? req.refId,
|
|
382
|
+
chargeBearer: p.parsed.chargeBearer ?? req.chargeBearer,
|
|
383
|
+
instructionPriority: p.parsed.instructionPriority ?? req.instructionPriority,
|
|
384
|
+
message: p.parsed.message ?? req.message,
|
|
385
|
+
vs: p.parsed.vs ?? req.vs,
|
|
386
|
+
ss: p.parsed.ss ?? req.ss,
|
|
387
|
+
ks: p.parsed.ks ?? req.ks,
|
|
388
|
+
creditor: {
|
|
389
|
+
...p.parsed.creditor,
|
|
390
|
+
holderName: p.parsed.creditor?.holderName ?? req.creditor?.holderName,
|
|
391
|
+
address: p.parsed.creditor?.address ?? req.creditor?.address,
|
|
392
|
+
swiftBic: p.parsed.creditor?.swiftBic ?? req.creditor?.swiftBic
|
|
393
|
+
},
|
|
394
|
+
debtor: {
|
|
395
|
+
...p.parsed.debtor,
|
|
396
|
+
holderName: p.parsed.debtor?.holderName ?? req.debtor?.holderName
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
});
|
|
401
|
+
const createCommands = enrichedPayments.map(
|
|
332
402
|
(p) => createPaymentCommand(db, { payment: p.parsed }).command
|
|
333
403
|
);
|
|
404
|
+
const softDeleteCommands = enrichedPayments.map(
|
|
405
|
+
(p) => db.update(tables.paymentRequest).set({
|
|
406
|
+
deletedAt: now,
|
|
407
|
+
status: p.parsed.status,
|
|
408
|
+
statusReason: p.parsed.statusReason ?? null
|
|
409
|
+
}).where(
|
|
410
|
+
or(
|
|
411
|
+
// Primary: match via paymentRequestId (our ID echoed back by bank)
|
|
412
|
+
p.parsed.paymentRequestId ? eq(tables.paymentRequest.id, p.parsed.paymentRequestId) : void 0,
|
|
413
|
+
// Fallback: match via bankRefId (set during processBatch)
|
|
414
|
+
and(
|
|
415
|
+
isNotNull(tables.paymentRequest.bankRefId),
|
|
416
|
+
eq(tables.paymentRequest.bankRefId, p.parsed.bankRefId),
|
|
417
|
+
eq(tables.paymentRequest.accountId, account.id),
|
|
418
|
+
eq(
|
|
419
|
+
tables.paymentRequest.connectorKey,
|
|
420
|
+
account.connectorKey
|
|
421
|
+
),
|
|
422
|
+
isNull(tables.paymentRequest.deletedAt)
|
|
423
|
+
)
|
|
424
|
+
)
|
|
425
|
+
)
|
|
426
|
+
);
|
|
334
427
|
eventsToEmit.push(
|
|
335
|
-
...
|
|
428
|
+
...enrichedPayments.map((p) => ({
|
|
336
429
|
eventType: "BANK_PAYMENT",
|
|
337
430
|
eventSignal: "paymentCreated",
|
|
338
431
|
bankPayment: p.parsed,
|
|
@@ -347,9 +440,7 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
347
440
|
payments: payments.length,
|
|
348
441
|
paymentsToProcess: paymentsToProcess.length,
|
|
349
442
|
paymentsInserted: paymentsToInsert.length,
|
|
350
|
-
lastSyncBankRefIds: paymentsToProcess.map(
|
|
351
|
-
(p) => p.parsed.bankRefId
|
|
352
|
-
),
|
|
443
|
+
lastSyncBankRefIds: paymentsToProcess.filter((p) => p.parsed.status === "COMPLETED").map((p) => p.parsed.bankRefId),
|
|
353
444
|
lastSyncPayments: lastSyncBankRefIds.length,
|
|
354
445
|
eventsEmitted: eventsToEmit.length
|
|
355
446
|
};
|
|
@@ -360,13 +451,38 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
360
451
|
}).command;
|
|
361
452
|
if (eventsToEmit.length) {
|
|
362
453
|
await db.batch(
|
|
363
|
-
asNonEmpty([
|
|
454
|
+
asNonEmpty([
|
|
455
|
+
updateLastSyncCommand,
|
|
456
|
+
...createCommands,
|
|
457
|
+
...softDeleteCommands
|
|
458
|
+
])
|
|
364
459
|
);
|
|
365
460
|
await pushToQueue(
|
|
366
461
|
this.env.QUEUE_BUS_QUEUE,
|
|
367
462
|
eventsToEmit
|
|
368
463
|
);
|
|
369
464
|
}
|
|
465
|
+
const paymentRequestIds = enrichedPayments.map((p) => p.parsed.paymentRequestId).filter((id) => id != null);
|
|
466
|
+
if (paymentRequestIds.length > 0) {
|
|
467
|
+
const processedPRs = await db.select({ batchId: tables.paymentRequest.batchId }).from(tables.paymentRequest).where(inArray(tables.paymentRequest.id, paymentRequestIds));
|
|
468
|
+
const batchIds = [
|
|
469
|
+
...new Set(
|
|
470
|
+
processedPRs.map((pr) => pr.batchId).filter((id) => id != null)
|
|
471
|
+
)
|
|
472
|
+
];
|
|
473
|
+
for (const batchId of batchIds) {
|
|
474
|
+
const allPRsInBatch = await db.select({ deletedAt: tables.paymentRequest.deletedAt }).from(tables.paymentRequest).where(eq(tables.paymentRequest.batchId, batchId));
|
|
475
|
+
const allDone = allPRsInBatch.length > 0 && allPRsInBatch.every((pr) => pr.deletedAt != null);
|
|
476
|
+
if (allDone) {
|
|
477
|
+
const batch = await getBatchByIdQuery(db, { batchId });
|
|
478
|
+
if (batch && batch.status !== "COMPLETED" && batch.status !== "FAILED") {
|
|
479
|
+
await upsertBatchCommand(db, {
|
|
480
|
+
batch: { ...batch, status: "COMPLETED" }
|
|
481
|
+
}).command.execute();
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
370
486
|
return {
|
|
371
487
|
...lastSyncMetadata,
|
|
372
488
|
newLastSyncAt: now
|
|
@@ -28,7 +28,8 @@ const BATCH_STATUSES = [
|
|
|
28
28
|
"READY_TO_SIGN",
|
|
29
29
|
"SIGNED",
|
|
30
30
|
"SIGNATURE_FAILED",
|
|
31
|
-
"FAILED"
|
|
31
|
+
"FAILED",
|
|
32
|
+
"COMPLETED"
|
|
32
33
|
];
|
|
33
34
|
const ACCOUNT_STATUSES = ["AUTHORIZED", "DISABLED", "EXPIRED"];
|
|
34
35
|
const COUNTRY_CODES = generalCodes.COUNTRY_CODES_2;
|
|
@@ -139,6 +140,7 @@ const payment = sqliteCore.sqliteTable(
|
|
|
139
140
|
{
|
|
140
141
|
...backendSdk.base,
|
|
141
142
|
correlationId: sqliteCore.text("correlation_id").notNull(),
|
|
143
|
+
paymentRequestId: sqliteCore.text("payment_request_id"),
|
|
142
144
|
refId: sqliteCore.text("ref_id"),
|
|
143
145
|
bankRefId: sqliteCore.text("bank_ref_id").notNull(),
|
|
144
146
|
accountId: sqliteCore.text("account_id").references(() => account.id, {
|
|
@@ -174,7 +176,18 @@ const payment = sqliteCore.sqliteTable(
|
|
|
174
176
|
debtor: sqliteCore.text("debtor", { mode: "json" }).$type().notNull(),
|
|
175
177
|
debtorIban: sqliteCore.text("debtor_iban")
|
|
176
178
|
},
|
|
177
|
-
(t) => [
|
|
179
|
+
(t) => [
|
|
180
|
+
sqliteCore.unique().on(t.connectorKey, t.bankRefId),
|
|
181
|
+
sqliteCore.index("payment_account_id_idx").on(t.accountId),
|
|
182
|
+
sqliteCore.index("payment_account_id_status_idx").on(t.accountId, t.status),
|
|
183
|
+
sqliteCore.index("payment_account_id_created_at_idx").on(t.accountId, t.createdAt),
|
|
184
|
+
sqliteCore.index("payment_created_at_idx").on(t.createdAt),
|
|
185
|
+
sqliteCore.index("payment_payment_request_id_idx").on(t.paymentRequestId),
|
|
186
|
+
sqliteCore.index("payment_direction_idx").on(t.direction),
|
|
187
|
+
sqliteCore.index("payment_batch_id_idx").on(t.batchId),
|
|
188
|
+
sqliteCore.index("payment_creditor_iban_idx").on(t.creditorIban),
|
|
189
|
+
sqliteCore.index("payment_debtor_iban_idx").on(t.debtorIban)
|
|
190
|
+
]
|
|
178
191
|
);
|
|
179
192
|
const paymentRelations = relations.relations(payment, ({ one }) => ({
|
|
180
193
|
batch: one(batch, { fields: [payment.batchId], references: [batch.id] })
|
|
@@ -217,9 +230,26 @@ const paymentRequest = sqliteCore.sqliteTable(
|
|
|
217
230
|
creditor: sqliteCore.text("creditor", { mode: "json" }).$type().notNull(),
|
|
218
231
|
creditorIban: sqliteCore.text("creditor_iban"),
|
|
219
232
|
debtor: sqliteCore.text("debtor", { mode: "json" }).$type().notNull(),
|
|
220
|
-
debtorIban: sqliteCore.text("debtor_iban")
|
|
233
|
+
debtorIban: sqliteCore.text("debtor_iban"),
|
|
234
|
+
sendAsSinglePayment: sqliteCore.integer("send_as_single_payment", {
|
|
235
|
+
mode: "boolean"
|
|
236
|
+
})
|
|
221
237
|
},
|
|
222
|
-
(t) => [
|
|
238
|
+
(t) => [
|
|
239
|
+
sqliteCore.index("payment_request_batch_id_idx").on(t.batchId),
|
|
240
|
+
sqliteCore.index("payment_request_account_id_idx").on(t.accountId),
|
|
241
|
+
sqliteCore.index("payment_request_creditor_iban_idx").on(t.creditorIban),
|
|
242
|
+
sqliteCore.index("payment_request_debtor_iban_idx").on(t.debtorIban),
|
|
243
|
+
sqliteCore.index("payment_request_status_idx").on(t.status),
|
|
244
|
+
sqliteCore.index("payment_request_created_at_idx").on(t.createdAt),
|
|
245
|
+
sqliteCore.index("payment_request_account_status_idx").on(t.accountId, t.status),
|
|
246
|
+
sqliteCore.index("payment_request_status_created_at_idx").on(t.status, t.createdAt),
|
|
247
|
+
sqliteCore.index("payment_request_account_status_created_at_idx").on(
|
|
248
|
+
t.accountId,
|
|
249
|
+
t.status,
|
|
250
|
+
t.createdAt
|
|
251
|
+
)
|
|
252
|
+
]
|
|
223
253
|
);
|
|
224
254
|
const paymentRequestRelations = relations.relations(paymentRequest, ({ one }) => ({
|
|
225
255
|
batch: one(batch, {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as CurrencyCode, J as BankCode, V as CountryCode } from './bank.Cns5ss41.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
type ReferenceType = `${'VS' | 'SS' | 'KS'}:${number}`;
|
|
@@ -210,6 +210,18 @@ type FinbricksAccountTransactionsResponse = {
|
|
|
210
210
|
transactions: FinbricksTransaction[];
|
|
211
211
|
};
|
|
212
212
|
|
|
213
|
+
/**
|
|
214
|
+
* @deprecated Use IncomingPayment from './payment-lifecycle' instead
|
|
215
|
+
* This type is kept for backward compatibility during migration
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Message pushed to PAYMENTS_READY_TO_BATCH_QUEUE after payment_request is created in DB
|
|
220
|
+
*/
|
|
221
|
+
type PaymentQueueMessage = {
|
|
222
|
+
paymentId: string;
|
|
223
|
+
};
|
|
224
|
+
|
|
213
225
|
declare const sendPaymentInputSchema: z.ZodObject<{
|
|
214
226
|
correlationId: z.ZodString;
|
|
215
227
|
refId: z.ZodOptional<z.ZodString>;
|
|
@@ -225,7 +237,6 @@ declare const sendPaymentInputSchema: z.ZodObject<{
|
|
|
225
237
|
OUR: "OUR";
|
|
226
238
|
BEN: "BEN";
|
|
227
239
|
}>>;
|
|
228
|
-
executionDate: z.ZodOptional<z.ZodString>;
|
|
229
240
|
instructionPriority: z.ZodOptional<z.ZodEnum<{
|
|
230
241
|
NORM: "NORM";
|
|
231
242
|
HIGH: "HIGH";
|
|
@@ -980,12 +991,13 @@ declare const sendPaymentInputSchema: z.ZodObject<{
|
|
|
980
991
|
bsb: z.ZodOptional<z.ZodString>;
|
|
981
992
|
brBankNumber: z.ZodOptional<z.ZodString>;
|
|
982
993
|
}, z.core.$strip>;
|
|
983
|
-
purpose: z.ZodOptional<z.ZodString>;
|
|
984
994
|
sendAsSinglePayment: z.ZodOptional<z.ZodBoolean>;
|
|
985
995
|
}, z.core.$strip>;
|
|
986
996
|
interface SendPaymentInput extends z.infer<typeof sendPaymentInputSchema> {
|
|
987
997
|
}
|
|
988
|
-
type SendPaymentOutput =
|
|
998
|
+
type SendPaymentOutput = {
|
|
999
|
+
paymentId: string;
|
|
1000
|
+
};
|
|
989
1001
|
|
|
990
1002
|
declare const sendPaymentSyncInputSchema: z.ZodObject<{
|
|
991
1003
|
correlationId: z.ZodString;
|
|
@@ -1002,7 +1014,6 @@ declare const sendPaymentSyncInputSchema: z.ZodObject<{
|
|
|
1002
1014
|
OUR: "OUR";
|
|
1003
1015
|
BEN: "BEN";
|
|
1004
1016
|
}>>;
|
|
1005
|
-
executionDate: z.ZodOptional<z.ZodString>;
|
|
1006
1017
|
instructionPriority: z.ZodOptional<z.ZodEnum<{
|
|
1007
1018
|
NORM: "NORM";
|
|
1008
1019
|
HIGH: "HIGH";
|
|
@@ -1757,7 +1768,6 @@ declare const sendPaymentSyncInputSchema: z.ZodObject<{
|
|
|
1757
1768
|
bsb: z.ZodOptional<z.ZodString>;
|
|
1758
1769
|
brBankNumber: z.ZodOptional<z.ZodString>;
|
|
1759
1770
|
}, z.core.$strip>;
|
|
1760
|
-
purpose: z.ZodOptional<z.ZodString>;
|
|
1761
1771
|
sendAsSinglePayment: z.ZodOptional<z.ZodBoolean>;
|
|
1762
1772
|
}, z.core.$strip>;
|
|
1763
1773
|
interface SendPaymentSyncInput extends z.infer<typeof sendPaymentSyncInputSchema> {
|
|
@@ -1767,4 +1777,4 @@ type SendPaymentSyncOutput = {
|
|
|
1767
1777
|
authorizationUrl: string;
|
|
1768
1778
|
};
|
|
1769
1779
|
|
|
1770
|
-
export type { FinbricksSupportedBanksResponse as F, ReferenceType as R, SendPaymentInput as S, SendPaymentOutput as a, SendPaymentSyncInput as b, SendPaymentSyncOutput as c, FinbricksAccount as d, FinbricksAccountTransactionsResponse as e, FinbricksAccountsListResponse as f, FinbricksAuthTokenResponse as g, FinbricksBatchResponse as h, FinbricksConnectAccountResponse as i, FinbricksPaymentResponse as j, FinbricksSupportedBank as k };
|
|
1780
|
+
export type { FinbricksSupportedBanksResponse as F, PaymentQueueMessage as P, ReferenceType as R, SendPaymentInput as S, SendPaymentOutput as a, SendPaymentSyncInput as b, SendPaymentSyncOutput as c, FinbricksAccount as d, FinbricksAccountTransactionsResponse as e, FinbricksAccountsListResponse as f, FinbricksAuthTokenResponse as g, FinbricksBatchResponse as h, FinbricksConnectAccountResponse as i, FinbricksPaymentResponse as j, FinbricksSupportedBank as k };
|
|
@@ -26,7 +26,8 @@ const BATCH_STATUSES = [
|
|
|
26
26
|
"READY_TO_SIGN",
|
|
27
27
|
"SIGNED",
|
|
28
28
|
"SIGNATURE_FAILED",
|
|
29
|
-
"FAILED"
|
|
29
|
+
"FAILED",
|
|
30
|
+
"COMPLETED"
|
|
30
31
|
];
|
|
31
32
|
const ACCOUNT_STATUSES = ["AUTHORIZED", "DISABLED", "EXPIRED"];
|
|
32
33
|
const COUNTRY_CODES = COUNTRY_CODES_2;
|
|
@@ -137,6 +138,7 @@ const payment = sqliteTable(
|
|
|
137
138
|
{
|
|
138
139
|
...base,
|
|
139
140
|
correlationId: text("correlation_id").notNull(),
|
|
141
|
+
paymentRequestId: text("payment_request_id"),
|
|
140
142
|
refId: text("ref_id"),
|
|
141
143
|
bankRefId: text("bank_ref_id").notNull(),
|
|
142
144
|
accountId: text("account_id").references(() => account.id, {
|
|
@@ -172,7 +174,18 @@ const payment = sqliteTable(
|
|
|
172
174
|
debtor: text("debtor", { mode: "json" }).$type().notNull(),
|
|
173
175
|
debtorIban: text("debtor_iban")
|
|
174
176
|
},
|
|
175
|
-
(t) => [
|
|
177
|
+
(t) => [
|
|
178
|
+
unique().on(t.connectorKey, t.bankRefId),
|
|
179
|
+
index("payment_account_id_idx").on(t.accountId),
|
|
180
|
+
index("payment_account_id_status_idx").on(t.accountId, t.status),
|
|
181
|
+
index("payment_account_id_created_at_idx").on(t.accountId, t.createdAt),
|
|
182
|
+
index("payment_created_at_idx").on(t.createdAt),
|
|
183
|
+
index("payment_payment_request_id_idx").on(t.paymentRequestId),
|
|
184
|
+
index("payment_direction_idx").on(t.direction),
|
|
185
|
+
index("payment_batch_id_idx").on(t.batchId),
|
|
186
|
+
index("payment_creditor_iban_idx").on(t.creditorIban),
|
|
187
|
+
index("payment_debtor_iban_idx").on(t.debtorIban)
|
|
188
|
+
]
|
|
176
189
|
);
|
|
177
190
|
const paymentRelations = relations(payment, ({ one }) => ({
|
|
178
191
|
batch: one(batch, { fields: [payment.batchId], references: [batch.id] })
|
|
@@ -215,9 +228,26 @@ const paymentRequest = sqliteTable(
|
|
|
215
228
|
creditor: text("creditor", { mode: "json" }).$type().notNull(),
|
|
216
229
|
creditorIban: text("creditor_iban"),
|
|
217
230
|
debtor: text("debtor", { mode: "json" }).$type().notNull(),
|
|
218
|
-
debtorIban: text("debtor_iban")
|
|
231
|
+
debtorIban: text("debtor_iban"),
|
|
232
|
+
sendAsSinglePayment: integer("send_as_single_payment", {
|
|
233
|
+
mode: "boolean"
|
|
234
|
+
})
|
|
219
235
|
},
|
|
220
|
-
(t) => [
|
|
236
|
+
(t) => [
|
|
237
|
+
index("payment_request_batch_id_idx").on(t.batchId),
|
|
238
|
+
index("payment_request_account_id_idx").on(t.accountId),
|
|
239
|
+
index("payment_request_creditor_iban_idx").on(t.creditorIban),
|
|
240
|
+
index("payment_request_debtor_iban_idx").on(t.debtorIban),
|
|
241
|
+
index("payment_request_status_idx").on(t.status),
|
|
242
|
+
index("payment_request_created_at_idx").on(t.createdAt),
|
|
243
|
+
index("payment_request_account_status_idx").on(t.accountId, t.status),
|
|
244
|
+
index("payment_request_status_created_at_idx").on(t.status, t.createdAt),
|
|
245
|
+
index("payment_request_account_status_created_at_idx").on(
|
|
246
|
+
t.accountId,
|
|
247
|
+
t.status,
|
|
248
|
+
t.createdAt
|
|
249
|
+
)
|
|
250
|
+
]
|
|
221
251
|
);
|
|
222
252
|
const paymentRequestRelations = relations(paymentRequest, ({ one }) => ({
|
|
223
253
|
batch: one(batch, {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as account, p as accountCredentials, q as batch, r as ott, s as payment, t as paymentRelations, u as paymentRequest, v as paymentRequestRelations } from './bank.
|
|
1
|
+
import { n as account, p as accountCredentials, q as batch, r as ott, s as payment, t as paymentRelations, u as paymentRequest, v as paymentRequestRelations } from './bank.C0UN6luZ.mjs';
|
|
2
2
|
|
|
3
3
|
const schema = {
|
|
4
4
|
__proto__: null,
|