@develit-services/bank 0.1.7 → 0.1.8
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.mjs +1 -1
- package/dist/export/worker.cjs +14 -15
- package/dist/export/worker.d.cts +0 -1
- package/dist/export/worker.d.mts +0 -1
- package/dist/export/worker.d.ts +0 -1
- package/dist/export/worker.mjs +4 -5
- package/dist/export/workflows.cjs +160 -9
- package/dist/export/workflows.d.cts +10 -2
- package/dist/export/workflows.d.mts +10 -2
- package/dist/export/workflows.d.ts +10 -2
- package/dist/export/workflows.mjs +163 -8
- package/dist/shared/bank.B_nwGY5X.mjs +113 -0
- package/dist/shared/{bank.xIMAnZ4v.mjs → bank.DHj3MnQJ.mjs} +60 -0
- package/dist/shared/{bank.PDmcU0T-.cjs → bank.DrMnskU2.cjs} +60 -0
- package/dist/shared/{bank.D2ZeOkyc.mjs → bank.DulU-rr_.mjs} +1 -1
- package/dist/shared/{bank.BcCfzRPi.cjs → bank.YNS7gdPU.cjs} +1 -1
- package/dist/shared/bank.pT49Hbb4.cjs +120 -0
- package/dist/types.cjs +2 -2
- package/dist/types.d.cts +65 -1
- package/dist/types.d.mts +65 -1
- package/dist/types.d.ts +65 -1
- package/dist/types.mjs +2 -2
- package/package.json +1 -1
- package/dist/shared/bank.B3isylGM.cjs +0 -284
- package/dist/shared/bank.ChAGzUFo.d.cts +0 -18
- package/dist/shared/bank.ChAGzUFo.d.mts +0 -18
- package/dist/shared/bank.ChAGzUFo.d.ts +0 -18
- package/dist/shared/bank.JtGSu6eH.mjs +0 -275
package/dist/database/schema.cjs
CHANGED
package/dist/database/schema.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { D as account, G as accountCredentials, w as batch, z as ott, x as payment, y as paymentRelations } from '../shared/bank.
|
|
1
|
+
export { D as account, G as accountCredentials, w as batch, z as ott, x as payment, y as paymentRelations } from '../shared/bank.DHj3MnQJ.mjs';
|
|
2
2
|
import '@develit-io/backend-sdk';
|
|
3
3
|
import 'drizzle-orm/sqlite-core';
|
|
4
4
|
import 'date-fns';
|
package/dist/export/worker.cjs
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const export_workflows = require('../shared/bank.B3isylGM.cjs');
|
|
4
3
|
const backendSdk = require('@develit-io/backend-sdk');
|
|
5
4
|
const cloudflare_workers = require('cloudflare:workers');
|
|
6
5
|
const d1 = require('drizzle-orm/d1');
|
|
7
|
-
const database_schema = require('../shared/bank.
|
|
6
|
+
const database_schema = require('../shared/bank.DrMnskU2.cjs');
|
|
8
7
|
require('jose');
|
|
9
8
|
const generalCodes = require('@develit-io/general-codes');
|
|
10
9
|
const zod = require('zod');
|
|
10
|
+
const bank = require('../shared/bank.pT49Hbb4.cjs');
|
|
11
11
|
const drizzleOrm = require('drizzle-orm');
|
|
12
|
-
require('cloudflare:workflows');
|
|
13
|
-
require('../shared/bank.BcCfzRPi.cjs');
|
|
14
12
|
require('drizzle-orm/sqlite-core');
|
|
15
13
|
require('date-fns');
|
|
16
14
|
require('drizzle-zod');
|
|
17
15
|
require('drizzle-orm/relations');
|
|
16
|
+
require('../shared/bank.YNS7gdPU.cjs');
|
|
18
17
|
|
|
19
18
|
const upsertAccountCommand = (db, { account }) => {
|
|
20
19
|
const id = account.id || backendSdk.uuidv4();
|
|
@@ -419,7 +418,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
419
418
|
}
|
|
420
419
|
if (allFetchedPayments.length < 1) return;
|
|
421
420
|
const bankRefIds = allFetchedPayments.map((payment) => payment.bankRefId).filter(Boolean);
|
|
422
|
-
const alreadyExistingPayments = await
|
|
421
|
+
const alreadyExistingPayments = await bank.getPaymentsByBankRefIdsQuery(
|
|
423
422
|
this.db,
|
|
424
423
|
{
|
|
425
424
|
ids: bankRefIds
|
|
@@ -442,7 +441,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
442
441
|
timestamp: (/* @__PURE__ */ new Date()).toDateString()
|
|
443
442
|
}
|
|
444
443
|
});
|
|
445
|
-
return
|
|
444
|
+
return bank.updatePaymentCommand(this.db, { payment }).command;
|
|
446
445
|
}
|
|
447
446
|
eventsToPush.push({
|
|
448
447
|
eventType: "BANK_PAYMENT",
|
|
@@ -454,7 +453,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
454
453
|
timestamp: (/* @__PURE__ */ new Date()).toDateString()
|
|
455
454
|
}
|
|
456
455
|
});
|
|
457
|
-
return
|
|
456
|
+
return bank.createPaymentCommand(this.db, { payment }).command;
|
|
458
457
|
});
|
|
459
458
|
await this.db.batch([paymentsCommands[0], ...paymentsCommands.slice(1)]);
|
|
460
459
|
await this.pushToQueue(
|
|
@@ -475,7 +474,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
475
474
|
)[0];
|
|
476
475
|
}
|
|
477
476
|
if (lastSyncPayment.createdAt) {
|
|
478
|
-
await
|
|
477
|
+
await bank.updateAccountLastSyncCommand(this.db, {
|
|
479
478
|
accountId: account.id,
|
|
480
479
|
lastSyncedAt: lastSyncPayment.createdAt
|
|
481
480
|
}).command.execute();
|
|
@@ -497,7 +496,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
497
496
|
);
|
|
498
497
|
const accountsWithCredentials = await Promise.all(
|
|
499
498
|
accountsForConnector.map(async (acc) => {
|
|
500
|
-
const credentials = await
|
|
499
|
+
const credentials = await bank.getCredentialsByAccountId(this.db, {
|
|
501
500
|
accountId: acc.id
|
|
502
501
|
});
|
|
503
502
|
if (!credentials) {
|
|
@@ -514,7 +513,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
514
513
|
};
|
|
515
514
|
})
|
|
516
515
|
);
|
|
517
|
-
this.bankConnector =
|
|
516
|
+
this.bankConnector = bank.initiateConnector({
|
|
518
517
|
bank: connectorKey,
|
|
519
518
|
connectedAccounts: accountsWithCredentials,
|
|
520
519
|
env: this.env
|
|
@@ -833,7 +832,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
833
832
|
...preparedBatch.failedPayments,
|
|
834
833
|
...preparedBatch.newlyPreparedPayments
|
|
835
834
|
].map(
|
|
836
|
-
(p) =>
|
|
835
|
+
(p) => bank.createPaymentCommand(this.db, { payment: p }).command.execute()
|
|
837
836
|
)
|
|
838
837
|
]);
|
|
839
838
|
await upsertBatchCommand(this.db, {
|
|
@@ -870,7 +869,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
870
869
|
}
|
|
871
870
|
});
|
|
872
871
|
const updatePayments = payments.map(
|
|
873
|
-
(payment) =>
|
|
872
|
+
(payment) => bank.updatePaymentCommand(this.db, {
|
|
874
873
|
payment: { ...payment, status: "INITIALIZED" }
|
|
875
874
|
}).command
|
|
876
875
|
);
|
|
@@ -1047,7 +1046,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
1047
1046
|
debtor,
|
|
1048
1047
|
debtorIban: debtor.iban
|
|
1049
1048
|
};
|
|
1050
|
-
const { command } =
|
|
1049
|
+
const { command } = bank.createPaymentCommand(this.db, { payment });
|
|
1051
1050
|
const createdPayment = await command.execute().then(backendSdk.first);
|
|
1052
1051
|
this.logQueuePush({ payment, isPaymentExecuted: true });
|
|
1053
1052
|
await this.pushToQueue(this.env.QUEUE_BUS_QUEUE, {
|
|
@@ -1078,7 +1077,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
1078
1077
|
message: "Account for this organization does not exist."
|
|
1079
1078
|
});
|
|
1080
1079
|
}
|
|
1081
|
-
await
|
|
1080
|
+
await bank.updateAccountLastSyncCommand(this.db, {
|
|
1082
1081
|
accountId: account.id,
|
|
1083
1082
|
lastSyncedAt
|
|
1084
1083
|
}).command.execute();
|
|
@@ -1114,6 +1113,7 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
1114
1113
|
}
|
|
1115
1114
|
return {
|
|
1116
1115
|
...a,
|
|
1116
|
+
bankCode: a.bankCode,
|
|
1117
1117
|
workflow: status ? {
|
|
1118
1118
|
instanceId: a.id,
|
|
1119
1119
|
details: status
|
|
@@ -1221,5 +1221,4 @@ function defineBankService({
|
|
|
1221
1221
|
};
|
|
1222
1222
|
}
|
|
1223
1223
|
|
|
1224
|
-
exports.BankWorkflows = export_workflows.workflows;
|
|
1225
1224
|
exports.defineBankService = defineBankService;
|
package/dist/export/worker.d.cts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { w as BankWorkflows } from '../shared/bank.ChAGzUFo.cjs';
|
|
2
1
|
import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
|
|
3
2
|
import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
|
|
4
3
|
import { WorkerEntrypoint } from 'cloudflare:workers';
|
package/dist/export/worker.d.mts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { w as BankWorkflows } from '../shared/bank.ChAGzUFo.mjs';
|
|
2
1
|
import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
|
|
3
2
|
import { WorkflowInstanceStatus, IRPCResponse } from '@develit-io/backend-sdk';
|
|
4
3
|
import { WorkerEntrypoint } from 'cloudflare:workers';
|
package/dist/export/worker.d.ts
CHANGED
package/dist/export/worker.mjs
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import { g as getPaymentsByBankRefIdsQuery, u as updatePaymentCommand, c as createPaymentCommand, a as updateAccountLastSyncCommand, b as getCredentialsByAccountId, i as initiateConnector } from '../shared/bank.JtGSu6eH.mjs';
|
|
2
|
-
export { w as BankWorkflows } from '../shared/bank.JtGSu6eH.mjs';
|
|
3
1
|
import { uuidv4, bankAccountMetadataSchema, workflowInstanceStatusSchema, develitWorker, createInternalError, first, action, service } from '@develit-io/backend-sdk';
|
|
4
2
|
import { WorkerEntrypoint } from 'cloudflare:workers';
|
|
5
3
|
import { drizzle } from 'drizzle-orm/d1';
|
|
6
|
-
import { t as tables, c as INSTRUCTION_PRIORITIES, C as CHARGE_BEARERS, P as PAYMENT_TYPES, g as CONNECTOR_KEYS, B as BATCH_STATUSES, d as PAYMENT_STATUSES, e as PAYMENT_DIRECTIONS, i as accountInsertSchema, v as getPaymentDirection, M as MockConnector, F as FinbricksConnector, E as ErsteConnector } from '../shared/bank.
|
|
4
|
+
import { t as tables, c as INSTRUCTION_PRIORITIES, C as CHARGE_BEARERS, P as PAYMENT_TYPES, g as CONNECTOR_KEYS, B as BATCH_STATUSES, d as PAYMENT_STATUSES, e as PAYMENT_DIRECTIONS, i as accountInsertSchema, v as getPaymentDirection, M as MockConnector, F as FinbricksConnector, E as ErsteConnector } from '../shared/bank.DHj3MnQJ.mjs';
|
|
7
5
|
import 'jose';
|
|
8
6
|
import { CURRENCY_CODES } from '@develit-io/general-codes';
|
|
9
7
|
import { z } from 'zod';
|
|
8
|
+
import { a as getPaymentsByBankRefIdsQuery, u as updatePaymentCommand, c as createPaymentCommand, b as updateAccountLastSyncCommand, g as getCredentialsByAccountId, i as initiateConnector } from '../shared/bank.B_nwGY5X.mjs';
|
|
10
9
|
import { eq, inArray, and, sql, asc, desc, gte, lte } from 'drizzle-orm';
|
|
11
|
-
import 'cloudflare:workflows';
|
|
12
|
-
import '../shared/bank.D2ZeOkyc.mjs';
|
|
13
10
|
import 'drizzle-orm/sqlite-core';
|
|
14
11
|
import 'date-fns';
|
|
15
12
|
import 'drizzle-zod';
|
|
16
13
|
import 'drizzle-orm/relations';
|
|
14
|
+
import '../shared/bank.DulU-rr_.mjs';
|
|
17
15
|
|
|
18
16
|
const upsertAccountCommand = (db, { account }) => {
|
|
19
17
|
const id = account.id || uuidv4();
|
|
@@ -1113,6 +1111,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
|
|
|
1113
1111
|
}
|
|
1114
1112
|
return {
|
|
1115
1113
|
...a,
|
|
1114
|
+
bankCode: a.bankCode,
|
|
1116
1115
|
workflow: status ? {
|
|
1117
1116
|
instanceId: a.id,
|
|
1118
1117
|
details: status
|
|
@@ -1,21 +1,172 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
require('cloudflare:
|
|
5
|
-
require('
|
|
6
|
-
require('
|
|
7
|
-
require('
|
|
8
|
-
require('
|
|
3
|
+
const cloudflare_workers = require('cloudflare:workers');
|
|
4
|
+
const cloudflare_workflows = require('cloudflare:workflows');
|
|
5
|
+
const d1 = require('drizzle-orm/d1');
|
|
6
|
+
const database_schema = require('../shared/bank.DrMnskU2.cjs');
|
|
7
|
+
const backendSdk = require('@develit-io/backend-sdk');
|
|
8
|
+
const bank = require('../shared/bank.pT49Hbb4.cjs');
|
|
9
|
+
const drizzleOrm = require('drizzle-orm');
|
|
9
10
|
require('drizzle-orm/sqlite-core');
|
|
10
11
|
require('date-fns');
|
|
11
|
-
require('drizzle-orm');
|
|
12
12
|
require('@develit-io/general-codes');
|
|
13
13
|
require('zod');
|
|
14
14
|
require('jose');
|
|
15
15
|
require('drizzle-zod');
|
|
16
16
|
require('drizzle-orm/relations');
|
|
17
|
-
require('../shared/bank.
|
|
17
|
+
require('../shared/bank.YNS7gdPU.cjs');
|
|
18
18
|
|
|
19
|
+
const getAccountByIdQuery = async (db, { accountId }) => {
|
|
20
|
+
return await db.select().from(database_schema.tables.account).where(drizzleOrm.eq(database_schema.tables.account.id, accountId)).get();
|
|
21
|
+
};
|
|
19
22
|
|
|
23
|
+
function pushToQueue(queue, message) {
|
|
24
|
+
if (!Array.isArray(message)) return queue.send(message, { contentType: "v8" });
|
|
25
|
+
return queue.sendBatch(
|
|
26
|
+
message.map((m) => ({
|
|
27
|
+
body: m,
|
|
28
|
+
contentType: "v8"
|
|
29
|
+
}))
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
class SyncAccountPaymentsWorkflow extends cloudflare_workers.WorkflowEntrypoint {
|
|
33
|
+
async run(event, step) {
|
|
34
|
+
const { accountId } = event.payload;
|
|
35
|
+
const db = d1.drizzle(this.env.BANK_D1, { schema: database_schema.tables });
|
|
36
|
+
while (true) {
|
|
37
|
+
const account = await step.do("load account", async () => {
|
|
38
|
+
const account2 = await getAccountByIdQuery(db, { accountId });
|
|
39
|
+
if (!account2) {
|
|
40
|
+
throw new cloudflare_workflows.NonRetryableError(`Bank account not found: ${accountId}`);
|
|
41
|
+
}
|
|
42
|
+
return account2;
|
|
43
|
+
});
|
|
44
|
+
if (!account.lastSyncedAt) {
|
|
45
|
+
throw new Error(`lastSyncedAt is not set for account: ${accountId}`);
|
|
46
|
+
}
|
|
47
|
+
const credentials = await step.do(
|
|
48
|
+
"load account credentials",
|
|
49
|
+
async () => {
|
|
50
|
+
const credentials2 = await bank.getCredentialsByAccountId(db, { accountId });
|
|
51
|
+
if (!credentials2) {
|
|
52
|
+
throw new cloudflare_workflows.NonRetryableError(
|
|
53
|
+
`No credentials found for account: ${accountId}`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return credentials2;
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
const payments = await step.do(
|
|
60
|
+
"fetch bank payments",
|
|
61
|
+
{
|
|
62
|
+
retries: { limit: 5, delay: 2e3, backoff: "constant" },
|
|
63
|
+
timeout: "30 seconds"
|
|
64
|
+
},
|
|
65
|
+
async () => {
|
|
66
|
+
const connector = bank.initiateConnector({
|
|
67
|
+
env: this.env,
|
|
68
|
+
bank: account.connectorKey,
|
|
69
|
+
connectedAccounts: [
|
|
70
|
+
{
|
|
71
|
+
...account,
|
|
72
|
+
iban: account.iban,
|
|
73
|
+
token: credentials.value
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
const fetched = await connector.getAllAccountPayments({
|
|
78
|
+
environment: this.env.ENVIRONMENT,
|
|
79
|
+
db,
|
|
80
|
+
account,
|
|
81
|
+
filter: { dateFrom: account.lastSyncedAt }
|
|
82
|
+
});
|
|
83
|
+
return fetched.map((p) => ({
|
|
84
|
+
...p,
|
|
85
|
+
direction: database_schema.getPaymentDirection(p, account.iban)
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
if (payments.length) {
|
|
90
|
+
const bankRefIds = payments.map((payment) => payment.bankRefId).filter(Boolean);
|
|
91
|
+
const existing = await step.do("load existing payments", async () => {
|
|
92
|
+
return await bank.getPaymentsByBankRefIdsQuery(db, {
|
|
93
|
+
ids: bankRefIds
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
const paymentsToUpdate = payments.filter(
|
|
97
|
+
(p) => existing.some((e) => e.bankRefId === p.bankRefId)
|
|
98
|
+
);
|
|
99
|
+
const paymentsToCreate = payments.filter(
|
|
100
|
+
(p) => !existing.some((e) => e.bankRefId === p.bankRefId)
|
|
101
|
+
);
|
|
102
|
+
await step.do("process payments and update lastSyncAt", async () => {
|
|
103
|
+
const eventsToEmit = [];
|
|
104
|
+
const updateCommands = paymentsToUpdate.map(
|
|
105
|
+
(p) => bank.updatePaymentCommand(db, { payment: p }).command
|
|
106
|
+
);
|
|
107
|
+
eventsToEmit.push(
|
|
108
|
+
...paymentsToUpdate.map((p) => ({
|
|
109
|
+
eventType: "BANK_PAYMENT",
|
|
110
|
+
eventSignal: "paymentUpdated",
|
|
111
|
+
bankPayment: p,
|
|
112
|
+
metadata: {
|
|
113
|
+
correlationId: p.correlationId,
|
|
114
|
+
entityId: p.id,
|
|
115
|
+
idempotencySuffix: p.status,
|
|
116
|
+
timestamp: (/* @__PURE__ */ new Date()).toDateString()
|
|
117
|
+
}
|
|
118
|
+
}))
|
|
119
|
+
);
|
|
120
|
+
const createCommands = paymentsToCreate.map(
|
|
121
|
+
(p) => bank.createPaymentCommand(db, { payment: p }).command
|
|
122
|
+
);
|
|
123
|
+
eventsToEmit.push(
|
|
124
|
+
...paymentsToCreate.map((p) => ({
|
|
125
|
+
eventType: "BANK_PAYMENT",
|
|
126
|
+
eventSignal: "paymentCreated",
|
|
127
|
+
bankPayment: p,
|
|
128
|
+
metadata: {
|
|
129
|
+
correlationId: p.correlationId,
|
|
130
|
+
entityId: p.id,
|
|
131
|
+
timestamp: (/* @__PURE__ */ new Date()).toDateString()
|
|
132
|
+
}
|
|
133
|
+
}))
|
|
134
|
+
);
|
|
135
|
+
const latest = payments.reduce((current, p) => {
|
|
136
|
+
return new Date(p.processedAt).getTime() > new Date(current.processedAt).getTime() ? p : current;
|
|
137
|
+
}, payments[0]);
|
|
138
|
+
const updateLastSyncCommand = bank.updateAccountLastSyncCommand(db, {
|
|
139
|
+
accountId: account.id,
|
|
140
|
+
lastSyncedAt: latest.processedAt
|
|
141
|
+
}).command;
|
|
142
|
+
if (eventsToEmit.length) {
|
|
143
|
+
await db.batch(
|
|
144
|
+
backendSdk.asNonEmpty([
|
|
145
|
+
updateLastSyncCommand,
|
|
146
|
+
...updateCommands,
|
|
147
|
+
...createCommands
|
|
148
|
+
])
|
|
149
|
+
);
|
|
150
|
+
await pushToQueue(
|
|
151
|
+
this.env.QUEUE_BUS_QUEUE,
|
|
152
|
+
eventsToEmit
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
payments: payments.length,
|
|
157
|
+
updated: paymentsToUpdate.length,
|
|
158
|
+
created: paymentsToCreate.length,
|
|
159
|
+
eventsEmitted: eventsToEmit.length,
|
|
160
|
+
lastSyncedAt: latest?.createdAt
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
await step.sleep(
|
|
165
|
+
"Sleep for next sync",
|
|
166
|
+
`${account.syncIntervalS} seconds`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
20
171
|
|
|
21
|
-
exports.SyncAccountPaymentsWorkflow =
|
|
172
|
+
exports.SyncAccountPaymentsWorkflow = SyncAccountPaymentsWorkflow;
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
|
+
|
|
3
|
+
type Params = {
|
|
4
|
+
accountId: string;
|
|
5
|
+
};
|
|
6
|
+
declare class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint<BankEnv, Params> {
|
|
7
|
+
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { SyncAccountPaymentsWorkflow };
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
|
+
|
|
3
|
+
type Params = {
|
|
4
|
+
accountId: string;
|
|
5
|
+
};
|
|
6
|
+
declare class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint<BankEnv, Params> {
|
|
7
|
+
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { SyncAccountPaymentsWorkflow };
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
|
+
|
|
3
|
+
type Params = {
|
|
4
|
+
accountId: string;
|
|
5
|
+
};
|
|
6
|
+
declare class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint<BankEnv, Params> {
|
|
7
|
+
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { SyncAccountPaymentsWorkflow };
|
|
@@ -1,15 +1,170 @@
|
|
|
1
|
-
|
|
2
|
-
import 'cloudflare:
|
|
3
|
-
import '
|
|
4
|
-
import '
|
|
5
|
-
import '
|
|
6
|
-
import '
|
|
1
|
+
import { WorkflowEntrypoint } from 'cloudflare:workers';
|
|
2
|
+
import { NonRetryableError } from 'cloudflare:workflows';
|
|
3
|
+
import { drizzle } from 'drizzle-orm/d1';
|
|
4
|
+
import { t as tables, v as getPaymentDirection } from '../shared/bank.DHj3MnQJ.mjs';
|
|
5
|
+
import { asNonEmpty } from '@develit-io/backend-sdk';
|
|
6
|
+
import { g as getCredentialsByAccountId, i as initiateConnector, a as getPaymentsByBankRefIdsQuery, u as updatePaymentCommand, c as createPaymentCommand, b as updateAccountLastSyncCommand } from '../shared/bank.B_nwGY5X.mjs';
|
|
7
|
+
import { eq } from 'drizzle-orm';
|
|
7
8
|
import 'drizzle-orm/sqlite-core';
|
|
8
9
|
import 'date-fns';
|
|
9
|
-
import 'drizzle-orm';
|
|
10
10
|
import '@develit-io/general-codes';
|
|
11
11
|
import 'zod';
|
|
12
12
|
import 'jose';
|
|
13
13
|
import 'drizzle-zod';
|
|
14
14
|
import 'drizzle-orm/relations';
|
|
15
|
-
import '../shared/bank.
|
|
15
|
+
import '../shared/bank.DulU-rr_.mjs';
|
|
16
|
+
|
|
17
|
+
const getAccountByIdQuery = async (db, { accountId }) => {
|
|
18
|
+
return await db.select().from(tables.account).where(eq(tables.account.id, accountId)).get();
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function pushToQueue(queue, message) {
|
|
22
|
+
if (!Array.isArray(message)) return queue.send(message, { contentType: "v8" });
|
|
23
|
+
return queue.sendBatch(
|
|
24
|
+
message.map((m) => ({
|
|
25
|
+
body: m,
|
|
26
|
+
contentType: "v8"
|
|
27
|
+
}))
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
class SyncAccountPaymentsWorkflow extends WorkflowEntrypoint {
|
|
31
|
+
async run(event, step) {
|
|
32
|
+
const { accountId } = event.payload;
|
|
33
|
+
const db = drizzle(this.env.BANK_D1, { schema: tables });
|
|
34
|
+
while (true) {
|
|
35
|
+
const account = await step.do("load account", async () => {
|
|
36
|
+
const account2 = await getAccountByIdQuery(db, { accountId });
|
|
37
|
+
if (!account2) {
|
|
38
|
+
throw new NonRetryableError(`Bank account not found: ${accountId}`);
|
|
39
|
+
}
|
|
40
|
+
return account2;
|
|
41
|
+
});
|
|
42
|
+
if (!account.lastSyncedAt) {
|
|
43
|
+
throw new Error(`lastSyncedAt is not set for account: ${accountId}`);
|
|
44
|
+
}
|
|
45
|
+
const credentials = await step.do(
|
|
46
|
+
"load account credentials",
|
|
47
|
+
async () => {
|
|
48
|
+
const credentials2 = await getCredentialsByAccountId(db, { accountId });
|
|
49
|
+
if (!credentials2) {
|
|
50
|
+
throw new NonRetryableError(
|
|
51
|
+
`No credentials found for account: ${accountId}`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
return credentials2;
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
const payments = await step.do(
|
|
58
|
+
"fetch bank payments",
|
|
59
|
+
{
|
|
60
|
+
retries: { limit: 5, delay: 2e3, backoff: "constant" },
|
|
61
|
+
timeout: "30 seconds"
|
|
62
|
+
},
|
|
63
|
+
async () => {
|
|
64
|
+
const connector = initiateConnector({
|
|
65
|
+
env: this.env,
|
|
66
|
+
bank: account.connectorKey,
|
|
67
|
+
connectedAccounts: [
|
|
68
|
+
{
|
|
69
|
+
...account,
|
|
70
|
+
iban: account.iban,
|
|
71
|
+
token: credentials.value
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
});
|
|
75
|
+
const fetched = await connector.getAllAccountPayments({
|
|
76
|
+
environment: this.env.ENVIRONMENT,
|
|
77
|
+
db,
|
|
78
|
+
account,
|
|
79
|
+
filter: { dateFrom: account.lastSyncedAt }
|
|
80
|
+
});
|
|
81
|
+
return fetched.map((p) => ({
|
|
82
|
+
...p,
|
|
83
|
+
direction: getPaymentDirection(p, account.iban)
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
if (payments.length) {
|
|
88
|
+
const bankRefIds = payments.map((payment) => payment.bankRefId).filter(Boolean);
|
|
89
|
+
const existing = await step.do("load existing payments", async () => {
|
|
90
|
+
return await getPaymentsByBankRefIdsQuery(db, {
|
|
91
|
+
ids: bankRefIds
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
const paymentsToUpdate = payments.filter(
|
|
95
|
+
(p) => existing.some((e) => e.bankRefId === p.bankRefId)
|
|
96
|
+
);
|
|
97
|
+
const paymentsToCreate = payments.filter(
|
|
98
|
+
(p) => !existing.some((e) => e.bankRefId === p.bankRefId)
|
|
99
|
+
);
|
|
100
|
+
await step.do("process payments and update lastSyncAt", async () => {
|
|
101
|
+
const eventsToEmit = [];
|
|
102
|
+
const updateCommands = paymentsToUpdate.map(
|
|
103
|
+
(p) => updatePaymentCommand(db, { payment: p }).command
|
|
104
|
+
);
|
|
105
|
+
eventsToEmit.push(
|
|
106
|
+
...paymentsToUpdate.map((p) => ({
|
|
107
|
+
eventType: "BANK_PAYMENT",
|
|
108
|
+
eventSignal: "paymentUpdated",
|
|
109
|
+
bankPayment: p,
|
|
110
|
+
metadata: {
|
|
111
|
+
correlationId: p.correlationId,
|
|
112
|
+
entityId: p.id,
|
|
113
|
+
idempotencySuffix: p.status,
|
|
114
|
+
timestamp: (/* @__PURE__ */ new Date()).toDateString()
|
|
115
|
+
}
|
|
116
|
+
}))
|
|
117
|
+
);
|
|
118
|
+
const createCommands = paymentsToCreate.map(
|
|
119
|
+
(p) => createPaymentCommand(db, { payment: p }).command
|
|
120
|
+
);
|
|
121
|
+
eventsToEmit.push(
|
|
122
|
+
...paymentsToCreate.map((p) => ({
|
|
123
|
+
eventType: "BANK_PAYMENT",
|
|
124
|
+
eventSignal: "paymentCreated",
|
|
125
|
+
bankPayment: p,
|
|
126
|
+
metadata: {
|
|
127
|
+
correlationId: p.correlationId,
|
|
128
|
+
entityId: p.id,
|
|
129
|
+
timestamp: (/* @__PURE__ */ new Date()).toDateString()
|
|
130
|
+
}
|
|
131
|
+
}))
|
|
132
|
+
);
|
|
133
|
+
const latest = payments.reduce((current, p) => {
|
|
134
|
+
return new Date(p.processedAt).getTime() > new Date(current.processedAt).getTime() ? p : current;
|
|
135
|
+
}, payments[0]);
|
|
136
|
+
const updateLastSyncCommand = updateAccountLastSyncCommand(db, {
|
|
137
|
+
accountId: account.id,
|
|
138
|
+
lastSyncedAt: latest.processedAt
|
|
139
|
+
}).command;
|
|
140
|
+
if (eventsToEmit.length) {
|
|
141
|
+
await db.batch(
|
|
142
|
+
asNonEmpty([
|
|
143
|
+
updateLastSyncCommand,
|
|
144
|
+
...updateCommands,
|
|
145
|
+
...createCommands
|
|
146
|
+
])
|
|
147
|
+
);
|
|
148
|
+
await pushToQueue(
|
|
149
|
+
this.env.QUEUE_BUS_QUEUE,
|
|
150
|
+
eventsToEmit
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
payments: payments.length,
|
|
155
|
+
updated: paymentsToUpdate.length,
|
|
156
|
+
created: paymentsToCreate.length,
|
|
157
|
+
eventsEmitted: eventsToEmit.length,
|
|
158
|
+
lastSyncedAt: latest?.createdAt
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
await step.sleep(
|
|
163
|
+
"Sleep for next sync",
|
|
164
|
+
`${account.syncIntervalS} seconds`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export { SyncAccountPaymentsWorkflow };
|