multivendor-wallet 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,10 @@ Framework-agnostic wallet ledger engine for multi-vendor marketplaces.
4
4
 
5
5
  ## Changelog
6
6
 
7
+ ### 0.0.7
8
+
9
+ - `onOrderPaid` customer debit is capped at `orderTotalRupees` when `walletAmountRupees` over-reports.
10
+
7
11
  ### 0.0.6
8
12
 
9
13
  - Customer checkout debit uses canonical key `wallet:order:{orderId}:customer_debit` and `metadata.purpose=customer_checkout_debit`. A second debit for the same order is a no-op (lock-then-lookup + unique generated column).
@@ -54,7 +54,7 @@ function createOrderHooks(runtime) {
54
54
  const orderTotalPaise = toMinorUnit(ctx.orderTotalRupees);
55
55
  const shouldDebitCustomer = isWalletOnlyPayment(ctx.paymentMethod) && ctx.customerId && !ctx.skipCustomerDebit;
56
56
  if (shouldDebitCustomer) {
57
- const debitRupees = ctx.walletAmountRupees ?? ctx.orderTotalRupees;
57
+ const debitRupees = Math.min(ctx.walletAmountRupees ?? ctx.orderTotalRupees, ctx.orderTotalRupees);
58
58
  const customer = await client.getOrCreateAccount(WalletAccountType.CUSTOMER, ctx.customerId, ctx.currency, txCtx);
59
59
  await client.debit({
60
60
  accountId: customer.id,
@@ -129,7 +129,7 @@ function walletCreditRupees(ctx) {
129
129
  __name(walletCreditRupees, "walletCreditRupees");
130
130
  function idempotencyPrefix(ctx) {
131
131
  const scope = ctx.idempotencyScope ?? String(ctx.orderProductId);
132
- return ctx.refundReason === "return" ? `return:${scope}` : `refund:${ctx.orderProductId}`;
132
+ return ctx.refundReason === "return" ? `return:${scope}` : `refund:${scope}`;
133
133
  }
134
134
  __name(idempotencyPrefix, "idempotencyPrefix");
135
135
  function createRefundHooks(runtime) {
@@ -142,13 +142,27 @@ function createRefundHooks(runtime) {
142
142
  }
143
143
  const keyPrefix = idempotencyPrefix(ctx);
144
144
  if (!ctx.skipEscrow) {
145
- await client.cancelHold({
146
- reference: {
147
- referenceType: "vendor_order",
148
- referenceId: String(ctx.vendorOrderId)
149
- },
150
- idempotencyKey: `${keyPrefix}:cancel_hold`
151
- });
145
+ if (ctx.sellerNetClawbackRupees != null) {
146
+ const clawbackPaise = toMinorUnit(ctx.sellerNetClawbackRupees);
147
+ if (clawbackPaise > 0) {
148
+ await client.cancelHold({
149
+ reference: {
150
+ referenceType: "vendor_order",
151
+ referenceId: String(ctx.vendorOrderId)
152
+ },
153
+ idempotencyKey: `${keyPrefix}:cancel_hold`,
154
+ amount: clawbackPaise
155
+ });
156
+ }
157
+ } else {
158
+ await client.cancelHold({
159
+ reference: {
160
+ referenceType: "vendor_order",
161
+ referenceId: String(ctx.vendorOrderId)
162
+ },
163
+ idempotencyKey: `${keyPrefix}:cancel_hold`
164
+ });
165
+ }
152
166
  }
153
167
  const refundPaise = toMinorUnit(ctx.lineTotalRupees);
154
168
  if (refundPaise > 0) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/currency.ts","../../src/orderCustomerDebit.ts","../../src/types.ts","../../src/hooks/order.ts","../../src/hooks/refund.ts","../../src/hooks/settlement.ts","../../src/plugin-instance.ts","../../src/timestamps.ts","../../src/typeorm/entities.ts","../../src/hooks/reconciliation.ts","../../src/hooks/index.ts"],"names":["toMinorUnit","amount","Math","round","fromMinorUnit","CUSTOMER_CHECKOUT_DEBIT_PURPOSE","orderCustomerDebitIdempotencyKey","orderId","WalletAccountType","isWalletOnlyPayment","paymentMethod","String","trim","toLowerCase","createOrderHooks","runtime","client","platformOwnerId","flags","onOrderPaid","ctx","enabled","ledgerWrites","txCtx","nativeTx","platform","getOrCreateAccount","PLATFORM","currency","orderTotalPaise","orderTotalRupees","shouldDebitCustomer","customerId","skipCustomerDebit","debitRupees","walletAmountRupees","customer","CUSTOMER","debit","accountId","id","idempotencyKey","reference","referenceType","referenceId","metadata","purpose","paymentNumber","credit","line","lines","vendorNetRupees","sellerNetRupees","Number","isFinite","commissionBaseRupees","commissionRupees","vendor","VENDOR","vendorId","hold","sourceAccountId","targetAccountId","vendorOrderId","onLineDelivered","release","undefined","isWalletPayment","walletCreditRupees","walletRefundRupees","lineTotalRupees","idempotencyPrefix","scope","idempotencyScope","orderProductId","refundReason","createRefundHooks","onRefund","processExternalRefund","keyPrefix","skipEscrow","cancelHold","refundPaise","balance","getBalance","available","creditRupees","createSettlementHooks","_runtime","onSettlementDebit","_ctx","resolveWalletConnection","Error","pad2","value","padStart","nowTimestamp","date","Date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","WalletAccountEntity","ownerType","ownerId","availableBalance","heldBalance","createdBy","createdDate","modifiedBy","modifiedDate","setCreated","setModified","name","length","default","type","nullable","WalletLedgerEntryEntity","entryType","balanceAfterAvailable","balanceAfterHeld","unique","WalletHoldEntity","status","runWalletReconciliation","parityDeltas","findVendorPaymentHoldParityDeltas","cacheMismatches","findCacheLedgerMismatches","rows","query","deltas","row","vendorPaymentRupees","vendorPaymentAmount","holdPaise","holdAmount","holdRupees","delta","abs","holdStatus","push","deltaRupees","connection","accounts","getRepository","find","mismatches","account","lastEntry","findOne","where","order","cachedAvailable","cachedHeld","ledgerAvailable","ledgerHeld","createLifecycleHooks"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Convert decimal currency amount (e.g. rupees) to smallest unit (paise).\n */\nexport function toMinorUnit(amount: number): number {\n return Math.round(amount * 100);\n}\n\n/**\n * Convert smallest currency unit (paise) back to decimal amount (rupees).\n */\nexport function fromMinorUnit(amount: number): number {\n return amount / 100;\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","export enum WalletAccountType {\n CUSTOMER = 'customer',\n VENDOR = 'vendor',\n PLATFORM = 'platform',\n /** Investor cash wallet (interest/bonus/withdrawable). */\n INVESTOR = 'investor',\n /** Platform liability balancing investor principal/returns. */\n PLATFORM_INVESTOR_LIABILITY = 'platform_investor_liability',\n /** TDS withheld on investor returns pending remittance. */\n PLATFORM_TDS_PAYABLE = 'platform_tds_payable',\n}\n\nexport enum LedgerEntryType {\n CREDIT = 'credit',\n DEBIT = 'debit',\n HOLD = 'hold',\n RELEASE = 'release',\n CANCEL_HOLD = 'cancel_hold',\n TRANSFER = 'transfer',\n}\n\nexport enum HoldStatus {\n ACTIVE = 'active',\n RELEASED = 'released',\n CANCELLED = 'cancelled',\n}\n\nexport interface WalletReference {\n referenceType: string;\n referenceId: string;\n}\n\nexport interface WalletAccount {\n id: number;\n ownerType: WalletAccountType;\n ownerId: number;\n currency: string;\n availableBalance: number;\n heldBalance: number;\n}\n\nexport interface WalletBalance {\n available: number;\n held: number;\n total: number;\n}\n\nexport interface WalletLedgerEntry {\n id: number;\n accountId: number;\n entryType: LedgerEntryType;\n amount: number;\n balanceAfterAvailable: number;\n balanceAfterHeld: number;\n idempotencyKey: string;\n referenceType?: string;\n referenceId?: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n}\n\nexport interface WalletHold {\n id: number;\n sourceAccountId: number;\n targetAccountId: number;\n amount: number;\n status: HoldStatus;\n referenceType: string;\n referenceId: string;\n idempotencyKey: string;\n createdAt: Date;\n}\n\nexport interface BalanceDeltas {\n availableDelta?: number;\n heldDelta?: number;\n}\n\nexport interface CreditParams {\n accountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface DebitParams {\n accountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface HoldParams {\n sourceAccountId: number;\n targetAccountId: number;\n amount: number;\n idempotencyKey: string;\n reference: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ReleaseParams {\n reference: WalletReference;\n idempotencyKey: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CancelHoldParams {\n reference: WalletReference;\n idempotencyKey: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface TransferParams {\n fromAccountId: number;\n toAccountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GetTransactionsParams {\n accountId: number;\n limit?: number;\n offset?: number;\n}\n\nexport interface LedgerMutationResult {\n entry: WalletLedgerEntry;\n account: WalletAccount;\n hold?: WalletHold;\n}\n","import { toMinorUnit } from '../currency';\nimport {\n CUSTOMER_CHECKOUT_DEBIT_PURPOSE,\n orderCustomerDebitIdempotencyKey,\n} from '../orderCustomerDebit';\nimport { WalletAccountType } from '../types';\nimport type { DeliveredContext, HookRuntime, OrderPaidContext, WalletLifecycleHooks } from './types';\n\nfunction isWalletOnlyPayment(paymentMethod?: string): boolean {\n return String(paymentMethod ?? '').trim().toLowerCase() === 'wallet';\n}\n\nexport function createOrderHooks(runtime: HookRuntime): Pick<\n WalletLifecycleHooks,\n 'onOrderPaid' | 'onLineDelivered'\n> {\n const { client, platformOwnerId, flags } = runtime;\n\n return {\n async onOrderPaid(ctx: OrderPaidContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n return;\n }\n\n const txCtx = { nativeTx: ctx.nativeTx };\n const platform = await client.getOrCreateAccount(\n WalletAccountType.PLATFORM,\n platformOwnerId,\n ctx.currency,\n txCtx\n );\n\n const orderTotalPaise = toMinorUnit(ctx.orderTotalRupees);\n const shouldDebitCustomer =\n isWalletOnlyPayment(ctx.paymentMethod) &&\n ctx.customerId &&\n !ctx.skipCustomerDebit;\n\n if (shouldDebitCustomer) {\n const debitRupees = ctx.walletAmountRupees ?? ctx.orderTotalRupees;\n const customer = await client.getOrCreateAccount(\n WalletAccountType.CUSTOMER,\n ctx.customerId,\n ctx.currency,\n txCtx\n );\n await client.debit(\n {\n accountId: customer.id,\n amount: toMinorUnit(debitRupees),\n idempotencyKey: orderCustomerDebitIdempotencyKey(ctx.orderId),\n reference: { referenceType: 'order', referenceId: String(ctx.orderId) },\n metadata: { purpose: CUSTOMER_CHECKOUT_DEBIT_PURPOSE, paymentNumber: ctx.paymentNumber },\n },\n txCtx\n );\n }\n\n await client.credit(\n {\n accountId: platform.id,\n amount: orderTotalPaise,\n idempotencyKey: `payment:${ctx.paymentNumber}`,\n reference: { referenceType: 'order', referenceId: String(ctx.orderId) },\n },\n txCtx\n );\n\n for (const line of ctx.lines) {\n const vendorNetRupees =\n line.sellerNetRupees != null && Number.isFinite(Number(line.sellerNetRupees))\n ? Number(line.sellerNetRupees)\n : line.commissionBaseRupees - line.commissionRupees;\n if (vendorNetRupees <= 0) {\n continue;\n }\n\n const vendor = await client.getOrCreateAccount(\n WalletAccountType.VENDOR,\n line.vendorId,\n ctx.currency,\n txCtx\n );\n\n await client.hold(\n {\n sourceAccountId: platform.id,\n targetAccountId: vendor.id,\n amount: toMinorUnit(vendorNetRupees),\n idempotencyKey: `order:${ctx.orderId}:hold:vendorOrder:${line.vendorOrderId}`,\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(line.vendorOrderId),\n },\n },\n txCtx\n );\n }\n },\n\n async onLineDelivered(ctx: DeliveredContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n return;\n }\n\n await client.release(\n {\n reference: { referenceType: 'vendor_order', referenceId: String(ctx.vendorOrderId) },\n idempotencyKey: `vendorOrder:${ctx.vendorOrderId}:release`,\n },\n ctx.nativeTx != null ? { nativeTx: ctx.nativeTx } : undefined\n );\n },\n };\n}\n","import { toMinorUnit } from '../currency';\nimport { WalletAccountType } from '../types';\nimport type { HookRuntime, RefundContext, WalletLifecycleHooks } from './types';\n\nfunction isWalletPayment(paymentMethod?: string): boolean {\n return String(paymentMethod ?? '').trim().toLowerCase() === 'wallet';\n}\n\nfunction walletCreditRupees(ctx: RefundContext): number {\n if (ctx.walletRefundRupees != null && ctx.walletRefundRupees > 0) {\n return ctx.walletRefundRupees;\n }\n return isWalletPayment(ctx.paymentMethod) ? ctx.lineTotalRupees : 0;\n}\n\nfunction idempotencyPrefix(ctx: RefundContext): string {\n const scope = ctx.idempotencyScope ?? String(ctx.orderProductId);\n return ctx.refundReason === 'return' ? `return:${scope}` : `refund:${ctx.orderProductId}`;\n}\n\nexport function createRefundHooks(runtime: HookRuntime): Pick<WalletLifecycleHooks, 'onRefund'> {\n const { client, platformOwnerId, flags } = runtime;\n\n return {\n async onRefund(ctx: RefundContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n await ctx.processExternalRefund();\n return;\n }\n\n const keyPrefix = idempotencyPrefix(ctx);\n\n if (!ctx.skipEscrow) {\n await client.cancelHold({\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(ctx.vendorOrderId),\n },\n idempotencyKey: `${keyPrefix}:cancel_hold`,\n });\n }\n\n const refundPaise = toMinorUnit(ctx.lineTotalRupees);\n if (refundPaise > 0) {\n const platform = await client.getOrCreateAccount(\n WalletAccountType.PLATFORM,\n platformOwnerId,\n ctx.currency\n );\n const balance = await client.getBalance(platform.id);\n if (balance.available >= refundPaise) {\n await client.debit({\n accountId: platform.id,\n amount: refundPaise,\n idempotencyKey: `${keyPrefix}:platform_debit`,\n reference: {\n referenceType: 'order_product',\n referenceId: String(ctx.orderProductId),\n },\n });\n }\n\n const creditRupees = walletCreditRupees(ctx);\n if (creditRupees > 0 && ctx.customerId) {\n const customer = await client.getOrCreateAccount(\n WalletAccountType.CUSTOMER,\n ctx.customerId,\n ctx.currency\n );\n await client.credit({\n accountId: customer.id,\n amount: toMinorUnit(creditRupees),\n idempotencyKey: `${keyPrefix}:customer_credit`,\n reference: {\n referenceType: 'order',\n referenceId: String(ctx.orderId ?? ctx.orderProductId),\n },\n });\n }\n }\n\n await ctx.processExternalRefund();\n },\n };\n}\n","import type { HookRuntime, SettlementDebitContext, WalletLifecycleHooks } from './types';\n\nexport function createSettlementHooks(\n _runtime: HookRuntime\n): Pick<WalletLifecycleHooks, 'onSettlementDebit'> {\n return {\n /** @deprecated Settlement wallet debits removed — vendor payouts use wallet payout requests. */\n async onSettlementDebit(_ctx: SettlementDebitContext): Promise<void> {\n return;\n },\n };\n}\n","import type { WalletPlugin } from './plugin-types';\n\nexport interface WalletHostConnection {\n manager: {\n transaction<T>(fn: (em: unknown) => Promise<T>): Promise<T>;\n };\n query(query: string, parameters?: unknown[]): Promise<unknown>;\n getRepository(entity: unknown): {\n find(options?: unknown): Promise<unknown[]>;\n findOne(options?: unknown): Promise<unknown | null>;\n };\n}\n\nlet activePlugin: WalletPlugin | undefined;\nlet activeConnection: WalletHostConnection | undefined;\n\nexport function bindWalletPlugin(plugin: WalletPlugin): void {\n activePlugin = plugin;\n}\n\nexport function bindWalletConnection(connection: unknown): void {\n activeConnection = connection as WalletHostConnection;\n}\n\nexport function resolveWalletPlugin(): WalletPlugin {\n if (!activePlugin) {\n throw new Error('Wallet plugin is not registered. Call registerWalletPlugin() during app bootstrap.');\n }\n return activePlugin;\n}\n\nexport function resolveWalletConnection(): WalletHostConnection {\n if (!activeConnection?.manager) {\n throw new Error('Wallet database connection is not registered. Pass host TypeORM Connection as dataSource.');\n }\n return activeConnection;\n}\n\nexport function clearWalletPluginForTests(): void {\n activePlugin = undefined;\n activeConnection = undefined;\n}\n","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","import { fromMinorUnit } from '../currency';\nimport { resolveWalletConnection } from '../plugin-instance';\nimport { WalletAccountEntity, WalletLedgerEntryEntity } from '../typeorm/entities';\n\nexport interface WalletParityDelta {\n orderId: number;\n vendorOrderId: number;\n vendorPaymentRupees: number;\n holdPaise: number;\n deltaRupees: number;\n}\n\nexport interface WalletCacheMismatch {\n accountId: number;\n cachedAvailable: number;\n cachedHeld: number;\n ledgerAvailable: number;\n ledgerHeld: number;\n}\n\nexport interface WalletReconciliationReport {\n parityDeltas: WalletParityDelta[];\n cacheMismatches: WalletCacheMismatch[];\n}\n\nexport async function runWalletReconciliation(): Promise<WalletReconciliationReport> {\n const parityDeltas = await findVendorPaymentHoldParityDeltas();\n const cacheMismatches = await findCacheLedgerMismatches();\n return { parityDeltas, cacheMismatches };\n}\n\nasync function findVendorPaymentHoldParityDeltas(): Promise<WalletParityDelta[]> {\n const rows = (await resolveWalletConnection().query(`\n SELECT\n vo.order_id AS orderId,\n vp.vendor_order_id AS vendorOrderId,\n vp.amount AS vendorPaymentAmount,\n wh.amount AS holdAmount,\n wh.status AS holdStatus\n FROM vendor_payment vp\n INNER JOIN vendor_orders vo ON vo.vendor_order_id = vp.vendor_order_id\n LEFT JOIN wallet_hold wh\n ON wh.reference_type = 'vendor_order'\n AND wh.reference_id = CAST(vp.vendor_order_id AS CHAR)\n WHERE vp.vendor_order_id IS NOT NULL\n `)) as Array<Record<string, unknown>>;\n\n const deltas: WalletParityDelta[] = [];\n for (const row of rows) {\n const vendorPaymentRupees = Number(row.vendorPaymentAmount) || 0;\n const holdPaise = row.holdAmount != null ? Number(row.holdAmount) : 0;\n const holdRupees = fromMinorUnit(holdPaise);\n const delta = Math.abs(vendorPaymentRupees - holdRupees);\n if (delta > 0.01 && row.holdStatus === 'active') {\n deltas.push({\n orderId: Number(row.orderId),\n vendorOrderId: Number(row.vendorOrderId),\n vendorPaymentRupees,\n holdPaise,\n deltaRupees: delta,\n });\n }\n }\n return deltas;\n}\n\nasync function findCacheLedgerMismatches(): Promise<WalletCacheMismatch[]> {\n const connection = resolveWalletConnection();\n const accounts = (await connection\n .getRepository(WalletAccountEntity)\n .find()) as WalletAccountEntity[];\n const mismatches: WalletCacheMismatch[] = [];\n\n for (const account of accounts) {\n const lastEntry = (await connection\n .getRepository(WalletLedgerEntryEntity)\n .findOne({\n where: { accountId: account.id },\n order: { id: 'DESC' },\n })) as WalletLedgerEntryEntity | null;\n if (!lastEntry) {\n continue;\n }\n const cachedAvailable = Number(account.availableBalance);\n const cachedHeld = Number(account.heldBalance);\n const ledgerAvailable = Number(lastEntry.balanceAfterAvailable);\n const ledgerHeld = Number(lastEntry.balanceAfterHeld);\n if (cachedAvailable !== ledgerAvailable || cachedHeld !== ledgerHeld) {\n mismatches.push({\n accountId: account.id,\n cachedAvailable,\n cachedHeld,\n ledgerAvailable,\n ledgerHeld,\n });\n }\n }\n return mismatches;\n}\n","import type { WalletLifecycleHooks } from './types';\nimport { createOrderHooks } from './order';\nimport { createRefundHooks } from './refund';\nimport { createSettlementHooks } from './settlement';\nimport type { HookRuntime } from './types';\n\nexport function createLifecycleHooks(runtime: HookRuntime): WalletLifecycleHooks {\n return {\n ...createOrderHooks(runtime),\n ...createSettlementHooks(runtime),\n ...createRefundHooks(runtime),\n };\n}\n\nexport type {\n DeliveredContext,\n OrderPaidContext,\n RefundContext,\n SettlementDebitContext,\n WalletLifecycleHooks,\n WalletOrderPaidLine,\n} from './types';\n\nexport { runWalletReconciliation } from './reconciliation';\nexport type {\n WalletCacheMismatch,\n WalletParityDelta,\n WalletReconciliationReport,\n} from './reconciliation';\n"]}
1
+ {"version":3,"sources":["../../src/currency.ts","../../src/orderCustomerDebit.ts","../../src/types.ts","../../src/hooks/order.ts","../../src/hooks/refund.ts","../../src/hooks/settlement.ts","../../src/plugin-instance.ts","../../src/timestamps.ts","../../src/typeorm/entities.ts","../../src/hooks/reconciliation.ts","../../src/hooks/index.ts"],"names":["toMinorUnit","amount","Math","round","fromMinorUnit","CUSTOMER_CHECKOUT_DEBIT_PURPOSE","orderCustomerDebitIdempotencyKey","orderId","WalletAccountType","isWalletOnlyPayment","paymentMethod","String","trim","toLowerCase","createOrderHooks","runtime","client","platformOwnerId","flags","onOrderPaid","ctx","enabled","ledgerWrites","txCtx","nativeTx","platform","getOrCreateAccount","PLATFORM","currency","orderTotalPaise","orderTotalRupees","shouldDebitCustomer","customerId","skipCustomerDebit","debitRupees","min","walletAmountRupees","customer","CUSTOMER","debit","accountId","id","idempotencyKey","reference","referenceType","referenceId","metadata","purpose","paymentNumber","credit","line","lines","vendorNetRupees","sellerNetRupees","Number","isFinite","commissionBaseRupees","commissionRupees","vendor","VENDOR","vendorId","hold","sourceAccountId","targetAccountId","vendorOrderId","onLineDelivered","release","undefined","isWalletPayment","walletCreditRupees","walletRefundRupees","lineTotalRupees","idempotencyPrefix","scope","idempotencyScope","orderProductId","refundReason","createRefundHooks","onRefund","processExternalRefund","keyPrefix","skipEscrow","sellerNetClawbackRupees","clawbackPaise","cancelHold","refundPaise","balance","getBalance","available","creditRupees","createSettlementHooks","_runtime","onSettlementDebit","_ctx","resolveWalletConnection","Error","pad2","value","padStart","nowTimestamp","date","Date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","WalletAccountEntity","ownerType","ownerId","availableBalance","heldBalance","createdBy","createdDate","modifiedBy","modifiedDate","setCreated","setModified","name","length","default","type","nullable","WalletLedgerEntryEntity","entryType","balanceAfterAvailable","balanceAfterHeld","unique","WalletHoldEntity","status","runWalletReconciliation","parityDeltas","findVendorPaymentHoldParityDeltas","cacheMismatches","findCacheLedgerMismatches","rows","query","deltas","row","vendorPaymentRupees","vendorPaymentAmount","holdPaise","holdAmount","holdRupees","delta","abs","holdStatus","push","deltaRupees","connection","accounts","getRepository","find","mismatches","account","lastEntry","findOne","where","order","cachedAvailable","cachedHeld","ledgerAvailable","ledgerHeld","createLifecycleHooks"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Convert decimal currency amount (e.g. rupees) to smallest unit (paise).\n */\nexport function toMinorUnit(amount: number): number {\n return Math.round(amount * 100);\n}\n\n/**\n * Convert smallest currency unit (paise) back to decimal amount (rupees).\n */\nexport function fromMinorUnit(amount: number): number {\n return amount / 100;\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","export enum WalletAccountType {\n CUSTOMER = 'customer',\n VENDOR = 'vendor',\n PLATFORM = 'platform',\n /** Investor cash wallet (interest/bonus/withdrawable). */\n INVESTOR = 'investor',\n /** Platform liability balancing investor principal/returns. */\n PLATFORM_INVESTOR_LIABILITY = 'platform_investor_liability',\n /** TDS withheld on investor returns pending remittance. */\n PLATFORM_TDS_PAYABLE = 'platform_tds_payable',\n}\n\nexport enum LedgerEntryType {\n CREDIT = 'credit',\n DEBIT = 'debit',\n HOLD = 'hold',\n RELEASE = 'release',\n CANCEL_HOLD = 'cancel_hold',\n TRANSFER = 'transfer',\n}\n\nexport enum HoldStatus {\n ACTIVE = 'active',\n RELEASED = 'released',\n CANCELLED = 'cancelled',\n}\n\nexport interface WalletReference {\n referenceType: string;\n referenceId: string;\n}\n\nexport interface WalletAccount {\n id: number;\n ownerType: WalletAccountType;\n ownerId: number;\n currency: string;\n availableBalance: number;\n heldBalance: number;\n}\n\nexport interface WalletBalance {\n available: number;\n held: number;\n total: number;\n}\n\nexport interface WalletLedgerEntry {\n id: number;\n accountId: number;\n entryType: LedgerEntryType;\n amount: number;\n balanceAfterAvailable: number;\n balanceAfterHeld: number;\n idempotencyKey: string;\n referenceType?: string;\n referenceId?: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n}\n\nexport interface WalletHold {\n id: number;\n sourceAccountId: number;\n targetAccountId: number;\n amount: number;\n status: HoldStatus;\n referenceType: string;\n referenceId: string;\n idempotencyKey: string;\n createdAt: Date;\n}\n\nexport interface BalanceDeltas {\n availableDelta?: number;\n heldDelta?: number;\n}\n\nexport interface CreditParams {\n accountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface DebitParams {\n accountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface HoldParams {\n sourceAccountId: number;\n targetAccountId: number;\n amount: number;\n idempotencyKey: string;\n reference: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ReleaseParams {\n reference: WalletReference;\n idempotencyKey: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CancelHoldParams {\n reference: WalletReference;\n idempotencyKey: string;\n metadata?: Record<string, unknown>;\n /** When set and less than the active hold, reduce the hold instead of cancelling it. */\n amount?: number;\n}\n\nexport interface TransferParams {\n fromAccountId: number;\n toAccountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GetTransactionsParams {\n accountId: number;\n limit?: number;\n offset?: number;\n}\n\nexport interface LedgerMutationResult {\n entry: WalletLedgerEntry;\n account: WalletAccount;\n hold?: WalletHold;\n}\n","import { toMinorUnit } from '../currency';\nimport {\n CUSTOMER_CHECKOUT_DEBIT_PURPOSE,\n orderCustomerDebitIdempotencyKey,\n} from '../orderCustomerDebit';\nimport { WalletAccountType } from '../types';\nimport type { DeliveredContext, HookRuntime, OrderPaidContext, WalletLifecycleHooks } from './types';\n\nfunction isWalletOnlyPayment(paymentMethod?: string): boolean {\n return String(paymentMethod ?? '').trim().toLowerCase() === 'wallet';\n}\n\nexport function createOrderHooks(runtime: HookRuntime): Pick<\n WalletLifecycleHooks,\n 'onOrderPaid' | 'onLineDelivered'\n> {\n const { client, platformOwnerId, flags } = runtime;\n\n return {\n async onOrderPaid(ctx: OrderPaidContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n return;\n }\n\n const txCtx = { nativeTx: ctx.nativeTx };\n const platform = await client.getOrCreateAccount(\n WalletAccountType.PLATFORM,\n platformOwnerId,\n ctx.currency,\n txCtx\n );\n\n const orderTotalPaise = toMinorUnit(ctx.orderTotalRupees);\n const shouldDebitCustomer =\n isWalletOnlyPayment(ctx.paymentMethod) &&\n ctx.customerId &&\n !ctx.skipCustomerDebit;\n\n if (shouldDebitCustomer) {\n const debitRupees = Math.min(\n ctx.walletAmountRupees ?? ctx.orderTotalRupees,\n ctx.orderTotalRupees\n );\n const customer = await client.getOrCreateAccount(\n WalletAccountType.CUSTOMER,\n ctx.customerId,\n ctx.currency,\n txCtx\n );\n await client.debit(\n {\n accountId: customer.id,\n amount: toMinorUnit(debitRupees),\n idempotencyKey: orderCustomerDebitIdempotencyKey(ctx.orderId),\n reference: { referenceType: 'order', referenceId: String(ctx.orderId) },\n metadata: { purpose: CUSTOMER_CHECKOUT_DEBIT_PURPOSE, paymentNumber: ctx.paymentNumber },\n },\n txCtx\n );\n }\n\n await client.credit(\n {\n accountId: platform.id,\n amount: orderTotalPaise,\n idempotencyKey: `payment:${ctx.paymentNumber}`,\n reference: { referenceType: 'order', referenceId: String(ctx.orderId) },\n },\n txCtx\n );\n\n for (const line of ctx.lines) {\n const vendorNetRupees =\n line.sellerNetRupees != null && Number.isFinite(Number(line.sellerNetRupees))\n ? Number(line.sellerNetRupees)\n : line.commissionBaseRupees - line.commissionRupees;\n if (vendorNetRupees <= 0) {\n continue;\n }\n\n const vendor = await client.getOrCreateAccount(\n WalletAccountType.VENDOR,\n line.vendorId,\n ctx.currency,\n txCtx\n );\n\n await client.hold(\n {\n sourceAccountId: platform.id,\n targetAccountId: vendor.id,\n amount: toMinorUnit(vendorNetRupees),\n idempotencyKey: `order:${ctx.orderId}:hold:vendorOrder:${line.vendorOrderId}`,\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(line.vendorOrderId),\n },\n },\n txCtx\n );\n }\n },\n\n async onLineDelivered(ctx: DeliveredContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n return;\n }\n\n await client.release(\n {\n reference: { referenceType: 'vendor_order', referenceId: String(ctx.vendorOrderId) },\n idempotencyKey: `vendorOrder:${ctx.vendorOrderId}:release`,\n },\n ctx.nativeTx != null ? { nativeTx: ctx.nativeTx } : undefined\n );\n },\n };\n}\n","import { toMinorUnit } from '../currency';\nimport { WalletAccountType } from '../types';\nimport type { HookRuntime, RefundContext, WalletLifecycleHooks } from './types';\n\nfunction isWalletPayment(paymentMethod?: string): boolean {\n return String(paymentMethod ?? '').trim().toLowerCase() === 'wallet';\n}\n\nfunction walletCreditRupees(ctx: RefundContext): number {\n if (ctx.walletRefundRupees != null && ctx.walletRefundRupees > 0) {\n return ctx.walletRefundRupees;\n }\n return isWalletPayment(ctx.paymentMethod) ? ctx.lineTotalRupees : 0;\n}\n\nfunction idempotencyPrefix(ctx: RefundContext): string {\n const scope = ctx.idempotencyScope ?? String(ctx.orderProductId);\n return ctx.refundReason === 'return' ? `return:${scope}` : `refund:${scope}`;\n}\n\nexport function createRefundHooks(runtime: HookRuntime): Pick<WalletLifecycleHooks, 'onRefund'> {\n const { client, platformOwnerId, flags } = runtime;\n\n return {\n async onRefund(ctx: RefundContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n await ctx.processExternalRefund();\n return;\n }\n\n const keyPrefix = idempotencyPrefix(ctx);\n\n if (!ctx.skipEscrow) {\n if (ctx.sellerNetClawbackRupees != null) {\n const clawbackPaise = toMinorUnit(ctx.sellerNetClawbackRupees);\n if (clawbackPaise > 0) {\n await client.cancelHold({\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(ctx.vendorOrderId),\n },\n idempotencyKey: `${keyPrefix}:cancel_hold`,\n amount: clawbackPaise,\n });\n }\n } else {\n await client.cancelHold({\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(ctx.vendorOrderId),\n },\n idempotencyKey: `${keyPrefix}:cancel_hold`,\n });\n }\n }\n\n const refundPaise = toMinorUnit(ctx.lineTotalRupees);\n if (refundPaise > 0) {\n const platform = await client.getOrCreateAccount(\n WalletAccountType.PLATFORM,\n platformOwnerId,\n ctx.currency\n );\n const balance = await client.getBalance(platform.id);\n if (balance.available >= refundPaise) {\n await client.debit({\n accountId: platform.id,\n amount: refundPaise,\n idempotencyKey: `${keyPrefix}:platform_debit`,\n reference: {\n referenceType: 'order_product',\n referenceId: String(ctx.orderProductId),\n },\n });\n }\n\n const creditRupees = walletCreditRupees(ctx);\n if (creditRupees > 0 && ctx.customerId) {\n const customer = await client.getOrCreateAccount(\n WalletAccountType.CUSTOMER,\n ctx.customerId,\n ctx.currency\n );\n await client.credit({\n accountId: customer.id,\n amount: toMinorUnit(creditRupees),\n idempotencyKey: `${keyPrefix}:customer_credit`,\n reference: {\n referenceType: 'order',\n referenceId: String(ctx.orderId ?? ctx.orderProductId),\n },\n });\n }\n }\n\n await ctx.processExternalRefund();\n },\n };\n}\n","import type { HookRuntime, SettlementDebitContext, WalletLifecycleHooks } from './types';\n\nexport function createSettlementHooks(\n _runtime: HookRuntime\n): Pick<WalletLifecycleHooks, 'onSettlementDebit'> {\n return {\n /** @deprecated Settlement wallet debits removed — vendor payouts use wallet payout requests. */\n async onSettlementDebit(_ctx: SettlementDebitContext): Promise<void> {\n return;\n },\n };\n}\n","import type { WalletPlugin } from './plugin-types';\n\nexport interface WalletHostConnection {\n manager: {\n transaction<T>(fn: (em: unknown) => Promise<T>): Promise<T>;\n };\n query(query: string, parameters?: unknown[]): Promise<unknown>;\n getRepository(entity: unknown): {\n find(options?: unknown): Promise<unknown[]>;\n findOne(options?: unknown): Promise<unknown | null>;\n };\n}\n\nlet activePlugin: WalletPlugin | undefined;\nlet activeConnection: WalletHostConnection | undefined;\n\nexport function bindWalletPlugin(plugin: WalletPlugin): void {\n activePlugin = plugin;\n}\n\nexport function bindWalletConnection(connection: unknown): void {\n activeConnection = connection as WalletHostConnection;\n}\n\nexport function resolveWalletPlugin(): WalletPlugin {\n if (!activePlugin) {\n throw new Error('Wallet plugin is not registered. Call registerWalletPlugin() during app bootstrap.');\n }\n return activePlugin;\n}\n\nexport function resolveWalletConnection(): WalletHostConnection {\n if (!activeConnection?.manager) {\n throw new Error('Wallet database connection is not registered. Pass host TypeORM Connection as dataSource.');\n }\n return activeConnection;\n}\n\nexport function clearWalletPluginForTests(): void {\n activePlugin = undefined;\n activeConnection = undefined;\n}\n","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","import { fromMinorUnit } from '../currency';\nimport { resolveWalletConnection } from '../plugin-instance';\nimport { WalletAccountEntity, WalletLedgerEntryEntity } from '../typeorm/entities';\n\nexport interface WalletParityDelta {\n orderId: number;\n vendorOrderId: number;\n vendorPaymentRupees: number;\n holdPaise: number;\n deltaRupees: number;\n}\n\nexport interface WalletCacheMismatch {\n accountId: number;\n cachedAvailable: number;\n cachedHeld: number;\n ledgerAvailable: number;\n ledgerHeld: number;\n}\n\nexport interface WalletReconciliationReport {\n parityDeltas: WalletParityDelta[];\n cacheMismatches: WalletCacheMismatch[];\n}\n\nexport async function runWalletReconciliation(): Promise<WalletReconciliationReport> {\n const parityDeltas = await findVendorPaymentHoldParityDeltas();\n const cacheMismatches = await findCacheLedgerMismatches();\n return { parityDeltas, cacheMismatches };\n}\n\nasync function findVendorPaymentHoldParityDeltas(): Promise<WalletParityDelta[]> {\n const rows = (await resolveWalletConnection().query(`\n SELECT\n vo.order_id AS orderId,\n vp.vendor_order_id AS vendorOrderId,\n vp.amount AS vendorPaymentAmount,\n wh.amount AS holdAmount,\n wh.status AS holdStatus\n FROM vendor_payment vp\n INNER JOIN vendor_orders vo ON vo.vendor_order_id = vp.vendor_order_id\n LEFT JOIN wallet_hold wh\n ON wh.reference_type = 'vendor_order'\n AND wh.reference_id = CAST(vp.vendor_order_id AS CHAR)\n WHERE vp.vendor_order_id IS NOT NULL\n `)) as Array<Record<string, unknown>>;\n\n const deltas: WalletParityDelta[] = [];\n for (const row of rows) {\n const vendorPaymentRupees = Number(row.vendorPaymentAmount) || 0;\n const holdPaise = row.holdAmount != null ? Number(row.holdAmount) : 0;\n const holdRupees = fromMinorUnit(holdPaise);\n const delta = Math.abs(vendorPaymentRupees - holdRupees);\n if (delta > 0.01 && row.holdStatus === 'active') {\n deltas.push({\n orderId: Number(row.orderId),\n vendorOrderId: Number(row.vendorOrderId),\n vendorPaymentRupees,\n holdPaise,\n deltaRupees: delta,\n });\n }\n }\n return deltas;\n}\n\nasync function findCacheLedgerMismatches(): Promise<WalletCacheMismatch[]> {\n const connection = resolveWalletConnection();\n const accounts = (await connection\n .getRepository(WalletAccountEntity)\n .find()) as WalletAccountEntity[];\n const mismatches: WalletCacheMismatch[] = [];\n\n for (const account of accounts) {\n const lastEntry = (await connection\n .getRepository(WalletLedgerEntryEntity)\n .findOne({\n where: { accountId: account.id },\n order: { id: 'DESC' },\n })) as WalletLedgerEntryEntity | null;\n if (!lastEntry) {\n continue;\n }\n const cachedAvailable = Number(account.availableBalance);\n const cachedHeld = Number(account.heldBalance);\n const ledgerAvailable = Number(lastEntry.balanceAfterAvailable);\n const ledgerHeld = Number(lastEntry.balanceAfterHeld);\n if (cachedAvailable !== ledgerAvailable || cachedHeld !== ledgerHeld) {\n mismatches.push({\n accountId: account.id,\n cachedAvailable,\n cachedHeld,\n ledgerAvailable,\n ledgerHeld,\n });\n }\n }\n return mismatches;\n}\n","import type { WalletLifecycleHooks } from './types';\nimport { createOrderHooks } from './order';\nimport { createRefundHooks } from './refund';\nimport { createSettlementHooks } from './settlement';\nimport type { HookRuntime } from './types';\n\nexport function createLifecycleHooks(runtime: HookRuntime): WalletLifecycleHooks {\n return {\n ...createOrderHooks(runtime),\n ...createSettlementHooks(runtime),\n ...createRefundHooks(runtime),\n };\n}\n\nexport type {\n DeliveredContext,\n OrderPaidContext,\n RefundContext,\n SettlementDebitContext,\n WalletLifecycleHooks,\n WalletOrderPaidLine,\n} from './types';\n\nexport { runWalletReconciliation } from './reconciliation';\nexport type {\n WalletCacheMismatch,\n WalletParityDelta,\n WalletReconciliationReport,\n} from './reconciliation';\n"]}
@@ -1,6 +1,6 @@
1
- import { H as HookRuntime, W as WalletLifecycleHooks } from '../types-D1Q4XCwx.mjs';
2
- export { D as DeliveredContext, O as OrderPaidContext, R as RefundContext, S as SettlementDebitContext, a as WalletCacheMismatch, b as WalletOrderPaidLine, c as WalletParityDelta, d as WalletReconciliationReport, r as runWalletReconciliation } from '../types-D1Q4XCwx.mjs';
3
- import '../store-nWCfzvwf.mjs';
1
+ import { H as HookRuntime, W as WalletLifecycleHooks } from '../types-D0mhOXHk.mjs';
2
+ export { D as DeliveredContext, O as OrderPaidContext, R as RefundContext, S as SettlementDebitContext, a as WalletCacheMismatch, b as WalletOrderPaidLine, c as WalletParityDelta, d as WalletReconciliationReport, r as runWalletReconciliation } from '../types-D0mhOXHk.mjs';
3
+ import '../store-vIkNzYjM.mjs';
4
4
 
5
5
  declare function createLifecycleHooks(runtime: HookRuntime): WalletLifecycleHooks;
6
6
 
@@ -1,6 +1,6 @@
1
- import { H as HookRuntime, W as WalletLifecycleHooks } from '../types-B4R1zaTK.js';
2
- export { D as DeliveredContext, O as OrderPaidContext, R as RefundContext, S as SettlementDebitContext, a as WalletCacheMismatch, b as WalletOrderPaidLine, c as WalletParityDelta, d as WalletReconciliationReport, r as runWalletReconciliation } from '../types-B4R1zaTK.js';
3
- import '../store-nWCfzvwf.js';
1
+ import { H as HookRuntime, W as WalletLifecycleHooks } from '../types-nBZ_GHJQ.js';
2
+ export { D as DeliveredContext, O as OrderPaidContext, R as RefundContext, S as SettlementDebitContext, a as WalletCacheMismatch, b as WalletOrderPaidLine, c as WalletParityDelta, d as WalletReconciliationReport, r as runWalletReconciliation } from '../types-nBZ_GHJQ.js';
3
+ import '../store-vIkNzYjM.js';
4
4
 
5
5
  declare function createLifecycleHooks(runtime: HookRuntime): WalletLifecycleHooks;
6
6
 
@@ -52,7 +52,7 @@ function createOrderHooks(runtime) {
52
52
  const orderTotalPaise = toMinorUnit(ctx.orderTotalRupees);
53
53
  const shouldDebitCustomer = isWalletOnlyPayment(ctx.paymentMethod) && ctx.customerId && !ctx.skipCustomerDebit;
54
54
  if (shouldDebitCustomer) {
55
- const debitRupees = ctx.walletAmountRupees ?? ctx.orderTotalRupees;
55
+ const debitRupees = Math.min(ctx.walletAmountRupees ?? ctx.orderTotalRupees, ctx.orderTotalRupees);
56
56
  const customer = await client.getOrCreateAccount(WalletAccountType.CUSTOMER, ctx.customerId, ctx.currency, txCtx);
57
57
  await client.debit({
58
58
  accountId: customer.id,
@@ -127,7 +127,7 @@ function walletCreditRupees(ctx) {
127
127
  __name(walletCreditRupees, "walletCreditRupees");
128
128
  function idempotencyPrefix(ctx) {
129
129
  const scope = ctx.idempotencyScope ?? String(ctx.orderProductId);
130
- return ctx.refundReason === "return" ? `return:${scope}` : `refund:${ctx.orderProductId}`;
130
+ return ctx.refundReason === "return" ? `return:${scope}` : `refund:${scope}`;
131
131
  }
132
132
  __name(idempotencyPrefix, "idempotencyPrefix");
133
133
  function createRefundHooks(runtime) {
@@ -140,13 +140,27 @@ function createRefundHooks(runtime) {
140
140
  }
141
141
  const keyPrefix = idempotencyPrefix(ctx);
142
142
  if (!ctx.skipEscrow) {
143
- await client.cancelHold({
144
- reference: {
145
- referenceType: "vendor_order",
146
- referenceId: String(ctx.vendorOrderId)
147
- },
148
- idempotencyKey: `${keyPrefix}:cancel_hold`
149
- });
143
+ if (ctx.sellerNetClawbackRupees != null) {
144
+ const clawbackPaise = toMinorUnit(ctx.sellerNetClawbackRupees);
145
+ if (clawbackPaise > 0) {
146
+ await client.cancelHold({
147
+ reference: {
148
+ referenceType: "vendor_order",
149
+ referenceId: String(ctx.vendorOrderId)
150
+ },
151
+ idempotencyKey: `${keyPrefix}:cancel_hold`,
152
+ amount: clawbackPaise
153
+ });
154
+ }
155
+ } else {
156
+ await client.cancelHold({
157
+ reference: {
158
+ referenceType: "vendor_order",
159
+ referenceId: String(ctx.vendorOrderId)
160
+ },
161
+ idempotencyKey: `${keyPrefix}:cancel_hold`
162
+ });
163
+ }
150
164
  }
151
165
  const refundPaise = toMinorUnit(ctx.lineTotalRupees);
152
166
  if (refundPaise > 0) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/currency.ts","../../src/orderCustomerDebit.ts","../../src/types.ts","../../src/hooks/order.ts","../../src/hooks/refund.ts","../../src/hooks/settlement.ts","../../src/plugin-instance.ts","../../src/timestamps.ts","../../src/typeorm/entities.ts","../../src/hooks/reconciliation.ts","../../src/hooks/index.ts"],"names":["toMinorUnit","amount","Math","round","fromMinorUnit","CUSTOMER_CHECKOUT_DEBIT_PURPOSE","orderCustomerDebitIdempotencyKey","orderId","WalletAccountType","isWalletOnlyPayment","paymentMethod","String","trim","toLowerCase","createOrderHooks","runtime","client","platformOwnerId","flags","onOrderPaid","ctx","enabled","ledgerWrites","txCtx","nativeTx","platform","getOrCreateAccount","PLATFORM","currency","orderTotalPaise","orderTotalRupees","shouldDebitCustomer","customerId","skipCustomerDebit","debitRupees","walletAmountRupees","customer","CUSTOMER","debit","accountId","id","idempotencyKey","reference","referenceType","referenceId","metadata","purpose","paymentNumber","credit","line","lines","vendorNetRupees","sellerNetRupees","Number","isFinite","commissionBaseRupees","commissionRupees","vendor","VENDOR","vendorId","hold","sourceAccountId","targetAccountId","vendorOrderId","onLineDelivered","release","undefined","isWalletPayment","walletCreditRupees","walletRefundRupees","lineTotalRupees","idempotencyPrefix","scope","idempotencyScope","orderProductId","refundReason","createRefundHooks","onRefund","processExternalRefund","keyPrefix","skipEscrow","cancelHold","refundPaise","balance","getBalance","available","creditRupees","createSettlementHooks","_runtime","onSettlementDebit","_ctx","resolveWalletConnection","Error","pad2","value","padStart","nowTimestamp","date","Date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","WalletAccountEntity","ownerType","ownerId","availableBalance","heldBalance","createdBy","createdDate","modifiedBy","modifiedDate","setCreated","setModified","name","length","default","type","nullable","WalletLedgerEntryEntity","entryType","balanceAfterAvailable","balanceAfterHeld","unique","WalletHoldEntity","status","runWalletReconciliation","parityDeltas","findVendorPaymentHoldParityDeltas","cacheMismatches","findCacheLedgerMismatches","rows","query","deltas","row","vendorPaymentRupees","vendorPaymentAmount","holdPaise","holdAmount","holdRupees","delta","abs","holdStatus","push","deltaRupees","connection","accounts","getRepository","find","mismatches","account","lastEntry","findOne","where","order","cachedAvailable","cachedHeld","ledgerAvailable","ledgerHeld","createLifecycleHooks"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Convert decimal currency amount (e.g. rupees) to smallest unit (paise).\n */\nexport function toMinorUnit(amount: number): number {\n return Math.round(amount * 100);\n}\n\n/**\n * Convert smallest currency unit (paise) back to decimal amount (rupees).\n */\nexport function fromMinorUnit(amount: number): number {\n return amount / 100;\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","export enum WalletAccountType {\n CUSTOMER = 'customer',\n VENDOR = 'vendor',\n PLATFORM = 'platform',\n /** Investor cash wallet (interest/bonus/withdrawable). */\n INVESTOR = 'investor',\n /** Platform liability balancing investor principal/returns. */\n PLATFORM_INVESTOR_LIABILITY = 'platform_investor_liability',\n /** TDS withheld on investor returns pending remittance. */\n PLATFORM_TDS_PAYABLE = 'platform_tds_payable',\n}\n\nexport enum LedgerEntryType {\n CREDIT = 'credit',\n DEBIT = 'debit',\n HOLD = 'hold',\n RELEASE = 'release',\n CANCEL_HOLD = 'cancel_hold',\n TRANSFER = 'transfer',\n}\n\nexport enum HoldStatus {\n ACTIVE = 'active',\n RELEASED = 'released',\n CANCELLED = 'cancelled',\n}\n\nexport interface WalletReference {\n referenceType: string;\n referenceId: string;\n}\n\nexport interface WalletAccount {\n id: number;\n ownerType: WalletAccountType;\n ownerId: number;\n currency: string;\n availableBalance: number;\n heldBalance: number;\n}\n\nexport interface WalletBalance {\n available: number;\n held: number;\n total: number;\n}\n\nexport interface WalletLedgerEntry {\n id: number;\n accountId: number;\n entryType: LedgerEntryType;\n amount: number;\n balanceAfterAvailable: number;\n balanceAfterHeld: number;\n idempotencyKey: string;\n referenceType?: string;\n referenceId?: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n}\n\nexport interface WalletHold {\n id: number;\n sourceAccountId: number;\n targetAccountId: number;\n amount: number;\n status: HoldStatus;\n referenceType: string;\n referenceId: string;\n idempotencyKey: string;\n createdAt: Date;\n}\n\nexport interface BalanceDeltas {\n availableDelta?: number;\n heldDelta?: number;\n}\n\nexport interface CreditParams {\n accountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface DebitParams {\n accountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface HoldParams {\n sourceAccountId: number;\n targetAccountId: number;\n amount: number;\n idempotencyKey: string;\n reference: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ReleaseParams {\n reference: WalletReference;\n idempotencyKey: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CancelHoldParams {\n reference: WalletReference;\n idempotencyKey: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface TransferParams {\n fromAccountId: number;\n toAccountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GetTransactionsParams {\n accountId: number;\n limit?: number;\n offset?: number;\n}\n\nexport interface LedgerMutationResult {\n entry: WalletLedgerEntry;\n account: WalletAccount;\n hold?: WalletHold;\n}\n","import { toMinorUnit } from '../currency';\nimport {\n CUSTOMER_CHECKOUT_DEBIT_PURPOSE,\n orderCustomerDebitIdempotencyKey,\n} from '../orderCustomerDebit';\nimport { WalletAccountType } from '../types';\nimport type { DeliveredContext, HookRuntime, OrderPaidContext, WalletLifecycleHooks } from './types';\n\nfunction isWalletOnlyPayment(paymentMethod?: string): boolean {\n return String(paymentMethod ?? '').trim().toLowerCase() === 'wallet';\n}\n\nexport function createOrderHooks(runtime: HookRuntime): Pick<\n WalletLifecycleHooks,\n 'onOrderPaid' | 'onLineDelivered'\n> {\n const { client, platformOwnerId, flags } = runtime;\n\n return {\n async onOrderPaid(ctx: OrderPaidContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n return;\n }\n\n const txCtx = { nativeTx: ctx.nativeTx };\n const platform = await client.getOrCreateAccount(\n WalletAccountType.PLATFORM,\n platformOwnerId,\n ctx.currency,\n txCtx\n );\n\n const orderTotalPaise = toMinorUnit(ctx.orderTotalRupees);\n const shouldDebitCustomer =\n isWalletOnlyPayment(ctx.paymentMethod) &&\n ctx.customerId &&\n !ctx.skipCustomerDebit;\n\n if (shouldDebitCustomer) {\n const debitRupees = ctx.walletAmountRupees ?? ctx.orderTotalRupees;\n const customer = await client.getOrCreateAccount(\n WalletAccountType.CUSTOMER,\n ctx.customerId,\n ctx.currency,\n txCtx\n );\n await client.debit(\n {\n accountId: customer.id,\n amount: toMinorUnit(debitRupees),\n idempotencyKey: orderCustomerDebitIdempotencyKey(ctx.orderId),\n reference: { referenceType: 'order', referenceId: String(ctx.orderId) },\n metadata: { purpose: CUSTOMER_CHECKOUT_DEBIT_PURPOSE, paymentNumber: ctx.paymentNumber },\n },\n txCtx\n );\n }\n\n await client.credit(\n {\n accountId: platform.id,\n amount: orderTotalPaise,\n idempotencyKey: `payment:${ctx.paymentNumber}`,\n reference: { referenceType: 'order', referenceId: String(ctx.orderId) },\n },\n txCtx\n );\n\n for (const line of ctx.lines) {\n const vendorNetRupees =\n line.sellerNetRupees != null && Number.isFinite(Number(line.sellerNetRupees))\n ? Number(line.sellerNetRupees)\n : line.commissionBaseRupees - line.commissionRupees;\n if (vendorNetRupees <= 0) {\n continue;\n }\n\n const vendor = await client.getOrCreateAccount(\n WalletAccountType.VENDOR,\n line.vendorId,\n ctx.currency,\n txCtx\n );\n\n await client.hold(\n {\n sourceAccountId: platform.id,\n targetAccountId: vendor.id,\n amount: toMinorUnit(vendorNetRupees),\n idempotencyKey: `order:${ctx.orderId}:hold:vendorOrder:${line.vendorOrderId}`,\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(line.vendorOrderId),\n },\n },\n txCtx\n );\n }\n },\n\n async onLineDelivered(ctx: DeliveredContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n return;\n }\n\n await client.release(\n {\n reference: { referenceType: 'vendor_order', referenceId: String(ctx.vendorOrderId) },\n idempotencyKey: `vendorOrder:${ctx.vendorOrderId}:release`,\n },\n ctx.nativeTx != null ? { nativeTx: ctx.nativeTx } : undefined\n );\n },\n };\n}\n","import { toMinorUnit } from '../currency';\nimport { WalletAccountType } from '../types';\nimport type { HookRuntime, RefundContext, WalletLifecycleHooks } from './types';\n\nfunction isWalletPayment(paymentMethod?: string): boolean {\n return String(paymentMethod ?? '').trim().toLowerCase() === 'wallet';\n}\n\nfunction walletCreditRupees(ctx: RefundContext): number {\n if (ctx.walletRefundRupees != null && ctx.walletRefundRupees > 0) {\n return ctx.walletRefundRupees;\n }\n return isWalletPayment(ctx.paymentMethod) ? ctx.lineTotalRupees : 0;\n}\n\nfunction idempotencyPrefix(ctx: RefundContext): string {\n const scope = ctx.idempotencyScope ?? String(ctx.orderProductId);\n return ctx.refundReason === 'return' ? `return:${scope}` : `refund:${ctx.orderProductId}`;\n}\n\nexport function createRefundHooks(runtime: HookRuntime): Pick<WalletLifecycleHooks, 'onRefund'> {\n const { client, platformOwnerId, flags } = runtime;\n\n return {\n async onRefund(ctx: RefundContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n await ctx.processExternalRefund();\n return;\n }\n\n const keyPrefix = idempotencyPrefix(ctx);\n\n if (!ctx.skipEscrow) {\n await client.cancelHold({\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(ctx.vendorOrderId),\n },\n idempotencyKey: `${keyPrefix}:cancel_hold`,\n });\n }\n\n const refundPaise = toMinorUnit(ctx.lineTotalRupees);\n if (refundPaise > 0) {\n const platform = await client.getOrCreateAccount(\n WalletAccountType.PLATFORM,\n platformOwnerId,\n ctx.currency\n );\n const balance = await client.getBalance(platform.id);\n if (balance.available >= refundPaise) {\n await client.debit({\n accountId: platform.id,\n amount: refundPaise,\n idempotencyKey: `${keyPrefix}:platform_debit`,\n reference: {\n referenceType: 'order_product',\n referenceId: String(ctx.orderProductId),\n },\n });\n }\n\n const creditRupees = walletCreditRupees(ctx);\n if (creditRupees > 0 && ctx.customerId) {\n const customer = await client.getOrCreateAccount(\n WalletAccountType.CUSTOMER,\n ctx.customerId,\n ctx.currency\n );\n await client.credit({\n accountId: customer.id,\n amount: toMinorUnit(creditRupees),\n idempotencyKey: `${keyPrefix}:customer_credit`,\n reference: {\n referenceType: 'order',\n referenceId: String(ctx.orderId ?? ctx.orderProductId),\n },\n });\n }\n }\n\n await ctx.processExternalRefund();\n },\n };\n}\n","import type { HookRuntime, SettlementDebitContext, WalletLifecycleHooks } from './types';\n\nexport function createSettlementHooks(\n _runtime: HookRuntime\n): Pick<WalletLifecycleHooks, 'onSettlementDebit'> {\n return {\n /** @deprecated Settlement wallet debits removed — vendor payouts use wallet payout requests. */\n async onSettlementDebit(_ctx: SettlementDebitContext): Promise<void> {\n return;\n },\n };\n}\n","import type { WalletPlugin } from './plugin-types';\n\nexport interface WalletHostConnection {\n manager: {\n transaction<T>(fn: (em: unknown) => Promise<T>): Promise<T>;\n };\n query(query: string, parameters?: unknown[]): Promise<unknown>;\n getRepository(entity: unknown): {\n find(options?: unknown): Promise<unknown[]>;\n findOne(options?: unknown): Promise<unknown | null>;\n };\n}\n\nlet activePlugin: WalletPlugin | undefined;\nlet activeConnection: WalletHostConnection | undefined;\n\nexport function bindWalletPlugin(plugin: WalletPlugin): void {\n activePlugin = plugin;\n}\n\nexport function bindWalletConnection(connection: unknown): void {\n activeConnection = connection as WalletHostConnection;\n}\n\nexport function resolveWalletPlugin(): WalletPlugin {\n if (!activePlugin) {\n throw new Error('Wallet plugin is not registered. Call registerWalletPlugin() during app bootstrap.');\n }\n return activePlugin;\n}\n\nexport function resolveWalletConnection(): WalletHostConnection {\n if (!activeConnection?.manager) {\n throw new Error('Wallet database connection is not registered. Pass host TypeORM Connection as dataSource.');\n }\n return activeConnection;\n}\n\nexport function clearWalletPluginForTests(): void {\n activePlugin = undefined;\n activeConnection = undefined;\n}\n","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","import { fromMinorUnit } from '../currency';\nimport { resolveWalletConnection } from '../plugin-instance';\nimport { WalletAccountEntity, WalletLedgerEntryEntity } from '../typeorm/entities';\n\nexport interface WalletParityDelta {\n orderId: number;\n vendorOrderId: number;\n vendorPaymentRupees: number;\n holdPaise: number;\n deltaRupees: number;\n}\n\nexport interface WalletCacheMismatch {\n accountId: number;\n cachedAvailable: number;\n cachedHeld: number;\n ledgerAvailable: number;\n ledgerHeld: number;\n}\n\nexport interface WalletReconciliationReport {\n parityDeltas: WalletParityDelta[];\n cacheMismatches: WalletCacheMismatch[];\n}\n\nexport async function runWalletReconciliation(): Promise<WalletReconciliationReport> {\n const parityDeltas = await findVendorPaymentHoldParityDeltas();\n const cacheMismatches = await findCacheLedgerMismatches();\n return { parityDeltas, cacheMismatches };\n}\n\nasync function findVendorPaymentHoldParityDeltas(): Promise<WalletParityDelta[]> {\n const rows = (await resolveWalletConnection().query(`\n SELECT\n vo.order_id AS orderId,\n vp.vendor_order_id AS vendorOrderId,\n vp.amount AS vendorPaymentAmount,\n wh.amount AS holdAmount,\n wh.status AS holdStatus\n FROM vendor_payment vp\n INNER JOIN vendor_orders vo ON vo.vendor_order_id = vp.vendor_order_id\n LEFT JOIN wallet_hold wh\n ON wh.reference_type = 'vendor_order'\n AND wh.reference_id = CAST(vp.vendor_order_id AS CHAR)\n WHERE vp.vendor_order_id IS NOT NULL\n `)) as Array<Record<string, unknown>>;\n\n const deltas: WalletParityDelta[] = [];\n for (const row of rows) {\n const vendorPaymentRupees = Number(row.vendorPaymentAmount) || 0;\n const holdPaise = row.holdAmount != null ? Number(row.holdAmount) : 0;\n const holdRupees = fromMinorUnit(holdPaise);\n const delta = Math.abs(vendorPaymentRupees - holdRupees);\n if (delta > 0.01 && row.holdStatus === 'active') {\n deltas.push({\n orderId: Number(row.orderId),\n vendorOrderId: Number(row.vendorOrderId),\n vendorPaymentRupees,\n holdPaise,\n deltaRupees: delta,\n });\n }\n }\n return deltas;\n}\n\nasync function findCacheLedgerMismatches(): Promise<WalletCacheMismatch[]> {\n const connection = resolveWalletConnection();\n const accounts = (await connection\n .getRepository(WalletAccountEntity)\n .find()) as WalletAccountEntity[];\n const mismatches: WalletCacheMismatch[] = [];\n\n for (const account of accounts) {\n const lastEntry = (await connection\n .getRepository(WalletLedgerEntryEntity)\n .findOne({\n where: { accountId: account.id },\n order: { id: 'DESC' },\n })) as WalletLedgerEntryEntity | null;\n if (!lastEntry) {\n continue;\n }\n const cachedAvailable = Number(account.availableBalance);\n const cachedHeld = Number(account.heldBalance);\n const ledgerAvailable = Number(lastEntry.balanceAfterAvailable);\n const ledgerHeld = Number(lastEntry.balanceAfterHeld);\n if (cachedAvailable !== ledgerAvailable || cachedHeld !== ledgerHeld) {\n mismatches.push({\n accountId: account.id,\n cachedAvailable,\n cachedHeld,\n ledgerAvailable,\n ledgerHeld,\n });\n }\n }\n return mismatches;\n}\n","import type { WalletLifecycleHooks } from './types';\nimport { createOrderHooks } from './order';\nimport { createRefundHooks } from './refund';\nimport { createSettlementHooks } from './settlement';\nimport type { HookRuntime } from './types';\n\nexport function createLifecycleHooks(runtime: HookRuntime): WalletLifecycleHooks {\n return {\n ...createOrderHooks(runtime),\n ...createSettlementHooks(runtime),\n ...createRefundHooks(runtime),\n };\n}\n\nexport type {\n DeliveredContext,\n OrderPaidContext,\n RefundContext,\n SettlementDebitContext,\n WalletLifecycleHooks,\n WalletOrderPaidLine,\n} from './types';\n\nexport { runWalletReconciliation } from './reconciliation';\nexport type {\n WalletCacheMismatch,\n WalletParityDelta,\n WalletReconciliationReport,\n} from './reconciliation';\n"]}
1
+ {"version":3,"sources":["../../src/currency.ts","../../src/orderCustomerDebit.ts","../../src/types.ts","../../src/hooks/order.ts","../../src/hooks/refund.ts","../../src/hooks/settlement.ts","../../src/plugin-instance.ts","../../src/timestamps.ts","../../src/typeorm/entities.ts","../../src/hooks/reconciliation.ts","../../src/hooks/index.ts"],"names":["toMinorUnit","amount","Math","round","fromMinorUnit","CUSTOMER_CHECKOUT_DEBIT_PURPOSE","orderCustomerDebitIdempotencyKey","orderId","WalletAccountType","isWalletOnlyPayment","paymentMethod","String","trim","toLowerCase","createOrderHooks","runtime","client","platformOwnerId","flags","onOrderPaid","ctx","enabled","ledgerWrites","txCtx","nativeTx","platform","getOrCreateAccount","PLATFORM","currency","orderTotalPaise","orderTotalRupees","shouldDebitCustomer","customerId","skipCustomerDebit","debitRupees","min","walletAmountRupees","customer","CUSTOMER","debit","accountId","id","idempotencyKey","reference","referenceType","referenceId","metadata","purpose","paymentNumber","credit","line","lines","vendorNetRupees","sellerNetRupees","Number","isFinite","commissionBaseRupees","commissionRupees","vendor","VENDOR","vendorId","hold","sourceAccountId","targetAccountId","vendorOrderId","onLineDelivered","release","undefined","isWalletPayment","walletCreditRupees","walletRefundRupees","lineTotalRupees","idempotencyPrefix","scope","idempotencyScope","orderProductId","refundReason","createRefundHooks","onRefund","processExternalRefund","keyPrefix","skipEscrow","sellerNetClawbackRupees","clawbackPaise","cancelHold","refundPaise","balance","getBalance","available","creditRupees","createSettlementHooks","_runtime","onSettlementDebit","_ctx","resolveWalletConnection","Error","pad2","value","padStart","nowTimestamp","date","Date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","WalletAccountEntity","ownerType","ownerId","availableBalance","heldBalance","createdBy","createdDate","modifiedBy","modifiedDate","setCreated","setModified","name","length","default","type","nullable","WalletLedgerEntryEntity","entryType","balanceAfterAvailable","balanceAfterHeld","unique","WalletHoldEntity","status","runWalletReconciliation","parityDeltas","findVendorPaymentHoldParityDeltas","cacheMismatches","findCacheLedgerMismatches","rows","query","deltas","row","vendorPaymentRupees","vendorPaymentAmount","holdPaise","holdAmount","holdRupees","delta","abs","holdStatus","push","deltaRupees","connection","accounts","getRepository","find","mismatches","account","lastEntry","findOne","where","order","cachedAvailable","cachedHeld","ledgerAvailable","ledgerHeld","createLifecycleHooks"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Convert decimal currency amount (e.g. rupees) to smallest unit (paise).\n */\nexport function toMinorUnit(amount: number): number {\n return Math.round(amount * 100);\n}\n\n/**\n * Convert smallest currency unit (paise) back to decimal amount (rupees).\n */\nexport function fromMinorUnit(amount: number): number {\n return amount / 100;\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","export enum WalletAccountType {\n CUSTOMER = 'customer',\n VENDOR = 'vendor',\n PLATFORM = 'platform',\n /** Investor cash wallet (interest/bonus/withdrawable). */\n INVESTOR = 'investor',\n /** Platform liability balancing investor principal/returns. */\n PLATFORM_INVESTOR_LIABILITY = 'platform_investor_liability',\n /** TDS withheld on investor returns pending remittance. */\n PLATFORM_TDS_PAYABLE = 'platform_tds_payable',\n}\n\nexport enum LedgerEntryType {\n CREDIT = 'credit',\n DEBIT = 'debit',\n HOLD = 'hold',\n RELEASE = 'release',\n CANCEL_HOLD = 'cancel_hold',\n TRANSFER = 'transfer',\n}\n\nexport enum HoldStatus {\n ACTIVE = 'active',\n RELEASED = 'released',\n CANCELLED = 'cancelled',\n}\n\nexport interface WalletReference {\n referenceType: string;\n referenceId: string;\n}\n\nexport interface WalletAccount {\n id: number;\n ownerType: WalletAccountType;\n ownerId: number;\n currency: string;\n availableBalance: number;\n heldBalance: number;\n}\n\nexport interface WalletBalance {\n available: number;\n held: number;\n total: number;\n}\n\nexport interface WalletLedgerEntry {\n id: number;\n accountId: number;\n entryType: LedgerEntryType;\n amount: number;\n balanceAfterAvailable: number;\n balanceAfterHeld: number;\n idempotencyKey: string;\n referenceType?: string;\n referenceId?: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n}\n\nexport interface WalletHold {\n id: number;\n sourceAccountId: number;\n targetAccountId: number;\n amount: number;\n status: HoldStatus;\n referenceType: string;\n referenceId: string;\n idempotencyKey: string;\n createdAt: Date;\n}\n\nexport interface BalanceDeltas {\n availableDelta?: number;\n heldDelta?: number;\n}\n\nexport interface CreditParams {\n accountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface DebitParams {\n accountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface HoldParams {\n sourceAccountId: number;\n targetAccountId: number;\n amount: number;\n idempotencyKey: string;\n reference: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ReleaseParams {\n reference: WalletReference;\n idempotencyKey: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CancelHoldParams {\n reference: WalletReference;\n idempotencyKey: string;\n metadata?: Record<string, unknown>;\n /** When set and less than the active hold, reduce the hold instead of cancelling it. */\n amount?: number;\n}\n\nexport interface TransferParams {\n fromAccountId: number;\n toAccountId: number;\n amount: number;\n idempotencyKey: string;\n reference?: WalletReference;\n metadata?: Record<string, unknown>;\n}\n\nexport interface GetTransactionsParams {\n accountId: number;\n limit?: number;\n offset?: number;\n}\n\nexport interface LedgerMutationResult {\n entry: WalletLedgerEntry;\n account: WalletAccount;\n hold?: WalletHold;\n}\n","import { toMinorUnit } from '../currency';\nimport {\n CUSTOMER_CHECKOUT_DEBIT_PURPOSE,\n orderCustomerDebitIdempotencyKey,\n} from '../orderCustomerDebit';\nimport { WalletAccountType } from '../types';\nimport type { DeliveredContext, HookRuntime, OrderPaidContext, WalletLifecycleHooks } from './types';\n\nfunction isWalletOnlyPayment(paymentMethod?: string): boolean {\n return String(paymentMethod ?? '').trim().toLowerCase() === 'wallet';\n}\n\nexport function createOrderHooks(runtime: HookRuntime): Pick<\n WalletLifecycleHooks,\n 'onOrderPaid' | 'onLineDelivered'\n> {\n const { client, platformOwnerId, flags } = runtime;\n\n return {\n async onOrderPaid(ctx: OrderPaidContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n return;\n }\n\n const txCtx = { nativeTx: ctx.nativeTx };\n const platform = await client.getOrCreateAccount(\n WalletAccountType.PLATFORM,\n platformOwnerId,\n ctx.currency,\n txCtx\n );\n\n const orderTotalPaise = toMinorUnit(ctx.orderTotalRupees);\n const shouldDebitCustomer =\n isWalletOnlyPayment(ctx.paymentMethod) &&\n ctx.customerId &&\n !ctx.skipCustomerDebit;\n\n if (shouldDebitCustomer) {\n const debitRupees = Math.min(\n ctx.walletAmountRupees ?? ctx.orderTotalRupees,\n ctx.orderTotalRupees\n );\n const customer = await client.getOrCreateAccount(\n WalletAccountType.CUSTOMER,\n ctx.customerId,\n ctx.currency,\n txCtx\n );\n await client.debit(\n {\n accountId: customer.id,\n amount: toMinorUnit(debitRupees),\n idempotencyKey: orderCustomerDebitIdempotencyKey(ctx.orderId),\n reference: { referenceType: 'order', referenceId: String(ctx.orderId) },\n metadata: { purpose: CUSTOMER_CHECKOUT_DEBIT_PURPOSE, paymentNumber: ctx.paymentNumber },\n },\n txCtx\n );\n }\n\n await client.credit(\n {\n accountId: platform.id,\n amount: orderTotalPaise,\n idempotencyKey: `payment:${ctx.paymentNumber}`,\n reference: { referenceType: 'order', referenceId: String(ctx.orderId) },\n },\n txCtx\n );\n\n for (const line of ctx.lines) {\n const vendorNetRupees =\n line.sellerNetRupees != null && Number.isFinite(Number(line.sellerNetRupees))\n ? Number(line.sellerNetRupees)\n : line.commissionBaseRupees - line.commissionRupees;\n if (vendorNetRupees <= 0) {\n continue;\n }\n\n const vendor = await client.getOrCreateAccount(\n WalletAccountType.VENDOR,\n line.vendorId,\n ctx.currency,\n txCtx\n );\n\n await client.hold(\n {\n sourceAccountId: platform.id,\n targetAccountId: vendor.id,\n amount: toMinorUnit(vendorNetRupees),\n idempotencyKey: `order:${ctx.orderId}:hold:vendorOrder:${line.vendorOrderId}`,\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(line.vendorOrderId),\n },\n },\n txCtx\n );\n }\n },\n\n async onLineDelivered(ctx: DeliveredContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n return;\n }\n\n await client.release(\n {\n reference: { referenceType: 'vendor_order', referenceId: String(ctx.vendorOrderId) },\n idempotencyKey: `vendorOrder:${ctx.vendorOrderId}:release`,\n },\n ctx.nativeTx != null ? { nativeTx: ctx.nativeTx } : undefined\n );\n },\n };\n}\n","import { toMinorUnit } from '../currency';\nimport { WalletAccountType } from '../types';\nimport type { HookRuntime, RefundContext, WalletLifecycleHooks } from './types';\n\nfunction isWalletPayment(paymentMethod?: string): boolean {\n return String(paymentMethod ?? '').trim().toLowerCase() === 'wallet';\n}\n\nfunction walletCreditRupees(ctx: RefundContext): number {\n if (ctx.walletRefundRupees != null && ctx.walletRefundRupees > 0) {\n return ctx.walletRefundRupees;\n }\n return isWalletPayment(ctx.paymentMethod) ? ctx.lineTotalRupees : 0;\n}\n\nfunction idempotencyPrefix(ctx: RefundContext): string {\n const scope = ctx.idempotencyScope ?? String(ctx.orderProductId);\n return ctx.refundReason === 'return' ? `return:${scope}` : `refund:${scope}`;\n}\n\nexport function createRefundHooks(runtime: HookRuntime): Pick<WalletLifecycleHooks, 'onRefund'> {\n const { client, platformOwnerId, flags } = runtime;\n\n return {\n async onRefund(ctx: RefundContext): Promise<void> {\n if (!flags.enabled || !flags.ledgerWrites) {\n await ctx.processExternalRefund();\n return;\n }\n\n const keyPrefix = idempotencyPrefix(ctx);\n\n if (!ctx.skipEscrow) {\n if (ctx.sellerNetClawbackRupees != null) {\n const clawbackPaise = toMinorUnit(ctx.sellerNetClawbackRupees);\n if (clawbackPaise > 0) {\n await client.cancelHold({\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(ctx.vendorOrderId),\n },\n idempotencyKey: `${keyPrefix}:cancel_hold`,\n amount: clawbackPaise,\n });\n }\n } else {\n await client.cancelHold({\n reference: {\n referenceType: 'vendor_order',\n referenceId: String(ctx.vendorOrderId),\n },\n idempotencyKey: `${keyPrefix}:cancel_hold`,\n });\n }\n }\n\n const refundPaise = toMinorUnit(ctx.lineTotalRupees);\n if (refundPaise > 0) {\n const platform = await client.getOrCreateAccount(\n WalletAccountType.PLATFORM,\n platformOwnerId,\n ctx.currency\n );\n const balance = await client.getBalance(platform.id);\n if (balance.available >= refundPaise) {\n await client.debit({\n accountId: platform.id,\n amount: refundPaise,\n idempotencyKey: `${keyPrefix}:platform_debit`,\n reference: {\n referenceType: 'order_product',\n referenceId: String(ctx.orderProductId),\n },\n });\n }\n\n const creditRupees = walletCreditRupees(ctx);\n if (creditRupees > 0 && ctx.customerId) {\n const customer = await client.getOrCreateAccount(\n WalletAccountType.CUSTOMER,\n ctx.customerId,\n ctx.currency\n );\n await client.credit({\n accountId: customer.id,\n amount: toMinorUnit(creditRupees),\n idempotencyKey: `${keyPrefix}:customer_credit`,\n reference: {\n referenceType: 'order',\n referenceId: String(ctx.orderId ?? ctx.orderProductId),\n },\n });\n }\n }\n\n await ctx.processExternalRefund();\n },\n };\n}\n","import type { HookRuntime, SettlementDebitContext, WalletLifecycleHooks } from './types';\n\nexport function createSettlementHooks(\n _runtime: HookRuntime\n): Pick<WalletLifecycleHooks, 'onSettlementDebit'> {\n return {\n /** @deprecated Settlement wallet debits removed — vendor payouts use wallet payout requests. */\n async onSettlementDebit(_ctx: SettlementDebitContext): Promise<void> {\n return;\n },\n };\n}\n","import type { WalletPlugin } from './plugin-types';\n\nexport interface WalletHostConnection {\n manager: {\n transaction<T>(fn: (em: unknown) => Promise<T>): Promise<T>;\n };\n query(query: string, parameters?: unknown[]): Promise<unknown>;\n getRepository(entity: unknown): {\n find(options?: unknown): Promise<unknown[]>;\n findOne(options?: unknown): Promise<unknown | null>;\n };\n}\n\nlet activePlugin: WalletPlugin | undefined;\nlet activeConnection: WalletHostConnection | undefined;\n\nexport function bindWalletPlugin(plugin: WalletPlugin): void {\n activePlugin = plugin;\n}\n\nexport function bindWalletConnection(connection: unknown): void {\n activeConnection = connection as WalletHostConnection;\n}\n\nexport function resolveWalletPlugin(): WalletPlugin {\n if (!activePlugin) {\n throw new Error('Wallet plugin is not registered. Call registerWalletPlugin() during app bootstrap.');\n }\n return activePlugin;\n}\n\nexport function resolveWalletConnection(): WalletHostConnection {\n if (!activeConnection?.manager) {\n throw new Error('Wallet database connection is not registered. Pass host TypeORM Connection as dataSource.');\n }\n return activeConnection;\n}\n\nexport function clearWalletPluginForTests(): void {\n activePlugin = undefined;\n activeConnection = undefined;\n}\n","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","import { fromMinorUnit } from '../currency';\nimport { resolveWalletConnection } from '../plugin-instance';\nimport { WalletAccountEntity, WalletLedgerEntryEntity } from '../typeorm/entities';\n\nexport interface WalletParityDelta {\n orderId: number;\n vendorOrderId: number;\n vendorPaymentRupees: number;\n holdPaise: number;\n deltaRupees: number;\n}\n\nexport interface WalletCacheMismatch {\n accountId: number;\n cachedAvailable: number;\n cachedHeld: number;\n ledgerAvailable: number;\n ledgerHeld: number;\n}\n\nexport interface WalletReconciliationReport {\n parityDeltas: WalletParityDelta[];\n cacheMismatches: WalletCacheMismatch[];\n}\n\nexport async function runWalletReconciliation(): Promise<WalletReconciliationReport> {\n const parityDeltas = await findVendorPaymentHoldParityDeltas();\n const cacheMismatches = await findCacheLedgerMismatches();\n return { parityDeltas, cacheMismatches };\n}\n\nasync function findVendorPaymentHoldParityDeltas(): Promise<WalletParityDelta[]> {\n const rows = (await resolveWalletConnection().query(`\n SELECT\n vo.order_id AS orderId,\n vp.vendor_order_id AS vendorOrderId,\n vp.amount AS vendorPaymentAmount,\n wh.amount AS holdAmount,\n wh.status AS holdStatus\n FROM vendor_payment vp\n INNER JOIN vendor_orders vo ON vo.vendor_order_id = vp.vendor_order_id\n LEFT JOIN wallet_hold wh\n ON wh.reference_type = 'vendor_order'\n AND wh.reference_id = CAST(vp.vendor_order_id AS CHAR)\n WHERE vp.vendor_order_id IS NOT NULL\n `)) as Array<Record<string, unknown>>;\n\n const deltas: WalletParityDelta[] = [];\n for (const row of rows) {\n const vendorPaymentRupees = Number(row.vendorPaymentAmount) || 0;\n const holdPaise = row.holdAmount != null ? Number(row.holdAmount) : 0;\n const holdRupees = fromMinorUnit(holdPaise);\n const delta = Math.abs(vendorPaymentRupees - holdRupees);\n if (delta > 0.01 && row.holdStatus === 'active') {\n deltas.push({\n orderId: Number(row.orderId),\n vendorOrderId: Number(row.vendorOrderId),\n vendorPaymentRupees,\n holdPaise,\n deltaRupees: delta,\n });\n }\n }\n return deltas;\n}\n\nasync function findCacheLedgerMismatches(): Promise<WalletCacheMismatch[]> {\n const connection = resolveWalletConnection();\n const accounts = (await connection\n .getRepository(WalletAccountEntity)\n .find()) as WalletAccountEntity[];\n const mismatches: WalletCacheMismatch[] = [];\n\n for (const account of accounts) {\n const lastEntry = (await connection\n .getRepository(WalletLedgerEntryEntity)\n .findOne({\n where: { accountId: account.id },\n order: { id: 'DESC' },\n })) as WalletLedgerEntryEntity | null;\n if (!lastEntry) {\n continue;\n }\n const cachedAvailable = Number(account.availableBalance);\n const cachedHeld = Number(account.heldBalance);\n const ledgerAvailable = Number(lastEntry.balanceAfterAvailable);\n const ledgerHeld = Number(lastEntry.balanceAfterHeld);\n if (cachedAvailable !== ledgerAvailable || cachedHeld !== ledgerHeld) {\n mismatches.push({\n accountId: account.id,\n cachedAvailable,\n cachedHeld,\n ledgerAvailable,\n ledgerHeld,\n });\n }\n }\n return mismatches;\n}\n","import type { WalletLifecycleHooks } from './types';\nimport { createOrderHooks } from './order';\nimport { createRefundHooks } from './refund';\nimport { createSettlementHooks } from './settlement';\nimport type { HookRuntime } from './types';\n\nexport function createLifecycleHooks(runtime: HookRuntime): WalletLifecycleHooks {\n return {\n ...createOrderHooks(runtime),\n ...createSettlementHooks(runtime),\n ...createRefundHooks(runtime),\n };\n}\n\nexport type {\n DeliveredContext,\n OrderPaidContext,\n RefundContext,\n SettlementDebitContext,\n WalletLifecycleHooks,\n WalletOrderPaidLine,\n} from './types';\n\nexport { runWalletReconciliation } from './reconciliation';\nexport type {\n WalletCacheMismatch,\n WalletParityDelta,\n WalletReconciliationReport,\n} from './reconciliation';\n"]}