@develit-services/ledger 0.0.1

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.
@@ -0,0 +1,18 @@
1
+ interface LedgerServiceEnvironmentConfig {
2
+ d1: {
3
+ id: string;
4
+ };
5
+ vars: Record<string, unknown>;
6
+ }
7
+ interface LedgerServiceWranglerConfig {
8
+ project: string;
9
+ name: string;
10
+ envs: {
11
+ local: LedgerServiceEnvironmentConfig;
12
+ [key: string]: LedgerServiceEnvironmentConfig;
13
+ };
14
+ }
15
+ interface LedgerServiceEnv extends LedgerEnv {
16
+ }
17
+
18
+ export type { LedgerServiceWranglerConfig as L, LedgerServiceEnvironmentConfig as a, LedgerServiceEnv as b };
@@ -0,0 +1,18 @@
1
+ interface LedgerServiceEnvironmentConfig {
2
+ d1: {
3
+ id: string;
4
+ };
5
+ vars: Record<string, unknown>;
6
+ }
7
+ interface LedgerServiceWranglerConfig {
8
+ project: string;
9
+ name: string;
10
+ envs: {
11
+ local: LedgerServiceEnvironmentConfig;
12
+ [key: string]: LedgerServiceEnvironmentConfig;
13
+ };
14
+ }
15
+ interface LedgerServiceEnv extends LedgerEnv {
16
+ }
17
+
18
+ export type { LedgerServiceWranglerConfig as L, LedgerServiceEnvironmentConfig as a, LedgerServiceEnv as b };
@@ -0,0 +1,18 @@
1
+ interface LedgerServiceEnvironmentConfig {
2
+ d1: {
3
+ id: string;
4
+ };
5
+ vars: Record<string, unknown>;
6
+ }
7
+ interface LedgerServiceWranglerConfig {
8
+ project: string;
9
+ name: string;
10
+ envs: {
11
+ local: LedgerServiceEnvironmentConfig;
12
+ [key: string]: LedgerServiceEnvironmentConfig;
13
+ };
14
+ }
15
+ interface LedgerServiceEnv extends LedgerEnv {
16
+ }
17
+
18
+ export type { LedgerServiceWranglerConfig as L, LedgerServiceEnvironmentConfig as a, LedgerServiceEnv as b };
@@ -0,0 +1,317 @@
1
+ 'use strict';
2
+
3
+ const generalCodes = require('@develit-io/general-codes');
4
+ const zod = require('zod');
5
+ const backendSdk = require('@develit-io/backend-sdk');
6
+
7
+ const ACCOUNT_TYPES = [
8
+ "INTERNAL",
9
+ // classic internal account managed in the system
10
+ "EXTERNAL",
11
+ // tracked external client account (e.g. at Spořka)
12
+ "NOSTRO",
13
+ // mirror bank account with third party (e.g. at Creditas)
14
+ "TECHNICAL",
15
+ // any internal account for system logic (AML, fees, ...)
16
+ "SETTLEMENT",
17
+ // account used for trade settlement
18
+ "FX",
19
+ // account serving currency conversion
20
+ "FEE",
21
+ // account for fee collection
22
+ "REVENUE",
23
+ // company profit account (e.g. from fees, FX)
24
+ "LOSS",
25
+ // loss account (e.g. FX spread, refunds)
26
+ "TRANSPORT",
27
+ // temporary parking of funds "in transit"
28
+ "HOLD",
29
+ // blocked funds (e.g. AML hold, pending settlement)
30
+ "SYSTEM",
31
+ // internal system account (e.g. provisioning, demo accounts)
32
+ "TEST"
33
+ // sandbox / test accounts
34
+ ];
35
+ const ASSET_TYPES = [
36
+ "FIAT",
37
+ // CZK, EUR, USD…
38
+ "CRYPTO",
39
+ // BTC, ETH, USDT…
40
+ "TOKEN",
41
+ // tokenized assets – e.g. stablecoins
42
+ "STOCK",
43
+ // securities, shares
44
+ "COMMODITY",
45
+ // physical assets like gold, silver
46
+ "OTHER"
47
+ // for specific cases
48
+ ];
49
+ const BALANCE_STRATEGIES = ["SNAPSHOT", "COMPUTED"];
50
+ const IDENTIFIER_KINDS = [
51
+ "IBAN",
52
+ "LOCAL_CZ",
53
+ "SWIFT",
54
+ "CRYPTO_ADDRESS"
55
+ ];
56
+ const ENTRY_STATUSES = [
57
+ "PENDING",
58
+ "REALIZED",
59
+ "FAILED",
60
+ "CANCELED"
61
+ ];
62
+ const TRANSACTION_STATUSES = [
63
+ "WAITING_FOR_PAYMENT",
64
+ "PAUSED",
65
+ "WAITING_FOR_MANUAL_PROCESSING",
66
+ "MATCHED",
67
+ "RETURNING",
68
+ "RETURNED",
69
+ "FAILED",
70
+ "CANCELLED",
71
+ "COMPLETED"
72
+ ];
73
+ const TRANSACTION_TYPES = [
74
+ "CLIENT_FUND_IN",
75
+ "CLIENT_FUND_OUT",
76
+ "PROVIDER_FUND_IN",
77
+ "PROVIDER_FUND_OUT",
78
+ "EXCHANGE",
79
+ // maybe in future
80
+ "UNMATCHED",
81
+ "ADJUSTMENT",
82
+ // manual correction
83
+ "TRANSFER"
84
+ // internal transfer between accounts
85
+ ];
86
+ const REFERENCE_TYPES = ["PAYMENT", "EXCHANGE", "ORDER"];
87
+ const PAYMENT_CHARGE_TYPES = ["SHA", "OUR", "BEN"];
88
+
89
+ const ALLOWED_TRANSACTION_FILTERS = {
90
+ CORRELATION_ID: "filterTransactionCorrelationId",
91
+ REFERENCE_TYPE: "filterTransactionReferenceType",
92
+ REFERENCE_ID: "filterTransactionReferenceId",
93
+ TYPE: "filterTransactionType",
94
+ FROM: "filterTransactionDateFrom",
95
+ TO: "filterTransactionDateTo",
96
+ DESCRIPTION: "filterTransactionDescription",
97
+ COMPLETED_AT: "filterTransactionCompletedAt",
98
+ STATUS: "filterTransactionStatus"
99
+ };
100
+
101
+ const PAYMENT_TYPES = ["SEPA", "SWIFT", "IFSC", "DOMESTIC"];
102
+ const PAYMENT_STATUSES = [
103
+ "PREPARED",
104
+ "INITIALIZED",
105
+ "FAILED",
106
+ "PENDING",
107
+ "COMPLETED",
108
+ "CREATED"
109
+ ];
110
+ const PAYMENT_DIRECTIONS = ["INCOMING", "OUTGOING"];
111
+ const BATCH_STATUSES = [
112
+ "OPEN",
113
+ "WAITING_FOR_PROCESSING",
114
+ "PROCESSING",
115
+ "READY_TO_SIGN",
116
+ "PREPARED",
117
+ "COMPLETED",
118
+ "FAILED"
119
+ ];
120
+ const COUNTRY_CODES = generalCodes.COUNTRY_CODES_2;
121
+
122
+ const createAccountInputSchema = zod.z.object({
123
+ name: zod.z.string().min(1),
124
+ ownerId: zod.z.string().min(1),
125
+ accountType: zod.z.enum(ACCOUNT_TYPES),
126
+ assetType: zod.z.enum(ASSET_TYPES),
127
+ currency: zod.z.enum(generalCodes.CURRENCY_CODES),
128
+ balanceStrategy: zod.z.enum(BALANCE_STRATEGIES),
129
+ parentAccountId: zod.z.string().optional(),
130
+ countryCode: zod.z.enum(COUNTRY_CODES).optional(),
131
+ identifier: zod.z.object({
132
+ kind: zod.z.enum(IDENTIFIER_KINDS),
133
+ iban: zod.z.string().optional(),
134
+ accountNumber: zod.z.string().optional(),
135
+ bankCode: zod.z.enum(generalCodes.BANK_CODES).optional(),
136
+ prefix: zod.z.string().optional(),
137
+ swift: zod.z.string().optional(),
138
+ cryptoAddress: zod.z.string().optional(),
139
+ label: zod.z.string().optional(),
140
+ holderName: zod.z.string().min(1)
141
+ }).optional()
142
+ });
143
+
144
+ const transactionMetadataSchema = zod.z.object({
145
+ rejectImbalanced: zod.z.boolean().optional(),
146
+ allowPartialFailure: zod.z.boolean().optional(),
147
+ tags: zod.z.array(zod.z.string()).optional(),
148
+ note: zod.z.string().optional(),
149
+ payment: zod.z.object({
150
+ vs: zod.z.string().optional(),
151
+ // variabilní symbol
152
+ ss: zod.z.string().optional(),
153
+ // specifický symbol
154
+ ks: zod.z.string().optional(),
155
+ // konstantní symbol
156
+ message: zod.z.string().optional(),
157
+ // zpráva pro příjemce
158
+ reference: zod.z.string().optional(),
159
+ // další reference
160
+ creditor: backendSdk.bankAccountMetadataSchema.optional(),
161
+ // příjemce
162
+ debtor: backendSdk.bankAccountMetadataSchema.optional(),
163
+ // plátce
164
+ executionDate: zod.z.string().optional(),
165
+ // ISO 8601
166
+ currency: zod.z.enum(generalCodes.CURRENCY_CODES).optional(),
167
+ amount: zod.z.number().optional(),
168
+ paymentChargeType: zod.z.string().optional()
169
+ // typ poplatku za platbu
170
+ }).optional()
171
+ }).catchall(zod.z.unknown());
172
+ const createTransactionInputSchema = zod.z.object({
173
+ correlationId: zod.z.string().min(1),
174
+ referenceType: zod.z.enum(REFERENCE_TYPES),
175
+ referenceId: zod.z.string().optional(),
176
+ type: zod.z.enum(TRANSACTION_TYPES),
177
+ description: zod.z.string().optional(),
178
+ paymentId: zod.z.string().optional(),
179
+ metadata: transactionMetadataSchema.optional().default({}),
180
+ status: zod.z.enum(TRANSACTION_STATUSES)
181
+ // entries: z.array(entryInputSchema).min(1),
182
+ });
183
+
184
+ const deleteAccountInputSchema = zod.z.object({
185
+ accountId: zod.z.uuid()
186
+ });
187
+
188
+ const findAccountByIdentifierInputSchema = zod.z.object({
189
+ iban: zod.z.string().optional(),
190
+ accountNumber: zod.z.string().optional(),
191
+ bankCode: zod.z.enum(generalCodes.BANK_CODES).optional(),
192
+ swift: zod.z.string().optional(),
193
+ cryptoAddress: zod.z.string().optional()
194
+ }).refine(
195
+ (data) => {
196
+ const hasIban = !!data.iban;
197
+ const hasAccountNumber = !!(data.accountNumber && data.bankCode);
198
+ const hasSwift = !!data.swift;
199
+ const hasCryptoAddress = !!data.cryptoAddress;
200
+ return hasIban || hasAccountNumber || hasSwift || hasCryptoAddress;
201
+ },
202
+ {
203
+ message: "At least one identifier (iban, accountNumber+bankCode, swift, or cryptoAddress) must be provided"
204
+ }
205
+ );
206
+
207
+ const getAccountInputSchema = zod.z.object({
208
+ accountId: zod.z.uuid()
209
+ });
210
+
211
+ const getAccountBalanceInputSchema = zod.z.object({
212
+ accountId: zod.z.uuid()
213
+ });
214
+
215
+ const getAccountIdentifierInputSchema = zod.z.object({
216
+ identifierId: zod.z.uuid()
217
+ });
218
+
219
+ const getAccountsByOwnerInputSchema = zod.z.object({
220
+ ownerId: zod.z.string().min(1)
221
+ });
222
+
223
+ const listAccountIdentifiersInputSchema = zod.z.object({
224
+ accountId: zod.z.uuid()
225
+ });
226
+
227
+ const listAccountsInputSchema = zod.z.object({
228
+ ownerId: zod.z.string().optional(),
229
+ accountType: zod.z.enum(ACCOUNT_TYPES).optional(),
230
+ assetType: zod.z.enum(ASSET_TYPES).optional(),
231
+ currency: zod.z.enum(generalCodes.CURRENCY_CODES).optional(),
232
+ parentAccountId: zod.z.string().optional(),
233
+ limit: zod.z.number().int().min(1).max(1e3).default(100),
234
+ offset: zod.z.number().int().min(0).default(0)
235
+ });
236
+
237
+ const updateAccountInputSchema = zod.z.object({
238
+ accountId: zod.z.uuid(),
239
+ name: zod.z.string().min(1).optional(),
240
+ accountType: zod.z.enum(ACCOUNT_TYPES).optional(),
241
+ assetType: zod.z.enum(ASSET_TYPES).optional(),
242
+ currency: zod.z.enum(generalCodes.CURRENCY_CODES).optional(),
243
+ balanceStrategy: zod.z.enum(BALANCE_STRATEGIES).optional(),
244
+ parentAccountId: zod.z.string().optional()
245
+ // todo: removed because its no longer in the account schema and the method using it does not update the account identifier which has it
246
+ // countryCode: z.enum(COUNTRY_CODES).optional(),
247
+ });
248
+
249
+ const updateTransactionInputSchema = zod.z.object({
250
+ transactionId: zod.z.uuid(),
251
+ status: zod.z.enum(TRANSACTION_STATUSES),
252
+ completedAt: zod.z.date().optional()
253
+ });
254
+
255
+ const getTransactionByIdInputSchema = zod.z.object({
256
+ id: zod.z.uuid()
257
+ });
258
+
259
+ const getTransactionsByReferenceIdInputSchema = zod.z.object({
260
+ referenceType: zod.z.enum(REFERENCE_TYPES),
261
+ referenceId: zod.z.uuid()
262
+ });
263
+
264
+ const getTransactionsInputSchema = zod.z.object({
265
+ page: zod.z.number().positive(),
266
+ limit: zod.z.number().positive(),
267
+ sort: zod.z.object({
268
+ column: zod.z.string(),
269
+ direction: zod.z.enum(["asc", "desc"])
270
+ }),
271
+ [ALLOWED_TRANSACTION_FILTERS.CORRELATION_ID]: zod.z.uuid().optional(),
272
+ [ALLOWED_TRANSACTION_FILTERS.REFERENCE_TYPE]: zod.z.enum(REFERENCE_TYPES).optional(),
273
+ [ALLOWED_TRANSACTION_FILTERS.REFERENCE_ID]: zod.z.uuid().optional(),
274
+ [ALLOWED_TRANSACTION_FILTERS.TYPE]: zod.z.enum(TRANSACTION_TYPES).optional(),
275
+ [ALLOWED_TRANSACTION_FILTERS.DESCRIPTION]: zod.z.string().optional(),
276
+ [ALLOWED_TRANSACTION_FILTERS.FROM]: zod.z.date().optional(),
277
+ [ALLOWED_TRANSACTION_FILTERS.TO]: zod.z.date().optional(),
278
+ [ALLOWED_TRANSACTION_FILTERS.COMPLETED_AT]: zod.z.date().optional(),
279
+ [ALLOWED_TRANSACTION_FILTERS.STATUS]: zod.z.enum(TRANSACTION_STATUSES).optional(),
280
+ search: zod.z.string().optional()
281
+ });
282
+
283
+ const updateTransactionConfirmationSentAtInputSchema = zod.z.object({
284
+ transactionId: zod.z.uuid()
285
+ });
286
+
287
+ exports.ACCOUNT_TYPES = ACCOUNT_TYPES;
288
+ exports.ALLOWED_TRANSACTION_FILTERS = ALLOWED_TRANSACTION_FILTERS;
289
+ exports.ASSET_TYPES = ASSET_TYPES;
290
+ exports.BALANCE_STRATEGIES = BALANCE_STRATEGIES;
291
+ exports.BATCH_STATUSES = BATCH_STATUSES;
292
+ exports.COUNTRY_CODES = COUNTRY_CODES;
293
+ exports.ENTRY_STATUSES = ENTRY_STATUSES;
294
+ exports.IDENTIFIER_KINDS = IDENTIFIER_KINDS;
295
+ exports.PAYMENT_CHARGE_TYPES = PAYMENT_CHARGE_TYPES;
296
+ exports.PAYMENT_DIRECTIONS = PAYMENT_DIRECTIONS;
297
+ exports.PAYMENT_STATUSES = PAYMENT_STATUSES;
298
+ exports.PAYMENT_TYPES = PAYMENT_TYPES;
299
+ exports.REFERENCE_TYPES = REFERENCE_TYPES;
300
+ exports.TRANSACTION_STATUSES = TRANSACTION_STATUSES;
301
+ exports.TRANSACTION_TYPES = TRANSACTION_TYPES;
302
+ exports.createAccountInputSchema = createAccountInputSchema;
303
+ exports.createTransactionInputSchema = createTransactionInputSchema;
304
+ exports.deleteAccountInputSchema = deleteAccountInputSchema;
305
+ exports.findAccountByIdentifierInputSchema = findAccountByIdentifierInputSchema;
306
+ exports.getAccountBalanceInputSchema = getAccountBalanceInputSchema;
307
+ exports.getAccountIdentifierInputSchema = getAccountIdentifierInputSchema;
308
+ exports.getAccountInputSchema = getAccountInputSchema;
309
+ exports.getAccountsByOwnerInputSchema = getAccountsByOwnerInputSchema;
310
+ exports.getTransactionByIdInputSchema = getTransactionByIdInputSchema;
311
+ exports.getTransactionsByReferenceIdInputSchema = getTransactionsByReferenceIdInputSchema;
312
+ exports.getTransactionsInputSchema = getTransactionsInputSchema;
313
+ exports.listAccountIdentifiersInputSchema = listAccountIdentifiersInputSchema;
314
+ exports.listAccountsInputSchema = listAccountsInputSchema;
315
+ exports.updateAccountInputSchema = updateAccountInputSchema;
316
+ exports.updateTransactionConfirmationSentAtInputSchema = updateTransactionConfirmationSentAtInputSchema;
317
+ exports.updateTransactionInputSchema = updateTransactionInputSchema;
@@ -0,0 +1,118 @@
1
+ 'use strict';
2
+
3
+ const backendSdk = require('@develit-io/backend-sdk');
4
+ const drizzleOrm = require('drizzle-orm');
5
+ const sqliteCore = require('drizzle-orm/sqlite-core');
6
+ const updateTransactionConfirmationSentAt = require('./ledger.D1MIlhpb.cjs');
7
+ require('@develit-io/general-codes');
8
+
9
+ const account = sqliteCore.sqliteTable("account", {
10
+ ...backendSdk.base,
11
+ name: sqliteCore.text("name").notNull(),
12
+ ownerId: sqliteCore.text("owner_id").notNull(),
13
+ accountType: sqliteCore.text("account_type").$type().notNull(),
14
+ assetType: sqliteCore.text("asset_type").$type().notNull(),
15
+ currency: sqliteCore.text("currency").$type().notNull(),
16
+ balanceStrategy: sqliteCore.text("balance_strategy").$type().notNull(),
17
+ parentAccountId: sqliteCore.text("parent_account_id"),
18
+ closedAt: sqliteCore.integer("closed_at", { mode: "timestamp_ms" })
19
+ });
20
+ const accountIdentifier = sqliteCore.sqliteTable("account_identifier", {
21
+ ...backendSdk.base,
22
+ kind: sqliteCore.text("kind").$type().notNull(),
23
+ iban: sqliteCore.text("iban"),
24
+ accountNumber: sqliteCore.text("account_number"),
25
+ bankCode: sqliteCore.text("bank_code").$type(),
26
+ prefix: sqliteCore.text("prefix"),
27
+ swift: sqliteCore.text("swift"),
28
+ cryptoAddress: sqliteCore.text("crypto_address"),
29
+ label: sqliteCore.text("label"),
30
+ holderName: sqliteCore.text("holder_name").notNull(),
31
+ network: sqliteCore.text("network").$type(),
32
+ countryCode: sqliteCore.text("country_code").$type()
33
+ });
34
+ const accountIdentifierMapping = sqliteCore.sqliteTable(
35
+ "account_identifier_mapping",
36
+ {
37
+ accountId: sqliteCore.text("account_id").notNull().references(() => account.id),
38
+ identifierId: sqliteCore.text("identifier_id").notNull().references(() => accountIdentifier.id)
39
+ }
40
+ );
41
+ const accountRelations = drizzleOrm.relations(account, ({ many }) => ({
42
+ identifiers: many(accountIdentifierMapping)
43
+ }));
44
+ const accountIdentifierRelations = drizzleOrm.relations(
45
+ accountIdentifier,
46
+ ({ many }) => ({
47
+ accountMappings: many(accountIdentifierMapping)
48
+ })
49
+ );
50
+ const accountIdentifierMappingRelations = drizzleOrm.relations(
51
+ accountIdentifierMapping,
52
+ ({ one }) => ({
53
+ account: one(account, {
54
+ fields: [accountIdentifierMapping.accountId],
55
+ references: [account.id]
56
+ }),
57
+ identifier: one(accountIdentifier, {
58
+ fields: [accountIdentifierMapping.identifierId],
59
+ references: [accountIdentifier.id]
60
+ })
61
+ })
62
+ );
63
+
64
+ const entry = sqliteCore.sqliteTable("entry", {
65
+ ...backendSdk.base,
66
+ accountId: sqliteCore.text("account_id").notNull(),
67
+ currency: sqliteCore.text("currency").notNull(),
68
+ creditAmount: sqliteCore.real("amount").notNull(),
69
+ debitAmount: sqliteCore.real("debit_amount").notNull(),
70
+ correlationId: sqliteCore.text("correlation_id").notNull(),
71
+ transactionId: sqliteCore.text("transaction_id").notNull(),
72
+ status: sqliteCore.text("status").$type().notNull(),
73
+ isBalanced: sqliteCore.integer("is_balanced", { mode: "boolean" }).notNull(),
74
+ metadata: sqliteCore.text("metadata", { mode: "json" }).$type().notNull(),
75
+ timestamp: sqliteCore.integer("timestamp", { mode: "timestamp_ms" }).notNull()
76
+ });
77
+
78
+ const transaction = sqliteCore.sqliteTable("transaction", {
79
+ ...backendSdk.base,
80
+ correlationId: sqliteCore.text("correlation_id").notNull(),
81
+ // Unique ID for the transaction, used for correlation
82
+ // Business context
83
+ referenceType: sqliteCore.text("reference_type", { enum: updateTransactionConfirmationSentAt.REFERENCE_TYPES }).$type().notNull(),
84
+ referenceId: sqliteCore.text("reference_id"),
85
+ // business transaction ID
86
+ type: sqliteCore.text("type", { enum: updateTransactionConfirmationSentAt.TRANSACTION_TYPES }).$type().notNull(),
87
+ description: sqliteCore.text("description"),
88
+ completedAt: sqliteCore.integer("completed_at", { mode: "timestamp_ms" }),
89
+ confirmationSentAt: sqliteCore.integer("confirmation_sent_at", { mode: "timestamp_ms" }),
90
+ status: sqliteCore.text("status", { enum: updateTransactionConfirmationSentAt.TRANSACTION_STATUSES }).$type().notNull(),
91
+ statusReason: sqliteCore.text("status_reason"),
92
+ paymentId: sqliteCore.text("payment_id"),
93
+ metadata: sqliteCore.text("metadata", { mode: "json" }).$type().notNull(),
94
+ value: sqliteCore.real("value"),
95
+ currency: sqliteCore.text("currency").$type()
96
+ });
97
+
98
+ const schema = {
99
+ __proto__: null,
100
+ account: account,
101
+ accountIdentifier: accountIdentifier,
102
+ accountIdentifierMapping: accountIdentifierMapping,
103
+ accountIdentifierMappingRelations: accountIdentifierMappingRelations,
104
+ accountIdentifierRelations: accountIdentifierRelations,
105
+ accountRelations: accountRelations,
106
+ entry: entry,
107
+ transaction: transaction
108
+ };
109
+
110
+ exports.account = account;
111
+ exports.accountIdentifier = accountIdentifier;
112
+ exports.accountIdentifierMapping = accountIdentifierMapping;
113
+ exports.accountIdentifierMappingRelations = accountIdentifierMappingRelations;
114
+ exports.accountIdentifierRelations = accountIdentifierRelations;
115
+ exports.accountRelations = accountRelations;
116
+ exports.entry = entry;
117
+ exports.schema = schema;
118
+ exports.transaction = transaction;