Files
vmall/openspec/changes/add-merchant-onboarding/tasks.md
T

5.5 KiB

1. Persistence and shared contract

  • 1.1 Add migration 0017_merchant_applications.sql (take the next free number if a sibling change claims it): merchant_applications with applicant user_id FK, entity_type enum (personal, enterprise), kind-specific entity and contact columns, category_ids, qualification URL columns (identity document, business license, extra materials as a JSONB URL array), status enum (pending, approved, rejected), rejection_reason, reviewed_by/reviewed_at, created_shop_id FK, and a partial unique index on user_id WHERE status IN ('pending', 'approved').
  • 1.2 Add shared discriminated application types (submit payloads for both entity kinds, application summary/detail with status and rejection reason, one-time approval credentials) and the submitMerchantApplication, getMyMerchantApplications, adminListMerchantApplications, adminGetMerchantApplication, adminApproveMerchantApplication, and adminRejectMerchantApplication methods to @vmall/shared.

2. Backend service and behavioral tests

  • 2.1 Implement apps/api/src/modules/merchant_onboarding/ repository, service, DTO, handlers, and module registration: authenticated customer routes for submit and self status, and platform_admin-guarded admin routes for list, detail, approve, and reject. Services return ApiResult<Dto>.
  • 2.2 Enforce submission validation (kind-specific required fields, published category references, qualification URL shape) and duplicate rejection for users holding a pending or approved application, with the partial unique index as the concurrency backstop.
  • 2.3 Implement guarded status transitions (UPDATE ... WHERE status = 'pending') with mandatory rejection reason and a 409 conflict for already-reviewed applications.
  • 2.4 Implement approval as a single transaction: create the shop, create a dedicated shop_owner account scoped to it, flip the application to approved with created_shop_id, and return the generated initial password exactly once; any failure rolls back the status flip and all provisioning.
  • 2.5 Add isolated API integration coverage in apps/api/tests/merchant_applications.rs (reuse the tests/common/mod.rs fixtures) for duplicate submission, double-review conflicts, terminal-state immutability, rejection-reason enforcement, and provisioning rollback.

3. Mall onboarding form

  • 3.1 Implement the six merchant-onboarding client methods in apps/mall/mock/api.ts with deterministic per-session fixture state mirroring dedupe conflicts, review status, and approval/rejection outcomes.
  • 3.2 Add the merchant-onboarding domain and exact shared-client method picks to Mall API selection (apps/mall/plugins/api.ts LIVE_PICKS) and enable it in the default live runtime configuration.
  • 3.3 Build the multi-step onboarding page (/merchant/join): entity-kind step (personal 个人 / enterprise 企业) switching kind-specific fields, entity information, operating categories from the published category tree, contact details, and qualification URL input fields with no upload controls; allow anonymous filling but gate submission behind registration/sign-in with return to the completed form.
  • 3.4 Build the application status page (/merchant/status) showing the applicant's latest application state, submitted entity kind, timestamps, and rejection reason, with a re-apply action after rejection.
  • 3.5 Land the top-bar "商家入驻" (sellerJoin) entry and the footer "Become a Seller" link on the onboarding page instead of the stores directory, and add bilingual onboarding, form, and status strings through the existing Mall locale source without per-page hard-coded copy.

4. Admin review console

  • 4.1 Add a platform-admin merchant applications page in apps/admin with a status-filtered paginated table and a detail view of entity kind, entity information, operating categories, contact details, and qualification URL fields through the shared contract.
  • 4.2 Add approve/reject actions: rejection requires a non-empty reason, approve shows a one-time initial-credentials dialog with explicit copy that the password cannot be retrieved again, and reviewed rows leave the pending queue immediately.
  • 4.3 Register the merchant applications entry in admin navigation beside existing platform operations and add bilingual console strings through the shared locale source.

5. Verification and tracker cleanup

  • 5.1 Add end-to-end API integration coverage in apps/api/tests/merchant_applications.rs (reuse the tests/common/mod.rs fixtures) for submit -> approve provisioning (the created shop_owner can log in and manage the linked shop) and submit -> reject -> re-apply, then run the focused merchant onboarding integration tests.
  • 5.2 Run the API plus Mall and browser-smoke: anonymous fill -> sign-in gate -> submit, duplicate submission conflict, mall status page after approve and after reject, admin queue filtering and detail, approve one-time credentials display, and reject-reason enforcement.
  • 5.3 Build all three frontends because the shared API contract changes: pnpm --filter @vmall/mall build, pnpm --filter @vmall/shop-admin build, and pnpm --filter @vmall/admin build.
  • 5.4 Update the README mock boundary for the merchant-onboarding adapter fallback, record any remaining fixture-driven onboarding surfaces in docs/TBD-marketing.md, check every OpenSpec task, and run openspec change validate add-merchant-onboarding --strict plus openspec validate --all --strict.