# frontend-shop-admin Specification ## Purpose The merchant console for managing a shop's products and fulfilling its orders. ## Requirements ### Requirement: Merchant product management Shop users SHALL manage only their own shop's products: create/edit bilingual content, manage SKUs, publish/unpublish with immediate effect on the storefront. #### Scenario: publish visible in mall - **WHEN** a merchant publishes a product in shop-admin - **THEN** it appears in the mall product list for the matching locale ### Requirement: Merchant fulfillment Shop users SHALL see incoming orders, create shipments, mark them shipped, and issue requested invoices. #### Scenario: ship an order - **WHEN** a merchant creates a shipment for a paid order and marks it shipped - **THEN** the shopper sees the shipment with tracking info ### Requirement: Merchant coupon management Shop users SHALL manage only their shop's coupon templates from shop-admin, including localized title, amount and threshold in minor units, currency, claim stock, active window, and enabled state. Shop-admin SHALL expose a coupons navigation entry beside existing shop operations. #### Scenario: create an active template - **WHEN** a shop owner creates a valid coupon template - **THEN** the template is available for eligible customers to claim during its active window #### Scenario: coupons appear in shop navigation - **WHEN** an authenticated shop user opens shop-admin - **THEN** a coupons management entry is reachable without leaving the shop-scoped console ### Requirement: Merchant flash-sale management Shop users SHALL manage only their flash-sale sessions and items in shop-admin, choosing their own SKU, active window, minor-unit sale price, reserved stock, and per-customer limit. Shop-admin SHALL expose a flash-sale navigation entry beside existing shop operations. #### Scenario: configure item - **WHEN** a merchant creates an active valid flash-sale item for its SKU - **THEN** it appears to customers through active flash-sale discovery #### Scenario: flash sales appear in shop navigation - **WHEN** an authenticated shop user opens shop-admin - **THEN** a flash-sale management entry is reachable without leaving the shop-scoped console ### Requirement: Merchant group-buying management Shop users SHALL manage only their shop's group-buying activities in shop-admin, configuring an owned SKU, localized display content, minor-unit group price, required paid-member count, active window, and group lifetime. Shop-admin SHALL expose a group-buying navigation entry beside existing shop operations. #### Scenario: publish activity - **WHEN** a merchant publishes a valid group-buying activity - **THEN** shoppers can discover it during its active window #### Scenario: group buying appears in shop navigation - **WHEN** an authenticated shop user opens shop-admin - **THEN** a group-buying management entry is reachable without leaving the shop-scoped console ### Requirement: Shared design system in the merchant console The shop-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 shop user opens shop-admin - **THEN** primary actions and page chrome render through the shared kit with the current accent preset ### Requirement: Accent preset switcher Shop-admin SHALL expose the shared accent preset control (`red`, `blue`, `teal`, `violet`) in the authenticated shell header. #### Scenario: switcher visible - **WHEN** an authenticated shop user opens shop-admin - **THEN** they can select an accent preset without leaving the current page ### Requirement: Merchant shop profile editing Shop users SHALL edit their own shop's profile from a shop-admin page reachable from the shop-scoped navigation, through the shared API adapter's shop-scoped profile update. The form SHALL prefill from the shop's current profile and cover the merchant-writable fields only: logo and banner URLs, company, region, and `{ en, zh }` bilingual address, notice and after-sale copy. Bilingual fields SHALL be validated with non-empty `en` and `zh` text before any request is sent, every write SHALL target the caller's own shop, and profile scores SHALL NOT be editable — they remain platform-set and saving never changes them. Saves SHALL give clear success feedback; a refused save SHALL keep the form values and show a visible failure message. #### Scenario: merchant updates their own profile - **WHEN** a shop owner edits their notice, saves, and the mall store page reloads - **THEN** only that shop shows the new notice and no other shop's profile changes #### Scenario: incomplete bilingual text is blocked before submit - **WHEN** a shop owner leaves the `zh` after-sale text empty and saves - **THEN** the field shows an inline error and no update request is sent #### Scenario: scores are not editable - **WHEN** the profile page loads and is saved - **THEN** no score fields are offered and the platform-set scores remain unchanged #### Scenario: refused save keeps the form - **WHEN** the API refuses an update - **THEN** the page keeps the entered values and shows a failure message ### Requirement: Shop-scoped aftersale workspace Shop-admin SHALL provide an aftersale list and detail workspace filtered to the authenticated shop's `own_shop` resources. Authorized shop users SHALL inspect order-item evidence and messages, approve or reject pending applications, and confirm returned goods with the guarded refund action. The UI SHALL show status transitions, remaining amount, ledger-backed refund result, and stale-action errors through the shared API contract. #### Scenario: merchant approves a request - **WHEN** a shop user opens a pending application for an item belonging to their shop and approves it - **THEN** the status advances according to the selected aftersale type and the customer can see the persisted result #### Scenario: merchant confirms return and refunds - **WHEN** a shop user confirms receipt of a buyer-shipped return - **THEN** the service records merchant confirmation, credits the customer's account once, and displays the refunded status and order total #### Scenario: shop scope is enforced - **WHEN** a shop user requests or mutates an aftersale for another shop - **THEN** the API denies the operation and the workspace exposes no cross-shop data #### Scenario: merchant messages buyer - **WHEN** an authorized shop user appends a localized message - **THEN** the message appears in the same chronological aftersale thread visible to the buyer ### Requirement: Merchant freight template management Shop-admin SHALL provide a freight template management page for the signed-in shop user's own shop only, listing the shop's templates with their default flag, always-free toggle, pricing method, minor-unit fees, integer unit sizes, free-shipping threshold, and region rules. Create, edit, default-toggle, region-rule editing, and delete SHALL go through the shared `@vmall/shared` contract, and making a template default SHALL reflect the server's single-default outcome. The page SHALL use `@vmall/ui` primitives and shared tokens. #### Scenario: manage a template and its region rules - **WHEN** a shop user creates a by-piece template, adds a region rule with higher fees, and saves - **THEN** reloading the page shows the template and rule from the backend #### Scenario: default template toggle - **WHEN** a shop user marks a second template as default - **THEN** the page shows exactly that template as default after the server confirms ### Requirement: Merchant shipping company selection When a shop user ships an order from the fulfillment view, shop-admin SHALL offer the shipping companies from the shared dictionary and require a selection before marking the order shipped. The chosen company SHALL reach the backend through the shared contract and appear on the order after shipping. #### Scenario: ship with a selected company - **WHEN** a shop user selects a shipping company and confirms shipment - **THEN** the order shows the shipped state and the selected company ### Requirement: Merchant review management Shop users SHALL list only their own shop's reviews in shop-admin through the shared API contract, with pagination and visible reply state, and SHALL submit at most one reply per review. Shop-admin SHALL expose a review management entry beside existing shop operations. #### Scenario: reply to a review - **WHEN** a merchant opens an unreplied review of their shop and submits a reply - **THEN** the reply is stored once and the review row shows it as replied #### Scenario: already replied review offers no second reply - **WHEN** a merchant opens a review that already carries their shop's reply - **THEN** no reply submission is offered and other shops' reviews are unreachable ### Requirement: Merchant settlement statements Shop-admin SHALL list and open the signed-in shop's settlement statements — period, amount snapshot, and status — through the shared API contract, and allow manual generation for a closed period of the own shop. Shop-scoped pages SHALL never expose another shop's statements or their order/refund breakdown. #### Scenario: statements list and detail - **WHEN** a merchant opens the settlement page - **THEN** only their own shop's statements are listed and each opens into its snapshot breakdown of orders, refunds, commission, and payable amount #### Scenario: generation is idempotent in the UI - **WHEN** the merchant generates a statement for a period that already has one - **THEN** the existing statement appears without duplication ### Requirement: Shop-account withdrawal The shop owner SHALL view the shop account summary (available and frozen balance of the shop owner's account) and apply to withdraw from it through the shared API contract, seeing the request as pending until the platform reviews it. #### Scenario: shop-account withdrawal freezes funds - **WHEN** the shop owner submits a withdrawal request from the shop-account page - **THEN** the summary reflects the frozen amount and the request lists as pending #### Scenario: reviewed request reflects outcome - **WHEN** the platform rejects the shop owner's pending withdrawal - **THEN** the shop-account summary shows the amount returned to available balance and the request shows as rejected