Date: 2026-08-10 Database change: None
PosOrder / pos_order本功能只使用现有字段,不新增列。
| Java 字段 | 数据库列 | 类型 | 本功能含义 |
|---|---|---|---|
id |
id |
BIGINT | 内部订单主键,管理端接口路径参数 |
ddId |
dd_id |
VARCHAR | 业务订单号,日志和 OMG 流水关联键 |
type |
type |
BIGINT | 0 外送、1 自取、2 堂食 |
state |
state |
BIGINT | 0 待处理、1 已接单、2 已出餐、3 已完成、4 已取消 |
deliveryStatus |
delivery_status |
BIGINT NULL | 外送:0 待接单、1 骑手已接单、2 配送中、3 已送达 |
payStatus |
pay_status |
BIGINT | 0 未支付、1 已支付、2 已退款 |
afterSaleStatus |
after_sale_status |
BIGINT | 0 无售后、1~6 为售后流程状态 |
payType |
pay_type |
VARCHAR | 1 线下/到付,7 OMG;历史类型不在本功能启用 |
collectPayment |
collect_payment |
VARCHAR | 到付标识,保留给既有账单逻辑 |
qsId |
qs_id |
BIGINT NULL | 骑手 ID;本功能不提供指派能力 |
sdTime |
sd_time |
DATETIME NULL | 实际送达时间 |
points |
points |
INT NULL | 退款/取消时需要返还的积分 |
PosOrderLog / pos_order_log| 字段 | 用途 |
|---|---|
ddId |
关联业务订单号 |
operatorType |
管理员固定为 1;系统资金日志为 0 |
operatorId |
当前后台管理员 ID |
operatorName |
当前后台管理员名称 |
content |
状态前后值、动作和原因,最大 512 字 |
logTime |
服务端写入时间 |
人工操作使用同步日志,保证状态事务回滚时不会残留“成功”日志。
PosOrderOmgPayment / pos_order_omg_payment订单层 payStatus 只有 0/1/2;OMG 流水有更细的内部状态:
pay_status |
含义 | 管理端行为 |
|---|---|---|
| 0 | 未支付 | 允许查询补单 |
| 1 | 已支付 | 未完成订单允许退款 |
| 2 | 支付失败 | 不得人工改为已支付;需要重新发起支付 |
| 3 | 已退款 | 订单层应补偿为 payStatus=2 |
| 4 | 退款中/结果未知 | 禁止重复退款,提示等待对账 |
PosOrderOmgRefund / pos_order_omg_refund| 字段组合 | 含义 |
|---|---|
action=R, rtnCode=1 |
OMG 自动退款成功 |
action=R, rtnCode!=1 |
OMG 明确退款失败 |
action=R, rtnCode=NULL |
请求处理中或结果未知,结合 rtnMsg 判断 |
action=NULL, rtnCode=NULL |
支付方式不支持退款 API,等待人工处理 |
action=NULL, rtnCode=1 |
管理员确认已在 OMG 后台完成人工退款 |
同一支付流水只保留一个未决人工待办;已存在时重复请求返回原状态。
AdminOrderActionRequest所有支付动作与状态动作共享的旧快照和审计字段。
| 字段 | Java 类型 | 校验 |
|---|---|---|
expectedState |
Long |
必填,0~4 |
expectedDeliveryStatus |
Long |
可空;非空时 0~3 |
expectedPayStatus |
Long |
必填,0~2 |
expectedAfterSaleStatus |
Long |
必填,0~6 |
reason |
String |
必填,trim 后 1~200 字 |
AdminOrderStatusUpdateRequest继承/组合 AdminOrderActionRequest,增加:
| 字段 | Java 类型 | 校验 |
|---|---|---|
targetState |
Long |
可空,非空时 0~4 |
targetDeliveryStatus |
Long |
可空,非空时 0~3 |
规则:至少一个目标值与快照不同;未提交的目标保持当前值。外送送达可以只提交 targetDeliveryStatus=3,服务端自动同步 state=3。
AdminOrderStatusContext| 字段 | 类型 | 说明 | |
|---|---|---|---|
id, ddId |
Long/String | 订单标识 | |
type, payType |
Long/String | 类型判定依据 | |
state, deliveryStatus, payStatus, afterSaleStatus |
Long | 当前快照 | |
sdTime |
Date | 当前送达时间 | |
riderAssigned |
Boolean | qsId != null |
|
allowedOrderStates |
List | 包含当前值及可选下一值 | |
allowedDeliveryStatuses |
List | 非外送为空 | |
canConfirmOfflinePayment |
Boolean | 可确认线下收款 | |
canConfirmOfflineRefund |
Boolean | 可确认线下退款 | |
canReconcileOmg |
Boolean | 可查询 OMG 补单 | |
canRefundOmg |
Boolean | 可发起 OMG 退款 | |
canConfirmManualOmgRefund |
Boolean | 已有待办且可确认人工退款完成 | |
omgPaymentStatus |
Integer NULL | 最新 OMG 流水状态 0~4 | |
manualRefundPending |
Boolean | 存在未决人工退款记录 | |
refundUnknown |
Boolean | OMG 流水为退款中/结果未知 |
| 状态 | 说明 | 订单层处理 |
|---|---|---|
REFUNDED |
OMG 明确退款成功 | 同步为已退款/已取消/售后已退款 |
MANUAL_PENDING |
无自动退款 API | 保持已支付,显示待人工处理和确认入口 |
UNKNOWN |
请求结果未知 | 保持已支付,OMG 流水保持退款中 |
FAILED |
网关明确失败 | 保持已支付,OMG 流水恢复已支付 |
IDEMPOTENT |
已退款或正在处理 | 返回当前最终状态,无重复副作用 |
以下不变量必须在每个写入口成立:
type IN (1,2) → deliveryStatus IS NULL。deliveryStatus=3 → type=0 AND state=3 AND sdTime IS NOT NULL。state=3 → payStatus=1 AND afterSaleStatus=0(本期不允许完成后退款)。payStatus=2 → state=4 AND afterSaleStatus=3(本功能处理的全额退款)。payType=7 AND payStatus=1 必须存在 OMG 已支付流水。payType=7 AND payStatus=2 必须存在 OMG 自动退款成功记录或管理员明确确认人工退款完成;人工待办不提前置 2。state IN (3,4)、payStatus=2 为本功能终态,普通状态接口不能重新打开。afterSaleStatus>0 时,普通订单/配送状态接口不得变更数据。| Current | Target | Additional conditions | Result |
|---|---|---|---|
| 0 | 1 | OMG 订单必须已支付;无售后 | state=1 |
| 1 | 2 | 无售后 | state=2;外送若配送为空则初始化为 0 |
| 2 | 3 | 已支付;外送已送达,自取/堂食无配送状态 | state=3 + 完成副作用 |
| 0 | 4 | 未支付、无售后 | state=4 |
| 1 | 4 | 未支付、无售后 | state=4 |
其他跳转全部拒绝。已支付订单取消必须使用退款动作。
| Current | Target | Conditions | Result |
|---|---|---|---|
| NULL | 0 | 外送,state=2 |
等待骑手接单 |
| 0 | 1 | 外送,已有 qsId,state=2 |
骑手已接单 |
| 1 | 2 | 外送,已有 qsId,state=2 |
配送中 |
| 2 | 3 | 外送,已有 qsId,已支付,无售后 |
配送已送达 + 订单完成 + 送达时间 + 账单 |
配送状态不得跳级或回退。相同值视为无变化。
payType="1"0 --confirm-payment--> 1
1 --confirm-refund--> 2
state=4 和 afterSaleStatus=3。payType="7"order.payStatus 0 --callback/query + ledger CAS--> 1
order.payStatus 1 --real refund success--> 2
管理员请求体不能携带目标 payStatus。OMG 流水状态 4 期间订单仍显示已支付,并额外显示“退款结果待核对”。
对于无退款 API 的支付方式:创建未决人工记录时订单和支付流水保持已支付;管理员完成外部人工退款并二次确认后,支付流水通过既有 1→4→3 CAS,新增 action=NULL, rtnCode=1 的完成记录,再同步订单三状态。
逻辑条件:
UPDATE pos_order
SET ...
WHERE id = :id
AND state = :expectedState
AND pay_status = :expectedPayStatus
AND after_sale_status = :expectedAfterSaleStatus
AND delivery_status <=> :expectedDeliveryStatus;
实现使用 MyBatis-Plus 条件构造器参数化生成;上面的 MySQL <=> 仅用于说明 NULL-safe 语义,不要求新增 XML SQL。
CAS 失败时:
status-context。日志内容保持可读且不超过 512 字:
平台调整[订单/配送]:state 2→3,delivery 2→3,pay 1→1,afterSale 0→0;原因:骑手端漏操作
平台确认线下收款:pay 0→1;原因:门店已收现金
平台发起OMG补单:pay 0→1;原因:用户提供付款凭证
平台OMG退款成功:state 1→4,pay 1→2,afterSale 0→3;原因:商家无法履约
不得记录 OMG HashKey/HashIV、token、完整回调原文或其他秘密。
无数据库迁移,不修改 updatesql/sql.md。如测试发现现有生产表 pos_order_log.content 不是 512 字,应暂停实现并单独提出迁移评审,不在本功能中自动执行 DDL。