multivendor-wallet 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.
- package/README.md +21 -0
- package/dist/hooks/index.cjs +681 -0
- package/dist/hooks/index.cjs.map +1 -0
- package/dist/hooks/index.d.mts +7 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.js +678 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.cjs +2194 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +131 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.js +2173 -0
- package/dist/index.js.map +1 -0
- package/dist/store-BQ3whei-.d.mts +140 -0
- package/dist/store-BQ3whei-.d.ts +140 -0
- package/dist/typeorm/index.cjs +768 -0
- package/dist/typeorm/index.cjs.map +1 -0
- package/dist/typeorm/index.d.mts +79 -0
- package/dist/typeorm/index.d.ts +79 -0
- package/dist/typeorm/index.js +764 -0
- package/dist/typeorm/index.js.map +1 -0
- package/dist/types-CrJxUVwX.d.mts +224 -0
- package/dist/types-iNUEzUgo.d.ts +224 -0
- package/package.json +118 -0
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# multivendor-wallet
|
|
2
|
+
|
|
3
|
+
Framework-agnostic wallet ledger engine for multi-vendor marketplaces.
|
|
4
|
+
|
|
5
|
+
## Operations
|
|
6
|
+
|
|
7
|
+
- `credit` / `debit` — adjust available balance (integer minor units / paise)
|
|
8
|
+
- `hold` / `release` / `cancelHold` — escrow lifecycle
|
|
9
|
+
- `transfer` — atomic debit + credit
|
|
10
|
+
- `getBalance` — `{ available, held, total }` where `total = available + held`
|
|
11
|
+
|
|
12
|
+
## Host integration
|
|
13
|
+
|
|
14
|
+
Implement `IWalletStore` with your persistence layer (TypeORM adapter ships in Myownbazaar_server). Pass `{ nativeTx: entityManager }` to join an existing database transaction.
|
|
15
|
+
|
|
16
|
+
## Publish
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm run build && pnpm run test
|
|
20
|
+
# tag: wallet-v0.0.1
|
|
21
|
+
```
|
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var typeorm = require('typeorm');
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
9
|
+
|
|
10
|
+
// src/currency.ts
|
|
11
|
+
function toMinorUnit(amount) {
|
|
12
|
+
return Math.round(amount * 100);
|
|
13
|
+
}
|
|
14
|
+
__name(toMinorUnit, "toMinorUnit");
|
|
15
|
+
function fromMinorUnit(amount) {
|
|
16
|
+
return amount / 100;
|
|
17
|
+
}
|
|
18
|
+
__name(fromMinorUnit, "fromMinorUnit");
|
|
19
|
+
|
|
20
|
+
// src/types.ts
|
|
21
|
+
var WalletAccountType = /* @__PURE__ */ (function(WalletAccountType2) {
|
|
22
|
+
WalletAccountType2["CUSTOMER"] = "customer";
|
|
23
|
+
WalletAccountType2["VENDOR"] = "vendor";
|
|
24
|
+
WalletAccountType2["PLATFORM"] = "platform";
|
|
25
|
+
return WalletAccountType2;
|
|
26
|
+
})({});
|
|
27
|
+
|
|
28
|
+
// src/hooks/order.ts
|
|
29
|
+
function isWalletOnlyPayment(paymentMethod) {
|
|
30
|
+
return String(paymentMethod ?? "").trim().toLowerCase() === "wallet";
|
|
31
|
+
}
|
|
32
|
+
__name(isWalletOnlyPayment, "isWalletOnlyPayment");
|
|
33
|
+
function createOrderHooks(runtime) {
|
|
34
|
+
const { client, platformOwnerId, flags } = runtime;
|
|
35
|
+
return {
|
|
36
|
+
async onOrderPaid(ctx) {
|
|
37
|
+
if (!flags.enabled || !flags.ledgerWrites) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const txCtx = {
|
|
41
|
+
nativeTx: ctx.nativeTx
|
|
42
|
+
};
|
|
43
|
+
const platform = await client.getOrCreateAccount(WalletAccountType.PLATFORM, platformOwnerId, ctx.currency, txCtx);
|
|
44
|
+
const orderTotalPaise = toMinorUnit(ctx.orderTotalRupees);
|
|
45
|
+
const shouldDebitCustomer = isWalletOnlyPayment(ctx.paymentMethod) && ctx.customerId && !ctx.skipCustomerDebit;
|
|
46
|
+
if (shouldDebitCustomer) {
|
|
47
|
+
const debitRupees = ctx.walletAmountRupees ?? ctx.orderTotalRupees;
|
|
48
|
+
const customer = await client.getOrCreateAccount(WalletAccountType.CUSTOMER, ctx.customerId, ctx.currency, txCtx);
|
|
49
|
+
await client.debit({
|
|
50
|
+
accountId: customer.id,
|
|
51
|
+
amount: toMinorUnit(debitRupees),
|
|
52
|
+
idempotencyKey: `wallet:payment:${ctx.paymentNumber}`,
|
|
53
|
+
reference: {
|
|
54
|
+
referenceType: "order",
|
|
55
|
+
referenceId: String(ctx.orderId)
|
|
56
|
+
}
|
|
57
|
+
}, txCtx);
|
|
58
|
+
}
|
|
59
|
+
await client.credit({
|
|
60
|
+
accountId: platform.id,
|
|
61
|
+
amount: orderTotalPaise,
|
|
62
|
+
idempotencyKey: `payment:${ctx.paymentNumber}`,
|
|
63
|
+
reference: {
|
|
64
|
+
referenceType: "order",
|
|
65
|
+
referenceId: String(ctx.orderId)
|
|
66
|
+
}
|
|
67
|
+
}, txCtx);
|
|
68
|
+
for (const line of ctx.lines) {
|
|
69
|
+
const vendorNetRupees = line.commissionBaseRupees - line.commissionRupees;
|
|
70
|
+
if (vendorNetRupees <= 0) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const vendor = await client.getOrCreateAccount(WalletAccountType.VENDOR, line.vendorId, ctx.currency, txCtx);
|
|
74
|
+
await client.hold({
|
|
75
|
+
sourceAccountId: platform.id,
|
|
76
|
+
targetAccountId: vendor.id,
|
|
77
|
+
amount: toMinorUnit(vendorNetRupees),
|
|
78
|
+
idempotencyKey: `order:${ctx.orderId}:hold:vendorOrder:${line.vendorOrderId}`,
|
|
79
|
+
reference: {
|
|
80
|
+
referenceType: "vendor_order",
|
|
81
|
+
referenceId: String(line.vendorOrderId)
|
|
82
|
+
}
|
|
83
|
+
}, txCtx);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
async onLineDelivered(ctx) {
|
|
87
|
+
if (!flags.enabled || !flags.ledgerWrites) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
await client.release({
|
|
91
|
+
reference: {
|
|
92
|
+
referenceType: "vendor_order",
|
|
93
|
+
referenceId: String(ctx.vendorOrderId)
|
|
94
|
+
},
|
|
95
|
+
idempotencyKey: `vendorOrder:${ctx.vendorOrderId}:release`
|
|
96
|
+
}, ctx.nativeTx != null ? {
|
|
97
|
+
nativeTx: ctx.nativeTx
|
|
98
|
+
} : void 0);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
__name(createOrderHooks, "createOrderHooks");
|
|
103
|
+
|
|
104
|
+
// src/hooks/refund.ts
|
|
105
|
+
function isWalletPayment(paymentMethod) {
|
|
106
|
+
return String(paymentMethod ?? "").trim().toLowerCase() === "wallet";
|
|
107
|
+
}
|
|
108
|
+
__name(isWalletPayment, "isWalletPayment");
|
|
109
|
+
function walletCreditRupees(ctx) {
|
|
110
|
+
if (ctx.walletRefundRupees != null && ctx.walletRefundRupees > 0) {
|
|
111
|
+
return ctx.walletRefundRupees;
|
|
112
|
+
}
|
|
113
|
+
return isWalletPayment(ctx.paymentMethod) ? ctx.lineTotalRupees : 0;
|
|
114
|
+
}
|
|
115
|
+
__name(walletCreditRupees, "walletCreditRupees");
|
|
116
|
+
function idempotencyPrefix(ctx) {
|
|
117
|
+
const scope = ctx.idempotencyScope ?? String(ctx.orderProductId);
|
|
118
|
+
return ctx.refundReason === "return" ? `return:${scope}` : `refund:${ctx.orderProductId}`;
|
|
119
|
+
}
|
|
120
|
+
__name(idempotencyPrefix, "idempotencyPrefix");
|
|
121
|
+
function createRefundHooks(runtime) {
|
|
122
|
+
const { client, platformOwnerId, flags } = runtime;
|
|
123
|
+
return {
|
|
124
|
+
async onRefund(ctx) {
|
|
125
|
+
if (!flags.enabled || !flags.ledgerWrites) {
|
|
126
|
+
await ctx.processExternalRefund();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const keyPrefix = idempotencyPrefix(ctx);
|
|
130
|
+
if (!ctx.skipEscrow) {
|
|
131
|
+
await client.cancelHold({
|
|
132
|
+
reference: {
|
|
133
|
+
referenceType: "vendor_order",
|
|
134
|
+
referenceId: String(ctx.vendorOrderId)
|
|
135
|
+
},
|
|
136
|
+
idempotencyKey: `${keyPrefix}:cancel_hold`
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const refundPaise = toMinorUnit(ctx.lineTotalRupees);
|
|
140
|
+
if (refundPaise > 0) {
|
|
141
|
+
const platform = await client.getOrCreateAccount(WalletAccountType.PLATFORM, platformOwnerId, ctx.currency);
|
|
142
|
+
const balance = await client.getBalance(platform.id);
|
|
143
|
+
if (balance.available >= refundPaise) {
|
|
144
|
+
await client.debit({
|
|
145
|
+
accountId: platform.id,
|
|
146
|
+
amount: refundPaise,
|
|
147
|
+
idempotencyKey: `${keyPrefix}:platform_debit`,
|
|
148
|
+
reference: {
|
|
149
|
+
referenceType: "order_product",
|
|
150
|
+
referenceId: String(ctx.orderProductId)
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
const creditRupees = walletCreditRupees(ctx);
|
|
155
|
+
if (creditRupees > 0 && ctx.customerId) {
|
|
156
|
+
const customer = await client.getOrCreateAccount(WalletAccountType.CUSTOMER, ctx.customerId, ctx.currency);
|
|
157
|
+
await client.credit({
|
|
158
|
+
accountId: customer.id,
|
|
159
|
+
amount: toMinorUnit(creditRupees),
|
|
160
|
+
idempotencyKey: `${keyPrefix}:customer_credit`,
|
|
161
|
+
reference: {
|
|
162
|
+
referenceType: "order",
|
|
163
|
+
referenceId: String(ctx.orderId ?? ctx.orderProductId)
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
await ctx.processExternalRefund();
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
__name(createRefundHooks, "createRefundHooks");
|
|
173
|
+
|
|
174
|
+
// src/hooks/settlement.ts
|
|
175
|
+
function createSettlementHooks(runtime) {
|
|
176
|
+
const { client, flags } = runtime;
|
|
177
|
+
return {
|
|
178
|
+
async onSettlementDebit(ctx) {
|
|
179
|
+
if (!flags.enabled || !flags.settlementDebit) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const txCtx = {
|
|
183
|
+
nativeTx: ctx.nativeTx
|
|
184
|
+
};
|
|
185
|
+
const amountPaise = toMinorUnit(ctx.amountRupees);
|
|
186
|
+
const vendorAccount = await client.getOrCreateAccount(WalletAccountType.VENDOR, ctx.vendorId, ctx.currency, txCtx);
|
|
187
|
+
const balance = await client.getBalance(vendorAccount.id, txCtx);
|
|
188
|
+
if (balance.available < amountPaise) {
|
|
189
|
+
throw new Error(`Insufficient vendor wallet balance for settlement (vendor ${ctx.vendorId})`);
|
|
190
|
+
}
|
|
191
|
+
await client.debit({
|
|
192
|
+
accountId: vendorAccount.id,
|
|
193
|
+
amount: amountPaise,
|
|
194
|
+
idempotencyKey: `settlement:${ctx.settlementId}:debit:${ctx.vendorId}`,
|
|
195
|
+
reference: {
|
|
196
|
+
referenceType: "settlement",
|
|
197
|
+
referenceId: String(ctx.settlementId)
|
|
198
|
+
}
|
|
199
|
+
}, txCtx);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
__name(createSettlementHooks, "createSettlementHooks");
|
|
204
|
+
function resolveWalletConnection() {
|
|
205
|
+
{
|
|
206
|
+
throw new Error("Wallet database connection is not registered. Pass host TypeORM Connection as dataSource.");
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
__name(resolveWalletConnection, "resolveWalletConnection");
|
|
210
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
211
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
212
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
213
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
214
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
215
|
+
}
|
|
216
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
217
|
+
function _ts_metadata(k, v) {
|
|
218
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
219
|
+
}
|
|
220
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
221
|
+
function nowTimestamp() {
|
|
222
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
|
|
223
|
+
}
|
|
224
|
+
__name(nowTimestamp, "nowTimestamp");
|
|
225
|
+
var _WalletAccountEntity = class _WalletAccountEntity {
|
|
226
|
+
constructor() {
|
|
227
|
+
__publicField(this, "id");
|
|
228
|
+
__publicField(this, "ownerType");
|
|
229
|
+
__publicField(this, "ownerId");
|
|
230
|
+
__publicField(this, "currency");
|
|
231
|
+
__publicField(this, "availableBalance");
|
|
232
|
+
__publicField(this, "heldBalance");
|
|
233
|
+
__publicField(this, "createdBy");
|
|
234
|
+
__publicField(this, "createdDate");
|
|
235
|
+
__publicField(this, "modifiedBy");
|
|
236
|
+
__publicField(this, "modifiedDate");
|
|
237
|
+
}
|
|
238
|
+
setCreated() {
|
|
239
|
+
this.createdDate = nowTimestamp();
|
|
240
|
+
this.modifiedDate = nowTimestamp();
|
|
241
|
+
}
|
|
242
|
+
setModified() {
|
|
243
|
+
this.modifiedDate = nowTimestamp();
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
__name(_WalletAccountEntity, "WalletAccountEntity");
|
|
247
|
+
var WalletAccountEntity = _WalletAccountEntity;
|
|
248
|
+
_ts_decorate([
|
|
249
|
+
typeorm.PrimaryGeneratedColumn({
|
|
250
|
+
name: "id"
|
|
251
|
+
}),
|
|
252
|
+
_ts_metadata("design:type", Number)
|
|
253
|
+
], WalletAccountEntity.prototype, "id", void 0);
|
|
254
|
+
_ts_decorate([
|
|
255
|
+
typeorm.Column({
|
|
256
|
+
name: "owner_type",
|
|
257
|
+
length: 32
|
|
258
|
+
}),
|
|
259
|
+
_ts_metadata("design:type", String)
|
|
260
|
+
], WalletAccountEntity.prototype, "ownerType", void 0);
|
|
261
|
+
_ts_decorate([
|
|
262
|
+
typeorm.Column({
|
|
263
|
+
name: "owner_id"
|
|
264
|
+
}),
|
|
265
|
+
_ts_metadata("design:type", Number)
|
|
266
|
+
], WalletAccountEntity.prototype, "ownerId", void 0);
|
|
267
|
+
_ts_decorate([
|
|
268
|
+
typeorm.Column({
|
|
269
|
+
name: "currency",
|
|
270
|
+
length: 8,
|
|
271
|
+
default: "INR"
|
|
272
|
+
}),
|
|
273
|
+
_ts_metadata("design:type", String)
|
|
274
|
+
], WalletAccountEntity.prototype, "currency", void 0);
|
|
275
|
+
_ts_decorate([
|
|
276
|
+
typeorm.Column({
|
|
277
|
+
name: "available_balance",
|
|
278
|
+
type: "bigint",
|
|
279
|
+
default: 0
|
|
280
|
+
}),
|
|
281
|
+
_ts_metadata("design:type", String)
|
|
282
|
+
], WalletAccountEntity.prototype, "availableBalance", void 0);
|
|
283
|
+
_ts_decorate([
|
|
284
|
+
typeorm.Column({
|
|
285
|
+
name: "held_balance",
|
|
286
|
+
type: "bigint",
|
|
287
|
+
default: 0
|
|
288
|
+
}),
|
|
289
|
+
_ts_metadata("design:type", String)
|
|
290
|
+
], WalletAccountEntity.prototype, "heldBalance", void 0);
|
|
291
|
+
_ts_decorate([
|
|
292
|
+
typeorm.Column({
|
|
293
|
+
name: "created_by",
|
|
294
|
+
nullable: true
|
|
295
|
+
}),
|
|
296
|
+
_ts_metadata("design:type", Number)
|
|
297
|
+
], WalletAccountEntity.prototype, "createdBy", void 0);
|
|
298
|
+
_ts_decorate([
|
|
299
|
+
typeorm.Column({
|
|
300
|
+
name: "created_date",
|
|
301
|
+
nullable: true
|
|
302
|
+
}),
|
|
303
|
+
_ts_metadata("design:type", String)
|
|
304
|
+
], WalletAccountEntity.prototype, "createdDate", void 0);
|
|
305
|
+
_ts_decorate([
|
|
306
|
+
typeorm.Column({
|
|
307
|
+
name: "modified_by",
|
|
308
|
+
nullable: true
|
|
309
|
+
}),
|
|
310
|
+
_ts_metadata("design:type", Number)
|
|
311
|
+
], WalletAccountEntity.prototype, "modifiedBy", void 0);
|
|
312
|
+
_ts_decorate([
|
|
313
|
+
typeorm.Column({
|
|
314
|
+
name: "modified_date",
|
|
315
|
+
nullable: true
|
|
316
|
+
}),
|
|
317
|
+
_ts_metadata("design:type", String)
|
|
318
|
+
], WalletAccountEntity.prototype, "modifiedDate", void 0);
|
|
319
|
+
_ts_decorate([
|
|
320
|
+
typeorm.BeforeInsert(),
|
|
321
|
+
_ts_metadata("design:type", Function),
|
|
322
|
+
_ts_metadata("design:paramtypes", []),
|
|
323
|
+
_ts_metadata("design:returntype", void 0)
|
|
324
|
+
], WalletAccountEntity.prototype, "setCreated", null);
|
|
325
|
+
_ts_decorate([
|
|
326
|
+
typeorm.BeforeUpdate(),
|
|
327
|
+
_ts_metadata("design:type", Function),
|
|
328
|
+
_ts_metadata("design:paramtypes", []),
|
|
329
|
+
_ts_metadata("design:returntype", void 0)
|
|
330
|
+
], WalletAccountEntity.prototype, "setModified", null);
|
|
331
|
+
WalletAccountEntity = _ts_decorate([
|
|
332
|
+
typeorm.Entity("wallet_account")
|
|
333
|
+
], WalletAccountEntity);
|
|
334
|
+
var _WalletLedgerEntryEntity = class _WalletLedgerEntryEntity {
|
|
335
|
+
constructor() {
|
|
336
|
+
__publicField(this, "id");
|
|
337
|
+
__publicField(this, "accountId");
|
|
338
|
+
__publicField(this, "entryType");
|
|
339
|
+
__publicField(this, "amount");
|
|
340
|
+
__publicField(this, "balanceAfterAvailable");
|
|
341
|
+
__publicField(this, "balanceAfterHeld");
|
|
342
|
+
__publicField(this, "idempotencyKey");
|
|
343
|
+
__publicField(this, "referenceType");
|
|
344
|
+
__publicField(this, "referenceId");
|
|
345
|
+
__publicField(this, "metadata");
|
|
346
|
+
__publicField(this, "createdBy");
|
|
347
|
+
__publicField(this, "createdDate");
|
|
348
|
+
__publicField(this, "modifiedBy");
|
|
349
|
+
__publicField(this, "modifiedDate");
|
|
350
|
+
}
|
|
351
|
+
setCreated() {
|
|
352
|
+
this.createdDate = nowTimestamp();
|
|
353
|
+
this.modifiedDate = nowTimestamp();
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
__name(_WalletLedgerEntryEntity, "WalletLedgerEntryEntity");
|
|
357
|
+
var WalletLedgerEntryEntity = _WalletLedgerEntryEntity;
|
|
358
|
+
_ts_decorate([
|
|
359
|
+
typeorm.PrimaryGeneratedColumn({
|
|
360
|
+
name: "id"
|
|
361
|
+
}),
|
|
362
|
+
_ts_metadata("design:type", Number)
|
|
363
|
+
], WalletLedgerEntryEntity.prototype, "id", void 0);
|
|
364
|
+
_ts_decorate([
|
|
365
|
+
typeorm.Column({
|
|
366
|
+
name: "account_id"
|
|
367
|
+
}),
|
|
368
|
+
_ts_metadata("design:type", Number)
|
|
369
|
+
], WalletLedgerEntryEntity.prototype, "accountId", void 0);
|
|
370
|
+
_ts_decorate([
|
|
371
|
+
typeorm.Column({
|
|
372
|
+
name: "entry_type",
|
|
373
|
+
length: 32
|
|
374
|
+
}),
|
|
375
|
+
_ts_metadata("design:type", String)
|
|
376
|
+
], WalletLedgerEntryEntity.prototype, "entryType", void 0);
|
|
377
|
+
_ts_decorate([
|
|
378
|
+
typeorm.Column({
|
|
379
|
+
name: "amount",
|
|
380
|
+
type: "bigint"
|
|
381
|
+
}),
|
|
382
|
+
_ts_metadata("design:type", String)
|
|
383
|
+
], WalletLedgerEntryEntity.prototype, "amount", void 0);
|
|
384
|
+
_ts_decorate([
|
|
385
|
+
typeorm.Column({
|
|
386
|
+
name: "balance_after_available",
|
|
387
|
+
type: "bigint"
|
|
388
|
+
}),
|
|
389
|
+
_ts_metadata("design:type", String)
|
|
390
|
+
], WalletLedgerEntryEntity.prototype, "balanceAfterAvailable", void 0);
|
|
391
|
+
_ts_decorate([
|
|
392
|
+
typeorm.Column({
|
|
393
|
+
name: "balance_after_held",
|
|
394
|
+
type: "bigint"
|
|
395
|
+
}),
|
|
396
|
+
_ts_metadata("design:type", String)
|
|
397
|
+
], WalletLedgerEntryEntity.prototype, "balanceAfterHeld", void 0);
|
|
398
|
+
_ts_decorate([
|
|
399
|
+
typeorm.Column({
|
|
400
|
+
name: "idempotency_key",
|
|
401
|
+
length: 255,
|
|
402
|
+
unique: true
|
|
403
|
+
}),
|
|
404
|
+
_ts_metadata("design:type", String)
|
|
405
|
+
], WalletLedgerEntryEntity.prototype, "idempotencyKey", void 0);
|
|
406
|
+
_ts_decorate([
|
|
407
|
+
typeorm.Column({
|
|
408
|
+
name: "reference_type",
|
|
409
|
+
length: 64,
|
|
410
|
+
nullable: true
|
|
411
|
+
}),
|
|
412
|
+
_ts_metadata("design:type", String)
|
|
413
|
+
], WalletLedgerEntryEntity.prototype, "referenceType", void 0);
|
|
414
|
+
_ts_decorate([
|
|
415
|
+
typeorm.Column({
|
|
416
|
+
name: "reference_id",
|
|
417
|
+
length: 128,
|
|
418
|
+
nullable: true
|
|
419
|
+
}),
|
|
420
|
+
_ts_metadata("design:type", String)
|
|
421
|
+
], WalletLedgerEntryEntity.prototype, "referenceId", void 0);
|
|
422
|
+
_ts_decorate([
|
|
423
|
+
typeorm.Column({
|
|
424
|
+
name: "metadata",
|
|
425
|
+
type: "json",
|
|
426
|
+
nullable: true
|
|
427
|
+
}),
|
|
428
|
+
_ts_metadata("design:type", typeof Record === "undefined" ? Object : Record)
|
|
429
|
+
], WalletLedgerEntryEntity.prototype, "metadata", void 0);
|
|
430
|
+
_ts_decorate([
|
|
431
|
+
typeorm.Column({
|
|
432
|
+
name: "created_by",
|
|
433
|
+
nullable: true
|
|
434
|
+
}),
|
|
435
|
+
_ts_metadata("design:type", Number)
|
|
436
|
+
], WalletLedgerEntryEntity.prototype, "createdBy", void 0);
|
|
437
|
+
_ts_decorate([
|
|
438
|
+
typeorm.Column({
|
|
439
|
+
name: "created_date",
|
|
440
|
+
nullable: true
|
|
441
|
+
}),
|
|
442
|
+
_ts_metadata("design:type", String)
|
|
443
|
+
], WalletLedgerEntryEntity.prototype, "createdDate", void 0);
|
|
444
|
+
_ts_decorate([
|
|
445
|
+
typeorm.Column({
|
|
446
|
+
name: "modified_by",
|
|
447
|
+
nullable: true
|
|
448
|
+
}),
|
|
449
|
+
_ts_metadata("design:type", Number)
|
|
450
|
+
], WalletLedgerEntryEntity.prototype, "modifiedBy", void 0);
|
|
451
|
+
_ts_decorate([
|
|
452
|
+
typeorm.Column({
|
|
453
|
+
name: "modified_date",
|
|
454
|
+
nullable: true
|
|
455
|
+
}),
|
|
456
|
+
_ts_metadata("design:type", String)
|
|
457
|
+
], WalletLedgerEntryEntity.prototype, "modifiedDate", void 0);
|
|
458
|
+
_ts_decorate([
|
|
459
|
+
typeorm.BeforeInsert(),
|
|
460
|
+
_ts_metadata("design:type", Function),
|
|
461
|
+
_ts_metadata("design:paramtypes", []),
|
|
462
|
+
_ts_metadata("design:returntype", void 0)
|
|
463
|
+
], WalletLedgerEntryEntity.prototype, "setCreated", null);
|
|
464
|
+
WalletLedgerEntryEntity = _ts_decorate([
|
|
465
|
+
typeorm.Entity("wallet_ledger_entry")
|
|
466
|
+
], WalletLedgerEntryEntity);
|
|
467
|
+
var _WalletHoldEntity = class _WalletHoldEntity {
|
|
468
|
+
constructor() {
|
|
469
|
+
__publicField(this, "id");
|
|
470
|
+
__publicField(this, "sourceAccountId");
|
|
471
|
+
__publicField(this, "targetAccountId");
|
|
472
|
+
__publicField(this, "amount");
|
|
473
|
+
__publicField(this, "status");
|
|
474
|
+
__publicField(this, "referenceType");
|
|
475
|
+
__publicField(this, "referenceId");
|
|
476
|
+
__publicField(this, "idempotencyKey");
|
|
477
|
+
__publicField(this, "createdBy");
|
|
478
|
+
__publicField(this, "createdDate");
|
|
479
|
+
__publicField(this, "modifiedBy");
|
|
480
|
+
__publicField(this, "modifiedDate");
|
|
481
|
+
}
|
|
482
|
+
setCreated() {
|
|
483
|
+
this.createdDate = nowTimestamp();
|
|
484
|
+
this.modifiedDate = nowTimestamp();
|
|
485
|
+
}
|
|
486
|
+
setModified() {
|
|
487
|
+
this.modifiedDate = nowTimestamp();
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
__name(_WalletHoldEntity, "WalletHoldEntity");
|
|
491
|
+
var WalletHoldEntity = _WalletHoldEntity;
|
|
492
|
+
_ts_decorate([
|
|
493
|
+
typeorm.PrimaryGeneratedColumn({
|
|
494
|
+
name: "id"
|
|
495
|
+
}),
|
|
496
|
+
_ts_metadata("design:type", Number)
|
|
497
|
+
], WalletHoldEntity.prototype, "id", void 0);
|
|
498
|
+
_ts_decorate([
|
|
499
|
+
typeorm.Column({
|
|
500
|
+
name: "source_account_id"
|
|
501
|
+
}),
|
|
502
|
+
_ts_metadata("design:type", Number)
|
|
503
|
+
], WalletHoldEntity.prototype, "sourceAccountId", void 0);
|
|
504
|
+
_ts_decorate([
|
|
505
|
+
typeorm.Column({
|
|
506
|
+
name: "target_account_id"
|
|
507
|
+
}),
|
|
508
|
+
_ts_metadata("design:type", Number)
|
|
509
|
+
], WalletHoldEntity.prototype, "targetAccountId", void 0);
|
|
510
|
+
_ts_decorate([
|
|
511
|
+
typeorm.Column({
|
|
512
|
+
name: "amount",
|
|
513
|
+
type: "bigint"
|
|
514
|
+
}),
|
|
515
|
+
_ts_metadata("design:type", String)
|
|
516
|
+
], WalletHoldEntity.prototype, "amount", void 0);
|
|
517
|
+
_ts_decorate([
|
|
518
|
+
typeorm.Column({
|
|
519
|
+
name: "status",
|
|
520
|
+
length: 16,
|
|
521
|
+
default: "active"
|
|
522
|
+
}),
|
|
523
|
+
_ts_metadata("design:type", String)
|
|
524
|
+
], WalletHoldEntity.prototype, "status", void 0);
|
|
525
|
+
_ts_decorate([
|
|
526
|
+
typeorm.Column({
|
|
527
|
+
name: "reference_type",
|
|
528
|
+
length: 64
|
|
529
|
+
}),
|
|
530
|
+
_ts_metadata("design:type", String)
|
|
531
|
+
], WalletHoldEntity.prototype, "referenceType", void 0);
|
|
532
|
+
_ts_decorate([
|
|
533
|
+
typeorm.Column({
|
|
534
|
+
name: "reference_id",
|
|
535
|
+
length: 128
|
|
536
|
+
}),
|
|
537
|
+
_ts_metadata("design:type", String)
|
|
538
|
+
], WalletHoldEntity.prototype, "referenceId", void 0);
|
|
539
|
+
_ts_decorate([
|
|
540
|
+
typeorm.Column({
|
|
541
|
+
name: "idempotency_key",
|
|
542
|
+
length: 255
|
|
543
|
+
}),
|
|
544
|
+
_ts_metadata("design:type", String)
|
|
545
|
+
], WalletHoldEntity.prototype, "idempotencyKey", void 0);
|
|
546
|
+
_ts_decorate([
|
|
547
|
+
typeorm.Column({
|
|
548
|
+
name: "created_by",
|
|
549
|
+
nullable: true
|
|
550
|
+
}),
|
|
551
|
+
_ts_metadata("design:type", Number)
|
|
552
|
+
], WalletHoldEntity.prototype, "createdBy", void 0);
|
|
553
|
+
_ts_decorate([
|
|
554
|
+
typeorm.Column({
|
|
555
|
+
name: "created_date",
|
|
556
|
+
nullable: true
|
|
557
|
+
}),
|
|
558
|
+
_ts_metadata("design:type", String)
|
|
559
|
+
], WalletHoldEntity.prototype, "createdDate", void 0);
|
|
560
|
+
_ts_decorate([
|
|
561
|
+
typeorm.Column({
|
|
562
|
+
name: "modified_by",
|
|
563
|
+
nullable: true
|
|
564
|
+
}),
|
|
565
|
+
_ts_metadata("design:type", Number)
|
|
566
|
+
], WalletHoldEntity.prototype, "modifiedBy", void 0);
|
|
567
|
+
_ts_decorate([
|
|
568
|
+
typeorm.Column({
|
|
569
|
+
name: "modified_date",
|
|
570
|
+
nullable: true
|
|
571
|
+
}),
|
|
572
|
+
_ts_metadata("design:type", String)
|
|
573
|
+
], WalletHoldEntity.prototype, "modifiedDate", void 0);
|
|
574
|
+
_ts_decorate([
|
|
575
|
+
typeorm.BeforeInsert(),
|
|
576
|
+
_ts_metadata("design:type", Function),
|
|
577
|
+
_ts_metadata("design:paramtypes", []),
|
|
578
|
+
_ts_metadata("design:returntype", void 0)
|
|
579
|
+
], WalletHoldEntity.prototype, "setCreated", null);
|
|
580
|
+
_ts_decorate([
|
|
581
|
+
typeorm.BeforeUpdate(),
|
|
582
|
+
_ts_metadata("design:type", Function),
|
|
583
|
+
_ts_metadata("design:paramtypes", []),
|
|
584
|
+
_ts_metadata("design:returntype", void 0)
|
|
585
|
+
], WalletHoldEntity.prototype, "setModified", null);
|
|
586
|
+
WalletHoldEntity = _ts_decorate([
|
|
587
|
+
typeorm.Entity("wallet_hold")
|
|
588
|
+
], WalletHoldEntity);
|
|
589
|
+
|
|
590
|
+
// src/hooks/reconciliation.ts
|
|
591
|
+
async function runWalletReconciliation() {
|
|
592
|
+
const parityDeltas = await findVendorPaymentHoldParityDeltas();
|
|
593
|
+
const cacheMismatches = await findCacheLedgerMismatches();
|
|
594
|
+
return {
|
|
595
|
+
parityDeltas,
|
|
596
|
+
cacheMismatches
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
__name(runWalletReconciliation, "runWalletReconciliation");
|
|
600
|
+
async function findVendorPaymentHoldParityDeltas() {
|
|
601
|
+
const rows = await resolveWalletConnection().query(`
|
|
602
|
+
SELECT
|
|
603
|
+
vo.order_id AS orderId,
|
|
604
|
+
vp.vendor_order_id AS vendorOrderId,
|
|
605
|
+
vp.amount AS vendorPaymentAmount,
|
|
606
|
+
wh.amount AS holdAmount,
|
|
607
|
+
wh.status AS holdStatus
|
|
608
|
+
FROM vendor_payment vp
|
|
609
|
+
INNER JOIN vendor_orders vo ON vo.vendor_order_id = vp.vendor_order_id
|
|
610
|
+
LEFT JOIN wallet_hold wh
|
|
611
|
+
ON wh.reference_type = 'vendor_order'
|
|
612
|
+
AND wh.reference_id = CAST(vp.vendor_order_id AS CHAR)
|
|
613
|
+
WHERE vp.vendor_order_id IS NOT NULL
|
|
614
|
+
`);
|
|
615
|
+
const deltas = [];
|
|
616
|
+
for (const row of rows) {
|
|
617
|
+
const vendorPaymentRupees = Number(row.vendorPaymentAmount) || 0;
|
|
618
|
+
const holdPaise = row.holdAmount != null ? Number(row.holdAmount) : 0;
|
|
619
|
+
const holdRupees = fromMinorUnit(holdPaise);
|
|
620
|
+
const delta = Math.abs(vendorPaymentRupees - holdRupees);
|
|
621
|
+
if (delta > 0.01 && row.holdStatus === "active") {
|
|
622
|
+
deltas.push({
|
|
623
|
+
orderId: Number(row.orderId),
|
|
624
|
+
vendorOrderId: Number(row.vendorOrderId),
|
|
625
|
+
vendorPaymentRupees,
|
|
626
|
+
holdPaise,
|
|
627
|
+
deltaRupees: delta
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return deltas;
|
|
632
|
+
}
|
|
633
|
+
__name(findVendorPaymentHoldParityDeltas, "findVendorPaymentHoldParityDeltas");
|
|
634
|
+
async function findCacheLedgerMismatches() {
|
|
635
|
+
const connection = resolveWalletConnection();
|
|
636
|
+
const accounts = await connection.getRepository(WalletAccountEntity).find();
|
|
637
|
+
const mismatches = [];
|
|
638
|
+
for (const account of accounts) {
|
|
639
|
+
const lastEntry = await connection.getRepository(WalletLedgerEntryEntity).findOne({
|
|
640
|
+
where: {
|
|
641
|
+
accountId: account.id
|
|
642
|
+
},
|
|
643
|
+
order: {
|
|
644
|
+
id: "DESC"
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
if (!lastEntry) {
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
const cachedAvailable = Number(account.availableBalance);
|
|
651
|
+
const cachedHeld = Number(account.heldBalance);
|
|
652
|
+
const ledgerAvailable = Number(lastEntry.balanceAfterAvailable);
|
|
653
|
+
const ledgerHeld = Number(lastEntry.balanceAfterHeld);
|
|
654
|
+
if (cachedAvailable !== ledgerAvailable || cachedHeld !== ledgerHeld) {
|
|
655
|
+
mismatches.push({
|
|
656
|
+
accountId: account.id,
|
|
657
|
+
cachedAvailable,
|
|
658
|
+
cachedHeld,
|
|
659
|
+
ledgerAvailable,
|
|
660
|
+
ledgerHeld
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return mismatches;
|
|
665
|
+
}
|
|
666
|
+
__name(findCacheLedgerMismatches, "findCacheLedgerMismatches");
|
|
667
|
+
|
|
668
|
+
// src/hooks/index.ts
|
|
669
|
+
function createLifecycleHooks(runtime) {
|
|
670
|
+
return {
|
|
671
|
+
...createOrderHooks(runtime),
|
|
672
|
+
...createSettlementHooks(runtime),
|
|
673
|
+
...createRefundHooks(runtime)
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
__name(createLifecycleHooks, "createLifecycleHooks");
|
|
677
|
+
|
|
678
|
+
exports.createLifecycleHooks = createLifecycleHooks;
|
|
679
|
+
exports.runWalletReconciliation = runWalletReconciliation;
|
|
680
|
+
//# sourceMappingURL=index.cjs.map
|
|
681
|
+
//# sourceMappingURL=index.cjs.map
|