6.9 KiB
6.9 KiB
1. Persistence and shared contract
- 1.1 Add migration
0018_wallet.sqladapting tigshop'suser_recharge_orderanduser_withdraw_apply:wallet_recharges(user, currency, amount_minor BIGINT, status, timestamps) andwallet_withdrawals(user, currency, amount_minor BIGINT, account_details JSONB, status pending/approved/rejected with CHECK, reviewing admin, reviewed_at, review_note, timestamps) with foreign keys, non-negative amount CHECKs, and customer-facing indexes. (Migration numbers 0016/0017 are taken by parallel changes.) - 1.2 Add migration
0019_settlement.sqladapting tigshop'svendor_settlement_order:settlement_statements(shop, period_kind week/month, period_start, period_end, order_count, gross_minor, refund_minor, commission_rate_bps, commission_minor, payable_minor, status pending/confirmed with CHECK, generated_by, confirmed_by, confirmed_at, timestamps) with a unique index on (shop_id, period_kind, period_start), plus a platform-level settings row forsettlement.commission_rate_bps. - 1.3 Add
@vmall/sharedwallet types and customer-client methods:getWallet(available/frozen minor with currency),listWalletEntries(paged signed ledger entries),rechargeWallet(demo),applyWithdrawal, andlistMyWithdrawals. - 1.4 Add
@vmall/sharedsettlement and review methods: admin clientlistWithdrawalApplications,reviewWithdrawal,getCommissionRate,setCommissionRate,listSettlementStatements,getSettlementStatement,generateSettlementStatement,confirmSettlementStatement; shop clientlistShopSettlementStatements,getShopSettlementStatement,generateShopSettlementStatement. All money fields are i64 minor units; no floating-point amounts cross the contract.
2. Wallet backend
- 2.1 Implement
apps/api/src/modules/wallet/(repo, service returningApiResult<Dto>, DTOs, handlers, module registration) with user-scoped/walletroutes and/admin/wallet/withdrawalsreview routes declaring the platform-admin role. - 2.2 Implement demo recharge: one transaction records a
wallet_rechargesrow and credits the available account through the existingcustomer-accountsprimitives with awallet_rechargeledger entry; the DTO carries an explicit demo marker. - 2.3 Implement the withdrawal lifecycle: application freezes funds via guarded
UPDATE ... WHERE balance_minor >= $amountmoving available to frozen with paired ledger entries; admin approve deducts frozen balance with a ledger entry; admin reject returns frozen balance to available with a ledger entry; each review is guarded byUPDATE ... WHERE status = 'pending', returns 409 on repeat, and records reviewer, timestamp, and note. - 2.4 Implement paginated fund-entry listing mapped to
customer_account_entriesfor the caller's monetary accounts (newest first; signed delta, resulting balance, reason, reference) with ownership filtering. - 2.5 Add
apps/api/tests/wallet.rscovering concurrent withdrawal overdraw, insufficient-balance no-op, double-review 409, reject unfreeze, approve frozen deduction, recharge ledger pairing, and entry pagination isolation, reusing thetests/common/mod.rsfixtures.
3. Settlement backend
- 3.1 Implement
apps/api/src/modules/settlement/(repo, service returningApiResult<Dto>, DTOs, handlers, module registration) with/shop/settlement/*routes scoped throughAuthUser::own_shopand/admin/settlement/*routes declaring the platform-admin role. - 3.2 Implement idempotent statement generation for a shop and closed week/month period: snapshot order count and gross totals of confirmed-received orders in the period, deduct completed refunds (
aftersalesrows with statusrefunded, per-order totals maintained byadd-aftersale-refunds— if developed in parallel with P0, merge the P0aftersalesmigration first), apply the platform commission rate in integer basis points with integer minor-unit arithmetic (payable = gross − refunds − commission), and return the existing statement untouched on repeat generation. - 3.3 Implement statement listing and detail with per-order and refund breakdown, with merchant routes restricted to the own shop and platform-admin routes seeing every shop.
- 3.4 Implement
pending -> confirmedpayout confirmation: guardedUPDATE ... WHERE status = 'pending'(409 on repeat) crediting the payable amount to the shop owner's available account with exactly one ledger entry referencing the statement. - 3.5 Implement platform commission-rate configuration (integer basis points), applied only to statements generated after a change; generated statements keep their snapshot.
- 3.6 Add
apps/api/tests/settlement.rscovering generation idempotency and period uniqueness, refund deduction, commission snapshot immutability after a rate change, double-confirmation 409 with exactly one payout ledger entry, and cross-shop isolation, reusing thetests/common/mod.rsfixtures.
4. Frontend surfaces
- 4.1 Add the mall buyer-center wallet page (available/frozen balance, paginated fund entries, clearly labeled demo recharge, withdrawal request and history) through
@vmall/shared, with bilingual strings in the existing Mall locale source. - 4.2 Add the
walletdomain to the Mall fixed-data adapter (apps/mall/mock/api.ts) with matching behavior, and wirewalletinto the Mall API selectionLIVE_PICKSand default live domains (apps/mall/plugins/api.ts). - 4.3 Add admin pages for withdrawal review (approve/reject with outcome and 409 feedback), commission-rate configuration, and settlement statement list/detail with manual generation and one-time payout confirmation.
- 4.4 Add shop-admin pages for own-shop settlement statement list/detail with manual generation and shop-account summary plus withdrawal request/history.
- 4.5 Keep all three frontends on the
@vmall/sharedcontract only (no page-level fetch of wallet/settlement endpoints) and render page chrome with@vmall/uiprimitives.
5. Verification and tracker cleanup
- 5.1 Run the wallet and settlement integration tests in
apps/api/tests/wallet.rsandapps/api/tests/settlement.rs(reusing thetests/common/mod.rsfixtures), thencargo test -p vmall-apito prove the suite stays green against the shared test database. - 5.2 Build all three frontends because the shared API contract changes:
pnpm --filter @vmall/mall build,pnpm --filter @vmall/admin build, andpnpm --filter @vmall/shop-admin build. - 5.3 Browser-smoke the API plus frontends: demo recharge updates the wallet; withdrawal freeze, admin reject unfreeze, and admin approve deduction round trip; wallet entries pagination; commission-rate configuration; idempotent statement generation with refund deduction; one-time payout confirmation writing one ledger entry; and shop-admin own-shop statement isolation.
- 5.4 Check every OpenSpec task, then run
openspec change validate add-wallet-settlement --strictandopenspec validate --all --strict.