# V1 状态、异常与事务矩阵 本文档是 V1 状态迁移的执行基线。`13`、`14` 解释业务过程,本表固定合法迁移、守卫条件、副作用和反向处理。代码常量、数据库状态注释、API `allowed_actions`、事件、测试和页面标签必须使用同一英文状态码。 ## 一、通用状态规则 1. 状态由领域命令改变,Controller、前端、Listener 和 Job 不直接赋值。 2. 每次成功迁移写 `eb_farm_state_transition`,记录原状态、目标状态、事件、操作码、聚合版本、结果键和原因。 3. 迁移前锁聚合主行并重查守卫;前端传入的旧状态只用于冲突提示。 4. 失败事务不留下半个状态、汇总或 Outbox;事务外副作用失败使用原业务结果键补偿。 5. `closed/completed/refunded` 等终态不得重新打开;确需修复时建立异常、冲正或新版本,不改历史。 6. `frozen/suspended/exception` 是业务限制,不等同删除或关闭;必须保存冻结范围和恢复条件。 ## 二、商品资料与管理范围状态矩阵 ### 1. 商品农业资料 状态:`draft → pending_review → approved/rejected → disabled`。不存在农业资料不等于 `draft`;首次保存才创建记录。 | From | 命令/事件 | To | 守卫 | 核心副作用 | | --- | --- | --- | --- | --- | | 无/`draft/rejected` | 平台或商户保存 | `draft` | 商品归属、字段、附件和版本合法 | 当前资料、材料关系、审计快照 | | `approved` | 修改已批准资料 | `draft` | 保留历史业务快照 | 当前供货资格关闭,既有活动/订单不变 | | `draft/rejected` | 提交审核 | `pending_review` | 必填资料和有效材料完整 | 提交人、时间和提交快照 | | `pending_review` | 审核通过 | `approved` | 商品可用、材料有效、来源一致 | 根据规则开启 `supply_eligible` | | `pending_review` | 审核驳回 | `rejected` | 驳回原因和缺项清单完整 | 保留提交与审核快照 | | `approved/rejected` | 管理员停用 | `disabled` | 说明影响范围 | 禁止新供货和新活动引用 | | `disabled` | 恢复编辑 | `draft` | 商品仍存在 | 重新提交审核,不直接恢复批准 | 商品本身的 CRMEB 审核状态与农业资料状态独立;新供货必须同时满足商品可售、农业资料 `approved`、材料有效和 `supply_eligible=true`。材料到期只禁止新引用并触发预警/复核,不改写历史订单和发布快照。 ### 2. 管理员农业范围 `eb_farm_admin_scope` 行只在 `active/disabled` 间变化,不物理删除。`FARM_ADMIN_SCOPE_SAVE` 请求必须显式携带 `scope_set_version`,以目标管理员当前最大集合版本做乐观锁;同一事务锁目标管理员和全部范围行,全量目标集合与当前集合求差异。首次出现的范围写新行,移除范围停用旧行,再次授权已停用范围则更新并重新启用原行,不插入违反 `(admin_id,domain_code,scope_type,scope_object_id)` 唯一键的新行。一次保存涉及的新增、保留、停用和重新启用行统一写同一个新 `scope_set_version`,完整前后集合、授权人和有效期进入审计。范围变更立即影响新请求,已进入事务的命令仍按事务开始时已校验并锁定的对象完成。 ## 三、云仓状态矩阵 ### 1. 活动 状态:`draft → scheduled → warming → active → ended → inventory_closing → closed`;无有效付款的未开始/异常活动可进入 `cancelled`。 | From | 命令/事件 | To | 守卫 | 核心副作用 | | --- | --- | --- | --- | --- | | 无 | `CW_ACTIVITY_CREATE` | `draft` | 创建权限、基础时间合法 | 草稿和版本 | | `draft` | `CW_ACTIVITY_PUBLISH` | `scheduled` | 所有发布预检通过 | 发布快照、活动库存占用、批次草稿 | | `scheduled` | 时间进入预热窗 | `warming` | 未关闭、来源诊断仍可用 | 前台预热投影 | | `scheduled/warming` | 开始时间 | `active` | 活动 SKU 可售库存大于 0 | 开放抢购 | | `active` | 结束时间 | `ended` | 禁止新单 | `activity.ended` | | `ended` | 未支付订单均关闭 | `inventory_closing` | `unpaid_locked_qty=0` | 逐 SKU 处理未抢库存 | | `inventory_closing` | 每 SKU 闭合 | `closed` | 释放、退回待办或平台承接之和闭合 | `activity.inventory_closed` | | `draft/scheduled/warming` | `CW_ACTIVITY_CLOSE` | `cancelled` | 无有效付款;库存可完整释放 | 关闭原因和库存闭合 | 禁止:有有效付款后直接 `cancelled`;`ended` 直接启动批次;活动关闭时先恢复已在平台仓的商户来源可售库存。 ### 2. 供货申请 | From | 命令/事件 | To | 守卫 | 核心副作用 | | --- | --- | --- | --- | --- | | 无 | `CW_SUPPLY_CREATE` | `draft` | 当前商户单一来源 SKU | 申请草稿 | | 无 | `CW_PLATFORM_SUPPLY_CREATE` | `approved` | 自营商户商品、农业资料和材料有效;锁商品与来源 SKU,可售量充足 | `source_type=platform`、`merchant_id=NULL`,原子预占来源库存、责任快照和库存流水 | | `draft/supplement_required/rejected` | `CW_SUPPLY_SUBMIT` | `pending_review` | 材料、来源和版本完整 | 提交快照 | | `pending_review` | 审核要求补充 | `supplement_required` | 原因和缺项清单 | 不占来源库存 | | `pending_review` | 审核驳回 | `rejected` | 原因必填 | 不占来源库存 | | `pending_review` | 审核通过 | `approved` | 来源可售量足够 | 预留 `approved_qty`、责任快照 | | `approved/partially_delivered` | 交付发运 | `partially_delivered/delivered` | 累计发运不超批准量 | 在途数量流水 | | `delivered/partially_delivered` | 平台收货 | `received/partially_received` | 实收、短少方程闭合 | 收货与短少流水 | | `received/partially_received` | 验收完成 | `partially_accepted/accepted` | 合格、待检、拒收方程闭合 | 云仓可用、退回候选 | | `approved/partially_delivered` | 释放未交付余量 | `partially_closed/closed` | 无活动占用 | 来源预留释放 | | 任一非终态 | 质量/守恒异常 | `frozen` | 原因、范围、影响快照 | 禁止新交付/分配 | | `frozen` | 异常方案闭合 | 原业务状态 | 账实和责任闭合 | 恢复允许动作 | | 已验收后全部数量去向闭合 | 闭合检查 | `closed` | 退回/平台承接/活动消耗闭合 | 归档 | `rejected` 是审核结果;验收拒收数量通过验收/退回记录表达,不把已通过申请整体改回 `rejected`。 ### 3. 交付、验收与退回 | 聚合 | From | 事件 | To | 守卫 | | --- | --- | --- | --- | --- | | delivery | `draft` | dispatch | `in_transit` | 数量不超可交付,物流/交接证据完整 | | delivery | `in_transit` | receive partial | `partially_received` | 实收大于 0 且小于发运 | | delivery | `in_transit/partially_received` | receive complete | `received` | 实收 + 确认短少 = 发运 | | delivery | `draft` | cancel | `cancelled` | 未发运 | | inspection | 无 | create | `pending` | delivery 有待检实收 | | inspection | `pending` | partial | `partially_completed` | 仍有待检量 | | inspection | `pending/partially_completed` | complete | `completed` | 合格 + 拒收 + 待检 = 实收,最终待检为 0 | | return | 无 | create | `pending_dispatch` | 实物仍在平台控制 | | return | `pending_dispatch` | dispatch | `in_transit` | 交接证据完整 | | return | `in_transit` | merchant acknowledge | `received/disputed` | 差异时不得恢复来源库存 | | return | `received` | platform complete | `completed` | 双方证据或等价移交确认 | | acquisition | 无 | `CW_SUPPLY_ACQUIRE_PREPARE` | `pending_review` | 数量、价格、目标平台 SKU 和证据完整 | | acquisition | `pending_review` | `CW_SUPPLY_ACQUIRE_REVIEW` | `approved/rejected` | 审核人与制单人分离 | | acquisition | `approved` | `CW_SUPPLY_ACQUIRE_EXECUTE` | `completed` | 平台库存、供货汇总和库存流水同事务;失败保持可重试 | ### 4. 首次订单明细 | From | 命令/事件 | To | 守卫 | 核心副作用 | | --- | --- | --- | --- | --- | | 无 | `CW_ORDER_CREATE` | `pending_payment` | 活动、限购和库存有效 | 锁活动库存、建 CRMEB 单 | | `pending_payment` | `CRM_ORDER_PAID_ADAPT` | `paid_pending_choice` | 支付事实一致 | 付款快照、选择截止 | | `pending_payment` | 取消/超时 | `closed` | 未支付 | 释放活动锁定库存 | | `paid_pending_choice` | 确认代销 | `consign_pending_batch` | 未退款、未过截止 | 全量待入批次持仓 | | `paid_pending_choice` | 确认自提 | `pickup_pending` | 自提点有效 | 核销凭证 | | `paid_pending_choice` | 确认包邮 | `delivery_pending_fulfillment` | 地址可达 | 邮寄履约 | | `paid_pending_choice` | 确认需补运费邮寄 | `delivery_pending_freight` | 报价有效 | 运费单;最终去向尚未生效 | | `delivery_pending_freight` | 运费成功 | `delivery_pending_fulfillment` | 支付金额/交易号/选择版本一致 | 地址快照、履约 | | `delivery_pending_freight` | 运费取消/超时且仍在选择期 | `paid_pending_choice` | 成功回调未开始 | 临时邮寄失效 | | `paid_pending_choice/delivery_pending_freight` | 选择截止 | `consign_pending_batch` | 与人工选择互斥 | 自动代销 | | `delivery_pending_fulfillment` | 发货 | `delivery_in_transit` | 履约包裹已出库 | 物流 | | `delivery_in_transit` | 收货/自动完成 | `completed` | 售后条件满足 | 首次完成时间 | | `pickup_pending/pickup_partially_verified` | 部分核销 | `pickup_partially_verified` | 凭证有效、核销量小于剩余量 | 不可变核销流水和数量级完成事实 | | `pickup_pending/pickup_partially_verified` | 全部核销 | `completed` | 凭证有效、剩余量归零 | 核销和明细首次完成 | | `pickup_pending/pickup_partially_verified` | 到期 | `pickup_overdue` | 剩余量大于 0 | 保留已核销量并创建异常待协商 | | `consign_pending_batch` | 批次启动 | `consigning` | 选择冻结、批次数量闭合 | 生效持仓 | | `consigning` | 节点/最终计算 | `settling` | 有待处理账本 | 不阻断真实销售进度 | | `settling` | 尚未最终闭合 | `consigning` | 当前账本处理完成 | 继续代销 | | `consigning/settling` | 持仓账本全部闭合 | `completed` | 批次已售罄或回购完成 | 历史归档 | | 允许退款状态 | 退款申请 | `after_sale` | 批次未开始且整条可退 | 冻结去向/持仓/履约 | | `after_sale` | 全额退款完成 | `closed` | CRMEB 退款事实 | 库存与商户货款影响 | | `after_sale` | 退款拒绝/取消 | 原状态 | 原业务对象仍有效 | 解冻 | 一个明细只能有一个最终去向;不得从 `pickup_pending` 或已生效邮寄直接改成代销。自提逾期只处理剩余量,延期、改寄、退款或异常回购必须经过有版本和用户确认结果的异常方案。 `eb_farm_cloud_pickup` 自身状态同步为 `pending → partially_verified → verified`,到期有剩余量进入 `overdue`,协商处理中为 `exception`,未生效撤销为 `cancelled`;这些代码与订单明细的 `pickup_*` 状态分开。 首次退款与代销批次冻结竞争时统一先锁 `eb_farm_cloud_order_item`:退款事务先提交则该明细不进入持仓;批次冻结事务先提交则普通首次退款返回稳定错误并转云仓异常处理。两条路径不得同时产生退款影响和有效持仓。 ### 4.1 商户云仓履约协作动作 这些入口不另建一套履约状态机,均操作 `eb_farm_fulfillment`、包裹、CRMEB 售后事实和统一异常。责任方必须来自供货审核快照,不从当前商品资料反推。 | 操作码 | 允许状态/前置 | 状态影响 | 必须写入 | 禁止 | | --- | --- | --- | --- | --- | | `FULFILLMENT_SHIP` | 商户为邮寄责任方;待出库/部分发货;运费条件满足 | 待出库/部分发货 → 部分发货/已发货 | 出库流水、包裹、物流、责任快照和 Outbox | 超发、替用户改去向、覆盖平台包裹 | | `CW_FULFILLMENT_LOGISTICS_UPDATE` | 未签收、未锁定售后;包裹版本一致 | 不改变履约状态 | 物流前后快照、版本和审计 | 修改已出库数量、删除旧运单事实 | | `CW_FULFILLMENT_EVIDENCE_ADD` | 商户为邮寄/质量责任方;附件归属有效 | 不改变履约状态 | 追加证据关联和完整性版本 | 覆盖、删除历史证据 | | `CW_FULFILLMENT_RETURN_RECEIVE` | 售后退回在途;商户为售后责任方 | 根据实收进入待检、差异异常或退回完成 | 实收/短少/质量证据、数量快照;差异时统一异常 | 未验收先恢复可售库存、把短少记为实收 | | `FARM_EXCEPTION_CREATE` | 商户为责任方且事实/证据完整 | 原履约保持当前事实并关联异常/冻结建议 | 履约与责任快照、异常主表、影响初稿和 Outbox | 商户提交最终冻结金额、库存修复量或处理方案结果 | 物流更正、补证和异常上报可并发读取,但都使用履约/包裹版本;退回验收和发货涉及数量时按履约 → 包裹/售后 → 库存关联顺序加锁。版本冲突只允许刷新重做,不允许最后写入覆盖。 ### 5. 云仓补运费单 状态:`pending_payment → paying → paid`;可从未支付进入 `cancelled/expired`;迟到成功进入 `late_paid → refund_pending → refunded`,最终失败为 `refund_failed`。 | From | 事实 | To | 守卫/结果 | | --- | --- | --- | --- | | 无 | 需补运费 | `pending_payment` | 固化报价、地址版本;`expired_at=min(创建+支付超时, 去向截止)` | | `pending_payment` | 发起在线支付 | `paying` | 保存渠道和支付请求号 | | `pending_payment/paying` | 成功回调先取得锁 | `paid` | 同事务确认邮寄和履约 | | `pending_payment/paying` | 取消/超时先取得锁 | `cancelled/expired` | 明细回待选或自动代销 | | `cancelled/expired` | 后到成功回调 | `late_paid` | 不改变当前去向,创建全额退款 | | `late_paid` | 固定退款单建立 | `refund_pending` | 原渠道/余额退款 | | `refund_pending` | 退款成功 | `refunded` | 只更新退款事实和通知 | | `refund_pending` | 重试耗尽/事实冲突 | `refund_failed` | 异常和人工复核 | ### 6. 云仓批次 | From | 事件 | To | 守卫 | 核心副作用 | | --- | --- | --- | --- | --- | | 无 | 活动 SKU 草稿 | `draft` | 一 SKU 一批次 | 规则草稿 | | `draft` | 活动发布 | `reserved` | 供货已验收、活动占用成功 | 发布快照 | | `reserved` | 活动开始 | `selling` | 活动 active | 抢购库存开放 | | `selling` | 活动结束 | `choice_window` | 禁止新抢购 | 等待库存/去向闭合 | | `choice_window` | `batch.ready` | `consign_ready` | 未支付和未抢库存闭合,选择截止 | 冻结代销数量 | | `consign_ready` | 启动任务 | `consigning` | 持仓总量等于代销池 | 开放二次代销 | | `consigning` | 到期且有未售/在途 | `matured` | 停止新分配,进入 7 至 60 天在途处置宽限 | 等待有效售出或释放 | | `matured` | 宽限截止 | `matured` | 固化所有权切换点和整数未售量 | 未生效在途由平台承接 | | `matured` | 回购执行开始 | `buying_back` | 已审核且预检有效 | 平台回购 | | `consigning/matured/buying_back` | 最终金额待闭合 | `final_settlement` | 已售/未售归属确定 | 最终差额账本 | | `final_settlement` | 闭合检查 | `closed` | 库存、持仓、账本、入账和回购闭合 | 归档 | | `consigning` | 全部有效售出 | `final_settlement` | 二次售后观察均结束 | 无回购 | | `selling/choice_window/consign_ready/consigning/matured` | 异常冻结 | `suspended` | 保存原状态 `suspended_from` | 停止新抢购/分配/结算 | | `suspended` | 异常处理完成 | `suspended_from` | 恒等式闭合 | 恢复 | | `draft/reserved` | 无有效付款取消 | `cancelled` | 活动库存可释放 | 取消 | 回购完成不把真实销售进度改成 `100%`。进度只由有效二次销售量决定,未售部分以回购数量单独展示。 ### 7. 二次零售分配 | From | 事件 | To | 守卫 | 结果/副作用 | | --- | --- | --- | --- | --- | | 无 | 普通订单创建内 FEFO | `locked` | `cloud_only` SKU、批次可售量足够 | 锁定确定性批次分配 | | `locked` | 普通订单支付 | `paid` | 原分配仍有效 | 固化支付事实 | | `locked` | 普通订单关闭 | `released` | 未支付 | 释放二次可售量 | | `paid` | 发货/履约 | `fulfilling` | CRMEB 正常履约 | 仅更新履约事实,不提前计入销售 | | `paid/fulfilling` | 订单完成 | `observing` | 固化二次售后观察期 | 保持销售进度冻结 | | `observing` | 观察期结束 | `effective` | 无退款/争议 | 计入真实销售进度 | | `locked/paid/fulfilling/observing/effective` | 退款影响 | `reversed/partially_reversed` | 按退款明细实际数量 | 释放或冲减进度、冻结/冲正账本 | V1 不提供运营手工把分配改成 `effective` 的入口。 ### 8. 持仓、账本、入账和回购 | 聚合 | 状态链 | 关键限制 | | --- | --- | --- | | holding | `pending_batch → active → settling → completed`;异常可 `frozen` | 用户数量按批次共同进度分摊;不逐件指定“卖了谁的” | | user ledger | `prepared → pending_review/eligible → approved → posting → settled`;可 `frozen/rejected/reversed/recovery_pending` | 业务账本与正式余额入账分离,用户账本不直接变负 | | merchant ledger | `pending_eligibility → eligible → statement_locked → settled`;可 `frozen/adjusted` | 首次完成、验收和售后观察期均满足后才 eligible | | merchant statement | `draft → generated → pending_review/approved → posting → settled`;可 `rejected/partial_failed/adjusting` | 自然日不可变明细,结单生成不等于到账 | | financial posting | `prepared → processing → succeeded`;可 `retry_pending/failed/recovery_pending/reversed` | `posting_key` 唯一,成功不得重做 | | buyback | `prepared → pending_review → approved/rejected → executing → posting_pending → succeeded`;事务失败回 `execution_failed` 后按原键重试 | V1 必须人工审核;执行不接收前端金额,数据库步骤原子完成,不存在部分提交状态 | ## 四、租地、认养和生产状态矩阵 ### 1. 租地订单 | From | 事件 | To | 守卫/副作用 | | --- | --- | --- | --- | | 无 | 下单 | `pending_payment` | CRMEB 单一商品订单和规则快照 | | `pending_payment` | 支付 | `paid_pending_allocation` | 进入地块分配待办 | | `pending_payment` | 取消/超时 | `closed` | 不占真实地块 | | `paid_pending_allocation` | 地块确认 | `allocated` | 真实占用周期 | | `allocated` | 生产开始 | `planting` | 关联种植批次 | | `planting` | 首批采收开始 | `harvesting` | 产出批次 | | `planting/harvesting` | 有可履约产出 | `pending_delivery` | 产出分配和履约 | | `pending_delivery/harvesting` | 部分履约完成 | `partial_delivered` | 仍有应交付量 | | `partial_delivered/harvesting/pending_delivery` | 全部履约及售后闭合 | `completed` | 权益完成 | | 生产/履约状态 | 延期方案生效 | `delayed` | 保存原阶段和新预计时间 | | 非终态 | 异常建立/执行 | `exception` | 保存原状态;按方案补足/延期/退款 | | 可售后状态 | 售后申请 | `after_sale` | 冻结未履约部分 | | `delayed/exception/after_sale` | 处理完成 | 原业务状态/`completed/closed` | 按不可变方案结果 | ### 2. 认养订单 与租地相同的支付、履约和售后骨架,领域阶段为: ```text pending_payment → paid_pending_allocation → allocated → breeding → producing → pending_delivery → partial_delivered → completed ``` 特殊迁移: | From | 事件 | To | 守卫/副作用 | | --- | --- | --- | --- | | `allocated/breeding/producing` | 个体疾病/死亡且需替换 | `replacement_pending` | 保留原分配和健康档案 | | `replacement_pending` | 已审核原子替换 | 原阶段 | 新分配、替换链、生产/溯源关联同步 | | 非终态 | 疾病、死亡、减产、质量异常 | `exception` | 单体和批次份额使用各自影响模型 | 批次份额认养不得因展示需要迁移到“个体已分配”;模式在套餐发布快照中固定。 ### 3. 地块/资产预留 状态:`reserved → confirmed/released/expired/conflicted`。 | 迁移 | 守卫 | | --- | --- | | 无 → `reserved` | 候选满足当前约束;令牌摘要唯一;到期时间为创建后 5 分钟 | | `reserved` → `confirmed` | 未过期、订单仍待分配、资源版本未变,事务重新检查冲突 | | `reserved` → `released` | 操作者主动释放且尚未确认 | | `reserved` → `expired` | 任务取得锁且 `lock_expires_at <= now` | | `reserved` → `conflicted` | 确认时资源状态变化;同事务释放临时容量 | 同一地块重叠有效占用、同一单体资产重叠有效分配、批次份额超容量必须由数据库唯一/锁约束兜底。 ### 4. 生产批次 | From | 命令 | To | 守卫 | | --- | --- | --- | --- | | 无 | create | `planned` | 类型扩展、对象、权益和周期完整 | | `planned` | start | `in_progress` | 占用、资产健康和必需任务预检通过 | | `in_progress` | pause | `paused` | 原因和影响明确 | | `paused` | resume | `in_progress` | 异常/资源预检通过 | | `in_progress/paused` | exception freeze | `exception` | 保存原状态 | | `exception` | 方案完成 | 原状态/`completed` | 恒等式闭合 | | `in_progress` | complete | `completed` | 必需任务、产出和异常闭合 | | `planned` | cancel | `cancelled` | 未开始且不破坏已付权益 | ### 5. 农业任务 状态链:`draft → pending_assignment → assigned → in_progress → completed`;允许 `reassigned` 作为分派历史事件,不作为长期当前状态;可进入 `paused/cancelled/failed`。 | 迁移 | 守卫 | | --- | --- | | `pending_assignment → assigned` | 执行人职责、农场/对象范围和时间匹配 | | `assigned → in_progress` | 当前分派仍有效,执行人范围版本未撤销 | | `assigned/in_progress → reassigned` | 保留旧分派结束原因并建立新分派 | | `in_progress → completed` | 必需过程/产出/仓储事实已提交,数量、附件和证据完整;内容审核作为关联事实独立推进 | | 非终态 → `cancelled` | 无不可逆执行事实;否则通过异常方案闭合 | 任务完成不等于其关联过程记录已公开或产出已验收。审核驳回时创建明确返工任务或异常,不把已完成现场动作原地抹除。 ### 6. 过程记录与溯源内容 过程记录版本:`draft → pending_review → approved → published → withdrawn`,审核驳回为 `rejected`,修改后建立新 `draft` 版本。 溯源版本使用相同骨架,但 `approved` 只代表内容审核通过;必须由独立发布权限执行 `approved → published`。已发布版本不原地修改。 ### 7. 产出批次 | From | 事件 | To | 守卫/副作用 | | --- | --- | --- | --- | | 无 | 现场录入 | `draft` | 总量方程初检 | | `draft` | 提交 | `pending_quality` | 来源、单位和证据完整 | | `pending_quality` | 部分验收 | `partially_accepted` | 合格 + 损耗 + 待检 = 总量 | | `pending_quality/partially_accepted` | 全部验收 | `accepted` | 待检为 0;合格库存入库 | | `accepted` | 部分分配 | `partially_allocated` | 分配不超可用量 | | `accepted/partially_allocated` | 全部分配或剩余有明确归属 | `allocated` | 库存流水闭合 | | 非终态 | 质量/数量异常 | `frozen` | 禁止分配 | | `frozen` | 异常闭合 | 原状态 | 重算数量方程 | | `allocated` | 关联履约和溯源闭合 | `closed` | 历史只读 | ### 8. 农业邮寄履约 状态链: ```text draft → pending_address → address_confirmed → pending_freight(仅需补运费) → ready_to_pack → partially_shipped / shipped → partially_completed / completed ``` 可进入 `after_sale/frozen/cancelled`,但只对未出库部分取消或退款。 | 关键迁移 | 守卫 | | --- | --- | | `pending_address → address_confirmed` | 本人确认、可达、保存不可变地址版本 | | `address_confirmed → pending_freight` | 套餐快照判定用户承担且报价有效 | | `address_confirmed/pending_freight → ready_to_pack` | 包邮或运费支付成功 | | `ready_to_pack → partially_shipped/shipped` | 包裹、拣货、库存出库和唯一运单闭合 | | `shipped → completed` | 用户确认或自动完成,售后窗口规则满足 | | 未出库状态 → `cancelled` | 只回退未出库产出库存 | 农业产出 V1 只邮寄,不进入云仓自提点,也不转用户云仓代销。 ## 五、统一异常状态机 ### 1. 异常主状态 ```text reported → triaged → impact_assessing → planning → pending_review → approved → executing → resolved → closed ``` 分支状态:`rejected` 返回 `planning` 建新版本;执行失败进入 `partial_failed`;事实不足进入 `information_required`;无效重复可 `duplicate_closed` 并关联主异常。 | From | 命令/事实 | To | 必须产物 | | --- | --- | --- | --- | | 无 | 上报/系统检测 | `reported` | 类型、严重度、对象、事实、证据、发现时间 | | `reported` | 分诊 | `triaged` | 负责人、SLA、初始冻结范围 | | `triaged` | 影响重算 | `impact_assessing` | 订单、库存、资产、持仓、账本和通知对象快照 | | `impact_assessing` | 影响快照完成 | `planning` | 不可变 impact version | | `planning` | 方案提交 | `pending_review` | 不可变 plan version、有序步骤、预计结果 | | `pending_review` | 审核通过 | `approved` | 审核人、时间、预检有效期 | | `pending_review` | 驳回 | `rejected` | 原因;旧方案不覆盖 | | `approved` | 需要用户确认 | `pending_user_confirmation` | 确认截止、等价校验和超时策略快照 | | `pending_user_confirmation` | 用户确认 | `approved_to_execute` | 本人、方案版本、时间和确认结果 | | `pending_user_confirmation` | 3 个自然日超时 | `approved_to_execute/rejected_to_refund` | 完全等价且未超容忍期自动接受;降级、减量、超期或补款默认拒绝并转未履约退款 | | `approved/approved_to_execute` | 执行受理 | `executing` | async operation 和步骤结果键 | | `executing` | 部分步骤最终失败 | `partial_failed` | 已成功/失败/未执行步骤,保持影响对象冻结 | | `executing/partial_failed` | 全部必需步骤成功 | `resolved` | 数量、金额、资产和状态恒等式 | | `resolved` | 通知/审计闭合 | `closed` | 用户/商户通知结果、关闭说明 | ### 2. 方案步骤类型 | `step_code` | 允许动作 | 事务边界 | 反向方式 | | --- | --- | --- | --- | | `freeze_object` | 冻结订单、批次、库存、账本或任务 | 单聚合事务 | `unfreeze_object`,仅在原因解除后 | | `replace_plot` | 更换等价地块并保留原占用 | 原占用 + 新占用原子事务 | 再建替换方案,不删历史 | | `replace_asset` | 更换认养个体/份额 | 分配、替换链和容量原子事务 | 新替换方案 | | `allocate_substitute_output` | 以合格等价产出补足 | 产出库存 + 权益分配事务 | 未出库可取消分配 | | `extend_schedule` | 延长生产/履约预计时间 | 计划版本事务 | 新计划版本 | | `create_reshipment` | 对损坏/丢失包裹补发 | 新履约/包裹事务 | 未出库可取消 | | `refund_unfulfilled` | 按交付退款基数和累计退款数量退未履约部分 | CRMEB 退款编排 + 影响记录;本次金额为累计应退减历史/在途退款 | 退款成功后只能冲正 | | `buyback_cloud_stock` | 云仓未售平台回购 | 使用已审核回购命令 | 正式入账后只走冲正 | | `adjust_ledger` | 建立账本冲正/补记 | 只建调整,不直接写余额 | 反向 posting | | `restore_inventory` | 恢复可证明的库存 | 库存主表 + 不可变流水 | 反向库存流水 | | `notify_party` | 通知用户、商户、负责人 | 事务后 Job | 原通知键重试 | | `close_external_case` | 关闭 CRMEB 售后/物流协同 | 事务后适配器 | 外部事实冲突人工复核 | 方案不能包含“直接设置余额”“直接设置已售数量”“直接把进度改成 100%”“删除原资产/事件”“跳过支付退款事实”等自由动作。 ### 3. 默认异常决策 | 异常类型 | 首次系统动作 | 默认方案顺序 | 必须审批 | | --- | --- | --- | --- | | 供货短少 | 冻结短少量,不冻结已验收合格量 | 责任确认 → 调整预留 → 补交/释放 | 影响活动库存时云仓主管 | | 供货质量不合格 | 冻结拒收量 | 复检 → 退回 → 平台承接/销毁按证据 | 仓储 + 质量 | | 活动库存不闭合 | 暂停批次启动 | 重算未付/未抢 → 修复流水 → 闭合 | 云仓主管 | | 云仓运费迟到支付 | 保持当前去向 | 固定单号全额退款 → 通知 → 对账 | 无需金额审批;冲突需财务 | | 二次退款已影响结算 | 冻结关联待入账 | 冲减进度 → 抵扣未入账/同持仓未来应付 → 不足记平台风险承担 | 财务 | | 到期未售 | 不视为系统异常 | 人工审核回购预案 → 平台回购 → 最终结算 | 云仓运营 + 财务 | | 地块无候选 | 保持订单待分配并告警 | 等价地块 → 延期 → 退未履约/全额 | 农业主管 | | 作物减产 | 冻结不合格/缺口数量 | 按未履约量比例和最大余数法分配合格量 → 等价批次 → 延期 → 按交付退款基数退缺口 | 农业主管 | | 作物绝收 | 暂停原批次 | 等价批次 → 重种延期 → 退未履约 | 农业主管 | | 动物疾病 | 隔离并冻结资产新分配 | 治疗观察 → 等价资产替换 → 延期 | 养殖主管 | | 动物死亡 | 冻结原分配关系 | 按物种、品种/性别/日龄体重、健康和时间标准校验等价资产 → 用户确认/超时规则 → 原子替换或退款 | 养殖主管 | | 产出质量不合格 | 禁止入履约库存 | 复检 → 等价产出补足 → 延期/退款 | 质量 + 农业 | | 包裹损坏/变质 | 冻结对应包裹售后 | 补发 → 无货退对应未履约金额 | 客服/仓储 | | 物流丢失 | 标记包裹异常 | 补发或退款 → 责任对账 | 客服/仓储 | | 溯源材料失效 | 对公开档案显示过期提示,必要时撤回 | 替换有效材料 → 重新审核发布 | 内容审核/发布人 | ## 六、事务失败与反向处理矩阵 | 场景 | 提交前失败 | 提交后事务外失败 | 已产生后续业务事实 | | --- | --- | --- | --- | | 云仓首次下单 | CRMEB 单、binding、明细、库存和 Outbox 全回滚 | 无事务外关键动作;支付由用户另行发起 | 未支付取消按 binding 恢复云仓库存 | | 支付成功适配 | 支付事实与农业状态同事务回滚,由回调/修复重试 | 通知、投影重试 | 不重复收款;冲突支付进入异常 | | 活动发布 | 快照、占用、批次草稿全回滚 | 缓存/预热重试 | 有付款后不得回滚发布,走关闭和库存闭合 | | 供货审核/验收 | 预留或验收流水全回滚 | 通知/任务重试 | 实物已移动时必须走退回/平台承接 | | 去向确认 | 不产生半个持仓、凭证或履约 | 通知重试 | 已最终生效不得直接改去向 | | 补运费支付 | 邮寄和履约未确认;回调可重试 | 物流待办重试 | 迟到支付只退款,不抢回去向 | | 二次 FEFO 分配 | 普通订单和普通 SKU 扣减一起回滚 | 投影修复 | 支付后不能换批次;退款按原分配冲正 | | 节点账本 | 进度、差额账本和 Outbox 全回滚 | 正式入账 Job 重试 | 已入账差异走冲正,不删账本 | | 回购 | 平台库存、回购量和用户账本全回滚 | 入账/通知重试 | 已入账错误走冲正 | | 商户结单 | 候选占用和结单明细全回滚 | posting 重试 | 已入账差异走 adjustment | | 资源分配 | 订单、预留、占用/分配全回滚 | 通知/生产准备重试 | 替换用新关系和替换链 | | 产出分配 | 产出库存、权益分配、履约全回滚 | 地址通知重试 | 已出库只能售后/补发/退款 | | 异常步骤 | 当前步骤业务结果和状态全回滚 | 通知/外部动作按原键重试 | 已成功步骤不反复执行,后续方案补偿 | | 溯源发布 | 当前公开指针和发布状态全回滚 | 缓存/二维码重试 | 错误版本走撤回和新版本 | ## 七、关键恒等式 ### 1. 供货 ```text approved_qty = source_reserved_qty + dispatched_qty + shortage_qty + post_approval_cancelled_qty received_qty = accepted_qty + rejected_qty + pending_inspection_qty accepted_qty = activity_reserved_qty + cloud_unallocated_qty + return_pending_qty + returned_qty + platform_acquired_qty ``` ### 2. 云仓活动与批次 ```text activity_reserved_qty = effective_paid_qty + unsold_released_or_return_pending_qty + unpaid_released_qty + primary_refund_returned_qty effective_paid_qty = shipping_qty + pickup_qty + consign_qty + primary_after_sale_frozen_qty consign_qty = effective_resale_qty + resale_locked_qty + available_resale_qty + resale_after_sale_frozen_qty + buyback_qty ``` ### 3. 产出与权益 ```text output_total_qty = qualified_qty + loss_qty + pending_inspection_qty qualified_qty = available_qty + allocated_qty + frozen_qty + disposed_qty right_promised_qty - refunded_unfulfilled_qty = allocated_output_qty + remaining_delivery_obligation_qty ``` 每次状态迁移涉及上述数量时,必须在同事务验证迁移前和迁移后的恒等式;页面汇总差异不能靠“重算按钮”直接覆盖。 ## 八、状态测试要求 - 每条表内合法迁移至少有成功和幂等重放测试。 - 每个未列出的跨状态请求必须失败并保持原状态、版本、库存、账本和 Outbox 不变。 - 支付、超时、自动代销、退款、分配确认、回购和异常步骤必须做双线程争锁测试。 - 冻结/暂停后所有禁止动作必须在后端返回稳定错误码,不能只隐藏按钮。 - 恢复动作必须验证冻结原因已解除和恒等式闭合。 - 所有终态必须验证历史可查询、不可物理删除、不可直接改回进行中。 ## 九、关联文档 - [13-cloud-warehouse-process-and-state-machines.md](13-cloud-warehouse-process-and-state-machines) - [14-land-adoption-and-traceability-prd.md](14-land-adoption-and-traceability-prd) - [15-v1-data-model-draft.md](15-v1-data-model-draft) - [31-v1-write-operation-contract-registry.md](31-v1-write-operation-contract-registry) - [32-v1-event-job-operation-registry.md](32-v1-event-job-operation-registry) - [34-v1-database-field-dictionary.md](34-v1-database-field-dictionary)