@develit-services/bank 0.3.44 → 0.3.46

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 (37) hide show
  1. package/dist/database/schema.cjs +4 -4
  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 +4 -4
  6. package/dist/export/worker.cjs +201 -183
  7. package/dist/export/worker.d.cts +51 -20
  8. package/dist/export/worker.d.mts +51 -20
  9. package/dist/export/worker.d.ts +51 -20
  10. package/dist/export/worker.mjs +161 -143
  11. package/dist/export/workflows.cjs +214 -18
  12. package/dist/export/workflows.mjs +207 -12
  13. package/dist/export/wrangler.d.cts +1 -2
  14. package/dist/export/wrangler.d.mts +1 -2
  15. package/dist/export/wrangler.d.ts +1 -2
  16. package/dist/shared/{bank.DFRS9oN5.mjs → bank.B1Gpn3ht.mjs} +9 -172
  17. package/dist/shared/{bank.D8wUOeOK.d.cts → bank.BEL1HIxZ.d.cts} +20 -1
  18. package/dist/shared/{bank.D8wUOeOK.d.mts → bank.BEL1HIxZ.d.mts} +20 -1
  19. package/dist/shared/{bank.D8wUOeOK.d.ts → bank.BEL1HIxZ.d.ts} +20 -1
  20. package/dist/shared/bank.BUEmFxS8.mjs +174 -0
  21. package/dist/shared/{bank.C335-raZ.cjs → bank.CPYfE-Ei.cjs} +9 -197
  22. package/dist/shared/bank.CpwLFudl.cjs +198 -0
  23. package/dist/shared/bank.D-3fzX63.mjs +170 -0
  24. package/dist/shared/bank.D0a-MZon.cjs +184 -0
  25. package/dist/shared/{bank.BchnXQDL.d.cts → bank.Dh_H_5rC.d.cts} +0 -1
  26. package/dist/shared/{bank.BchnXQDL.d.mts → bank.Dh_H_5rC.d.mts} +0 -1
  27. package/dist/shared/{bank.BchnXQDL.d.ts → bank.Dh_H_5rC.d.ts} +0 -1
  28. package/dist/types.cjs +14 -14
  29. package/dist/types.d.cts +3 -6
  30. package/dist/types.d.mts +3 -6
  31. package/dist/types.d.ts +3 -6
  32. package/dist/types.mjs +5 -5
  33. package/package.json +1 -1
  34. package/dist/shared/bank.Cj-oB02_.mjs +0 -392
  35. package/dist/shared/bank.ClRIj2Ma.cjs +0 -11
  36. package/dist/shared/bank.DhPfZ6b_.mjs +0 -9
  37. package/dist/shared/bank.DwyrLcKu.cjs +0 -402
@@ -3,24 +3,23 @@
3
3
  const backendSdk = require('@develit-io/backend-sdk');
4
4
  const cloudflare_workers = require('cloudflare:workers');
5
5
  const d1 = require('drizzle-orm/d1');
6
- const database_schema = require('../shared/bank.C335-raZ.cjs');
7
- require('jose');
8
- const generalCodes = require('@develit-io/general-codes');
6
+ const drizzle = require('../shared/bank.CPYfE-Ei.cjs');
9
7
  const zod = require('zod');
10
- const processBatch_workflow = require('../shared/bank.DwyrLcKu.cjs');
8
+ const database_schema = require('../shared/bank.CpwLFudl.cjs');
9
+ const generalCodes = require('@develit-io/general-codes');
10
+ require('date-fns');
11
11
  const drizzleOrm = require('drizzle-orm');
12
+ require('jose');
13
+ require('node:crypto');
14
+ const encryption = require('../shared/bank.D0a-MZon.cjs');
12
15
  require('drizzle-orm/sqlite-core');
13
- require('date-fns');
14
- require('drizzle-zod');
15
16
  require('drizzle-orm/relations');
16
- require('node:crypto');
17
- require('cloudflare:workflows');
18
- require('../shared/bank.ClRIj2Ma.cjs');
17
+ require('drizzle-zod');
19
18
 
20
19
  const upsertAccountCommand = (db, { account }) => {
21
20
  const id = account.id || backendSdk.uuidv4();
22
- const command = db.insert(database_schema.tables.account).values({ ...account, id }).onConflictDoUpdate({
23
- target: database_schema.tables.account.iban,
21
+ const command = db.insert(drizzle.tables.account).values({ ...account, id }).onConflictDoUpdate({
22
+ target: drizzle.tables.account.iban,
24
23
  set: {
25
24
  ...account
26
25
  }
@@ -38,7 +37,7 @@ const createOneTimeTokenCommand = (db, {
38
37
  }) => {
39
38
  const id = backendSdk.uuidv4();
40
39
  const expiresAt = new Date(Date.now() + 1e3 * 60 * 60) ;
41
- const command = db.insert(database_schema.tables.ott).values({
40
+ const command = db.insert(drizzle.tables.ott).values({
42
41
  id,
43
42
  oneTimeToken: ott,
44
43
  tokenType,
@@ -50,7 +49,7 @@ const createOneTimeTokenCommand = (db, {
50
49
 
51
50
  const updateAccountCommand = (db, { account }) => {
52
51
  return {
53
- command: db.update(database_schema.tables.account).set({ ...account }).where(drizzleOrm.eq(database_schema.tables.account.id, account.id)).returning()
52
+ command: db.update(drizzle.tables.account).set({ ...account }).where(drizzleOrm.eq(drizzle.tables.account.id, account.id)).returning()
54
53
  };
55
54
  };
56
55
 
@@ -58,16 +57,16 @@ const expireOneTimeTokenCommand = (db, {
58
57
  ott
59
58
  }) => {
60
59
  return {
61
- command: db.update(database_schema.tables.ott).set({
60
+ command: db.update(drizzle.tables.ott).set({
62
61
  expiresAt: /* @__PURE__ */ new Date()
63
- }).where(drizzleOrm.eq(database_schema.tables.ott.oneTimeToken, ott))
62
+ }).where(drizzleOrm.eq(drizzle.tables.ott.oneTimeToken, ott))
64
63
  };
65
64
  };
66
65
 
67
66
  const createAccountCredentialsCommand = async (db, encryptionKey, { credentials }) => {
68
67
  const id = credentials.id || backendSdk.uuidv4();
69
- const encryptedValue = await processBatch_workflow.encrypt(credentials.value, encryptionKey);
70
- const command = db.insert(database_schema.tables.accountCredentials).values({
68
+ const encryptedValue = await encryption.encrypt(credentials.value, encryptionKey);
69
+ const command = db.insert(drizzle.tables.accountCredentials).values({
71
70
  ...credentials,
72
71
  id,
73
72
  value: encryptedValue
@@ -79,29 +78,29 @@ const createAccountCredentialsCommand = async (db, encryptionKey, { credentials
79
78
  };
80
79
 
81
80
  const deleteAccountCredentialsCommand = (db, { accountId }) => {
82
- const command = db.delete(database_schema.tables.accountCredentials).where(drizzleOrm.eq(database_schema.tables.accountCredentials.accountId, accountId));
81
+ const command = db.delete(drizzle.tables.accountCredentials).where(drizzleOrm.eq(drizzle.tables.accountCredentials.accountId, accountId));
83
82
  return {
84
83
  command
85
84
  };
86
85
  };
87
86
 
88
87
  const deletePaymentsByAccountCommand = (db, { accountId }) => {
89
- const command = db.update(database_schema.tables.payment).set({
88
+ const command = db.update(drizzle.tables.payment).set({
90
89
  deletedAt: /* @__PURE__ */ new Date()
91
- }).where(drizzleOrm.eq(database_schema.tables.payment.accountId, accountId));
90
+ }).where(drizzleOrm.eq(drizzle.tables.payment.accountId, accountId));
92
91
  return {
93
92
  command
94
93
  };
95
94
  };
96
95
 
97
96
  const getAccountByIbanQuery = async (db, { iban }) => {
98
- return await db.select().from(database_schema.tables.account).where(drizzleOrm.eq(database_schema.tables.account.iban, iban)).get();
97
+ return await db.select().from(drizzle.tables.account).where(drizzleOrm.eq(drizzle.tables.account.iban, iban)).get();
99
98
  };
100
99
 
101
100
  const getAllAccountsQuery = async (db) => {
102
- const accountsWithExpiration = await db.select().from(database_schema.tables.account).leftJoin(
103
- database_schema.tables.accountCredentials,
104
- drizzleOrm.eq(database_schema.tables.accountCredentials.accountId, database_schema.tables.account.id)
101
+ const accountsWithExpiration = await db.select().from(drizzle.tables.account).leftJoin(
102
+ drizzle.tables.accountCredentials,
103
+ drizzleOrm.eq(drizzle.tables.accountCredentials.accountId, drizzle.tables.account.id)
105
104
  );
106
105
  return accountsWithExpiration.map(({ account, account_credentials }) => {
107
106
  return {
@@ -112,7 +111,7 @@ const getAllAccountsQuery = async (db) => {
112
111
  };
113
112
 
114
113
  const getAllPendingBatchesQuery = (db) => {
115
- return db.select().from(database_schema.tables.batch).where(drizzleOrm.inArray(database_schema.tables.batch.status, ["READY_TO_SIGN"]));
114
+ return db.select().from(drizzle.tables.batch).where(drizzleOrm.inArray(drizzle.tables.batch.status, ["READY_TO_SIGN"]));
116
115
  };
117
116
 
118
117
  const buildMultiFilterConditions = (column, value) => {
@@ -153,28 +152,28 @@ const getPaymentsWithPaginationQuery = async (db, {
153
152
  }) => {
154
153
  const whereConditions = drizzleOrm.and(
155
154
  buildMultiFilterConditions(
156
- database_schema.tables.payment.accountId,
155
+ drizzle.tables.payment.accountId,
157
156
  filterPaymentAccountId
158
157
  ),
159
- buildMultiFilterConditions(database_schema.tables.payment.amount, filterPaymentAmount),
160
- buildMultiFilterConditions(database_schema.tables.payment.currency, filterPaymentCurrency),
158
+ buildMultiFilterConditions(drizzle.tables.payment.amount, filterPaymentAmount),
159
+ buildMultiFilterConditions(drizzle.tables.payment.currency, filterPaymentCurrency),
161
160
  buildRangeFilterConditions(
162
- database_schema.tables.payment.createdAt,
161
+ drizzle.tables.payment.createdAt,
163
162
  filterPaymentDateFrom,
164
163
  filterPaymentDateTo
165
164
  ),
166
- buildMultiFilterConditions(database_schema.tables.payment.status, filterPaymentStatus),
165
+ buildMultiFilterConditions(drizzle.tables.payment.status, filterPaymentStatus),
167
166
  buildMultiFilterConditions(
168
- database_schema.tables.payment.direction,
167
+ drizzle.tables.payment.direction,
169
168
  filterPaymentyDirection
170
169
  ),
171
- buildMultiFilterConditions(database_schema.tables.payment.id, ids)
170
+ buildMultiFilterConditions(drizzle.tables.payment.id, ids)
172
171
  );
173
- const sortColumn = resolveColumn(database_schema.tables.payment, sort.column);
172
+ const sortColumn = resolveColumn(drizzle.tables.payment, sort.column);
174
173
  const [{ totalCount }] = await db.select({
175
174
  totalCount: drizzleOrm.sql`count(*)`
176
- }).from(database_schema.tables.payment).where(whereConditions);
177
- const payments = await db.select().from(database_schema.tables.payment).where(whereConditions).limit(limit).offset((page - 1) * limit).orderBy(sort.direction === "asc" ? drizzleOrm.asc(sortColumn) : drizzleOrm.desc(sortColumn));
175
+ }).from(drizzle.tables.payment).where(whereConditions);
176
+ const payments = await db.select().from(drizzle.tables.payment).where(whereConditions).limit(limit).offset((page - 1) * limit).orderBy(sort.direction === "asc" ? drizzleOrm.asc(sortColumn) : drizzleOrm.desc(sortColumn));
178
177
  return {
179
178
  payments,
180
179
  totalCount
@@ -189,14 +188,14 @@ const getBatchesQuery = async (db, {
189
188
  filterBatchStatus
190
189
  }) => {
191
190
  const whereConditions = drizzleOrm.and(
192
- buildMultiFilterConditions(database_schema.tables.batch.accountId, filterBatchAccountId),
193
- buildMultiFilterConditions(database_schema.tables.batch.status, filterBatchStatus)
191
+ buildMultiFilterConditions(drizzle.tables.batch.accountId, filterBatchAccountId),
192
+ buildMultiFilterConditions(drizzle.tables.batch.status, filterBatchStatus)
194
193
  );
195
- const sortColumn = resolveColumn(database_schema.tables.batch, sort.column);
194
+ const sortColumn = resolveColumn(drizzle.tables.batch, sort.column);
196
195
  const [{ totalCount }] = await db.select({
197
196
  totalCount: drizzleOrm.sql`count(*)`
198
- }).from(database_schema.tables.batch).where(whereConditions);
199
- const batches = await db.select().from(database_schema.tables.batch).where(whereConditions).limit(limit).offset((page - 1) * limit).orderBy(sort.direction === "asc" ? drizzleOrm.asc(sortColumn) : drizzleOrm.desc(sortColumn));
197
+ }).from(drizzle.tables.batch).where(whereConditions);
198
+ const batches = await db.select().from(drizzle.tables.batch).where(whereConditions).limit(limit).offset((page - 1) * limit).orderBy(sort.direction === "asc" ? drizzleOrm.asc(sortColumn) : drizzleOrm.desc(sortColumn));
200
199
  return {
201
200
  batches,
202
201
  totalCount
@@ -204,16 +203,16 @@ const getBatchesQuery = async (db, {
204
203
  };
205
204
 
206
205
  const getAccountOpenBatchesQuery = async (db, { accountId }) => {
207
- return await db.select().from(database_schema.tables.batch).where(
206
+ return await db.select().from(drizzle.tables.batch).where(
208
207
  drizzleOrm.and(
209
- drizzleOrm.eq(database_schema.tables.batch.accountId, accountId),
210
- drizzleOrm.eq(database_schema.tables.batch.status, "OPEN")
208
+ drizzleOrm.eq(drizzle.tables.batch.accountId, accountId),
209
+ drizzleOrm.eq(drizzle.tables.batch.status, "OPEN")
211
210
  )
212
211
  );
213
212
  };
214
213
 
215
214
  const getOttQuery = async (db, { ott }) => {
216
- return await db.select().from(database_schema.tables.ott).where(drizzleOrm.eq(database_schema.tables.ott.oneTimeToken, ott)).get();
215
+ return await db.select().from(drizzle.tables.ott).where(drizzleOrm.eq(drizzle.tables.ott.oneTimeToken, ott)).get();
217
216
  };
218
217
 
219
218
  const seperateSupportedPayments = (mappedPayments, accounts) => {
@@ -261,7 +260,9 @@ const getAuthUriInputSchema = zod.z.object({
261
260
 
262
261
  const authorizeAccountInputSchema = zod.z.object({
263
262
  ott: zod.z.string(),
264
- urlParams: zod.z.string()
263
+ urlParams: zod.z.string(),
264
+ syncIntervalS: zod.z.number().int().positive().optional(),
265
+ startSync: zod.z.boolean().optional()
265
266
  });
266
267
 
267
268
  const simulateDepositInputSchema = zod.z.object({
@@ -315,20 +316,12 @@ zod.z.object({
315
316
  details: backendSdk.workflowInstanceStatusSchema
316
317
  });
317
318
 
318
- const batchAuthorizedEventPayloadSchema = zod.z.object({
319
- authorized: zod.z.boolean()
320
- });
321
- const processBatchEventInputSchema = zod.z.discriminatedUnion("eventType", [
322
- zod.z.object({
323
- batchId: zod.z.uuid(),
324
- eventType: zod.z.literal(processBatch_workflow.PROCESS_BATCH_WORKFLOW_EVENTS.batchAuthorized),
325
- payload: batchAuthorizedEventPayloadSchema
326
- })
327
- // Future event types can be added here as new objects in the array
328
- ]);
319
+ const updateBatchStatusesInputSchema = zod.z.object({
320
+ batchId: zod.z.uuid().optional()
321
+ }).optional();
329
322
  zod.z.object({
330
- success: zod.z.boolean(),
331
- message: zod.z.string()
323
+ processed: zod.z.number(),
324
+ statusChanged: zod.z.number()
332
325
  });
333
326
 
334
327
  const ALLOWED_PAYMENT_FILTERS = {
@@ -411,14 +404,18 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
411
404
  super(ctx, env);
412
405
  this.allowedProviders = [];
413
406
  this.allowedProviders = config.allowedProviders;
414
- this.db = d1.drizzle(this.env.BANK_D1, { schema: database_schema.tables });
407
+ this.db = d1.drizzle(this.env.BANK_D1, { schema: drizzle.tables });
415
408
  }
416
409
  async _getAccounts() {
417
410
  return await getAllAccountsQuery(this.db);
418
411
  }
412
+ async _getConnectedAccounts() {
413
+ const accounts = await this._getAccounts();
414
+ return accounts.filter((acc) => acc.status !== "DISABLED");
415
+ }
419
416
  async _initiateBankConnector({
420
417
  connectorKey,
421
- withAuth
418
+ skipAccounts
422
419
  }) {
423
420
  if (!this.allowedProviders.includes(connectorKey)) {
424
421
  throw backendSdk.createInternalError(null, {
@@ -427,55 +424,45 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
427
424
  status: 400
428
425
  });
429
426
  }
430
- const accounts = await this._getAccounts();
431
- const accountsForConnector = accounts.filter(
432
- (acc) => acc.connectorKey === connectorKey && acc.status !== "DISABLED"
433
- );
434
- const encryptionKey = await processBatch_workflow.importAesKey(this.env.ENCRYPTION_KEY);
435
- const accountsWithCredentials = await Promise.all(
436
- accountsForConnector.map(async (acc) => {
437
- const credentials = await processBatch_workflow.getCredentialsByAccountId(
438
- this.db,
439
- encryptionKey,
440
- {
441
- accountId: acc.id
427
+ let connectedAccounts = [];
428
+ if (!skipAccounts) {
429
+ const encryptionKey = await encryption.importAesKey(this.env.ENCRYPTION_KEY);
430
+ const accounts = await this._getConnectedAccounts();
431
+ const accountsForConnector = accounts.filter(
432
+ (acc) => acc.connectorKey === connectorKey
433
+ );
434
+ connectedAccounts = await Promise.all(
435
+ accountsForConnector.map(async (acc) => {
436
+ const credentials = await encryption.getCredentialsByAccountId(
437
+ this.db,
438
+ encryptionKey,
439
+ {
440
+ accountId: acc.id
441
+ }
442
+ );
443
+ if (!credentials) {
444
+ throw backendSdk.createInternalError(null, {
445
+ message: `No credentials found for account ${acc.id}`,
446
+ code: "DB-B-001",
447
+ status: 404
448
+ });
442
449
  }
443
- );
444
- if (!credentials) {
445
- throw backendSdk.createInternalError(null, {
446
- message: `No credentials found for account ${acc.id}`,
447
- code: "DB-B-001",
448
- status: 404
449
- });
450
- }
451
- return {
452
- currency: acc.currency,
453
- iban: acc.iban,
454
- token: credentials.value,
455
- id: acc.id,
456
- connectorKey: acc.connectorKey
457
- };
458
- })
459
- );
460
- this.bankConnector = processBatch_workflow.initiateConnector({
450
+ return {
451
+ currency: acc.currency,
452
+ iban: acc.iban,
453
+ token: credentials.value,
454
+ id: acc.id,
455
+ connectorKey: acc.connectorKey
456
+ };
457
+ })
458
+ );
459
+ }
460
+ const connector = encryption.initiateConnector({
461
461
  bank: connectorKey,
462
- connectedAccounts: accountsWithCredentials,
462
+ connectedAccounts,
463
463
  env: this.env
464
464
  });
465
- if (!withAuth) return;
466
- await this.bankConnector.authenticate();
467
- }
468
- _accountFetchInterval(connectorKey) {
469
- switch (connectorKey) {
470
- case "ERSTE":
471
- return database_schema.ErsteConnector.FETCH_INTERVAL;
472
- case "FINBRICKS":
473
- return database_schema.FinbricksConnector.FETCH_INTERVAL;
474
- case "MOCK":
475
- return database_schema.MockConnector.FETCH_INTERVAL;
476
- default:
477
- return 0;
478
- }
465
+ return connector;
479
466
  }
480
467
  async getPayments(input) {
481
468
  return this.handleAction(
@@ -563,65 +550,97 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
563
550
  await this.updateBatchStatuses();
564
551
  }
565
552
  }
566
- async updateBatchStatuses() {
567
- const pendingBatches = await getAllPendingBatchesQuery(this.db);
568
- const uniqueConnectors = /* @__PURE__ */ new Set();
569
- const accounts = await this._getAccounts();
570
- for (const batch of pendingBatches) {
571
- const connectorKey = accounts.find(
572
- (acc) => acc.id === batch.accountId
573
- ).connectorKey;
574
- if (!uniqueConnectors.has(connectorKey)) {
575
- uniqueConnectors.add(connectorKey);
576
- }
553
+ async _resolveSingleBatch(batch, connector) {
554
+ const previousStatus = batch.status;
555
+ const currentStatus = await connector.getBatchStatus({
556
+ batchId: batch.id
557
+ });
558
+ let statusChanged = false;
559
+ if (previousStatus !== currentStatus) {
560
+ await encryption.upsertBatchCommand(this.db, {
561
+ batch: {
562
+ ...batch,
563
+ status: currentStatus
564
+ }
565
+ }).command.execute();
566
+ statusChanged = true;
577
567
  }
578
- const finalBatches = [];
579
- for (const connectorKey of uniqueConnectors) {
580
- const accs = accounts.filter((acc) => acc.connectorKey === connectorKey);
581
- const updatedBatches = await Promise.all(
582
- accs.map(async (account) => {
583
- const batch = pendingBatches.find((acc) => acc.id === account.id);
584
- const newStatus = await this.bankConnector.getBatchStatus({
585
- batchId: batch.id
568
+ return {
569
+ batchId: batch.id,
570
+ previousStatus,
571
+ currentStatus,
572
+ statusChanged
573
+ // eventSent,
574
+ };
575
+ }
576
+ async updateBatchStatuses(input) {
577
+ return this.handleAction(
578
+ { data: input, schema: updateBatchStatusesInputSchema },
579
+ { successMessage: "Batch statuses updated" },
580
+ async (validatedInput) => {
581
+ let pendingBatches;
582
+ if (validatedInput?.batchId) {
583
+ const batch = await encryption.getBatchByIdQuery(this.db, {
584
+ batchId: validatedInput.batchId
586
585
  });
587
- return {
588
- ...batch,
589
- status: newStatus
590
- };
591
- })
592
- );
593
- finalBatches.push(...updatedBatches);
594
- }
595
- const updateBatchesCommands = finalBatches.map((batch) => {
596
- const { command } = processBatch_workflow.upsertBatchCommand(this.db, {
597
- batch: {
598
- ...batch
586
+ if (!batch) {
587
+ throw backendSdk.createInternalError(null, {
588
+ message: `Batch not found: ${validatedInput.batchId}`,
589
+ code: "DB-B-007",
590
+ status: 404
591
+ });
592
+ }
593
+ pendingBatches = [batch];
594
+ } else {
595
+ pendingBatches = await getAllPendingBatchesQuery(this.db);
599
596
  }
600
- });
601
- return command;
602
- });
603
- await this.db.batch([
604
- updateBatchesCommands[0],
605
- ...updateBatchesCommands.slice(1)
606
- ]);
607
- for (const batch of finalBatches) {
608
- try {
609
- const instance = await this.env.PROCESS_BATCH_WORKFLOW.get(batch.id);
610
- if (batch.status === "SIGNED" || batch.status === "SIGNATURE_FAILED") {
611
- instance.sendEvent({
612
- type: processBatch_workflow.PROCESS_BATCH_WORKFLOW_EVENTS.batchAuthorized,
613
- payload: {
614
- authorized: batch.status === "SIGNED"
615
- }
597
+ const accounts = await this._getConnectedAccounts();
598
+ console.log(`Processing ${pendingBatches.length} pending batche(s)`);
599
+ const batchesByConnector = /* @__PURE__ */ new Map();
600
+ for (const batch of pendingBatches) {
601
+ const account = accounts.find((acc) => acc.id === batch.accountId);
602
+ if (!account) {
603
+ this.logError({
604
+ message: `Account not found for batch ${batch.id}, skipping`
605
+ });
606
+ await encryption.upsertBatchCommand(this.db, {
607
+ batch: {
608
+ ...batch,
609
+ status: "FAILED",
610
+ statusReason: "ACCOUNT_NOT_FOUND"
611
+ }
612
+ }).command.execute();
613
+ continue;
614
+ }
615
+ const batches = batchesByConnector.get(account.connectorKey) || [];
616
+ batches.push(batch);
617
+ batchesByConnector.set(account.connectorKey, batches);
618
+ }
619
+ const allResults = [];
620
+ for (const [connectorKey, batches] of batchesByConnector) {
621
+ console.log(
622
+ `Initializing ${connectorKey} connector for ${batches.length} batches`
623
+ );
624
+ const connector = await this._initiateBankConnector({
625
+ connectorKey
616
626
  });
627
+ for (const batch of batches) {
628
+ const result = await this._resolveSingleBatch(batch, connector);
629
+ if (result) {
630
+ allResults.push(result);
631
+ }
632
+ }
617
633
  }
618
- } catch (_) {
634
+ const changedCount = allResults.filter((r) => r.statusChanged).length;
619
635
  console.log(
620
- `No workflow instance found for batch ${batch.id}, skipping.`
636
+ `Batch update completed: ${changedCount} status change(s) detected`
621
637
  );
638
+ return {
639
+ processed: allResults.length,
640
+ statusChanged: changedCount
641
+ };
622
642
  }
623
- }
624
- console.log("Batch update completed");
643
+ );
625
644
  }
626
645
  async addPaymentsToBatch({
627
646
  paymentsToBatch
@@ -699,7 +718,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
699
718
  this.log({
700
719
  message: availableBatch ? `\u{1F504} Found existing OPEN batches for account ${acc.id}, merging ${availableBatch.payments.length} existing + ${newPayments.length} new payments` : `\u2728 Creating new batch for account ${acc.id} with ${newPayments.length} payments`
701
720
  });
702
- const { command } = processBatch_workflow.upsertBatchCommand(this.db, {
721
+ const { command } = encryption.upsertBatchCommand(this.db, {
703
722
  batch: availableBatch ? {
704
723
  ...availableBatch,
705
724
  payments: [...availableBatch.payments, ...newPayments]
@@ -764,23 +783,6 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
764
783
  }
765
784
  );
766
785
  }
767
- async processBatchEvent(input) {
768
- return this.handleAction(
769
- { data: input, schema: processBatchEventInputSchema },
770
- { successMessage: "Event sent to batch processing workflow" },
771
- async ({ batchId, eventType, payload }) => {
772
- const instance = await this.env.PROCESS_BATCH_WORKFLOW.get(batchId);
773
- await instance.sendEvent({
774
- type: eventType,
775
- payload
776
- });
777
- return {
778
- success: true,
779
- message: `Event '${eventType}' sent to workflow instance ${batchId}`
780
- };
781
- }
782
- );
783
- }
784
786
  async queue(b) {
785
787
  await this.handleAction(
786
788
  null,
@@ -799,7 +801,10 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
799
801
  { data: input, schema: getAuthUriInputSchema },
800
802
  { successMessage: "Auth URI obtained." },
801
803
  async ({ connectorKey }) => {
802
- await this._initiateBankConnector({ connectorKey, withAuth: false });
804
+ const connector = await this._initiateBankConnector({
805
+ connectorKey,
806
+ skipAccounts: true
807
+ });
803
808
  const ott = backendSdk.uuidv4();
804
809
  const { command: createOneTimeToken } = createOneTimeTokenCommand(
805
810
  this.db,
@@ -810,7 +815,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
810
815
  }
811
816
  );
812
817
  await createOneTimeToken.execute();
813
- const uri = await this.bankConnector.getAuthUri({ ott });
818
+ const uri = await connector.getAuthUri({ ott });
814
819
  return { uri };
815
820
  }
816
821
  );
@@ -819,7 +824,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
819
824
  return this.handleAction(
820
825
  { data: input, schema: authorizeAccountInputSchema },
821
826
  { successMessage: "Erste code saved." },
822
- async ({ ott, urlParams }) => {
827
+ async ({ ott, urlParams, syncIntervalS, startSync }) => {
823
828
  const ottRow = await getOttQuery(this.db, {
824
829
  ott
825
830
  });
@@ -837,10 +842,10 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
837
842
  status: 400
838
843
  });
839
844
  }
840
- await this._initiateBankConnector({
845
+ const connector = await this._initiateBankConnector({
841
846
  connectorKey: ottRow.refId
842
847
  });
843
- const { credentials, accounts } = await this.bankConnector.authorizeAccount({
848
+ const { credentials, accounts } = await connector.authorizeAccount({
844
849
  urlParams
845
850
  });
846
851
  console.log("Bank connector initiated");
@@ -849,7 +854,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
849
854
  );
850
855
  const upsertAccounts = accounts.map(
851
856
  (acc) => upsertAccountCommand(this.db, {
852
- account: acc
857
+ account: syncIntervalS ? { ...acc, syncIntervalS } : acc
853
858
  }).command
854
859
  );
855
860
  const deleteCredentials = alreadyExistingAccounts.map(
@@ -857,7 +862,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
857
862
  accountId: acc.id
858
863
  }).command
859
864
  );
860
- const encryptionKey = await processBatch_workflow.importAesKey(this.env.ENCRYPTION_KEY);
865
+ const encryptionKey = await encryption.importAesKey(this.env.ENCRYPTION_KEY);
861
866
  const createAccountCredentials = (await Promise.all(
862
867
  credentials.map(
863
868
  async (cr) => createAccountCredentialsCommand(this.db, encryptionKey, {
@@ -881,6 +886,19 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
881
886
  code: "DB-B-003",
882
887
  status: 404
883
888
  });
889
+ if (startSync) {
890
+ for (const account of fetchedAccounts) {
891
+ const { error } = await this.syncAccount({
892
+ accountId: account.id
893
+ });
894
+ if (error) {
895
+ this.logError({
896
+ message: `Failed to auto-start sync workflow for account ${account.id}`,
897
+ error
898
+ });
899
+ }
900
+ }
901
+ }
884
902
  return {
885
903
  accounts: fetchedAccounts
886
904
  };
@@ -934,7 +952,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
934
952
  debtor,
935
953
  debtorIban: debtor.iban
936
954
  };
937
- const { command } = processBatch_workflow.createPaymentCommand(this.db, { payment });
955
+ const { command } = encryption.createPaymentCommand(this.db, { payment });
938
956
  const createdPayment = await command.execute().then(backendSdk.first);
939
957
  this.logQueuePush({ payment, isPaymentExecuted: true });
940
958
  await this.pushToQueue(this.env.QUEUE_BUS_QUEUE, {
@@ -1021,7 +1039,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
1021
1039
  { data: input, schema: disconnectAccountInputSchema },
1022
1040
  { successMessage: "Account disconnected successfully" },
1023
1041
  async ({ accountId }) => {
1024
- const account = await processBatch_workflow.getAccountByIdQuery(this.db, { accountId });
1042
+ const account = await encryption.getAccountByIdQuery(this.db, { accountId });
1025
1043
  if (!account) {
1026
1044
  throw backendSdk.createInternalError(null, {
1027
1045
  message: "Account not found",