@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,22 +1,22 @@
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 batchLifecycle = require('../shared/bank.Bg3Pdwm4.cjs');
6
- const mock_connector = require('../shared/bank.CQURey1E.cjs');
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.SQ4Mmr8u.cjs');
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.C-T1FQxg.cjs');
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
- if (batch.batchPaymentInitiatedAt) {
95
+ const currentBatch = await drizzle.getBatchByIdQuery(db, { batchId });
96
+ if (currentBatch?.batchPaymentInitiatedAt) {
96
97
  return {
97
- authorizationUrls: batch.authorizationUrls,
98
+ authorizationUrls: currentBatch.authorizationUrls,
98
99
  preparedPayments: batchedPayments.map(
99
- (p) => mock_connector.toPreparedPayment(p, void 0, batch.batchPaymentInitiatedAt)
100
+ (p) => mock_connector.toPreparedPayment(
101
+ p,
102
+ void 0,
103
+ currentBatch.batchPaymentInitiatedAt
104
+ )
100
105
  ),
101
- metadata: batch.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 createCommands = paymentsToInsert.map(
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
- ...paymentsToInsert.map((p) => ({
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([updateLastSyncCommand, ...createCommands])
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.Cpy9PULF.mjs';
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 { f as toBatchedPaymentFromPaymentRequest, j as toPreparedPayment, k as initiateConnector } from '../shared/bank.DRrBrAdI.mjs';
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.C4VOdIx1.mjs';
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.DDHrdFgy.mjs';
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
- if (batch.batchPaymentInitiatedAt) {
93
+ const currentBatch = await getBatchByIdQuery(db, { batchId });
94
+ if (currentBatch?.batchPaymentInitiatedAt) {
94
95
  return {
95
- authorizationUrls: batch.authorizationUrls,
96
+ authorizationUrls: currentBatch.authorizationUrls,
96
97
  preparedPayments: batchedPayments.map(
97
- (p) => toPreparedPayment(p, void 0, batch.batchPaymentInitiatedAt)
98
+ (p) => toPreparedPayment(
99
+ p,
100
+ void 0,
101
+ currentBatch.batchPaymentInitiatedAt
102
+ )
98
103
  ),
99
- metadata: batch.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 createCommands = paymentsToInsert.map(
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
- ...paymentsToInsert.map((p) => ({
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([updateLastSyncCommand, ...createCommands])
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
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const paymentRequest_schema = require('./bank.SQ4Mmr8u.cjs');
3
+ const paymentRequest_schema = require('./bank.BS7fFjGA.cjs');
4
4
 
5
5
  const schema = {
6
6
  __proto__: null,
@@ -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) => [sqliteCore.unique().on(t.connectorKey, t.bankRefId)]
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) => [sqliteCore.index("payment_request_batch_id_idx").on(t.batchId)]
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, {