323 lines
9.6 KiB
JavaScript
323 lines
9.6 KiB
JavaScript
import { makeRecoveredPage } from "../../runtime/makeRecoveredPage.js";
|
|
import FinanceOrderPageView from "./FinanceOrderPage.jsx";
|
|
|
|
export default makeRecoveredPage({
|
|
title: "Finance Order",
|
|
routePath: "/finance/order",
|
|
moduleId: "R3t",
|
|
featureKey: "finance.order",
|
|
component: FinanceOrderPageView,
|
|
translationNamespaces: ["order", "common"],
|
|
summary:
|
|
"The order management page is a server-driven data table with a lightweight create/assign dialog, multi-dimensional faceted filters, detail dialog drill-down, pending-order action menu, and commission workflow updates.",
|
|
api: [
|
|
{
|
|
name: "order.fetch",
|
|
method: "POST",
|
|
path: "{secure}/order/fetch",
|
|
queryKey: ["orderList", "{pagination}", "{filters}", "{sorting}"],
|
|
purpose: "Loads paginated order table data for the main management view.",
|
|
requestShape: {
|
|
pageSize: "number",
|
|
current: "1-based page number",
|
|
filter: [{ id: "column id", value: "raw value or operator:value string" }],
|
|
sort: [{ id: "column id", desc: "boolean" }],
|
|
},
|
|
responseShape: {
|
|
data: [
|
|
{
|
|
id: "number",
|
|
trade_no: "string",
|
|
type: "number",
|
|
period: "string",
|
|
status: "number",
|
|
total_amount: "number",
|
|
balance_amount: "number",
|
|
discount_amount: "number",
|
|
refund_amount: "number",
|
|
surplus_amount: "number",
|
|
commission_balance: "number",
|
|
commission_status: "number",
|
|
created_at: "unix timestamp",
|
|
updated_at: "unix timestamp",
|
|
callback_no: "string | null",
|
|
user: {
|
|
id: "number",
|
|
email: "string",
|
|
},
|
|
plan: {
|
|
id: "number",
|
|
name: "string",
|
|
},
|
|
invite_user: {
|
|
id: "number",
|
|
email: "string",
|
|
},
|
|
},
|
|
],
|
|
total: "number",
|
|
},
|
|
},
|
|
{
|
|
name: "order.detail",
|
|
method: "POST",
|
|
path: "{secure}/order/detail",
|
|
purpose: "Loads the order detail dialog on demand when the trade number trigger is opened.",
|
|
payloadExamples: [{ id: 1001 }],
|
|
},
|
|
{
|
|
name: "order.paid",
|
|
method: "POST",
|
|
path: "{secure}/order/paid",
|
|
purpose: "Marks a pending order as paid from the row action menu.",
|
|
payloadExamples: [{ trade_no: "202604170001" }],
|
|
},
|
|
{
|
|
name: "order.cancel",
|
|
method: "POST",
|
|
path: "{secure}/order/cancel",
|
|
purpose: "Cancels a pending order from the row action menu.",
|
|
payloadExamples: [{ trade_no: "202604170001" }],
|
|
},
|
|
{
|
|
name: "order.update",
|
|
method: "POST",
|
|
path: "{secure}/order/update",
|
|
purpose: "Transitions commission workflow state from the commission status action menu.",
|
|
payloadExamples: [
|
|
{ trade_no: "202604170001", commission_status: 1 },
|
|
{ trade_no: "202604170001", commission_status: 3 },
|
|
],
|
|
},
|
|
{
|
|
name: "order.assign",
|
|
method: "POST",
|
|
path: "{secure}/order/assign",
|
|
purpose: "Creates an admin-assigned order from the toolbar dialog or user-row embedded trigger.",
|
|
payloadExamples: [
|
|
{
|
|
email: "user@example.com",
|
|
plan_id: 1,
|
|
period: "month_price",
|
|
total_amount: 1999,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "plan.fetch",
|
|
method: "GET",
|
|
path: "{secure}/plan/fetch",
|
|
purpose: "Supplies plan options for the assign-order dialog.",
|
|
},
|
|
],
|
|
enums: {
|
|
orderStatus: {
|
|
PENDING: 0,
|
|
PROCESSING: 1,
|
|
CANCELLED: 2,
|
|
COMPLETED: 3,
|
|
DISCOUNTED: 4,
|
|
},
|
|
orderType: {
|
|
NEW: 1,
|
|
RENEWAL: 2,
|
|
UPGRADE: 3,
|
|
RESET_FLOW: 4,
|
|
},
|
|
commissionStatus: {
|
|
PENDING: 0,
|
|
PROCESSING: 1,
|
|
VALID: 2,
|
|
INVALID: 3,
|
|
},
|
|
periodKeys: [
|
|
"month_price",
|
|
"quarter_price",
|
|
"half_year_price",
|
|
"year_price",
|
|
"two_year_price",
|
|
"three_year_price",
|
|
"onetime_price",
|
|
"reset_price",
|
|
],
|
|
},
|
|
stateModel: {
|
|
list: {
|
|
rowSelection: {},
|
|
columnVisibility: {},
|
|
columnFilters: [],
|
|
sorting: [],
|
|
pagination: {
|
|
pageIndex: 0,
|
|
pageSize: 20,
|
|
},
|
|
initialColumnPinning: {
|
|
right: ["actions"],
|
|
},
|
|
},
|
|
routeBootstrap: {
|
|
searchParamsToFilters: [
|
|
{ key: "user_id", parser: "string" },
|
|
{ key: "order_id", parser: "string" },
|
|
{ key: "commission_status", parser: "number" },
|
|
{ key: "status", parser: "number" },
|
|
{ key: "commission_balance", parser: "string" },
|
|
],
|
|
},
|
|
assignDialog: {
|
|
open: false,
|
|
defaultValues: {
|
|
email: "",
|
|
plan_id: 0,
|
|
period: "",
|
|
total_amount: 0,
|
|
},
|
|
planOptions: "Loaded lazily when the dialog is opened.",
|
|
},
|
|
detailDialog: {
|
|
open: false,
|
|
orderId: null,
|
|
data: null,
|
|
},
|
|
},
|
|
toolbarModel: {
|
|
quickActions: [
|
|
"Assign/create order dialog button",
|
|
"Trade number search on trade_no column",
|
|
],
|
|
facetedFilters: [
|
|
{
|
|
column: "type",
|
|
source: "order type enum",
|
|
},
|
|
{
|
|
column: "period",
|
|
source: "order period enum",
|
|
},
|
|
{
|
|
column: "status",
|
|
source: "order status enum",
|
|
},
|
|
{
|
|
column: "commission_status",
|
|
source: "commission status enum",
|
|
},
|
|
],
|
|
resetBehavior: "Reset button appears when any column filter exists and clears all filters.",
|
|
},
|
|
tableModel: {
|
|
columns: [
|
|
{
|
|
key: "trade_no",
|
|
titleKey: "table.columns.tradeNo",
|
|
renderer:
|
|
"Truncated trade number button that opens an on-demand detail dialog for the current order.",
|
|
},
|
|
{
|
|
key: "type",
|
|
titleKey: "table.columns.type",
|
|
renderer: "Enum badge with per-type color token mapping.",
|
|
},
|
|
{
|
|
key: "plan.name",
|
|
titleKey: "table.columns.plan",
|
|
renderer: "Plan name text cell using nested plan relation.",
|
|
},
|
|
{
|
|
key: "period",
|
|
titleKey: "table.columns.period",
|
|
renderer: "Period badge using period color mapping.",
|
|
},
|
|
{
|
|
key: "total_amount",
|
|
titleKey: "table.columns.amount",
|
|
renderer: "Currency text using fen-to-yuan formatting.",
|
|
sortable: true,
|
|
},
|
|
{
|
|
key: "status",
|
|
titleKey: "table.columns.status",
|
|
renderer:
|
|
"Status cell with icon + text. Pending rows expose a dropdown action menu for mark-as-paid and cancel.",
|
|
sortable: true,
|
|
},
|
|
{
|
|
key: "commission_balance",
|
|
titleKey: "table.columns.commission",
|
|
renderer: "Currency text, hidden when absent.",
|
|
sortable: true,
|
|
},
|
|
{
|
|
key: "commission_status",
|
|
titleKey: "table.columns.commissionStatus",
|
|
renderer:
|
|
"Commission status badge with conditional action menu. Only shown as actionable when commission_balance is non-zero and order status is COMPLETED.",
|
|
sortable: true,
|
|
},
|
|
{
|
|
key: "created_at",
|
|
titleKey: "table.columns.createdAt",
|
|
renderer: "Timestamp rendered as yyyy/MM/dd HH:mm:ss.",
|
|
sortable: true,
|
|
},
|
|
],
|
|
mobileLayout: {
|
|
primaryField: "trade_no",
|
|
gridFields: ["plan.name", "total_amount", "status", "created_at"],
|
|
},
|
|
},
|
|
dialogs: {
|
|
assignOrder: {
|
|
formFields: ["email", "plan_id", "period", "total_amount"],
|
|
amountBehavior: "UI edits in yuan, submitted as fen by multiplying the numeric input by 100.",
|
|
successBehavior: "Refetch list, reset form, close dialog, show success toast.",
|
|
},
|
|
orderDetail: {
|
|
sections: [
|
|
"basicInfo",
|
|
"amountInfo",
|
|
"timeInfo",
|
|
"commissionInfo",
|
|
],
|
|
fields: [
|
|
"user.email",
|
|
"period",
|
|
"plan.name",
|
|
"callback_no",
|
|
"total_amount",
|
|
"balance_amount",
|
|
"discount_amount",
|
|
"refund_amount",
|
|
"surplus_amount",
|
|
"created_at",
|
|
"updated_at",
|
|
"commission_balance",
|
|
"commission_status",
|
|
],
|
|
links: [
|
|
"user email links to /user/manage?email=<email>",
|
|
"invite user email links to /user/manage?email=<email> when present",
|
|
],
|
|
},
|
|
},
|
|
interactions: [
|
|
"Opening the page with query parameters such as user_id, status, or commission_status preloads matching column filters from the URL.",
|
|
"Trade number cells are the primary detail entrypoint and fetch full order data only when the dialog opens.",
|
|
"Pending orders expose mark-as-paid and cancel actions from the status dropdown menu.",
|
|
"Pending commissions on completed orders expose PROCESSING and INVALID transitions through order.update.",
|
|
"Assign order dialog is reused from user-row actions and prefilled with the current user email when launched there.",
|
|
],
|
|
notes: [
|
|
"The list is fully server-driven: pagination, filtering, and sorting all flow back through order.fetch.",
|
|
"The compiled page uses the shared generic faceted-filter popover component for type/period/status/commission filters.",
|
|
"Actions are concentrated on status and commission_status columns instead of a dedicated trailing actions column.",
|
|
],
|
|
sourceRefs: [
|
|
"frontend/admin/reverse/output/index-CO3BwsT2.pretty.js:27362",
|
|
"frontend/admin/reverse/output/index-CO3BwsT2.pretty.js:296650",
|
|
"frontend/admin/reverse/output/index-CO3BwsT2.pretty.js:296936",
|
|
"frontend/admin/reverse/output/index-CO3BwsT2.pretty.js:297228",
|
|
"frontend/admin/reverse/output/index-CO3BwsT2.pretty.js:297575",
|
|
],
|
|
});
|