diff --git a/changelogs/2026-04/23_refactor_order-v2_process-status-v2.md b/changelogs/2026-04/23_refactor_order-v2_process-status-v2.md new file mode 100644 index 0000000..f34cf35 --- /dev/null +++ b/changelogs/2026-04/23_refactor_order-v2_process-status-v2.md @@ -0,0 +1,114 @@ +# 订单内部流程 ProcessStatus V2 重构(Cola 状态机 + 清单确认 + 申请开票) + +**日期**: 2026-04-23 +**PR**: #1318 (dev) +**Issue**: #1310 +**类型**: refactor +**服务**: hl-order-service-v2 + +--- + +## 摘要 + +订单内部流程状态 `ProcessStatus` 彻底重构:线性 switch → Cola 状态机;新增"清单确认"节点统一改尾款;新增"申请开票"C 端入口;房差/车差自动写入优惠/增项。 + +## 新流程 + +``` +PENDING_TRAVELER_INFO → PENDING_ROOM_CONFIG → PENDING_VEHICLE_CONFIG + → PENDING_CHECKLIST_CONFIRM → READY → PENDING_INVOICE +``` + +## 枚举值变化(字典 order_process_status) + +### 删除(老值软删) +- PENDING_INFO / PENDING_ROOM / PENDING_VEHICLE / PENDING_FINANCE +- PENDING_INSURANCE / PENDING_CONTRACT / INTERNAL_CONFIRMED + +### 新增(6 个) +| value | label | 业务含义 | +|-------|-------|---------| +| `PENDING_TRAVELER_INFO` | 待补全出行人信息 | 支付订金/全款后初始态 | +| `PENDING_ROOM_CONFIG` | 配置房子 | 出行人齐全后 | +| `PENDING_VEHICLE_CONFIG` | 配置车辆 | 房型分配后 | +| `PENDING_CHECKLIST_CONFIRM` | 确认清单 | 车辆分配后,确认前 | +| `READY` | 已就绪 | 清单确认通过,保险/合同异步触发 | +| `PENDING_INVOICE` | 待开票 | 尾款付清后用户主动申请开票 | + +## 接口变化(管理端 + C 端) + +### 新增接口 + +#### 1. `POST /admin/order/{orderId}/checklist-confirm` +**管理员确认清单**(把所有未确认优惠/增项批量锁定 → 推进到 READY → 触发保险/合同自动化) +- **权限**: Admin +- **幂等**: `@Idempotent(60s)` · key = `orderId + operatorId` +- **校验**: + - `processStatus == PENDING_CHECKLIST_CONFIRM` + - 尾款计算 `totalPrice - SUM(confirmedDiscount) + SUM(confirmedSurcharge) - paidAmount >= 0`(含即将 confirmed=true 的条目) + - `checklist_confirmed != true`(幂等双保险) +- **响应**: `Result` +- **失败**: `确认后尾款为负(¥-xxx),请调整优惠/增项` / `流程状态不正确` / `清单已确认` + +#### 2. `POST /mp/orders/{orderId}/checklist/confirm` +**用户端确认清单**(架构预留,本次 PR 未上线 MP Controller,待下个 PR) + +### 修改接口 + +#### 3. `POST /mp/invoices/apply`(既有 `OrderInvoiceService.applyInvoice` 升级) +**申请开票** +- **幂等**: `@Idempotent(300s)` · key = `userId + orderId` +- **新增 Guard**: + - `processStatus == READY` + - OrderStatus NOT IN `{CANCELLED, REFUNDED, REFUNDING}` + - `paidAmount >= totalPrice`(原只检查 `paidAmount > 0`) +- **保留**: 原 countValidByOrderId 判重兜底 +- **失败**: + - `流程状态不允许开票,请先完成确认清单` + - `订单已取消或退款,无法开票` + - `尾款未结清,无法开票` + +### VO 字段变化 + +#### `OrderDiscountVO` / `OrderSurchargeVO`(新增 3 字段) +```json +{ + "confirmed": true, // false=未确认不影响尾款,true=已确认 + "sourceType": "ROOM_ASSIGN", // MANUAL / ROOM_ASSIGN / VEHICLE_ASSIGN + "sourceRefId": 12345 // 来源主键(如 hotel_assignment_id) +} +``` + +#### `OrderVO` / `OrderDetailVO` +- `待确认差价`(`pendingUpgradeAmount`)字段过渡期保留,返回值恒为 0(T+2 周清理 PR 硬删) +- `processStatus` / `processStatusLabel` 返回新 6 个枚举值(字典自动下发 label) + +## 保险/合同触发时机变化(⚠️ 重要) + +- **旧**: 订单 CONFIRMED 时立即自动投保/签约(`OrderConfirmedEvent`) +- **新**: **清单确认时**触发(`ChecklistConfirmedEvent`)→ 避免出行人/房型未定就投保导致的退保重投 +- 失败处理: 业务失败 → 创建 `OrderTodo` 人工补救;5xx/超时 → LocalEvent 兜底 +- ProcessStatus 保持 READY 不变(即使保险或合同失败) + +## 追加优惠/增项自动 REOPEN + +- 订单 `process_status ∈ {READY, PENDING_INVOICE}` + `checklist_confirmed = true` 时 +- 调用 `addDiscount` / `addSurcharge` 会自动触发 `PROC_CHECKLIST_REOPENED` +- 订单回退到 `PENDING_CHECKLIST_CONFIRM`,`checklist_confirmed=false` +- **已完成的保险/合同不反向取消**(业务硬规则) +- 新追加的条目 `confirmed=false`,需要再次"确认清单" + +## 前端影响(前端 AI 必读) + +1. 订单详情页的 `待确认差价` 字段**过渡期保留值为 0**,**不要**继续读此字段做展示;改读 `discounts[]` / `surcharges[]` 数组 + 按 `confirmed` 字段分组展示 +2. 流程状态标签 6 个新中文(字典自动下发) +3. Admin 端**新增"确认清单"按钮**,调 `POST /admin/order/{orderId}/checklist-confirm` +4. Admin 端 `addDiscount` / `addSurcharge` 在订单已 READY/PENDING_INVOICE 时会**自动 REOPEN**,前端需要刷新订单状态 +5. C 端新增"申请开票"入口,调 `POST /mp/invoices/apply`(需订单 processStatus = READY + 尾款已付清) + +## 文档 + +- 需求单 V2: `docs/tasks/order-process-v2-statemachine-20260423.md` +- 架构详设: `docs/tasks/order-process-v2-arch-design-20260423.md` +- 评审报告: `docs/tasks/order-process-v2-review-v2-20260423.md` +- CR 报告: `docs/tasks/order-process-v2-cr-20260423.md`