multivendor-wallet 0.0.4 → 0.0.6
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 +9 -0
- package/dist/hooks/index.cjs +25 -6
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.mts +3 -3
- package/dist/hooks/index.d.ts +3 -3
- package/dist/hooks/index.js +25 -6
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +347 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +41 -6
- package/dist/index.d.ts +41 -6
- package/dist/index.js +334 -29
- package/dist/index.js.map +1 -1
- package/dist/{store-By30oqos.d.mts → store-nWCfzvwf.d.mts} +1 -0
- package/dist/{store-By30oqos.d.ts → store-nWCfzvwf.d.ts} +1 -0
- package/dist/typeorm/index.cjs +174 -9
- package/dist/typeorm/index.cjs.map +1 -1
- package/dist/typeorm/index.d.mts +11 -2
- package/dist/typeorm/index.d.ts +11 -2
- package/dist/typeorm/index.js +175 -11
- package/dist/typeorm/index.js.map +1 -1
- package/dist/{types-BzaT7Aqh.d.ts → types-B4R1zaTK.d.ts} +16 -2
- package/dist/{types-D46FcrKZ.d.mts → types-D1Q4XCwx.d.mts} +16 -2
- package/package.json +3 -3
package/dist/typeorm/index.js
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
|
-
import { PrimaryGeneratedColumn, Column, BeforeInsert, BeforeUpdate, Entity } from 'typeorm';
|
|
1
|
+
import { PrimaryGeneratedColumn, Column, BeforeInsert, BeforeUpdate, Entity, Brackets } from 'typeorm';
|
|
2
2
|
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
5
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
6
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
7
|
+
|
|
8
|
+
// src/timestamps.ts
|
|
9
|
+
function pad2(value) {
|
|
10
|
+
return String(value).padStart(2, "0");
|
|
11
|
+
}
|
|
12
|
+
__name(pad2, "pad2");
|
|
13
|
+
function nowTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
14
|
+
return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}`;
|
|
15
|
+
}
|
|
16
|
+
__name(nowTimestamp, "nowTimestamp");
|
|
17
|
+
function parseLedgerDate(value) {
|
|
18
|
+
if (value instanceof Date) {
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})/.exec(String(value));
|
|
22
|
+
if (!match) {
|
|
23
|
+
return new Date(value);
|
|
24
|
+
}
|
|
25
|
+
return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]), Number(match[4]), Number(match[5]), Number(match[6]));
|
|
26
|
+
}
|
|
27
|
+
__name(parseLedgerDate, "parseLedgerDate");
|
|
28
|
+
|
|
29
|
+
// src/typeorm/entities.ts
|
|
7
30
|
function _ts_decorate(decorators, target, key, desc) {
|
|
8
31
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
9
32
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -15,10 +38,6 @@ function _ts_metadata(k, v) {
|
|
|
15
38
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
16
39
|
}
|
|
17
40
|
__name(_ts_metadata, "_ts_metadata");
|
|
18
|
-
function nowTimestamp() {
|
|
19
|
-
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
|
|
20
|
-
}
|
|
21
|
-
__name(nowTimestamp, "nowTimestamp");
|
|
22
41
|
var _WalletAccountEntity = class _WalletAccountEntity {
|
|
23
42
|
constructor() {
|
|
24
43
|
__publicField(this, "id");
|
|
@@ -404,6 +423,42 @@ var _DuplicateOperationError = class _DuplicateOperationError extends WalletErro
|
|
|
404
423
|
__name(_DuplicateOperationError, "DuplicateOperationError");
|
|
405
424
|
var DuplicateOperationError = _DuplicateOperationError;
|
|
406
425
|
|
|
426
|
+
// src/orderCustomerDebit.ts
|
|
427
|
+
var CUSTOMER_CHECKOUT_DEBIT_PURPOSE = "customer_checkout_debit";
|
|
428
|
+
var BACKFILL_SENTINEL_KEY = "customer_checkout_debit_backfill";
|
|
429
|
+
var WALLET_OPS_TABLE = "wallet_ops";
|
|
430
|
+
function orderCustomerDebitIdempotencyKey(orderId) {
|
|
431
|
+
return `wallet:order:${orderId}:customer_debit`;
|
|
432
|
+
}
|
|
433
|
+
__name(orderCustomerDebitIdempotencyKey, "orderCustomerDebitIdempotencyKey");
|
|
434
|
+
var UNREIMBURSED_TWIN_COUNT_SQL = `
|
|
435
|
+
SELECT COUNT(*) AS c
|
|
436
|
+
FROM wallet_ledger_entry f
|
|
437
|
+
JOIN wallet_ledger_entry p
|
|
438
|
+
ON p.account_id = f.account_id
|
|
439
|
+
AND p.reference_type = 'order'
|
|
440
|
+
AND p.reference_id = f.reference_id
|
|
441
|
+
AND p.entry_type = 'debit'
|
|
442
|
+
AND p.idempotency_key LIKE 'wallet:payment:%'
|
|
443
|
+
WHERE f.entry_type = 'debit'
|
|
444
|
+
AND f.reference_type = 'order'
|
|
445
|
+
AND (
|
|
446
|
+
f.idempotency_key LIKE 'wallet:full:%'
|
|
447
|
+
OR f.idempotency_key LIKE 'wallet:split:%'
|
|
448
|
+
)
|
|
449
|
+
AND NOT EXISTS (
|
|
450
|
+
SELECT 1 FROM wallet_ledger_entry r
|
|
451
|
+
WHERE r.entry_type = 'credit'
|
|
452
|
+
AND r.account_id = p.account_id
|
|
453
|
+
AND r.reference_type = 'order'
|
|
454
|
+
AND r.reference_id = p.reference_id
|
|
455
|
+
AND (
|
|
456
|
+
r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))
|
|
457
|
+
OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'
|
|
458
|
+
)
|
|
459
|
+
)
|
|
460
|
+
`;
|
|
461
|
+
|
|
407
462
|
// src/typeorm/store.ts
|
|
408
463
|
function toNumber(value) {
|
|
409
464
|
if (value == null) {
|
|
@@ -433,7 +488,7 @@ function toLedgerHold(row) {
|
|
|
433
488
|
referenceType: row.referenceType,
|
|
434
489
|
referenceId: row.referenceId,
|
|
435
490
|
idempotencyKey: row.idempotencyKey,
|
|
436
|
-
createdAt:
|
|
491
|
+
createdAt: parseLedgerDate(row.createdDate)
|
|
437
492
|
};
|
|
438
493
|
}
|
|
439
494
|
__name(toLedgerHold, "toLedgerHold");
|
|
@@ -449,7 +504,7 @@ function toLedgerEntry(row) {
|
|
|
449
504
|
referenceType: row.referenceType,
|
|
450
505
|
referenceId: row.referenceId,
|
|
451
506
|
metadata: row.metadata,
|
|
452
|
-
createdAt:
|
|
507
|
+
createdAt: parseLedgerDate(row.createdDate)
|
|
453
508
|
};
|
|
454
509
|
}
|
|
455
510
|
__name(toLedgerEntry, "toLedgerEntry");
|
|
@@ -587,7 +642,7 @@ var TypeOrmWalletStoreTx = (_a = class {
|
|
|
587
642
|
where: {
|
|
588
643
|
id: hold.id
|
|
589
644
|
}
|
|
590
|
-
});
|
|
645
|
+
}) ?? void 0;
|
|
591
646
|
}
|
|
592
647
|
if (!row) {
|
|
593
648
|
row = await repo.findOne({
|
|
@@ -595,7 +650,7 @@ var TypeOrmWalletStoreTx = (_a = class {
|
|
|
595
650
|
referenceType: hold.referenceType,
|
|
596
651
|
referenceId: hold.referenceId
|
|
597
652
|
}
|
|
598
|
-
});
|
|
653
|
+
}) ?? void 0;
|
|
599
654
|
}
|
|
600
655
|
if (!row) {
|
|
601
656
|
row = repo.create({
|
|
@@ -625,6 +680,36 @@ var TypeOrmWalletStoreTx = (_a = class {
|
|
|
625
680
|
});
|
|
626
681
|
return row ? toLedgerEntry(row) : null;
|
|
627
682
|
}
|
|
683
|
+
async findOrderCustomerCheckoutDebit(accountId, orderId) {
|
|
684
|
+
const canonical = orderCustomerDebitIdempotencyKey(orderId);
|
|
685
|
+
const row = await this.em.getRepository(WalletLedgerEntryEntity).createQueryBuilder("e").where("e.account_id = :accountId", {
|
|
686
|
+
accountId
|
|
687
|
+
}).andWhere("e.entry_type = :entryType", {
|
|
688
|
+
entryType: "debit"
|
|
689
|
+
}).andWhere("e.reference_type = :referenceType", {
|
|
690
|
+
referenceType: "order"
|
|
691
|
+
}).andWhere("e.reference_id = :orderId", {
|
|
692
|
+
orderId
|
|
693
|
+
}).andWhere(new Brackets((qb) => {
|
|
694
|
+
qb.where(`JSON_UNQUOTE(JSON_EXTRACT(e.metadata, '$.purpose')) = :purpose`, {
|
|
695
|
+
purpose: CUSTOMER_CHECKOUT_DEBIT_PURPOSE
|
|
696
|
+
}).orWhere("e.idempotency_key = :canonical", {
|
|
697
|
+
canonical
|
|
698
|
+
}).orWhere("e.idempotency_key LIKE :fullPrefix", {
|
|
699
|
+
fullPrefix: "wallet:full:%"
|
|
700
|
+
}).orWhere("e.idempotency_key LIKE :splitPrefix", {
|
|
701
|
+
splitPrefix: "wallet:split:%"
|
|
702
|
+
}).orWhere("e.idempotency_key LIKE :paymentPrefix", {
|
|
703
|
+
paymentPrefix: "wallet:payment:%"
|
|
704
|
+
});
|
|
705
|
+
})).orderBy(`CASE
|
|
706
|
+
WHEN JSON_UNQUOTE(JSON_EXTRACT(e.metadata, '$.purpose')) = :purpose THEN 0
|
|
707
|
+
WHEN e.idempotency_key = :canonical THEN 1
|
|
708
|
+
WHEN e.idempotency_key LIKE 'wallet:full:%' OR e.idempotency_key LIKE 'wallet:split:%' THEN 2
|
|
709
|
+
ELSE 3
|
|
710
|
+
END`, "ASC").addOrderBy("e.id", "ASC").setParameter("purpose", CUSTOMER_CHECKOUT_DEBIT_PURPOSE).setParameter("canonical", canonical).getOne();
|
|
711
|
+
return row ? toLedgerEntry(row) : null;
|
|
712
|
+
}
|
|
628
713
|
async listLedgerEntries(accountId, limit, offset) {
|
|
629
714
|
const rows = await this.em.getRepository(WalletLedgerEntryEntity).find({
|
|
630
715
|
where: {
|
|
@@ -761,6 +846,84 @@ var _CreateWalletTables1790000000000 = class _CreateWalletTables1790000000000 {
|
|
|
761
846
|
__name(_CreateWalletTables1790000000000, "CreateWalletTables1790000000000");
|
|
762
847
|
var CreateWalletTables1790000000000 = _CreateWalletTables1790000000000;
|
|
763
848
|
|
|
849
|
+
// src/typeorm/migrations/AddOrderCustomerDebitUnique.ts
|
|
850
|
+
var _AddOrderCustomerDebitUnique1790000001000 = class _AddOrderCustomerDebitUnique1790000001000 {
|
|
851
|
+
async up(queryRunner) {
|
|
852
|
+
const opsTables = await queryRunner.query(`SELECT COUNT(*) AS c
|
|
853
|
+
FROM information_schema.tables
|
|
854
|
+
WHERE table_schema = DATABASE()
|
|
855
|
+
AND table_name = ?`, [
|
|
856
|
+
WALLET_OPS_TABLE
|
|
857
|
+
]);
|
|
858
|
+
if (Number(opsTables[0]?.c ?? 0) === 0) {
|
|
859
|
+
throw new Error(`Wallet unique-index gate: ${WALLET_OPS_TABLE} is missing. Run npm run wallet:credit-duplicate-order-debits`);
|
|
860
|
+
}
|
|
861
|
+
const sentinel = await queryRunner.query(`SELECT status FROM \`${WALLET_OPS_TABLE}\` WHERE ops_key = ? LIMIT 1`, [
|
|
862
|
+
BACKFILL_SENTINEL_KEY
|
|
863
|
+
]);
|
|
864
|
+
if (!sentinel[0] || sentinel[0].status !== "complete") {
|
|
865
|
+
throw new Error(`Wallet unique-index gate: sentinel ${BACKFILL_SENTINEL_KEY} is missing. Run npm run wallet:credit-duplicate-order-debits`);
|
|
866
|
+
}
|
|
867
|
+
const twins = await queryRunner.query(UNREIMBURSED_TWIN_COUNT_SQL);
|
|
868
|
+
const twinCount = Number(twins[0]?.c ?? 0);
|
|
869
|
+
if (twinCount > 0) {
|
|
870
|
+
throw new Error(`Wallet unique-index gate: unreimbursed twin COUNT is ${twinCount}. Run npm run wallet:credit-duplicate-order-debits`);
|
|
871
|
+
}
|
|
872
|
+
const columns = await queryRunner.query(`SELECT COUNT(*) AS c
|
|
873
|
+
FROM information_schema.columns
|
|
874
|
+
WHERE table_schema = DATABASE()
|
|
875
|
+
AND table_name = 'wallet_ledger_entry'
|
|
876
|
+
AND column_name = 'order_customer_debit_key'`);
|
|
877
|
+
if (Number(columns[0]?.c ?? 0) === 0) {
|
|
878
|
+
await queryRunner.query(`
|
|
879
|
+
ALTER TABLE \`wallet_ledger_entry\`
|
|
880
|
+
ADD COLUMN \`order_customer_debit_key\` VARCHAR(191)
|
|
881
|
+
GENERATED ALWAYS AS (
|
|
882
|
+
CASE
|
|
883
|
+
WHEN \`entry_type\` = 'debit'
|
|
884
|
+
AND \`reference_type\` = 'order'
|
|
885
|
+
AND \`reference_id\` IS NOT NULL
|
|
886
|
+
AND JSON_UNQUOTE(JSON_EXTRACT(\`metadata\`, '$.purpose')) = 'customer_checkout_debit'
|
|
887
|
+
THEN CONCAT(\`account_id\`, ':', \`reference_id\`)
|
|
888
|
+
ELSE NULL
|
|
889
|
+
END
|
|
890
|
+
) STORED
|
|
891
|
+
`);
|
|
892
|
+
}
|
|
893
|
+
const indexes = await queryRunner.query(`SELECT COUNT(*) AS c
|
|
894
|
+
FROM information_schema.statistics
|
|
895
|
+
WHERE table_schema = DATABASE()
|
|
896
|
+
AND table_name = 'wallet_ledger_entry'
|
|
897
|
+
AND index_name = 'UQ_wallet_order_customer_debit'`);
|
|
898
|
+
if (Number(indexes[0]?.c ?? 0) === 0) {
|
|
899
|
+
await queryRunner.query(`
|
|
900
|
+
CREATE UNIQUE INDEX \`UQ_wallet_order_customer_debit\`
|
|
901
|
+
ON \`wallet_ledger_entry\` (\`order_customer_debit_key\`)
|
|
902
|
+
`);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
async down(queryRunner) {
|
|
906
|
+
const indexes = await queryRunner.query(`SELECT COUNT(*) AS c
|
|
907
|
+
FROM information_schema.statistics
|
|
908
|
+
WHERE table_schema = DATABASE()
|
|
909
|
+
AND table_name = 'wallet_ledger_entry'
|
|
910
|
+
AND index_name = 'UQ_wallet_order_customer_debit'`);
|
|
911
|
+
if (Number(indexes[0]?.c ?? 0) > 0) {
|
|
912
|
+
await queryRunner.query(`DROP INDEX \`UQ_wallet_order_customer_debit\` ON \`wallet_ledger_entry\``);
|
|
913
|
+
}
|
|
914
|
+
const columns = await queryRunner.query(`SELECT COUNT(*) AS c
|
|
915
|
+
FROM information_schema.columns
|
|
916
|
+
WHERE table_schema = DATABASE()
|
|
917
|
+
AND table_name = 'wallet_ledger_entry'
|
|
918
|
+
AND column_name = 'order_customer_debit_key'`);
|
|
919
|
+
if (Number(columns[0]?.c ?? 0) > 0) {
|
|
920
|
+
await queryRunner.query(`ALTER TABLE \`wallet_ledger_entry\` DROP COLUMN \`order_customer_debit_key\``);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
__name(_AddOrderCustomerDebitUnique1790000001000, "AddOrderCustomerDebitUnique1790000001000");
|
|
925
|
+
var AddOrderCustomerDebitUnique1790000001000 = _AddOrderCustomerDebitUnique1790000001000;
|
|
926
|
+
|
|
764
927
|
// src/typeorm/metadata.ts
|
|
765
928
|
function getWalletOrmMetadata() {
|
|
766
929
|
return {
|
|
@@ -770,12 +933,13 @@ function getWalletOrmMetadata() {
|
|
|
770
933
|
WalletHoldEntity
|
|
771
934
|
],
|
|
772
935
|
migrations: [
|
|
773
|
-
CreateWalletTables1790000000000
|
|
936
|
+
CreateWalletTables1790000000000,
|
|
937
|
+
AddOrderCustomerDebitUnique1790000001000
|
|
774
938
|
]
|
|
775
939
|
};
|
|
776
940
|
}
|
|
777
941
|
__name(getWalletOrmMetadata, "getWalletOrmMetadata");
|
|
778
942
|
|
|
779
|
-
export { CreateWalletTables1790000000000, TypeOrmWalletStore, WalletAccountEntity, WalletHoldEntity, WalletLedgerEntryEntity, getWalletOrmMetadata };
|
|
943
|
+
export { AddOrderCustomerDebitUnique1790000001000, CreateWalletTables1790000000000, TypeOrmWalletStore, WalletAccountEntity, WalletHoldEntity, WalletLedgerEntryEntity, getWalletOrmMetadata };
|
|
780
944
|
//# sourceMappingURL=index.js.map
|
|
781
945
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/typeorm/entities.ts","../../src/errors.ts","../../src/typeorm/store.ts","../../src/typeorm/migrations/CreateWalletTables.ts","../../src/typeorm/metadata.ts"],"names":["nowTimestamp","Date","toISOString","slice","replace","WalletAccountEntity","id","ownerType","ownerId","currency","availableBalance","heldBalance","createdBy","createdDate","modifiedBy","modifiedDate","setCreated","setModified","name","length","default","type","nullable","WalletLedgerEntryEntity","accountId","entryType","amount","balanceAfterAvailable","balanceAfterHeld","idempotencyKey","referenceType","referenceId","metadata","unique","WalletHoldEntity","sourceAccountId","targetAccountId","status","WalletError","Error","message","DuplicateOperationError","existingEntry","toNumber","value","Number","toLedgerAccount","row","toLedgerHold","createdAt","toLedgerEntry","isEntityManager","getRepository","TypeOrmWalletStoreTx","em","getOrCreateAccount","repo","findOne","where","save","create","error","err","code","errno","lockAccount","createQueryBuilder","setLock","getOne","getAccountById","appendLedgerEntry","entry","existing","findLedgerByIdempotencyKey","String","dup","updateBalances","deltas","available","availableDelta","held","heldDelta","saved","findHoldByReference","ref","order","upsertHold","hold","key","listLedgerEntries","limit","offset","rows","find","take","skip","map","TypeOrmWalletStore","connection","runInTransaction","fn","ctx","nativeTx","manager","transaction","indexExists","queryRunner","tableName","indexName","query","c","CreateWalletTables1790000000000","up","hasTable","down","getWalletOrmMetadata","entities","migrations"],"mappings":"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","file":"index.js","sourcesContent":["import { BeforeInsert, BeforeUpdate, Column, Entity, PrimaryGeneratedColumn } from 'typeorm';\n\nfunction nowTimestamp(): string {\n return new Date().toISOString().slice(0, 19).replace('T', ' ');\n}\n\n@Entity('wallet_account')\nexport class WalletAccountEntity {\n @PrimaryGeneratedColumn({ name: 'id' })\n public id!: number;\n\n @Column({ name: 'owner_type', length: 32 })\n public ownerType!: string;\n\n @Column({ name: 'owner_id' })\n public ownerId!: number;\n\n @Column({ name: 'currency', length: 8, default: 'INR' })\n public currency!: string;\n\n @Column({ name: 'available_balance', type: 'bigint', default: 0 })\n public availableBalance!: string;\n\n @Column({ name: 'held_balance', type: 'bigint', default: 0 })\n public heldBalance!: string;\n\n @Column({ name: 'created_by', nullable: true })\n public createdBy?: number;\n\n @Column({ name: 'created_date', nullable: true })\n public createdDate!: string;\n\n @Column({ name: 'modified_by', nullable: true })\n public modifiedBy?: number;\n\n @Column({ name: 'modified_date', nullable: true })\n public modifiedDate!: string;\n\n @BeforeInsert()\n public setCreated(): void {\n this.createdDate = nowTimestamp();\n this.modifiedDate = nowTimestamp();\n }\n\n @BeforeUpdate()\n public setModified(): void {\n this.modifiedDate = nowTimestamp();\n }\n}\n\n@Entity('wallet_ledger_entry')\nexport class WalletLedgerEntryEntity {\n @PrimaryGeneratedColumn({ name: 'id' })\n public id!: number;\n\n @Column({ name: 'account_id' })\n public accountId!: number;\n\n @Column({ name: 'entry_type', length: 32 })\n public entryType!: string;\n\n @Column({ name: 'amount', type: 'bigint' })\n public amount!: string;\n\n @Column({ name: 'balance_after_available', type: 'bigint' })\n public balanceAfterAvailable!: string;\n\n @Column({ name: 'balance_after_held', type: 'bigint' })\n public balanceAfterHeld!: string;\n\n @Column({ name: 'idempotency_key', length: 255, unique: true })\n public idempotencyKey!: string;\n\n @Column({ name: 'reference_type', length: 64, nullable: true })\n public referenceType?: string;\n\n @Column({ name: 'reference_id', length: 128, nullable: true })\n public referenceId?: string;\n\n @Column({ name: 'metadata', type: 'json', nullable: true })\n public metadata?: Record<string, unknown>;\n\n @Column({ name: 'created_by', nullable: true })\n public createdBy?: number;\n\n @Column({ name: 'created_date', nullable: true })\n public createdDate!: string;\n\n @Column({ name: 'modified_by', nullable: true })\n public modifiedBy?: number;\n\n @Column({ name: 'modified_date', nullable: true })\n public modifiedDate!: string;\n\n @BeforeInsert()\n public setCreated(): void {\n this.createdDate = nowTimestamp();\n this.modifiedDate = nowTimestamp();\n }\n}\n\n@Entity('wallet_hold')\nexport class WalletHoldEntity {\n @PrimaryGeneratedColumn({ name: 'id' })\n public id!: number;\n\n @Column({ name: 'source_account_id' })\n public sourceAccountId!: number;\n\n @Column({ name: 'target_account_id' })\n public targetAccountId!: number;\n\n @Column({ name: 'amount', type: 'bigint' })\n public amount!: string;\n\n @Column({ name: 'status', length: 16, default: 'active' })\n public status!: string;\n\n @Column({ name: 'reference_type', length: 64 })\n public referenceType!: string;\n\n @Column({ name: 'reference_id', length: 128 })\n public referenceId!: string;\n\n @Column({ name: 'idempotency_key', length: 255 })\n public idempotencyKey!: string;\n\n @Column({ name: 'created_by', nullable: true })\n public createdBy?: number;\n\n @Column({ name: 'created_date', nullable: true })\n public createdDate!: string;\n\n @Column({ name: 'modified_by', nullable: true })\n public modifiedBy?: number;\n\n @Column({ name: 'modified_date', nullable: true })\n public modifiedDate!: string;\n\n @BeforeInsert()\n public setCreated(): void {\n this.createdDate = nowTimestamp();\n this.modifiedDate = nowTimestamp();\n }\n\n @BeforeUpdate()\n public setModified(): void {\n this.modifiedDate = nowTimestamp();\n }\n}\n","export class WalletError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WalletError';\n }\n}\n\nexport class WalletConfigError extends WalletError {\n constructor(message: string) {\n super(message);\n this.name = 'WalletConfigError';\n }\n}\n\nexport class InsufficientBalanceError extends WalletError {\n constructor(message: string = 'Insufficient available balance') {\n super(message);\n this.name = 'InsufficientBalanceError';\n }\n}\n\nexport class HoldNotFoundError extends WalletError {\n constructor(message: string = 'Active hold not found for reference') {\n super(message);\n this.name = 'HoldNotFoundError';\n }\n}\n\nexport class DuplicateOperationError extends WalletError {\n public readonly existingEntry: unknown;\n\n constructor(message: string, existingEntry: unknown) {\n super(message);\n this.name = 'DuplicateOperationError';\n this.existingEntry = existingEntry;\n }\n}\n\nexport class InvalidAmountError extends WalletError {\n constructor(message: string = 'Amount must be a positive integer in minor units') {\n super(message);\n this.name = 'InvalidAmountError';\n }\n}\n","import type { EntityManager } from 'typeorm';\nimport { DuplicateOperationError } from '../errors';\nimport type { WalletHostConnection } from '../plugin-instance';\nimport type { IWalletStore, IWalletStoreTx, WalletStoreContext } from '../store';\nimport {\n HoldStatus,\n LedgerEntryType,\n type BalanceDeltas,\n type WalletAccount,\n type WalletAccountType,\n type WalletHold,\n type WalletLedgerEntry,\n type WalletReference,\n} from '../types';\nimport {\n WalletAccountEntity,\n WalletHoldEntity,\n WalletLedgerEntryEntity,\n} from './entities';\n\nfunction toNumber(value: string | number | null | undefined): number {\n if (value == null) {\n return 0;\n }\n return Number(value);\n}\n\nfunction toLedgerAccount(row: WalletAccountEntity): WalletAccount {\n return {\n id: row.id,\n ownerType: row.ownerType as WalletAccountType,\n ownerId: row.ownerId,\n currency: row.currency,\n availableBalance: toNumber(row.availableBalance),\n heldBalance: toNumber(row.heldBalance),\n };\n}\n\nfunction toLedgerHold(row: WalletHoldEntity): WalletHold {\n return {\n id: row.id,\n sourceAccountId: row.sourceAccountId,\n targetAccountId: row.targetAccountId,\n amount: toNumber(row.amount),\n status: row.status as HoldStatus,\n referenceType: row.referenceType,\n referenceId: row.referenceId,\n idempotencyKey: row.idempotencyKey,\n createdAt: new Date(row.createdDate),\n };\n}\n\nfunction toLedgerEntry(row: WalletLedgerEntryEntity): WalletLedgerEntry {\n return {\n id: row.id,\n accountId: row.accountId,\n entryType: row.entryType as LedgerEntryType,\n amount: toNumber(row.amount),\n balanceAfterAvailable: toNumber(row.balanceAfterAvailable),\n balanceAfterHeld: toNumber(row.balanceAfterHeld),\n idempotencyKey: row.idempotencyKey,\n referenceType: row.referenceType,\n referenceId: row.referenceId,\n metadata: row.metadata,\n createdAt: new Date(row.createdDate),\n };\n}\n\nfunction isEntityManager(value: unknown): value is EntityManager {\n return (\n value != null &&\n typeof value === 'object' &&\n typeof (value as EntityManager).getRepository === 'function'\n );\n}\n\nclass TypeOrmWalletStoreTx implements IWalletStoreTx {\n constructor(private readonly em: EntityManager) {}\n\n public async getOrCreateAccount(\n type: WalletAccountType,\n ownerId: number,\n currency: string\n ): Promise<WalletAccount> {\n const repo = this.em.getRepository(WalletAccountEntity);\n let row = await repo.findOne({ where: { ownerType: type, ownerId, currency } });\n if (!row) {\n try {\n row = await repo.save(\n repo.create({\n ownerType: type,\n ownerId,\n currency,\n availableBalance: '0',\n heldBalance: '0',\n }),\n );\n } catch (error: unknown) {\n const err = error as { code?: string | number; errno?: string | number };\n const code = err?.code || err?.errno;\n if (code === 'ER_DUP_ENTRY' || code === 1062) {\n // Unique (owner) race or PRIMARY auto-increment collision — re-read winner.\n row = await repo.findOne({ where: { ownerType: type, ownerId, currency } });\n if (row) {\n return toLedgerAccount(row);\n }\n }\n throw error;\n }\n }\n return toLedgerAccount(row);\n }\n\n public async lockAccount(accountId: number): Promise<WalletAccount> {\n const row = await this.em\n .getRepository(WalletAccountEntity)\n .createQueryBuilder('wa')\n .setLock('pessimistic_write')\n .where('wa.id = :id', { id: accountId })\n .getOne();\n if (!row) {\n throw new Error(`Wallet account ${accountId} not found`);\n }\n return toLedgerAccount(row);\n }\n\n public async getAccountById(accountId: number): Promise<WalletAccount | null> {\n const row = await this.em.getRepository(WalletAccountEntity).findOne({ where: { id: accountId } });\n return row ? toLedgerAccount(row) : null;\n }\n\n public async appendLedgerEntry(\n entry: Omit<WalletLedgerEntry, 'id' | 'createdAt'>\n ): Promise<WalletLedgerEntry> {\n const existing = await this.findLedgerByIdempotencyKey(entry.idempotencyKey);\n if (existing) {\n return existing;\n }\n\n const repo = this.em.getRepository(WalletLedgerEntryEntity);\n try {\n const row = await repo.save(\n repo.create({\n accountId: entry.accountId,\n entryType: entry.entryType,\n amount: String(entry.amount),\n balanceAfterAvailable: String(entry.balanceAfterAvailable),\n balanceAfterHeld: String(entry.balanceAfterHeld),\n idempotencyKey: entry.idempotencyKey,\n referenceType: entry.referenceType,\n referenceId: entry.referenceId,\n metadata: entry.metadata,\n })\n );\n return toLedgerEntry(row);\n } catch (error: unknown) {\n const err = error as { code?: string | number; errno?: string | number };\n const code = err?.code || err?.errno;\n if (code === 'ER_DUP_ENTRY' || code === 1062) {\n const dup = await this.findLedgerByIdempotencyKey(entry.idempotencyKey);\n if (dup) {\n return dup;\n }\n throw new DuplicateOperationError('Duplicate idempotency key', null);\n }\n throw error;\n }\n }\n\n public async updateBalances(accountId: number, deltas: BalanceDeltas): Promise<WalletAccount> {\n const row = await this.em\n .getRepository(WalletAccountEntity)\n .createQueryBuilder('wa')\n .setLock('pessimistic_write')\n .where('wa.id = :id', { id: accountId })\n .getOne();\n if (!row) {\n throw new Error(`Wallet account ${accountId} not found`);\n }\n\n const available = toNumber(row.availableBalance) + (deltas.availableDelta ?? 0);\n const held = toNumber(row.heldBalance) + (deltas.heldDelta ?? 0);\n if (available < 0 || held < 0) {\n throw new Error('Balance cannot be negative');\n }\n\n row.availableBalance = String(available);\n row.heldBalance = String(held);\n const saved = await this.em.getRepository(WalletAccountEntity).save(row);\n return toLedgerAccount(saved);\n }\n\n public async findHoldByReference(ref: WalletReference): Promise<WalletHold | null> {\n const row = await this.em.getRepository(WalletHoldEntity).findOne({\n where: { referenceType: ref.referenceType, referenceId: ref.referenceId },\n order: { id: 'DESC' },\n });\n return row ? toLedgerHold(row) : null;\n }\n\n public async upsertHold(\n hold: Omit<WalletHold, 'id' | 'createdAt'> & { id?: number }\n ): Promise<WalletHold> {\n const repo = this.em.getRepository(WalletHoldEntity);\n let row: WalletHoldEntity | undefined;\n if (hold.id != null) {\n row = await repo.findOne({ where: { id: hold.id } });\n }\n if (!row) {\n row = await repo.findOne({\n where: { referenceType: hold.referenceType, referenceId: hold.referenceId },\n });\n }\n if (!row) {\n row = repo.create({\n sourceAccountId: hold.sourceAccountId,\n targetAccountId: hold.targetAccountId,\n amount: String(hold.amount),\n status: hold.status,\n referenceType: hold.referenceType,\n referenceId: hold.referenceId,\n idempotencyKey: hold.idempotencyKey,\n });\n } else {\n row.sourceAccountId = hold.sourceAccountId;\n row.targetAccountId = hold.targetAccountId;\n row.amount = String(hold.amount);\n row.status = hold.status;\n row.idempotencyKey = hold.idempotencyKey;\n }\n const saved = await repo.save(row);\n return toLedgerHold(saved);\n }\n\n public async findLedgerByIdempotencyKey(key: string): Promise<WalletLedgerEntry | null> {\n const row = await this.em.getRepository(WalletLedgerEntryEntity).findOne({\n where: { idempotencyKey: key },\n });\n return row ? toLedgerEntry(row) : null;\n }\n\n public async listLedgerEntries(\n accountId: number,\n limit: number,\n offset: number\n ): Promise<WalletLedgerEntry[]> {\n const rows = await this.em.getRepository(WalletLedgerEntryEntity).find({\n where: { accountId },\n order: { id: 'DESC' },\n take: limit,\n skip: offset,\n });\n return rows.map(toLedgerEntry);\n }\n}\n\nexport class TypeOrmWalletStore implements IWalletStore {\n constructor(private readonly connection: WalletHostConnection) {}\n\n public async runInTransaction<T>(\n fn: (tx: IWalletStoreTx) => Promise<T>,\n ctx?: WalletStoreContext\n ): Promise<T> {\n if (isEntityManager(ctx?.nativeTx)) {\n return fn(new TypeOrmWalletStoreTx(ctx.nativeTx));\n }\n\n return this.connection.manager.transaction(async (em) =>\n fn(new TypeOrmWalletStoreTx(em as EntityManager))\n );\n }\n}\n","import { MigrationInterface, QueryRunner } from 'typeorm';\n\nasync function indexExists(\n queryRunner: QueryRunner,\n tableName: string,\n indexName: string\n): Promise<boolean> {\n const rows: Array<{ c: number }> = await queryRunner.query(\n `SELECT COUNT(1) AS c\n FROM information_schema.statistics\n WHERE table_schema = DATABASE()\n AND table_name = ?\n AND index_name = ?`,\n [tableName, indexName]\n );\n return Number(rows[0]?.c ?? 0) > 0;\n}\n\nexport class CreateWalletTables1790000000000 implements MigrationInterface {\n public async up(queryRunner: QueryRunner): Promise<void> {\n if (!(await queryRunner.hasTable('wallet_account'))) {\n await queryRunner.query(`\n CREATE TABLE \\`wallet_account\\` (\n \\`id\\` int NOT NULL AUTO_INCREMENT,\n \\`owner_type\\` varchar(32) NOT NULL,\n \\`owner_id\\` int NOT NULL,\n \\`currency\\` varchar(8) NOT NULL DEFAULT 'INR',\n \\`available_balance\\` bigint NOT NULL DEFAULT 0,\n \\`held_balance\\` bigint NOT NULL DEFAULT 0,\n \\`created_by\\` int NULL,\n \\`created_date\\` datetime NULL,\n \\`modified_by\\` int NULL,\n \\`modified_date\\` datetime NULL,\n PRIMARY KEY (\\`id\\`)\n ) ENGINE=InnoDB\n `);\n }\n\n if (!(await indexExists(queryRunner, 'wallet_account', 'IDX_wallet_account_owner_currency'))) {\n await queryRunner.query(`\n CREATE UNIQUE INDEX \\`IDX_wallet_account_owner_currency\\`\n ON \\`wallet_account\\` (\\`owner_type\\`, \\`owner_id\\`, \\`currency\\`)\n `);\n }\n\n if (!(await queryRunner.hasTable('wallet_ledger_entry'))) {\n await queryRunner.query(`\n CREATE TABLE \\`wallet_ledger_entry\\` (\n \\`id\\` int NOT NULL AUTO_INCREMENT,\n \\`account_id\\` int NOT NULL,\n \\`entry_type\\` varchar(32) NOT NULL,\n \\`amount\\` bigint NOT NULL,\n \\`balance_after_available\\` bigint NOT NULL,\n \\`balance_after_held\\` bigint NOT NULL,\n \\`idempotency_key\\` varchar(255) NOT NULL,\n \\`reference_type\\` varchar(64) NULL,\n \\`reference_id\\` varchar(128) NULL,\n \\`metadata\\` json NULL,\n \\`created_by\\` int NULL,\n \\`created_date\\` datetime NULL,\n \\`modified_by\\` int NULL,\n \\`modified_date\\` datetime NULL,\n PRIMARY KEY (\\`id\\`),\n UNIQUE INDEX \\`UQ_wallet_ledger_idempotency_key\\` (\\`idempotency_key\\`)\n ) ENGINE=InnoDB\n `);\n }\n\n if (!(await indexExists(queryRunner, 'wallet_ledger_entry', 'IDX_wallet_ledger_account_id'))) {\n await queryRunner.query(`\n CREATE INDEX \\`IDX_wallet_ledger_account_id\\`\n ON \\`wallet_ledger_entry\\` (\\`account_id\\`)\n `);\n }\n\n if (!(await queryRunner.hasTable('wallet_hold'))) {\n await queryRunner.query(`\n CREATE TABLE \\`wallet_hold\\` (\n \\`id\\` int NOT NULL AUTO_INCREMENT,\n \\`source_account_id\\` int NOT NULL,\n \\`target_account_id\\` int NOT NULL,\n \\`amount\\` bigint NOT NULL,\n \\`status\\` varchar(16) NOT NULL DEFAULT 'active',\n \\`reference_type\\` varchar(64) NOT NULL,\n \\`reference_id\\` varchar(128) NOT NULL,\n \\`idempotency_key\\` varchar(255) NOT NULL,\n \\`created_by\\` int NULL,\n \\`created_date\\` datetime NULL,\n \\`modified_by\\` int NULL,\n \\`modified_date\\` datetime NULL,\n PRIMARY KEY (\\`id\\`)\n ) ENGINE=InnoDB\n `);\n }\n\n if (!(await indexExists(queryRunner, 'wallet_hold', 'IDX_wallet_hold_reference'))) {\n await queryRunner.query(`\n CREATE INDEX \\`IDX_wallet_hold_reference\\`\n ON \\`wallet_hold\\` (\\`reference_type\\`, \\`reference_id\\`)\n `);\n }\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n if (await queryRunner.hasTable('wallet_hold')) {\n await queryRunner.query('DROP TABLE `wallet_hold`');\n }\n if (await queryRunner.hasTable('wallet_ledger_entry')) {\n await queryRunner.query('DROP TABLE `wallet_ledger_entry`');\n }\n if (await queryRunner.hasTable('wallet_account')) {\n await queryRunner.query('DROP TABLE `wallet_account`');\n }\n }\n}\n","import {\n WalletAccountEntity,\n WalletHoldEntity,\n WalletLedgerEntryEntity,\n} from './entities';\nimport { CreateWalletTables1790000000000 } from './migrations/CreateWalletTables';\n\nexport function getWalletOrmMetadata(): {\n entities: Function[];\n migrations: Function[];\n} {\n return {\n entities: [WalletAccountEntity, WalletLedgerEntryEntity, WalletHoldEntity],\n migrations: [CreateWalletTables1790000000000],\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/timestamps.ts","../../src/typeorm/entities.ts","../../src/errors.ts","../../src/orderCustomerDebit.ts","../../src/typeorm/store.ts","../../src/typeorm/migrations/CreateWalletTables.ts","../../src/typeorm/migrations/AddOrderCustomerDebitUnique.ts","../../src/typeorm/metadata.ts"],"names":["pad2","value","String","padStart","nowTimestamp","date","Date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","parseLedgerDate","match","exec","Number","WalletAccountEntity","id","ownerType","ownerId","currency","availableBalance","heldBalance","createdBy","createdDate","modifiedBy","modifiedDate","setCreated","setModified","name","length","default","type","nullable","WalletLedgerEntryEntity","accountId","entryType","amount","balanceAfterAvailable","balanceAfterHeld","idempotencyKey","referenceType","referenceId","metadata","unique","WalletHoldEntity","sourceAccountId","targetAccountId","status","WalletError","Error","message","DuplicateOperationError","existingEntry","CUSTOMER_CHECKOUT_DEBIT_PURPOSE","BACKFILL_SENTINEL_KEY","WALLET_OPS_TABLE","orderCustomerDebitIdempotencyKey","orderId","UNREIMBURSED_TWIN_COUNT_SQL","toNumber","toLedgerAccount","row","toLedgerHold","createdAt","toLedgerEntry","isEntityManager","getRepository","TypeOrmWalletStoreTx","em","getOrCreateAccount","repo","findOne","where","save","create","error","err","code","errno","lockAccount","createQueryBuilder","setLock","getOne","getAccountById","appendLedgerEntry","entry","existing","findLedgerByIdempotencyKey","dup","updateBalances","deltas","available","availableDelta","held","heldDelta","saved","findHoldByReference","ref","order","upsertHold","hold","undefined","key","findOrderCustomerCheckoutDebit","canonical","andWhere","Brackets","qb","purpose","orWhere","fullPrefix","splitPrefix","paymentPrefix","orderBy","addOrderBy","setParameter","listLedgerEntries","limit","offset","rows","find","take","skip","map","TypeOrmWalletStore","connection","runInTransaction","fn","ctx","nativeTx","manager","transaction","indexExists","queryRunner","tableName","indexName","query","c","CreateWalletTables1790000000000","up","hasTable","down","AddOrderCustomerDebitUnique1790000001000","opsTables","sentinel","twins","twinCount","columns","indexes","getWalletOrmMetadata","entities","migrations"],"mappings":"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","file":"index.js","sourcesContent":["function pad2(value: number): string {\n return String(value).padStart(2, '0');\n}\n\n/** Server-local wall clock `YYYY-MM-DD HH:mm:ss` (matches host order paidDate, not UTC ISO). */\nexport function nowTimestamp(date: Date = new Date()): string {\n return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}`;\n}\n\n/** Parse naive datetime as local wall clock (do not treat as UTC). */\nexport function parseLedgerDate(value: string | Date): Date {\n if (value instanceof Date) {\n return value;\n }\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})[ T](\\d{2}):(\\d{2}):(\\d{2})/.exec(String(value));\n if (!match) {\n return new Date(value);\n }\n return new Date(\n Number(match[1]),\n Number(match[2]) - 1,\n Number(match[3]),\n Number(match[4]),\n Number(match[5]),\n Number(match[6])\n );\n}\n","import { BeforeInsert, BeforeUpdate, Column, Entity, PrimaryGeneratedColumn } from 'typeorm';\nimport { nowTimestamp } from '../timestamps';\n\n@Entity('wallet_account')\nexport class WalletAccountEntity {\n @PrimaryGeneratedColumn({ name: 'id' })\n public id!: number;\n\n @Column({ name: 'owner_type', length: 32 })\n public ownerType!: string;\n\n @Column({ name: 'owner_id' })\n public ownerId!: number;\n\n @Column({ name: 'currency', length: 8, default: 'INR' })\n public currency!: string;\n\n @Column({ name: 'available_balance', type: 'bigint', default: 0 })\n public availableBalance!: string;\n\n @Column({ name: 'held_balance', type: 'bigint', default: 0 })\n public heldBalance!: string;\n\n @Column({ name: 'created_by', nullable: true })\n public createdBy?: number;\n\n @Column({ name: 'created_date', nullable: true })\n public createdDate!: string;\n\n @Column({ name: 'modified_by', nullable: true })\n public modifiedBy?: number;\n\n @Column({ name: 'modified_date', nullable: true })\n public modifiedDate!: string;\n\n @BeforeInsert()\n public setCreated(): void {\n this.createdDate = nowTimestamp();\n this.modifiedDate = nowTimestamp();\n }\n\n @BeforeUpdate()\n public setModified(): void {\n this.modifiedDate = nowTimestamp();\n }\n}\n\n@Entity('wallet_ledger_entry')\nexport class WalletLedgerEntryEntity {\n @PrimaryGeneratedColumn({ name: 'id' })\n public id!: number;\n\n @Column({ name: 'account_id' })\n public accountId!: number;\n\n @Column({ name: 'entry_type', length: 32 })\n public entryType!: string;\n\n @Column({ name: 'amount', type: 'bigint' })\n public amount!: string;\n\n @Column({ name: 'balance_after_available', type: 'bigint' })\n public balanceAfterAvailable!: string;\n\n @Column({ name: 'balance_after_held', type: 'bigint' })\n public balanceAfterHeld!: string;\n\n @Column({ name: 'idempotency_key', length: 255, unique: true })\n public idempotencyKey!: string;\n\n @Column({ name: 'reference_type', length: 64, nullable: true })\n public referenceType?: string;\n\n @Column({ name: 'reference_id', length: 128, nullable: true })\n public referenceId?: string;\n\n @Column({ name: 'metadata', type: 'json', nullable: true })\n public metadata?: Record<string, unknown>;\n\n @Column({ name: 'created_by', nullable: true })\n public createdBy?: number;\n\n @Column({ name: 'created_date', nullable: true })\n public createdDate!: string;\n\n @Column({ name: 'modified_by', nullable: true })\n public modifiedBy?: number;\n\n @Column({ name: 'modified_date', nullable: true })\n public modifiedDate!: string;\n\n @BeforeInsert()\n public setCreated(): void {\n this.createdDate = nowTimestamp();\n this.modifiedDate = nowTimestamp();\n }\n}\n\n@Entity('wallet_hold')\nexport class WalletHoldEntity {\n @PrimaryGeneratedColumn({ name: 'id' })\n public id!: number;\n\n @Column({ name: 'source_account_id' })\n public sourceAccountId!: number;\n\n @Column({ name: 'target_account_id' })\n public targetAccountId!: number;\n\n @Column({ name: 'amount', type: 'bigint' })\n public amount!: string;\n\n @Column({ name: 'status', length: 16, default: 'active' })\n public status!: string;\n\n @Column({ name: 'reference_type', length: 64 })\n public referenceType!: string;\n\n @Column({ name: 'reference_id', length: 128 })\n public referenceId!: string;\n\n @Column({ name: 'idempotency_key', length: 255 })\n public idempotencyKey!: string;\n\n @Column({ name: 'created_by', nullable: true })\n public createdBy?: number;\n\n @Column({ name: 'created_date', nullable: true })\n public createdDate!: string;\n\n @Column({ name: 'modified_by', nullable: true })\n public modifiedBy?: number;\n\n @Column({ name: 'modified_date', nullable: true })\n public modifiedDate!: string;\n\n @BeforeInsert()\n public setCreated(): void {\n this.createdDate = nowTimestamp();\n this.modifiedDate = nowTimestamp();\n }\n\n @BeforeUpdate()\n public setModified(): void {\n this.modifiedDate = nowTimestamp();\n }\n}\n","export class WalletError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WalletError';\n }\n}\n\nexport class WalletConfigError extends WalletError {\n constructor(message: string) {\n super(message);\n this.name = 'WalletConfigError';\n }\n}\n\nexport class InsufficientBalanceError extends WalletError {\n constructor(message: string = 'Insufficient available balance') {\n super(message);\n this.name = 'InsufficientBalanceError';\n }\n}\n\nexport class HoldNotFoundError extends WalletError {\n constructor(message: string = 'Active hold not found for reference') {\n super(message);\n this.name = 'HoldNotFoundError';\n }\n}\n\nexport class DuplicateOperationError extends WalletError {\n public readonly existingEntry: unknown;\n\n constructor(message: string, existingEntry: unknown) {\n super(message);\n this.name = 'DuplicateOperationError';\n this.existingEntry = existingEntry;\n }\n}\n\nexport class InvalidAmountError extends WalletError {\n constructor(message: string = 'Amount must be a positive integer in minor units') {\n super(message);\n this.name = 'InvalidAmountError';\n }\n}\n","export const CUSTOMER_CHECKOUT_DEBIT_PURPOSE = 'customer_checkout_debit';\nexport const CUSTOMER_CHECKOUT_DEBIT_REVERSAL_PURPOSE = 'customer_checkout_debit_reversal';\nexport const BACKFILL_SENTINEL_KEY = 'customer_checkout_debit_backfill';\nexport const WALLET_OPS_TABLE = 'wallet_ops';\n\nexport function orderCustomerDebitIdempotencyKey(orderId: number | string): string {\n return `wallet:order:${orderId}:customer_debit`;\n}\n\nexport function paymentReversalIdempotencyKey(paymentNumber: string): string {\n return `wallet:payment-reversal:${paymentNumber}`;\n}\n\nexport function paymentNumberFromWalletPaymentKey(idempotencyKey: string): string | null {\n const prefix = 'wallet:payment:';\n if (!idempotencyKey.startsWith(prefix)) {\n return null;\n }\n return idempotencyKey.slice(prefix.length);\n}\n\n/**\n * True when this debit is a customer checkout (product-amount) debit for an order.\n * Settlement/vendor/affiliate debits must not use these keys or purpose.\n */\nexport function isCustomerCheckoutDebit(params: {\n idempotencyKey: string;\n referenceType?: string;\n purpose?: unknown;\n}): boolean {\n if (params.purpose === CUSTOMER_CHECKOUT_DEBIT_PURPOSE) {\n return true;\n }\n const key = params.idempotencyKey;\n if (key.startsWith('wallet:order:') && key.endsWith(':customer_debit')) {\n return true;\n }\n if (params.referenceType !== 'order') {\n return false;\n }\n return isLegacyCustomerCheckoutDebitKey(key);\n}\n\n/**\n * Legacy keys accepted during rollout only.\n * Sunset: `npm run wallet:legacy-order-debit-sunset` — drop this helper when LEGACY_ORDER_DEBIT_SUNSET_SQL returns 0 on prod.\n */\nexport function isLegacyCustomerCheckoutDebitKey(key: string): boolean {\n return (\n key.startsWith('wallet:full:') ||\n key.startsWith('wallet:split:') ||\n key.startsWith('wallet:payment:')\n );\n}\n\n/** Unreimbursed full/split + wallet:payment twins (duplicate customer checkout debits). */\nexport const UNREIMBURSED_TWIN_COUNT_SQL = `\nSELECT COUNT(*) AS c\nFROM wallet_ledger_entry f\nJOIN wallet_ledger_entry p\n ON p.account_id = f.account_id\n AND p.reference_type = 'order'\n AND p.reference_id = f.reference_id\n AND p.entry_type = 'debit'\n AND p.idempotency_key LIKE 'wallet:payment:%'\nWHERE f.entry_type = 'debit'\n AND f.reference_type = 'order'\n AND (\n f.idempotency_key LIKE 'wallet:full:%'\n OR f.idempotency_key LIKE 'wallet:split:%'\n )\n AND NOT EXISTS (\n SELECT 1 FROM wallet_ledger_entry r\n WHERE r.entry_type = 'credit'\n AND r.account_id = p.account_id\n AND r.reference_type = 'order'\n AND r.reference_id = p.reference_id\n AND (\n r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))\n OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'\n )\n )\n`;\n\nexport const UNREIMBURSED_TWIN_DETAIL_SQL = `\nSELECT\n f.reference_id AS order_id,\n f.account_id,\n f.amount AS first_paise,\n p.amount AS second_paise,\n f.idempotency_key AS kept_key,\n p.idempotency_key AS duplicate_key,\n f.created_date AS first_at,\n p.created_date AS duplicate_at,\n f.id AS kept_id,\n p.id AS duplicate_id\nFROM wallet_ledger_entry f\nJOIN wallet_ledger_entry p\n ON p.account_id = f.account_id\n AND p.reference_type = 'order'\n AND p.reference_id = f.reference_id\n AND p.entry_type = 'debit'\n AND p.idempotency_key LIKE 'wallet:payment:%'\nWHERE f.entry_type = 'debit'\n AND f.reference_type = 'order'\n AND (\n f.idempotency_key LIKE 'wallet:full:%'\n OR f.idempotency_key LIKE 'wallet:split:%'\n )\n AND NOT EXISTS (\n SELECT 1 FROM wallet_ledger_entry r\n WHERE r.entry_type = 'credit'\n AND r.account_id = p.account_id\n AND r.reference_type = 'order'\n AND r.reference_id = p.reference_id\n AND (\n r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))\n OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'\n )\n )\n`;\n\n/**\n * Exit condition for removing isLegacyCustomerCheckoutDebitKey from debit lookup.\n * File the sunset PR the same week this count hits 0 on prod.\n */\nexport const LEGACY_ORDER_DEBIT_SUNSET_SQL = `\nSELECT COUNT(*) AS c\nFROM wallet_ledger_entry\nWHERE entry_type = 'debit'\n AND reference_type = 'order'\n AND (\n idempotency_key LIKE 'wallet:full:%'\n OR idempotency_key LIKE 'wallet:split:%'\n OR idempotency_key LIKE 'wallet:payment:%'\n )\n`;\n","import { Brackets, type EntityManager } from 'typeorm';\nimport { DuplicateOperationError } from '../errors';\nimport {\n CUSTOMER_CHECKOUT_DEBIT_PURPOSE,\n orderCustomerDebitIdempotencyKey,\n} from '../orderCustomerDebit';\nimport type { WalletHostConnection } from '../plugin-instance';\nimport type { IWalletStore, IWalletStoreTx, WalletStoreContext } from '../store';\nimport { parseLedgerDate } from '../timestamps';\nimport {\n HoldStatus,\n LedgerEntryType,\n type BalanceDeltas,\n type WalletAccount,\n type WalletAccountType,\n type WalletHold,\n type WalletLedgerEntry,\n type WalletReference,\n} from '../types';\nimport {\n WalletAccountEntity,\n WalletHoldEntity,\n WalletLedgerEntryEntity,\n} from './entities';\n\nfunction toNumber(value: string | number | null | undefined): number {\n if (value == null) {\n return 0;\n }\n return Number(value);\n}\n\nfunction toLedgerAccount(row: WalletAccountEntity): WalletAccount {\n return {\n id: row.id,\n ownerType: row.ownerType as WalletAccountType,\n ownerId: row.ownerId,\n currency: row.currency,\n availableBalance: toNumber(row.availableBalance),\n heldBalance: toNumber(row.heldBalance),\n };\n}\n\nfunction toLedgerHold(row: WalletHoldEntity): WalletHold {\n return {\n id: row.id,\n sourceAccountId: row.sourceAccountId,\n targetAccountId: row.targetAccountId,\n amount: toNumber(row.amount),\n status: row.status as HoldStatus,\n referenceType: row.referenceType,\n referenceId: row.referenceId,\n idempotencyKey: row.idempotencyKey,\n createdAt: parseLedgerDate(row.createdDate),\n };\n}\n\nfunction toLedgerEntry(row: WalletLedgerEntryEntity): WalletLedgerEntry {\n return {\n id: row.id,\n accountId: row.accountId,\n entryType: row.entryType as LedgerEntryType,\n amount: toNumber(row.amount),\n balanceAfterAvailable: toNumber(row.balanceAfterAvailable),\n balanceAfterHeld: toNumber(row.balanceAfterHeld),\n idempotencyKey: row.idempotencyKey,\n referenceType: row.referenceType,\n referenceId: row.referenceId,\n metadata: row.metadata,\n createdAt: parseLedgerDate(row.createdDate),\n };\n}\n\nfunction isEntityManager(value: unknown): value is EntityManager {\n return (\n value != null &&\n typeof value === 'object' &&\n typeof (value as EntityManager).getRepository === 'function'\n );\n}\n\nclass TypeOrmWalletStoreTx implements IWalletStoreTx {\n constructor(private readonly em: EntityManager) {}\n\n public async getOrCreateAccount(\n type: WalletAccountType,\n ownerId: number,\n currency: string\n ): Promise<WalletAccount> {\n const repo = this.em.getRepository(WalletAccountEntity);\n let row = await repo.findOne({ where: { ownerType: type, ownerId, currency } });\n if (!row) {\n try {\n row = await repo.save(\n repo.create({\n ownerType: type,\n ownerId,\n currency,\n availableBalance: '0',\n heldBalance: '0',\n }),\n );\n } catch (error: unknown) {\n const err = error as { code?: string | number; errno?: string | number };\n const code = err?.code || err?.errno;\n if (code === 'ER_DUP_ENTRY' || code === 1062) {\n // Unique (owner) race or PRIMARY auto-increment collision — re-read winner.\n row = await repo.findOne({ where: { ownerType: type, ownerId, currency } });\n if (row) {\n return toLedgerAccount(row);\n }\n }\n throw error;\n }\n }\n return toLedgerAccount(row);\n }\n\n public async lockAccount(accountId: number): Promise<WalletAccount> {\n const row = await this.em\n .getRepository(WalletAccountEntity)\n .createQueryBuilder('wa')\n .setLock('pessimistic_write')\n .where('wa.id = :id', { id: accountId })\n .getOne();\n if (!row) {\n throw new Error(`Wallet account ${accountId} not found`);\n }\n return toLedgerAccount(row);\n }\n\n public async getAccountById(accountId: number): Promise<WalletAccount | null> {\n const row = await this.em.getRepository(WalletAccountEntity).findOne({ where: { id: accountId } });\n return row ? toLedgerAccount(row) : null;\n }\n\n public async appendLedgerEntry(\n entry: Omit<WalletLedgerEntry, 'id' | 'createdAt'>\n ): Promise<WalletLedgerEntry> {\n const existing = await this.findLedgerByIdempotencyKey(entry.idempotencyKey);\n if (existing) {\n return existing;\n }\n\n const repo = this.em.getRepository(WalletLedgerEntryEntity);\n try {\n const row = await repo.save(\n repo.create({\n accountId: entry.accountId,\n entryType: entry.entryType,\n amount: String(entry.amount),\n balanceAfterAvailable: String(entry.balanceAfterAvailable),\n balanceAfterHeld: String(entry.balanceAfterHeld),\n idempotencyKey: entry.idempotencyKey,\n referenceType: entry.referenceType,\n referenceId: entry.referenceId,\n metadata: entry.metadata,\n })\n );\n return toLedgerEntry(row);\n } catch (error: unknown) {\n const err = error as { code?: string | number; errno?: string | number };\n const code = err?.code || err?.errno;\n if (code === 'ER_DUP_ENTRY' || code === 1062) {\n const dup = await this.findLedgerByIdempotencyKey(entry.idempotencyKey);\n if (dup) {\n return dup;\n }\n throw new DuplicateOperationError('Duplicate idempotency key', null);\n }\n throw error;\n }\n }\n\n public async updateBalances(accountId: number, deltas: BalanceDeltas): Promise<WalletAccount> {\n const row = await this.em\n .getRepository(WalletAccountEntity)\n .createQueryBuilder('wa')\n .setLock('pessimistic_write')\n .where('wa.id = :id', { id: accountId })\n .getOne();\n if (!row) {\n throw new Error(`Wallet account ${accountId} not found`);\n }\n\n const available = toNumber(row.availableBalance) + (deltas.availableDelta ?? 0);\n const held = toNumber(row.heldBalance) + (deltas.heldDelta ?? 0);\n if (available < 0 || held < 0) {\n throw new Error('Balance cannot be negative');\n }\n\n row.availableBalance = String(available);\n row.heldBalance = String(held);\n const saved = await this.em.getRepository(WalletAccountEntity).save(row);\n return toLedgerAccount(saved);\n }\n\n public async findHoldByReference(ref: WalletReference): Promise<WalletHold | null> {\n const row = await this.em.getRepository(WalletHoldEntity).findOne({\n where: { referenceType: ref.referenceType, referenceId: ref.referenceId },\n order: { id: 'DESC' },\n });\n return row ? toLedgerHold(row) : null;\n }\n\n public async upsertHold(\n hold: Omit<WalletHold, 'id' | 'createdAt'> & { id?: number }\n ): Promise<WalletHold> {\n const repo = this.em.getRepository(WalletHoldEntity);\n let row: WalletHoldEntity | undefined;\n if (hold.id != null) {\n row = (await repo.findOne({ where: { id: hold.id } })) ?? undefined;\n }\n if (!row) {\n row =\n (await repo.findOne({\n where: { referenceType: hold.referenceType, referenceId: hold.referenceId },\n })) ?? undefined;\n }\n if (!row) {\n row = repo.create({\n sourceAccountId: hold.sourceAccountId,\n targetAccountId: hold.targetAccountId,\n amount: String(hold.amount),\n status: hold.status,\n referenceType: hold.referenceType,\n referenceId: hold.referenceId,\n idempotencyKey: hold.idempotencyKey,\n });\n } else {\n row.sourceAccountId = hold.sourceAccountId;\n row.targetAccountId = hold.targetAccountId;\n row.amount = String(hold.amount);\n row.status = hold.status;\n row.idempotencyKey = hold.idempotencyKey;\n }\n const saved = await repo.save(row);\n return toLedgerHold(saved);\n }\n\n public async findLedgerByIdempotencyKey(key: string): Promise<WalletLedgerEntry | null> {\n const row = await this.em.getRepository(WalletLedgerEntryEntity).findOne({\n where: { idempotencyKey: key },\n });\n return row ? toLedgerEntry(row) : null;\n }\n\n public async findOrderCustomerCheckoutDebit(\n accountId: number,\n orderId: string\n ): Promise<WalletLedgerEntry | null> {\n const canonical = orderCustomerDebitIdempotencyKey(orderId);\n const row = await this.em\n .getRepository(WalletLedgerEntryEntity)\n .createQueryBuilder('e')\n .where('e.account_id = :accountId', { accountId })\n .andWhere('e.entry_type = :entryType', { entryType: 'debit' })\n .andWhere('e.reference_type = :referenceType', { referenceType: 'order' })\n .andWhere('e.reference_id = :orderId', { orderId })\n .andWhere(\n new Brackets((qb) => {\n qb.where(\n `JSON_UNQUOTE(JSON_EXTRACT(e.metadata, '$.purpose')) = :purpose`,\n { purpose: CUSTOMER_CHECKOUT_DEBIT_PURPOSE }\n )\n .orWhere('e.idempotency_key = :canonical', { canonical })\n .orWhere('e.idempotency_key LIKE :fullPrefix', { fullPrefix: 'wallet:full:%' })\n .orWhere('e.idempotency_key LIKE :splitPrefix', { splitPrefix: 'wallet:split:%' })\n .orWhere('e.idempotency_key LIKE :paymentPrefix', { paymentPrefix: 'wallet:payment:%' });\n })\n )\n .orderBy(\n `CASE\n WHEN JSON_UNQUOTE(JSON_EXTRACT(e.metadata, '$.purpose')) = :purpose THEN 0\n WHEN e.idempotency_key = :canonical THEN 1\n WHEN e.idempotency_key LIKE 'wallet:full:%' OR e.idempotency_key LIKE 'wallet:split:%' THEN 2\n ELSE 3\n END`,\n 'ASC'\n )\n .addOrderBy('e.id', 'ASC')\n .setParameter('purpose', CUSTOMER_CHECKOUT_DEBIT_PURPOSE)\n .setParameter('canonical', canonical)\n .getOne();\n return row ? toLedgerEntry(row) : null;\n }\n\n public async listLedgerEntries(\n accountId: number,\n limit: number,\n offset: number\n ): Promise<WalletLedgerEntry[]> {\n const rows = await this.em.getRepository(WalletLedgerEntryEntity).find({\n where: { accountId },\n order: { id: 'DESC' },\n take: limit,\n skip: offset,\n });\n return rows.map(toLedgerEntry);\n }\n}\n\nexport class TypeOrmWalletStore implements IWalletStore {\n constructor(private readonly connection: WalletHostConnection) {}\n\n public async runInTransaction<T>(\n fn: (tx: IWalletStoreTx) => Promise<T>,\n ctx?: WalletStoreContext\n ): Promise<T> {\n if (isEntityManager(ctx?.nativeTx)) {\n return fn(new TypeOrmWalletStoreTx(ctx.nativeTx));\n }\n\n return this.connection.manager.transaction(async (em) =>\n fn(new TypeOrmWalletStoreTx(em as EntityManager))\n );\n }\n}\n","import { MigrationInterface, QueryRunner } from 'typeorm';\n\nasync function indexExists(\n queryRunner: QueryRunner,\n tableName: string,\n indexName: string\n): Promise<boolean> {\n const rows: Array<{ c: number }> = await queryRunner.query(\n `SELECT COUNT(1) AS c\n FROM information_schema.statistics\n WHERE table_schema = DATABASE()\n AND table_name = ?\n AND index_name = ?`,\n [tableName, indexName]\n );\n return Number(rows[0]?.c ?? 0) > 0;\n}\n\nexport class CreateWalletTables1790000000000 implements MigrationInterface {\n public async up(queryRunner: QueryRunner): Promise<void> {\n if (!(await queryRunner.hasTable('wallet_account'))) {\n await queryRunner.query(`\n CREATE TABLE \\`wallet_account\\` (\n \\`id\\` int NOT NULL AUTO_INCREMENT,\n \\`owner_type\\` varchar(32) NOT NULL,\n \\`owner_id\\` int NOT NULL,\n \\`currency\\` varchar(8) NOT NULL DEFAULT 'INR',\n \\`available_balance\\` bigint NOT NULL DEFAULT 0,\n \\`held_balance\\` bigint NOT NULL DEFAULT 0,\n \\`created_by\\` int NULL,\n \\`created_date\\` datetime NULL,\n \\`modified_by\\` int NULL,\n \\`modified_date\\` datetime NULL,\n PRIMARY KEY (\\`id\\`)\n ) ENGINE=InnoDB\n `);\n }\n\n if (!(await indexExists(queryRunner, 'wallet_account', 'IDX_wallet_account_owner_currency'))) {\n await queryRunner.query(`\n CREATE UNIQUE INDEX \\`IDX_wallet_account_owner_currency\\`\n ON \\`wallet_account\\` (\\`owner_type\\`, \\`owner_id\\`, \\`currency\\`)\n `);\n }\n\n if (!(await queryRunner.hasTable('wallet_ledger_entry'))) {\n await queryRunner.query(`\n CREATE TABLE \\`wallet_ledger_entry\\` (\n \\`id\\` int NOT NULL AUTO_INCREMENT,\n \\`account_id\\` int NOT NULL,\n \\`entry_type\\` varchar(32) NOT NULL,\n \\`amount\\` bigint NOT NULL,\n \\`balance_after_available\\` bigint NOT NULL,\n \\`balance_after_held\\` bigint NOT NULL,\n \\`idempotency_key\\` varchar(255) NOT NULL,\n \\`reference_type\\` varchar(64) NULL,\n \\`reference_id\\` varchar(128) NULL,\n \\`metadata\\` json NULL,\n \\`created_by\\` int NULL,\n \\`created_date\\` datetime NULL,\n \\`modified_by\\` int NULL,\n \\`modified_date\\` datetime NULL,\n PRIMARY KEY (\\`id\\`),\n UNIQUE INDEX \\`UQ_wallet_ledger_idempotency_key\\` (\\`idempotency_key\\`)\n ) ENGINE=InnoDB\n `);\n }\n\n if (!(await indexExists(queryRunner, 'wallet_ledger_entry', 'IDX_wallet_ledger_account_id'))) {\n await queryRunner.query(`\n CREATE INDEX \\`IDX_wallet_ledger_account_id\\`\n ON \\`wallet_ledger_entry\\` (\\`account_id\\`)\n `);\n }\n\n if (!(await queryRunner.hasTable('wallet_hold'))) {\n await queryRunner.query(`\n CREATE TABLE \\`wallet_hold\\` (\n \\`id\\` int NOT NULL AUTO_INCREMENT,\n \\`source_account_id\\` int NOT NULL,\n \\`target_account_id\\` int NOT NULL,\n \\`amount\\` bigint NOT NULL,\n \\`status\\` varchar(16) NOT NULL DEFAULT 'active',\n \\`reference_type\\` varchar(64) NOT NULL,\n \\`reference_id\\` varchar(128) NOT NULL,\n \\`idempotency_key\\` varchar(255) NOT NULL,\n \\`created_by\\` int NULL,\n \\`created_date\\` datetime NULL,\n \\`modified_by\\` int NULL,\n \\`modified_date\\` datetime NULL,\n PRIMARY KEY (\\`id\\`)\n ) ENGINE=InnoDB\n `);\n }\n\n if (!(await indexExists(queryRunner, 'wallet_hold', 'IDX_wallet_hold_reference'))) {\n await queryRunner.query(`\n CREATE INDEX \\`IDX_wallet_hold_reference\\`\n ON \\`wallet_hold\\` (\\`reference_type\\`, \\`reference_id\\`)\n `);\n }\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n if (await queryRunner.hasTable('wallet_hold')) {\n await queryRunner.query('DROP TABLE `wallet_hold`');\n }\n if (await queryRunner.hasTable('wallet_ledger_entry')) {\n await queryRunner.query('DROP TABLE `wallet_ledger_entry`');\n }\n if (await queryRunner.hasTable('wallet_account')) {\n await queryRunner.query('DROP TABLE `wallet_account`');\n }\n }\n}\n","import { MigrationInterface, QueryRunner } from 'typeorm';\nimport {\n BACKFILL_SENTINEL_KEY,\n UNREIMBURSED_TWIN_COUNT_SQL,\n WALLET_OPS_TABLE,\n} from '../../orderCustomerDebit';\n\n/**\n * Unique purpose key for one customer checkout debit per order.\n * `up()` throws before any DDL unless backfill sentinel exists and twin COUNT is 0.\n */\nexport class AddOrderCustomerDebitUnique1790000001000 implements MigrationInterface {\n public async up(queryRunner: QueryRunner): Promise<void> {\n const opsTables: Array<{ c: number }> = await queryRunner.query(\n `SELECT COUNT(*) AS c\n FROM information_schema.tables\n WHERE table_schema = DATABASE()\n AND table_name = ?`,\n [WALLET_OPS_TABLE]\n );\n if (Number(opsTables[0]?.c ?? 0) === 0) {\n throw new Error(\n `Wallet unique-index gate: ${WALLET_OPS_TABLE} is missing. Run npm run wallet:credit-duplicate-order-debits`\n );\n }\n\n const sentinel: Array<{ status: string }> = await queryRunner.query(\n `SELECT status FROM \\`${WALLET_OPS_TABLE}\\` WHERE ops_key = ? LIMIT 1`,\n [BACKFILL_SENTINEL_KEY]\n );\n if (!sentinel[0] || sentinel[0].status !== 'complete') {\n throw new Error(\n `Wallet unique-index gate: sentinel ${BACKFILL_SENTINEL_KEY} is missing. Run npm run wallet:credit-duplicate-order-debits`\n );\n }\n\n const twins: Array<{ c: number }> = await queryRunner.query(UNREIMBURSED_TWIN_COUNT_SQL);\n const twinCount = Number(twins[0]?.c ?? 0);\n if (twinCount > 0) {\n throw new Error(\n `Wallet unique-index gate: unreimbursed twin COUNT is ${twinCount}. Run npm run wallet:credit-duplicate-order-debits`\n );\n }\n\n const columns: Array<{ c: number }> = await queryRunner.query(\n `SELECT COUNT(*) AS c\n FROM information_schema.columns\n WHERE table_schema = DATABASE()\n AND table_name = 'wallet_ledger_entry'\n AND column_name = 'order_customer_debit_key'`\n );\n if (Number(columns[0]?.c ?? 0) === 0) {\n await queryRunner.query(`\n ALTER TABLE \\`wallet_ledger_entry\\`\n ADD COLUMN \\`order_customer_debit_key\\` VARCHAR(191)\n GENERATED ALWAYS AS (\n CASE\n WHEN \\`entry_type\\` = 'debit'\n AND \\`reference_type\\` = 'order'\n AND \\`reference_id\\` IS NOT NULL\n AND JSON_UNQUOTE(JSON_EXTRACT(\\`metadata\\`, '$.purpose')) = 'customer_checkout_debit'\n THEN CONCAT(\\`account_id\\`, ':', \\`reference_id\\`)\n ELSE NULL\n END\n ) STORED\n `);\n }\n\n const indexes: Array<{ c: number }> = await queryRunner.query(\n `SELECT COUNT(*) AS c\n FROM information_schema.statistics\n WHERE table_schema = DATABASE()\n AND table_name = 'wallet_ledger_entry'\n AND index_name = 'UQ_wallet_order_customer_debit'`\n );\n if (Number(indexes[0]?.c ?? 0) === 0) {\n await queryRunner.query(`\n CREATE UNIQUE INDEX \\`UQ_wallet_order_customer_debit\\`\n ON \\`wallet_ledger_entry\\` (\\`order_customer_debit_key\\`)\n `);\n }\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n const indexes: Array<{ c: number }> = await queryRunner.query(\n `SELECT COUNT(*) AS c\n FROM information_schema.statistics\n WHERE table_schema = DATABASE()\n AND table_name = 'wallet_ledger_entry'\n AND index_name = 'UQ_wallet_order_customer_debit'`\n );\n if (Number(indexes[0]?.c ?? 0) > 0) {\n await queryRunner.query(\n `DROP INDEX \\`UQ_wallet_order_customer_debit\\` ON \\`wallet_ledger_entry\\``\n );\n }\n const columns: Array<{ c: number }> = await queryRunner.query(\n `SELECT COUNT(*) AS c\n FROM information_schema.columns\n WHERE table_schema = DATABASE()\n AND table_name = 'wallet_ledger_entry'\n AND column_name = 'order_customer_debit_key'`\n );\n if (Number(columns[0]?.c ?? 0) > 0) {\n await queryRunner.query(\n `ALTER TABLE \\`wallet_ledger_entry\\` DROP COLUMN \\`order_customer_debit_key\\``\n );\n }\n }\n}\n","import {\n WalletAccountEntity,\n WalletHoldEntity,\n WalletLedgerEntryEntity,\n} from './entities';\nimport { CreateWalletTables1790000000000 } from './migrations/CreateWalletTables';\nimport { AddOrderCustomerDebitUnique1790000001000 } from './migrations/AddOrderCustomerDebitUnique';\n\nexport function getWalletOrmMetadata(): {\n entities: Function[];\n migrations: Function[];\n} {\n return {\n entities: [WalletAccountEntity, WalletLedgerEntryEntity, WalletHoldEntity],\n migrations: [CreateWalletTables1790000000000, AddOrderCustomerDebitUnique1790000001000],\n };\n}\n"]}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import { I as IWalletStore, W as WalletAccountType, a as WalletStoreContext, b as WalletAccount, c as WalletBalance, C as CreditParams, L as LedgerMutationResult, D as DebitParams, H as HoldParams, R as ReleaseParams, d as CancelHoldParams, T as TransferParams, G as GetTransactionsParams, e as WalletLedgerEntry } from './store-
|
|
1
|
+
import { I as IWalletStore, W as WalletAccountType, a as WalletStoreContext, b as WalletAccount, c as WalletBalance, C as CreditParams, L as LedgerMutationResult, D as DebitParams, H as HoldParams, R as ReleaseParams, d as CancelHoldParams, T as TransferParams, G as GetTransactionsParams, e as WalletLedgerEntry } from './store-nWCfzvwf.js';
|
|
2
2
|
|
|
3
|
+
type WalletDuplicateOrderDebitKind = 'idempotent_retry' | 'cross_key_collision';
|
|
4
|
+
interface WalletDuplicateOrderDebitInfo {
|
|
5
|
+
orderId: string;
|
|
6
|
+
accountId: number;
|
|
7
|
+
requestedKey: string;
|
|
8
|
+
existingKey: string;
|
|
9
|
+
kind: WalletDuplicateOrderDebitKind;
|
|
10
|
+
}
|
|
3
11
|
interface WalletConfig {
|
|
4
12
|
/** Default currency when not specified (e.g. INR). */
|
|
5
13
|
defaultCurrency?: string;
|
|
6
14
|
/** Platform wallet owner id in the host system. */
|
|
7
15
|
platformOwnerId?: number;
|
|
16
|
+
/** Fired when a customer checkout debit hits an existing purpose/legacy row. */
|
|
17
|
+
onDuplicateOrderDebit?: (info: WalletDuplicateOrderDebitInfo) => void;
|
|
8
18
|
}
|
|
9
19
|
|
|
10
20
|
declare class WalletLedgerClient {
|
|
@@ -25,6 +35,7 @@ declare class WalletLedgerClient {
|
|
|
25
35
|
getTransactions(params: GetTransactionsParams, ctx?: WalletStoreContext): Promise<WalletLedgerEntry[]>;
|
|
26
36
|
private creditInTx;
|
|
27
37
|
private debitInTx;
|
|
38
|
+
private notifyDuplicateOrderDebit;
|
|
28
39
|
private holdInTx;
|
|
29
40
|
private releaseInTx;
|
|
30
41
|
private cancelHoldInTx;
|
|
@@ -135,6 +146,7 @@ interface WalletPluginConfig {
|
|
|
135
146
|
reconciliation?: WalletReconciliationConfig;
|
|
136
147
|
onAdminMutation?: (event: WalletAdminMutationEvent) => Promise<void>;
|
|
137
148
|
resolveOrderCustomerId?: (orderId: number) => Promise<number | null>;
|
|
149
|
+
onDuplicateOrderDebit?: (info: WalletDuplicateOrderDebitInfo) => void;
|
|
138
150
|
}
|
|
139
151
|
interface WalletPlugin {
|
|
140
152
|
readonly client: WalletLedgerClient;
|
|
@@ -162,6 +174,8 @@ interface WalletOrderPaidLine {
|
|
|
162
174
|
vendorId: number;
|
|
163
175
|
commissionBaseRupees: number;
|
|
164
176
|
commissionRupees: number;
|
|
177
|
+
/** Frozen seller net when present; onOrderPaid holds this instead of base − commission. */
|
|
178
|
+
sellerNetRupees?: number;
|
|
165
179
|
}
|
|
166
180
|
interface OrderPaidContext {
|
|
167
181
|
nativeTx: unknown;
|
|
@@ -221,4 +235,4 @@ interface HookRuntime {
|
|
|
221
235
|
flags: WalletFeatureFlags;
|
|
222
236
|
}
|
|
223
237
|
|
|
224
|
-
export { type CreatePaymentInput as C, type DeliveredContext as D, type HookRuntime as H, type IWalletPaymentProvider as I, type OrderPaidContext as O, PaymentProviderWallet as P, type RefundContext as R, type SettlementDebitContext as S, type WalletLifecycleHooks as W, type WalletCacheMismatch as a, type WalletOrderPaidLine as b, type WalletParityDelta as c, type WalletReconciliationReport as d, type WalletPluginConfig as e, type WalletPlugin as f, WALLET_PLUGIN_TOKEN as g, type WalletAdminMutationEvent as h, type WalletConfig as i, type
|
|
238
|
+
export { type CreatePaymentInput as C, type DeliveredContext as D, type HookRuntime as H, type IWalletPaymentProvider as I, type OrderPaidContext as O, PaymentProviderWallet as P, type RefundContext as R, type SettlementDebitContext as S, type WalletLifecycleHooks as W, type WalletCacheMismatch as a, type WalletOrderPaidLine as b, type WalletParityDelta as c, type WalletReconciliationReport as d, type WalletPluginConfig as e, type WalletPlugin as f, WALLET_PLUGIN_TOKEN as g, type WalletAdminMutationEvent as h, type WalletConfig as i, type WalletDuplicateOrderDebitInfo as j, type WalletDuplicateOrderDebitKind as k, type WalletFeatureFlags as l, type WalletHttpConfig as m, WalletLedgerClient as n, type WalletReconciliationConfig as o, runWalletReconciliation as r };
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import { I as IWalletStore, W as WalletAccountType, a as WalletStoreContext, b as WalletAccount, c as WalletBalance, C as CreditParams, L as LedgerMutationResult, D as DebitParams, H as HoldParams, R as ReleaseParams, d as CancelHoldParams, T as TransferParams, G as GetTransactionsParams, e as WalletLedgerEntry } from './store-
|
|
1
|
+
import { I as IWalletStore, W as WalletAccountType, a as WalletStoreContext, b as WalletAccount, c as WalletBalance, C as CreditParams, L as LedgerMutationResult, D as DebitParams, H as HoldParams, R as ReleaseParams, d as CancelHoldParams, T as TransferParams, G as GetTransactionsParams, e as WalletLedgerEntry } from './store-nWCfzvwf.mjs';
|
|
2
2
|
|
|
3
|
+
type WalletDuplicateOrderDebitKind = 'idempotent_retry' | 'cross_key_collision';
|
|
4
|
+
interface WalletDuplicateOrderDebitInfo {
|
|
5
|
+
orderId: string;
|
|
6
|
+
accountId: number;
|
|
7
|
+
requestedKey: string;
|
|
8
|
+
existingKey: string;
|
|
9
|
+
kind: WalletDuplicateOrderDebitKind;
|
|
10
|
+
}
|
|
3
11
|
interface WalletConfig {
|
|
4
12
|
/** Default currency when not specified (e.g. INR). */
|
|
5
13
|
defaultCurrency?: string;
|
|
6
14
|
/** Platform wallet owner id in the host system. */
|
|
7
15
|
platformOwnerId?: number;
|
|
16
|
+
/** Fired when a customer checkout debit hits an existing purpose/legacy row. */
|
|
17
|
+
onDuplicateOrderDebit?: (info: WalletDuplicateOrderDebitInfo) => void;
|
|
8
18
|
}
|
|
9
19
|
|
|
10
20
|
declare class WalletLedgerClient {
|
|
@@ -25,6 +35,7 @@ declare class WalletLedgerClient {
|
|
|
25
35
|
getTransactions(params: GetTransactionsParams, ctx?: WalletStoreContext): Promise<WalletLedgerEntry[]>;
|
|
26
36
|
private creditInTx;
|
|
27
37
|
private debitInTx;
|
|
38
|
+
private notifyDuplicateOrderDebit;
|
|
28
39
|
private holdInTx;
|
|
29
40
|
private releaseInTx;
|
|
30
41
|
private cancelHoldInTx;
|
|
@@ -135,6 +146,7 @@ interface WalletPluginConfig {
|
|
|
135
146
|
reconciliation?: WalletReconciliationConfig;
|
|
136
147
|
onAdminMutation?: (event: WalletAdminMutationEvent) => Promise<void>;
|
|
137
148
|
resolveOrderCustomerId?: (orderId: number) => Promise<number | null>;
|
|
149
|
+
onDuplicateOrderDebit?: (info: WalletDuplicateOrderDebitInfo) => void;
|
|
138
150
|
}
|
|
139
151
|
interface WalletPlugin {
|
|
140
152
|
readonly client: WalletLedgerClient;
|
|
@@ -162,6 +174,8 @@ interface WalletOrderPaidLine {
|
|
|
162
174
|
vendorId: number;
|
|
163
175
|
commissionBaseRupees: number;
|
|
164
176
|
commissionRupees: number;
|
|
177
|
+
/** Frozen seller net when present; onOrderPaid holds this instead of base − commission. */
|
|
178
|
+
sellerNetRupees?: number;
|
|
165
179
|
}
|
|
166
180
|
interface OrderPaidContext {
|
|
167
181
|
nativeTx: unknown;
|
|
@@ -221,4 +235,4 @@ interface HookRuntime {
|
|
|
221
235
|
flags: WalletFeatureFlags;
|
|
222
236
|
}
|
|
223
237
|
|
|
224
|
-
export { type CreatePaymentInput as C, type DeliveredContext as D, type HookRuntime as H, type IWalletPaymentProvider as I, type OrderPaidContext as O, PaymentProviderWallet as P, type RefundContext as R, type SettlementDebitContext as S, type WalletLifecycleHooks as W, type WalletCacheMismatch as a, type WalletOrderPaidLine as b, type WalletParityDelta as c, type WalletReconciliationReport as d, type WalletPluginConfig as e, type WalletPlugin as f, WALLET_PLUGIN_TOKEN as g, type WalletAdminMutationEvent as h, type WalletConfig as i, type
|
|
238
|
+
export { type CreatePaymentInput as C, type DeliveredContext as D, type HookRuntime as H, type IWalletPaymentProvider as I, type OrderPaidContext as O, PaymentProviderWallet as P, type RefundContext as R, type SettlementDebitContext as S, type WalletLifecycleHooks as W, type WalletCacheMismatch as a, type WalletOrderPaidLine as b, type WalletParityDelta as c, type WalletReconciliationReport as d, type WalletPluginConfig as e, type WalletPlugin as f, WALLET_PLUGIN_TOKEN as g, type WalletAdminMutationEvent as h, type WalletConfig as i, type WalletDuplicateOrderDebitInfo as j, type WalletDuplicateOrderDebitKind as k, type WalletFeatureFlags as l, type WalletHttpConfig as m, WalletLedgerClient as n, type WalletReconciliationConfig as o, runWalletReconciliation as r };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "multivendor-wallet",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Install-and-use wallet plugin with ledger engine, TypeORM store, lifecycle hooks, and HTTP routes for multi-vendor marketplaces",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SmartByteLabs",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"dist"
|
|
52
52
|
],
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"typeorm": "
|
|
54
|
+
"typeorm": "^1.1.0",
|
|
55
55
|
"express": ">=4",
|
|
56
56
|
"routing-controllers": ">=0.10",
|
|
57
57
|
"class-validator": ">=0.14",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"routing-controllers": "^0.10.4",
|
|
98
98
|
"tsup": "^8.4.0",
|
|
99
99
|
"typedi": "^0.10.0",
|
|
100
|
-
"typeorm": "^
|
|
100
|
+
"typeorm": "^1.1.0",
|
|
101
101
|
"typescript": "^5.7.3",
|
|
102
102
|
"vitest": "^3.0.5"
|
|
103
103
|
},
|