@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.
- package/dist/database/schema.cjs +4 -4
- 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 +4 -4
- package/dist/export/worker.cjs +201 -183
- package/dist/export/worker.d.cts +51 -20
- package/dist/export/worker.d.mts +51 -20
- package/dist/export/worker.d.ts +51 -20
- package/dist/export/worker.mjs +161 -143
- package/dist/export/workflows.cjs +214 -18
- package/dist/export/workflows.mjs +207 -12
- package/dist/export/wrangler.d.cts +1 -2
- package/dist/export/wrangler.d.mts +1 -2
- package/dist/export/wrangler.d.ts +1 -2
- package/dist/shared/{bank.DFRS9oN5.mjs → bank.B1Gpn3ht.mjs} +9 -172
- package/dist/shared/{bank.D8wUOeOK.d.cts → bank.BEL1HIxZ.d.cts} +20 -1
- package/dist/shared/{bank.D8wUOeOK.d.mts → bank.BEL1HIxZ.d.mts} +20 -1
- package/dist/shared/{bank.D8wUOeOK.d.ts → bank.BEL1HIxZ.d.ts} +20 -1
- package/dist/shared/bank.BUEmFxS8.mjs +174 -0
- package/dist/shared/{bank.C335-raZ.cjs → bank.CPYfE-Ei.cjs} +9 -197
- package/dist/shared/bank.CpwLFudl.cjs +198 -0
- package/dist/shared/bank.D-3fzX63.mjs +170 -0
- package/dist/shared/bank.D0a-MZon.cjs +184 -0
- package/dist/shared/{bank.BchnXQDL.d.cts → bank.Dh_H_5rC.d.cts} +0 -1
- package/dist/shared/{bank.BchnXQDL.d.mts → bank.Dh_H_5rC.d.mts} +0 -1
- package/dist/shared/{bank.BchnXQDL.d.ts → bank.Dh_H_5rC.d.ts} +0 -1
- package/dist/types.cjs +14 -14
- package/dist/types.d.cts +3 -6
- package/dist/types.d.mts +3 -6
- package/dist/types.d.ts +3 -6
- package/dist/types.mjs +5 -5
- package/package.json +1 -1
- package/dist/shared/bank.Cj-oB02_.mjs +0 -392
- package/dist/shared/bank.ClRIj2Ma.cjs +0 -11
- package/dist/shared/bank.DhPfZ6b_.mjs +0 -9
- package/dist/shared/bank.DwyrLcKu.cjs +0 -402
package/dist/export/worker.cjs
CHANGED
|
@@ -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
|
|
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
|
|
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('
|
|
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(
|
|
23
|
-
target:
|
|
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(
|
|
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(
|
|
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(
|
|
60
|
+
command: db.update(drizzle.tables.ott).set({
|
|
62
61
|
expiresAt: /* @__PURE__ */ new Date()
|
|
63
|
-
}).where(drizzleOrm.eq(
|
|
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
|
|
70
|
-
const command = db.insert(
|
|
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(
|
|
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(
|
|
88
|
+
const command = db.update(drizzle.tables.payment).set({
|
|
90
89
|
deletedAt: /* @__PURE__ */ new Date()
|
|
91
|
-
}).where(drizzleOrm.eq(
|
|
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(
|
|
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(
|
|
103
|
-
|
|
104
|
-
drizzleOrm.eq(
|
|
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(
|
|
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
|
-
|
|
155
|
+
drizzle.tables.payment.accountId,
|
|
157
156
|
filterPaymentAccountId
|
|
158
157
|
),
|
|
159
|
-
buildMultiFilterConditions(
|
|
160
|
-
buildMultiFilterConditions(
|
|
158
|
+
buildMultiFilterConditions(drizzle.tables.payment.amount, filterPaymentAmount),
|
|
159
|
+
buildMultiFilterConditions(drizzle.tables.payment.currency, filterPaymentCurrency),
|
|
161
160
|
buildRangeFilterConditions(
|
|
162
|
-
|
|
161
|
+
drizzle.tables.payment.createdAt,
|
|
163
162
|
filterPaymentDateFrom,
|
|
164
163
|
filterPaymentDateTo
|
|
165
164
|
),
|
|
166
|
-
buildMultiFilterConditions(
|
|
165
|
+
buildMultiFilterConditions(drizzle.tables.payment.status, filterPaymentStatus),
|
|
167
166
|
buildMultiFilterConditions(
|
|
168
|
-
|
|
167
|
+
drizzle.tables.payment.direction,
|
|
169
168
|
filterPaymentyDirection
|
|
170
169
|
),
|
|
171
|
-
buildMultiFilterConditions(
|
|
170
|
+
buildMultiFilterConditions(drizzle.tables.payment.id, ids)
|
|
172
171
|
);
|
|
173
|
-
const sortColumn = resolveColumn(
|
|
172
|
+
const sortColumn = resolveColumn(drizzle.tables.payment, sort.column);
|
|
174
173
|
const [{ totalCount }] = await db.select({
|
|
175
174
|
totalCount: drizzleOrm.sql`count(*)`
|
|
176
|
-
}).from(
|
|
177
|
-
const payments = await db.select().from(
|
|
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(
|
|
193
|
-
buildMultiFilterConditions(
|
|
191
|
+
buildMultiFilterConditions(drizzle.tables.batch.accountId, filterBatchAccountId),
|
|
192
|
+
buildMultiFilterConditions(drizzle.tables.batch.status, filterBatchStatus)
|
|
194
193
|
);
|
|
195
|
-
const sortColumn = resolveColumn(
|
|
194
|
+
const sortColumn = resolveColumn(drizzle.tables.batch, sort.column);
|
|
196
195
|
const [{ totalCount }] = await db.select({
|
|
197
196
|
totalCount: drizzleOrm.sql`count(*)`
|
|
198
|
-
}).from(
|
|
199
|
-
const batches = await db.select().from(
|
|
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(
|
|
206
|
+
return await db.select().from(drizzle.tables.batch).where(
|
|
208
207
|
drizzleOrm.and(
|
|
209
|
-
drizzleOrm.eq(
|
|
210
|
-
drizzleOrm.eq(
|
|
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(
|
|
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
|
|
319
|
-
|
|
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
|
-
|
|
331
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
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
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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
|
|
462
|
+
connectedAccounts,
|
|
463
463
|
env: this.env
|
|
464
464
|
});
|
|
465
|
-
|
|
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
|
|
567
|
-
const
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
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
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
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
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
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
|
-
|
|
634
|
+
const changedCount = allResults.filter((r) => r.statusChanged).length;
|
|
619
635
|
console.log(
|
|
620
|
-
`
|
|
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 } =
|
|
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({
|
|
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
|
|
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
|
|
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
|
|
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 } =
|
|
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
|
|
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",
|