# Quickstart & Verification: 平台订单状态受控调整

本文供 `/speckit.tasks` 和实现阶段使用。当前阶段不执行数据库写入，也不创建分支。

## 1. Prerequisites

- JDK 21、Maven 可用；
- 管理后台依赖已安装，Node 环境能运行 Vue CLI 4；
- 测试账号拥有 `system:order:list/query/edit`；
- OMG 自动退款测试使用 mock；stage 环境不支持真实 DoAction；
- 正式小额退款必须另行取得授权，本地自动化不得调用真实退款端点。

## 2. Automated Verification

### Backend focused tests

```powershell
mvn -pl ruoyi-admin -am `
  -Dtest=OrderLifecycleServiceTest,PosOrderAdminStatusControllerTest,OmgPayControllerTest `
  -Dsurefire.failIfNoSpecifiedTests=false test
```

### Existing OMG service regressions

```powershell
mvn -pl ruoyi-system `
  -Dtest=PosOrderOmgPaymentServiceImplTest,PosOrderOmgRefundServiceImplTest test
```

### Backend compile

```powershell
mvn -pl ruoyi-admin -am -DskipTests compile
```

### Admin frontend

在 `E:\QtwCode\foodie\foodie-admin-vue` 执行：

```powershell
npm run lint
npm run build:prod
```

如果全库 lint 存在与本功能无关的历史错误，必须同时记录：全库结果、仅本次修改文件的 ESLint 结果，以及确认未新增错误的证据；不得顺手改无关文件。

## 3. Required Test Cases

### 3.1 State policy

- 订单只允许 `0→1→2→3` 和未支付的 `0/1→4`；
- 终态、回退、跳级、非法范围拒绝；
- `afterSaleStatus>0` 拒绝普通调整；
- 自取/堂食配送目标拒绝；
- 配送 `0→1→2→3`，无骑手不能进入 1/2/3；
- 完成前必须已支付；外送完成前必须已送达。

### 3.2 CAS and side effects

- 四状态快照匹配时更新一行；
- 任一快照已变化时更新零行并返回刷新提示；
- CAS 失败不写日志、不生成账单、不返积分；
- 相同目标重复请求不产生重复日志/账单；
- 请求中的未知金额、用户、商品字段无法进入专用 DTO 的更新逻辑。

### 3.3 Delivery completion

- 骑手/管理员送达同步写 `deliveryStatus=3, state=3, sdTime`；
- 外送生成商家和骑手账单；
- 订单与配送完成并发时只有首次完成者产生副作用；
- 到付订单保留既有用户账单处理；
- 推送只在事务提交后执行。

### 3.4 Offline payment

- `payType=1, payStatus=0` 可确认收款；
- `payType=7` 或历史在线支付类型不能确认线下收款；
- 线下退款同步三状态并返还积分；
- 已完成订单、重复退款、售后处理中拒绝。

### 3.5 OMG

- 补单成功必须校验金额、交易号、日期；
- OMG 未支付/失败/未知不写订单已支付；
- 回调与管理员补单并发只核销一次；
- 信用卡退款成功同步三状态；
- 人工退款方式保持订单已支付并只建一个待办；
- 已在 OMG 后台完成的人工退款只有在存在待办并二次确认后才同步三状态；重复确认无副作用；
- 超时结果未知保持流水退款中，重复请求不再次调用网关；
- 明确失败恢复流水已支付；
- 网关成功、本地同步失败只允许补偿本地状态。

### 3.6 Security

- 无 token 返回未认证；无 `system:order:edit` 返回无权限；
- 原因空白、超长、非法状态值被后端拒绝；
- 错误响应不含堆栈、凭证或原始网关报文；
- 状态专用接口不能修改金额、用户、门店、商品、支付类型或骑手；
- 旧 `PUT /system/order` 不能再写五个受保护状态/时间字段。

## 4. Manual Scenario Matrix

测试前准备可恢复的测试订单，不直接在生产库执行 SQL 写入。

| Scenario | Initial `state/delivery/pay/afterSale` | Action | Expected |
|---|---|---|---|
| 外送配送中→送达 | `2/2/1/0` | 修改配送为 3 | `3/3/1/0`，有 `sdTime`、账单、管理员日志 |
| 自取线下收款 | `2/NULL/0/0`, payType=1 | 确认收款 | `2/NULL/1/0`，无 OMG 流水 |
| 自取完成 | `2/NULL/1/0` | 订单改为 3 | `3/NULL/1/0`，商家账单一次 |
| 线下退款 | `1/NULL/1/0`, payType=1 | 二次确认退款 | `4/NULL/2/3`，积分幂等返还 |
| OMG 漏单 | `0/NULL/0/0`, payType=7 | 查询 OMG | 仅 OMG 实付时变 `pay=1` |
| OMG 信用卡退款 | `1/NULL/1/0`, payType=7 | 发起退款 | 网关成功后 `4/NULL/2/3` |
| OMG 延期支付退款 | `1/NULL/1/0`, payType=7 | 发起退款 | 状态不变，显示人工待办 |
| OMG 人工退款完成 | `1/NULL/1/0`, payType=7，已有待办 | 二次确认人工退款完成 | `4/NULL/2/3`，待办关闭并记录管理员 |
| 陈旧页面 | 任意 | 其他链路先改状态后提交 | 提示刷新，最新数据不被覆盖 |
| 已完成退款 | `3/*/1/0` | 任一退款 | 拒绝并说明需结算冲正 |

## 5. UI Verification

对 `zh_CN`、`zh_TW`、`en_US`、`vi` 逐一检查：

1. 搜索区状态标签；
2. 表格状态 tag；
3. 订单详情状态；
4. 修改弹窗当前值和允许下拉项；
5. 修改原因校验；
6. 确认收款、补单、退款按钮；
7. 二次确认、成功、冲突、人工待办和结果未知提示。

不得出现原始 i18n key、空白按钮或新增中文硬编码。

## 6. Read-only Data Checks

仅在测试/预发布环境进行只读核对：

```sql
SELECT id, dd_id, type, pay_type, state, delivery_status,
       pay_status, after_sale_status, qs_id, sd_time
FROM pos_order
WHERE id = ?;

SELECT operator_type, operator_id, operator_name, content, create_time
FROM pos_order_log
WHERE dd_id = ?
ORDER BY id DESC;

SELECT id, dd_id, trade_no, pay_type, amount, pay_status, update_time
FROM pos_order_omg_payment
WHERE dd_id = ?
ORDER BY id DESC;

SELECT payment_id, action, amount, rtn_code, rtn_msg, create_time
FROM pos_order_omg_refund
WHERE dd_id = ?
ORDER BY id DESC;
```

## 7. Exit Criteria

- 所有新增/修改后端测试通过；
- 后端编译通过；
- 前端 lint 与生产构建通过，或仅存在已记录的无关历史问题；
- 手工矩阵全部符合契约；
- 四语言无缺失；
- `git diff --check` 通过；
- Git 当前分支仍为 `test`，未创建新分支；
- 没有数据库 DDL 或真实支付退款副作用。
