Files
Chengdong Zhang a7cd392bd4 feat(payments): configurable checkout payments — wallet + Stripe crypto, original-method refunds (add-configurable-payments)
- payment domain: payments/memberships/attempts/receipts/refunds/commands/events, legacy-demo provenance (0024), checkout header-hash idempotency (0025)
- wallet collection all-or-none across shop orders; group-wide cancellation; checkout cutover, status-only payOrder removed
- Stripe crypto-only Checkout adapter, raw-body HMAC webhooks, durable command worker with leases
- original-method refunds with receipt/allocation budgets; refund_pending/refund_failed aftersale states
- admin channel CRUD/revisions/audit/verify + operations list/detail/reconcile; secret-ref allowlist (VMALL_PAYMENT_*), env-fixed demo/sandbox/live
- mall/mobile checkout pay surfaces, admin console pages; shared contract updated
- pre-launch leftovers recorded in docs/TBD-payments.md

cargo test -p vmall-api green twice; four frontend builds green; browser smoke: mall wallet checkout paid, admin channels/operations verified
2026-10-15 16:14:28 +08:00

14 KiB

frontend-admin Specification

Purpose

The platform console for managing users, shops and currencies.

Requirements

Requirement: Platform user and shop management

Platform admins SHALL assign user roles (with shop scope), create shops, and suspend/activate shops. Suspended shops' products MUST NOT be purchasable (enforced by API, reflected in UI).

Scenario: assign shop owner

  • WHEN an admin assigns role shop_owner with a shop to a user
  • THEN that user can log into shop-admin and manage that shop

Requirement: Currency management

Platform admins SHALL view currencies and update exchange rates; new rates affect subsequent conversions.

Scenario: rate update

  • WHEN an admin updates CNY rate_to_base
  • THEN the mall conversion endpoint returns amounts computed with the new rate

Requirement: Platform points mall management

Platform admins SHALL manage points products and inspect and fulfill redemption orders through the admin console using the shared API contract. Admin SHALL expose points-mall navigation beside existing platform operations.

Scenario: manage a redemption catalog item

  • WHEN a platform admin publishes a configured points product
  • THEN it becomes available in the customer points mall

Scenario: points mall appears in admin navigation

  • WHEN an authenticated platform admin opens the admin console
  • THEN points-product and redemption-order management are reachable from the console nav

Requirement: Shared design system in the platform console

The platform admin console SHALL use @vmall/ui primitives and @vmall/shared theme tokens for chrome (buttons, fields, cards, tables, page headers, nav). It MUST NOT depend on Element Plus or the removed ui.css stylesheet.

Scenario: console chrome from the kit

  • WHEN an authenticated platform admin opens the dashboard
  • THEN primary actions and page chrome render through the shared kit with the current accent preset

Requirement: Accent preset switcher

Platform admin SHALL expose the shared accent preset control (red, blue, teal, violet) in the authenticated shell header.

Scenario: switcher visible

  • WHEN an authenticated platform admin opens the console
  • THEN they can select an accent preset without leaving the current page

Requirement: Storefront content management

The platform console SHALL manage the four home-content kinds — banners, promos, quick links and floor adverts — on a content page reachable from the console navigation, loading every entry including inactive ones through the shared API adapter. Each kind SHALL be edited as its ordered list of rows with add, remove and reorder controls (no drag and drop), the per-entry fields the API accepts, an active flag per entry, and a preview of how the storefront renders each entry. Saving a kind SHALL submit the whole edited list in its displayed order as one replacement with the semantics of PUT /api/admin/content/{kind}, so positions follow the submitted order and the other three kinds are untouched. Rows SHALL be validated before any request with the rules the API enforces — non-empty image and destination URLs, non-empty glyph, and non-empty en and zh quick-link labels in { en, zh } JSONB text — with inline field errors on failing rows. Saves SHALL give clear success feedback; a rejected save SHALL keep the edited rows and show a visible failure message.

Scenario: save replaces one kind only

  • WHEN an admin reorders banners, saves that kind, and the mall reloads its home content
  • THEN banners appear in the new order while promos, quick links and floor adverts are unchanged

Scenario: invalid row is blocked before submit

  • WHEN an admin leaves a banner image URL empty and saves
  • THEN the row shows an inline field error and no replacement request is sent

Scenario: rejected save keeps the editor state

  • WHEN the API rejects a replacement
  • THEN the page shows a failure message and keeps the edited rows for correction

Requirement: Brand management

Platform admins SHALL manage the ordered brand registry on a brands page reachable from the console navigation, through the shared API adapter. The page SHALL edit the whole list — slug, non-empty { en, zh } names and an active flag per row — with add, remove and reorder controls and a preview of each brand as the public list serves it. Saving SHALL replace the whole list in its displayed order so positions follow the submitted order. Slugs SHALL be validated against the ascii a-z, 0-9, - pattern and duplicate slugs and incomplete bilingual names SHALL be rejected with inline errors before any request is sent. Saves SHALL give clear success feedback; a rejected save SHALL keep the edited rows and show a visible failure message.

Scenario: replace round-trips to the public list

  • WHEN an admin reorders brands, renames one, and saves
  • THEN the public brand list returns the same entries in the submitted order

Scenario: duplicate slug is blocked before submit

  • WHEN an admin saves with two rows carrying the same slug
  • THEN the duplicate rows show inline errors and no replacement request is sent

Scenario: save feedback distinguishes success and failure

  • WHEN a save succeeds or the API refuses the list
  • THEN the page shows a success confirmation or keeps the edited rows with a failure message, respectively

Requirement: Platform aftersale monitoring and arbitration

The platform console SHALL provide a cross-shop aftersale list/detail with customer, shop, order-item, amounts, evidence, status, message history, completed totals and original-payment refund-operation context. Administrators SHALL resolve eligible disputes through the same guarded original-method refund or rejection path without editing balances or claiming synchronous external completion. Pending/unknown/failed refunds SHALL show their authoritative state and permit only server-authorized actions.

Scenario: admin inspects a cross-shop application

  • WHEN an administrator opens the aftersale workspace
  • THEN cross-shop applications, authoritative amounts and original-method refund state are available with filters

Scenario: admin grants terminal refund

  • WHEN an administrator grants an eligible refund
  • THEN wallet completion appears immediately if committed, while crypto remains refund_pending until verified provider success updates the total

Scenario: admin rejects terminal dispute

  • WHEN an administrator rejects an eligible dispute
  • THEN the console shows rejected and only the permitted one-time customer reopen can resume it

Requirement: Platform review moderation

Platform admins SHALL review a paginated moderation list of all reviews with their product, customer, and shop context and SHALL hide or delete reviews through the shared API contract. Admin SHALL expose review moderation navigation beside existing platform operations.

Scenario: hide a review from the moderation list

  • WHEN a platform admin hides a review
  • THEN the list shows it as hidden and the review leaves the mall storefront and rating summary

Scenario: delete a review

  • WHEN a platform admin deletes a review
  • THEN the row is removed and absent from both admin and storefront listings

Scenario: moderation appears in admin navigation

  • WHEN an authenticated platform admin opens the admin console
  • THEN a review moderation entry is reachable from the console nav

Requirement: Withdrawal review and commission configuration

The platform console SHALL list withdrawal applications and approve or reject each pending application through the shared API contract, surfacing review outcomes and conflicts (409 on a repeated review) without silent failure. It SHALL expose the platform commission rate as an integer basis-point setting that admins can read and update.

Scenario: reject returns funds

  • WHEN an admin rejects a pending withdrawal application
  • THEN the console shows the rejected status and the buyer's wallet reflects the amount back in available balance

Scenario: approve deducts frozen funds

  • WHEN an admin approves a pending withdrawal application
  • THEN the console shows the approved status and the frozen balance decreases by the requested amount

Scenario: set commission rate

  • WHEN an admin updates the commission rate
  • THEN settlement statements generated afterwards snapshot the new rate

Requirement: Settlement statement confirmation

The platform console SHALL list settlement statements across shops with their amount snapshots and statuses, allow manual generation for a shop and closed period, and confirm payout exactly once per statement through the shared API contract, surfacing a 409 on repeated confirmation.

Scenario: confirm payout

  • WHEN an admin confirms a pending statement
  • THEN the console shows the statement confirmed and the shop owner's ledger records the payout

Scenario: manual generation is idempotent

  • WHEN an admin generates a statement for a shop and period that already has one
  • THEN the existing statement is shown and no duplicate is created

Requirement: Merchant application review console

Platform admins SHALL review merchant onboarding applications in a dedicated console entry beside existing platform operations: a status-filtered paginated list and a detail view showing entity kind, entity information, operating categories, contact details, and qualification URL fields. Approving SHALL provision the shop and shop_owner account and display the one-time initial credentials exactly once, with copy stating the password cannot be retrieved again. Rejecting SHALL require a reason. Reviewed applications SHALL leave the pending queue immediately.

Scenario: review an enterprise application

  • WHEN a platform admin opens a pending enterprise application
  • THEN the company entity data, operating categories, contact details, and qualification URLs are visible for review

Scenario: approve shows one-time credentials

  • WHEN a platform admin approves an application
  • THEN the created shop owner's initial credentials are shown once and the application moves to the approved list

Scenario: reject requires a reason

  • WHEN a platform admin attempts to reject without entering a reason
  • THEN the action is blocked until a non-empty reason is provided

Scenario: entry beside platform operations

  • WHEN an authenticated platform admin opens the admin console
  • THEN merchant application review is reachable from the console navigation

Requirement: Member level management

Platform admins SHALL manage member levels from a dedicated admin console page through the shared API contract: levels listed in growth-threshold order, and create, edit, and delete actions over name, icon, growth threshold, and benefits with both locales editable. Deleting a level in use SHALL surface the API rejection instead of silently succeeding, and member-level management SHALL be reachable from the authenticated console navigation beside existing platform operations.

Scenario: manage a member level

  • WHEN a platform admin creates a level with bilingual name and benefits, an icon, and a growth threshold
  • THEN it appears in threshold order and is available for automatic leveling

Scenario: edit a growth threshold

  • WHEN a platform admin changes a level's growth threshold to a unique value
  • THEN the level persists with the new threshold and the bilingual content unchanged

Scenario: deleting a level in use fails visibly

  • WHEN a platform admin deletes a level that customers hold
  • THEN the console surfaces the rejection and the level and its members remain unchanged

Scenario: level management appears in admin navigation

  • WHEN an authenticated platform admin opens the admin console
  • THEN member-level management is reachable from the console nav

Requirement: Payment channel management console

The platform console SHALL provide navigable channel management through the shared client: installed adapter capabilities, bilingual label, display order, enabled state, supported fiat currencies, integer limits, environment, provider account, allowlisted secret references, read-only connection verification and revision/audit history. It SHALL show missing approval/credentials and reject unsupported controls. Existing secret values SHALL never be displayed. Disabling SHALL explain that it stops new attempts but preserves existing callback/refund processing. Stale edits SHALL show 409 and retain user input while refreshing authoritative revision context. All controls SHALL use shared UI primitives and en/zh copy.

Scenario: configure and activate crypto

  • WHEN an administrator saves valid USD Stripe crypto configuration and successfully verifies the approved account
  • THEN activation becomes available and the enabled channel appears to eligible storefront payments

Scenario: credential reference is missing

  • WHEN verification cannot resolve a configured allowlisted secret reference
  • THEN the UI shows the unmet prerequisite without exposing a secret and does not claim the method is ready

Requirement: Payment and refund recovery console

The platform console SHALL provide paginated payment/refund/exception lists and details, showing allocation breakdown, receipt evidence, attempts, pending/unknown states and redacted audit history. Reconciliation SHALL request evidence fetching through the shared API; the UI SHALL never offer an unconditional mark-paid/refunded action. Received-but-unapplied and additional genuine collections SHALL show compensation progress. Disabling a channel SHALL not remove historical records from operations views.

Scenario: recover provider timeout

  • WHEN an administrator reconciles an unknown attempt
  • THEN the console shows queued evidence lookup and later authoritative status without starting a second collection

Scenario: seat rejection after collection

  • WHEN an external receipt could not be applied to a group-bearing checkout
  • THEN its receipt, unchanged order application and compensating refund remain inspectable