# V1 写操作契约登记表 本文档把 [19-v1-api-contract-draft.md](19-v1-api-contract-draft) 中的写接口进一步冻结为可实现、可测试、可审计的命令契约。页面字段仍以 `18`、`30` 为准,物理表字段以 `34` 为准,状态迁移以 `33` 为准。 ## 一、适用规则 ### 1. 每个写请求的固定信封 除支付渠道回调、事件消费者和定时任务外,所有 HTTP 写请求都必须具备: | 项目 | 冻结规则 | | --- | --- | | 操作者 | 从登录态取得 `actor_type + actor_id`,禁止客户端指定 | | 数据范围 | 平台管理员按 `eb_farm_admin_scope`,服务人员按 `eb_farm_service_scope`,商户强制当前 `mer_id`,用户强制当前 `uid` | | 幂等键 | 业务请求体携带 UUID `request_id`;唯一键为 `operation_code + actor_type + actor_id + request_id` | | 请求摘要 | 服务端对规范化请求计算 `request_hash`;同键不同摘要返回 `COMMON_IDEMPOTENCY_CONFLICT` | | 乐观锁 | 修改已有聚合必须携带 `version`;不匹配返回 `COMMON_VERSION_CONFLICT` | | 金额数量 | 金额为两位十进制字符串,数量按业务单位使用三位或四位十进制字符串;不得使用浮点计算 | | 审计原因 | 关闭、驳回、冻结、解冻、冲正、回购、异常执行和权限变更必须提交稳定 `reason_code` 与说明 | | 响应动作 | 返回 `allowed_actions`、最新 `version`、业务状态和 `next_action`;前端不得自行推导可写状态 | `GET`、纯预检和纯预览不写 `eb_farm_idempotency_record`;一旦预检需要产生可复用报价、选择令牌或候选预留,就改为写命令并分配稳定操作码。 ### 2. 固定响应类型 | 类型 | HTTP | 响应要求 | | --- | --- | --- | | 同步完成 | `200` | 返回目标 ID、业务号、状态、版本、首次完成时间和 `allowed_actions` | | 创建完成 | `200` | 延续 CRMEB 当前成功外壳,不因 REST 风格改成 `201` | | 异步受理 | `202` | 返回 `operation_no`、状态查询地址和建议轮询间隔 | | 幂等重放 | 与首次相同 | 返回首次业务结果,`meta.idempotent_replay=true` | | 业务冲突 | `200` + CRMEB 失败外壳 | 使用 `19` 的稳定业务错误码,不把可预期冲突伪装成 500 | | 系统故障 | `500` | 记录 `trace_id`,响应不暴露 SQL、密钥、内部类名或堆栈 | 异步状态统一查询: `GET farm/operation/detail/:operation_no` 查询仍执行操作者和数据范围校验;成功结果只返回脱敏业务摘要或受控下载地址,不返回 Job 内部对象。 ### 3. 固定事务顺序 所有命令遵守: ```text 幂等/回调事实 → CRMEB 订单组、订单、订单明细或支付/退款单 → 农业聚合主表 → 物理资源主表 → 分配/占用/履约子表 → 业务账本或结单 → 用户/商户账户 → 库存/财务不可变流水 → 状态迁移、审计和 Outbox ``` 表中“事务写集”只列业务核心;每个成功状态变化还必须写 `eb_farm_state_transition`、必要的 `eb_farm_audit_log` 和同事务 `eb_farm_domain_outbox`。通知、缓存、第三方物流查询、二维码生成和导出不得放在业务事务中。 ## 二、CRMEB 核心适配命令 这些命令不是新公开路由,而是现有 CRMEB 下单、支付、取消和退款链路内的策略分支。 | 操作码 | 触发点 | 前置与策略 | 事务写集 | 事件/结果 | | --- | --- | --- | --- | --- | | `CRM_ORDER_GROUP_POLICY_CHECK` | 确认订单、提交订单前 | 一个 `group_order_id` 只能有一种 `finance_policy`;普通与 `farm_managed` 必须拆组或拒绝 | 只读校验;创建时固化 `eb_farm_order_binding` | 冲突返回 `CW_CART_FINANCE_POLICY_MIXED` | | `CRM_ORDER_PAID_ADAPT` | `paySuccess` 进入普通副作用前 | 锁订单组、子订单、明细和 binding;按 `normal/cloud_primary/cloud_resale/land/adoption` 选择副作用矩阵 | 付款事实、农业扩展状态、迁移、Outbox;农业策略跳过普通商户净收入/分销副作用 | 产生对应 `*.paid` 事件;重复回调返回首次事实 | | `CRM_ORDER_CANCEL_ADAPT` | 核心库存、活动、优惠券恢复前 | 先解析整组单一策略;仅未支付/允许关闭状态 | 按策略恢复普通库存、云仓首次库存或二次分配,不重复恢复 | `farm.cloud.order.pay_expired` 或 `farm.cloud.resale.released` | | `CRM_REFUND_PREPARE_ADAPT` | `executeRefund` 调用 `subLockMoney` 前 | 决定普通锁定款、云仓账本、履约和库存影响;首次只允许整条明细 | 退款影响草稿、冻结关联业务对象、Outbox | 不可退返回稳定窗口/状态错误 | | `CRM_REFUND_AFTER_ADAPT` | 核心退款事实提交后 | 使用退款单号和退款事实幂等 | 首次/二次影响、库存或分配冲正、账本冻结/冲正、Outbox | `farm.cloud.primary.refunded` 或 `farm.cloud.resale.reversed` | | `CRM_PAYMENT_RETURN_RESOLVE` | 支付结果页 | 只读 binding,不改变支付事实 | 无 | 返回安全白名单 `returnPath` 与业务 `next_action` | ### 1. 定时任务和事件消费者内部操作码 内部任务不伪造 HTTP 请求,也必须使用唯一稳定操作码写状态迁移、审计或任务结果。以下代码均不注册公开路由;其事实键、选择器和重试参数以 `32` 为准。 | 操作码 | 唯一触发器 | 核心业务结果 | | --- | --- | --- | | `SYS_CW_ACTIVITY_ADVANCE` | `CloudActivityStatusJob.php` | 活动预热、开始或自然结束 | | `SYS_CW_INVENTORY_CLOSE` | `CloudActivityInventoryCloseJob.php` | 未抢库存释放、退回待办/承接和活动库存闭合 | | `SYS_CW_UNPAID_RELEASE` | `CloudUnpaidReleaseJob.php` | 修复未支付首次库存释放 | | `SYS_CW_PAID_REPAIR` | `CloudPaidRepairJob.php` | 修复 CRMEB 已付与农业付款事实差异 | | `SYS_CW_CHOICE_REMIND` | `CloudChoiceReminderJob.php` | 去向截止分阶段通知 | | `SYS_CW_CHOICE_EXPIRE` | `CloudChoiceExpireJob.php` | 超时整条自动转代销 | | `SYS_CW_FREIGHT_EXPIRE` | `CloudFreightExpireJob.php` | 运费单本地超时收敛和渠道关单投递 | | `SYS_CW_FREIGHT_REPAIR` | `CloudFreightPaymentRepairJob.php` | 云仓运费支付、关单和退款事实修复 | | `SYS_CW_FREIGHT_REFUND` | `RefundCloudFreightJob.php` | 以原退款单号提交并确认全额运费退款 | | `SYS_CW_BATCH_START` | `CloudBatchStartJob.php` | 冻结选择、建立持仓并开放二次可售 | | `SYS_CW_PICKUP_OVERDUE` | `CloudPickupOverdueJob.php` | 自提剩余数量进入协商异常 | | `SYS_CW_RESALE_ALLOCATE` | 二次订单创建适配器/`CloudResaleAllocationRepairJob.php` | FEFO 批次分配 | | `SYS_CW_RESALE_RELEASE` | 二次订单关闭适配器/`CloudResaleReleaseJob.php` | 释放未支付二次分配 | | `SYS_CW_RESALE_EFFECTIVE` | `CloudResaleEffectiveJob.php` | 观察期后固化有效销售和批次进度 | | `SYS_CW_REFUND_SYNC` | `CloudRefundSyncJob.php` | 首次/二次退款影响差异修复 | | `SYS_CW_MILESTONE` | `CloudMilestoneJob.php` | 计算最高新节点和累计差额账本 | | `SYS_CW_USER_SETTLE` | `CloudUserSettlementJob.php` | 校验用户账本并投递正式入账 | | `SYS_CW_MERCHANT_ELIGIBLE` | `CloudMerchantEligibilityJob.php` | 商户货款进入可结资格 | | `SYS_CW_STATEMENT_GENERATE` | `CloudMerchantStatementJob.php` | 按商户自然日生成不可变结单 | | `SYS_CW_MERCHANT_POST` | `CloudMerchantPostingJob.php` | 商户结单正式入账 | | `SYS_FIN_POST_REPAIR` | `FarmFinancialPostingRepairJob.php` | 回收超时租约并用原 `posting_key` 重试 | | `SYS_CW_MATURITY_START` | `CloudMaturityJob.php` | 停止新分配并开始在途处置宽限 | | `SYS_CW_MATURITY_FINALIZE` | `CloudMaturityFinalizeJob.php` | 固化所有权切换、整数未售量和回购预案 | | `SYS_CW_BUYBACK_EXECUTE` | `ExecuteCloudBuybackJob.php` | 执行已审核且预检仍有效的回购 | | `SYS_CW_RECONCILE_SCAN` | `CloudReconciliationJob.php` | 生成五段对账差异 | | `SYS_CW_SUPPLY_RECONCILE` | `CloudSupplyInventoryReconcileJob.php` | 重算供货、退回、承接和库存守恒 | | `SYS_FARM_ALLOC_REPAIR` | `FarmAllocationRepairJob.php` | 修复已支付未分配待办 | | `SYS_FARM_RESERVE_EXPIRE` | `FarmAllocationReservationExpireJob.php` | 释放过期地块/资产/份额预留 | | `SYS_FARM_TASK_REMIND` | `FarmTaskReminderJob.php` | 现场任务分阶段提醒 | | `SYS_FARM_OUTPUT_ALLOCATE` | `FarmOutputAllocationJob.php` | 合格产出自动分配 | | `SYS_FARM_EXCEPTION_STEP` | `ExecuteFarmExceptionStepJob.php` | 按原结果键执行单个异常方案步骤 | | `SYS_FARM_CONFIRM_EXPIRE` | `FarmExceptionConfirmationExpireJob.php` | 按方案超时策略推进用户确认 | | `SYS_FARM_EXCEPTION_SLA` | `FarmExceptionSlaJob.php` | 异常 SLA 预警与升级 | | `SYS_FARM_FULFILL_REMIND` | `FarmFulfillmentReminderJob.php` | 地址确认和收货提醒 | | `SYS_FARM_FREIGHT_REPAIR` | `RepairFarmFulfillmentFreightJob.php` | 农业运费支付、迟到退款差异修复 | | `SYS_FARM_FULFILL_AUTO` | CRMEB 自动收货完成适配器 | 以同一完成服务固化自动签收和履约完成 | | `SYS_TRACE_MATERIAL_EXPIRY` | `TraceMaterialExpiryJob.php` | 溯源材料 30/7/0 天提醒和失效标记 | | `SYS_TRACE_PUBLIC_REPAIR` | `TracePublicCacheRepairJob.php` | 公开版本指针、缓存和二维码解析修复 | | `SYS_FARM_ATTACHMENT_CLEAN` | `CleanupFarmUnboundAttachmentJob.php` | 删除到期且仍未绑定的临时附件 | | `SYS_FARM_OUTBOX_DISPATCH` | `PublishFarmDomainEventJob.php` | 抢占并发布一条 Outbox 事件 | | `SYS_FARM_JOB_ALERT` | `FarmFailedJobAlertJob.php` | 对最终失败任务建立唯一告警事实 | ## 三、商品资料、管理范围、云仓活动与供货命令 ### 0. 商品农业资料与管理员范围 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/响应 | | --- | --- | --- | --- | --- | | `PRODUCT_AGRI_SAVE_ADMIN` | `ADM-CM-001` `POST farm/agriculture/product_profile/save/:product_id` | 平台自营商品;编辑权限;`draft/rejected/approved`;版本匹配 | 当前 profile、材料关系、递增版本、前后审计快照;已批准资料修改后回到 `draft` | 返回完整性检查、版本和待提交动作 | | `PRODUCT_AGRI_SUBMIT_ADMIN` | `ADM-CM-001` `POST farm/agriculture/product_profile/submit/:product_id` | 当前草稿完整;材料未过期;商品可用 | `pending_review`、提交人/时间、不可变审计快照 | `farm.product.agriculture.submitted` | | `PRODUCT_AGRI_SAVE_MERCHANT` | `MER-CM-002` `POST farm/catalog/product_agriculture/save/:product_id` | 当前商户商品;`draft/rejected/approved`;版本匹配 | 当前 profile、材料关系、递增版本、前后审计快照;批准后修改回草稿 | 返回完整性检查和版本 | | `PRODUCT_AGRI_SUBMIT_MERCHANT` | `MER-CM-002` `POST farm/catalog/product_agriculture/submit/:product_id` | 当前商户;材料完整有效;来源 SKU 可读 | `pending_review`、提交人/时间和审计快照 | `farm.product.agriculture.submitted` | | `PRODUCT_AGRI_REVIEW` | `ADM-CM-002` `POST farm/agriculture/product_profile/review/:product_id` | 审核权限;锁 profile、商品、材料;审核人不能改提交内容 | 审核结论、备注、`supply_eligible`、审计;驳回保留提交快照 | 通过发 `farm.product.agriculture.approved`,驳回发 `rejected` | | `FARM_ADMIN_SCOPE_SAVE` | 现有管理员页抽屉 `POST farm/support/admin_scope/save/:admin_id` | 独立范围管理权限;不能授权超出本人范围;目标管理员有效;请求 `scope_set_version` 与当前集合版本匹配 | 锁目标管理员和全部 scope 行;差异新增、原行重新启用、停用或保留;全部写同一新 `scope_set_version`,完整前后集合写审计 | `farm.admin.scope.changed`;返回新增/重新启用/停用/保留项与新集合版本 | | `PRODUCT_MATERIAL_EXPIRY_APPLY` | 内部 `ProductMaterialExpiryJob.php` | 锁商品农业资料、当前必需材料及商品;以 `product_id + material_set_version + expire_stage` 幂等 | 重新计算完整必需材料集合后更新 `material_status/supply_eligible`;审计、状态历史和 Outbox 同事务 | `farm.product.material.expired`;历史活动/订单快照不变 | 商品资料当前表保存可编辑事实,完整历史通过 `eb_farm_audit_log.before_snapshot/after_snapshot` 和状态迁移查询;活动、供货、订单和溯源继续保存各自不可变业务快照。资料审核与 CRMEB 商品本身的上架审核可在同一页面展示,但两种状态不得互相覆盖。 ### 1. 活动和活动商品 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/响应 | | --- | --- | --- | --- | --- | | `CW_ACTIVITY_CREATE` | `ADM-CW-002` `POST farm/cloud/activity/create` | 活动创建权限;名称和时间为草稿合法值 | 活动草稿、默认规则版本 | 返回活动 ID、`draft`、版本 | | `CW_ACTIVITY_UPDATE` | `ADM-CW-002` `POST farm/cloud/activity/update/:id` | 仅 `draft/unpublished`;锁活动版本 | 更新草稿字段;不覆盖发布快照 | 返回新版本 | | `CW_ACTIVITY_PRECHECK` | `ADM-CW-002` `POST farm/cloud/activity/precheck/:id` | 只读活动、商品、SKU、供货、库存和二次 SKU | 不写业务事实;可写普通诊断日志 | 返回逐项 `pass/warn/block` | | `CW_ACTIVITY_PUBLISH` | `ADM-CW-002` `POST farm/cloud/activity/publish/:id` | 预检全通过;锁活动、活动商品/SKU、供货可用池 | 固化发布快照、每 SKU 批次草稿、活动库存占用 | `farm.cloud.activity.published`;返回发布时间 | | `CW_ACTIVITY_CLOSE` | `ADM-CW-002` `POST farm/cloud/activity/close/:id` | 仅未开始或异常活动;已产生付款事实不得直接关闭 | 关闭原因、状态;释放动作交事件消费者 | `farm.cloud.activity.closed` | | `CW_ACTIVITY_COPY` | `ADM-CW-001` `POST farm/cloud/activity/copy/:id` | 来源可读;不复制交易、库存占用和历史批次 | 新活动、新活动商品/SKU 草稿和来源诊断 | 返回新草稿 ID | | `CW_ACTIVITY_PRODUCT_CREATE` | `ADM-CW-003` `POST farm/cloud/activity_product/create` | 活动草稿;来源商品可用 | 活动商品和选中 SKU 草稿 | 返回商品规则 ID | | `CW_ACTIVITY_PRODUCT_UPDATE` | `ADM-CW-003` `POST farm/cloud/activity_product/update/:id` | 活动草稿;锁规则版本 | 更新展示和默认规则 | 返回新版本 | | `CW_ACTIVITY_PRODUCT_REMOVE` | `ADM-CW-003` `POST farm/cloud/activity_product/remove/:id` | 未发布、无库存占用 | 软删除活动商品/SKU 草稿 | 返回剩余商品数 | | `CW_ACTIVITY_SKU_UPDATE` | `ADM-CW-003` `POST farm/cloud/activity_sku/update/:id` | 草稿;供货可用量充足;三种结算模式只能选一 | SKU 价格、周期、分成、回购、运费/自提和快照草稿 | 返回规则校验摘要 | | `CW_SOURCE_CHECK_ONE` | `ADM-CW-003` `POST farm/cloud/activity_sku/source_check/:id` | 锁草稿 SKU;读取当前来源商品/SKU | 来源诊断和检查时间;不改已发布快照 | 返回 `matched/changed/missing/ambiguous` | | `CW_SOURCE_CHECK_BATCH` | `ADM-CW-003` `POST farm/cloud/activity/source_check/:id` | 活动草稿 | 建立异步操作;逐 SKU 写诊断 | `202 operation_no` | | `CW_RESALE_SKU_MAP` | `ADM-CW-003` `POST farm/cloud/activity_sku/resale_map/:id` | 目标 SKU 为 `cloud_only`、平台控制、未被冲突映射 | 二次 SKU 映射及版本 | 返回映射与回归风险提示 | 活动关闭、结束和库存闭合是不同事实。自然到时由任务产生 `farm.cloud.activity.ended`,再等待未支付订单关闭和未抢库存分别释放、退回待办或平台承接,最终才产生 `farm.cloud.activity.inventory_closed`。 ### 2. 商户申请、交付、收货和验收 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/响应 | | --- | --- | --- | --- | --- | | `CW_SUPPLY_CREATE` | `MER-CW-002` `POST farm/cloud/supply/create` | 当前商户;一个申请一个来源 SKU;不扣来源库存 | 申请草稿、材料关联草稿 | 返回申请 ID、版本 | | `CW_PLATFORM_SUPPLY_CREATE` | `ADM-CW-005/006` `POST farm/cloud/supply/platform/create` | 平台供货权限;来源商品所属商户 `is_trader=1`;农业资料/材料有效;锁商品和来源 SKU | `source_type=platform`、`merchant_id=NULL` 的供货记录,原子来源库存预占、责任快照、农业库存流水和 Outbox | `farm.cloud.supply.approved`;返回供货 ID、来源剩余可售量和版本 | | `CW_SUPPLY_UPDATE` | `MER-CW-002` `POST farm/cloud/supply/update/:id` | 当前商户;`draft/supplement_required/rejected` | 新草稿版本和材料关系 | 返回校验摘要 | | `CW_SUPPLY_SUBMIT` | `MER-CW-002` `POST farm/cloud/supply/submit/:id` | 材料完整、来源 SKU 当前可用;仍不扣库存 | 提交快照、状态和 Outbox | `farm.cloud.supply.submitted` | | `CW_SUPPLY_AUDIT` | `ADM-CW-006` `POST farm/cloud/supply/audit/:id` | 审核权限;锁申请和来源 SKU;审批量不得超可预留量 | 审核快照、三类责任方、来源预留和库存流水 | 通过发 `farm.cloud.supply.approved`;驳回保留版本 | | `CW_SUPPLY_DELIVERY_CREATE` | `MER-CW-004` `POST farm/cloud/supply/delivery/create/:supply_id` | 当前商户;尚可交付量大于 0 | 交付草稿 | 返回 delivery ID | | `CW_SUPPLY_DELIVERY_UPDATE` | `MER-CW-004` `POST farm/cloud/supply/delivery/update/:delivery_id` | `draft` 且未发运 | 交付数量、物流和证据草稿 | 返回版本 | | `CW_SUPPLY_DELIVERY_DISPATCH` | `MER-CW-004` `POST farm/cloud/supply/delivery/dispatch/:delivery_id` | 锁申请、交付和剩余可交付量 | 固化发运数量和证据;增加在途量流水 | `farm.cloud.supply.dispatched` | | `CW_SUPPLY_DELIVERY_CANCEL` | `MER-CW-004` `POST farm/cloud/supply/delivery/cancel/:delivery_id` | 仅未发运草稿 | 取消交付草稿;不关闭申请、不释放审批预留 | 返回申请剩余可交付量 | | `CW_SUPPLY_RECEIVE` | `ADM-CW-006` `POST farm/cloud/supply/delivery/receive/:delivery_id` | 仓储权限;已发运未完成收货 | 实收、短少、收货证据和流水 | `received`;有短少再发 `shortage_confirmed` | | `CW_SUPPLY_INSPECTION_CREATE` | `ADM-CW-006` `POST farm/cloud/supply/inspection/create/:delivery_id` | 已收货且仍有待检数量 | 待检单和任务 | 返回 inspection ID | | `CW_SUPPLY_INSPECTION_COMPLETE` | `ADM-CW-006` `POST farm/cloud/supply/inspection/complete/:inspection_id` | 锁交付、验收、库位和供货量;数量方程闭合 | 合格/待检/拒收量、库位、证据、云仓可用库存流水 | `farm.cloud.supply.inspection_completed` | | `CW_SUPPLY_RELEASE` | `ADM-CW-006` `POST farm/cloud/supply/release/:id` | 未交付/已取消余量且无活动占用 | 释放来源预留和流水 | `reservation_released` | | `CW_SUPPLY_RETURN_ACK` | `MER-CW-004` `POST farm/cloud/supply/return/acknowledge/:return_id` | 当前商户;退回在途 | 收货确认或差异异常;差异时不恢复来源库存 | 返回 return 状态 | | `CW_SUPPLY_RETURN_COMPLETE` | `ADM-CW-006` `POST farm/cloud/supply/return/complete/:return_id` | 实物交接证据完整或等价库存移交已确认 | 退回记录完成、来源库存恢复和流水 | `farm.cloud.supply.returned` | | `CW_SUPPLY_ACQUIRE_PREPARE` | `ADM-CW-006` `POST farm/cloud/supply/platform_acquire/prepare/:supply_id` | 承接制单权限;锁供货与剩余可承接量;数量、价格、目标自营 SKU 和证据预检通过 | 新增 `pending_review` 承接记录和计算快照,不改平台库存 | 返回 acquisition ID、金额和版本 | | `CW_SUPPLY_ACQUIRE_REVIEW` | `ADM-CW-006` `POST farm/cloud/supply/platform_acquire/review/:acquisition_id` | 独立复核权限;审核人与制单人分离;目标版本和价格依据未变 | 审核通过/驳回、复核人、备注和审计 | 返回 `approved/rejected` 与版本 | | `CW_SUPPLY_ACQUIRE_EXECUTE` | `ADM-CW-006` `POST farm/cloud/supply/platform_acquire/execute/:acquisition_id` | 已批准;锁承接、供货、目标自营商品/SKU 和库存;结果键可取得 | 平台库存、供货 `platform_acquired_qty`、库存流水和状态同事务 | `farm.cloud.supply.platform_acquired` | | `CW_SUPPLY_FREEZE` | `ADM-CW-006` `POST farm/cloud/supply/freeze/:supply_id` | 质量/库存异常原因必填 | 冻结范围、原因和受影响库存 | 创建/关联异常 | ## 四、云仓订单、去向、批次和回购命令 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/响应 | | --- | --- | --- | --- | --- | | `CW_ORDER_CHECK` | `USR-CW-003` `POST farm/cloud/order/check` | 登录用户;活动进行中;限购、库存、来源和规则有效 | 短期 `check_key`;不扣库存 | 返回 10 分钟内有效的价格/规则快照 | | `CW_ORDER_CREATE` | `USR-CW-003` `POST farm/cloud/order/create` | 有效 `check_key`;锁活动 SKU 和可抢库存 | CRMEB 订单组/订单/单明细、binding、首次明细、库存流水、Outbox | `farm.cloud.order.created`,返回现有支付入口 | | `CW_CHOICE_PREVIEW` | `USR-CW-006` `POST farm/cloud/order_item/:id/disposition/preview` | 本人已付待选择明细;未过截止;版本匹配 | 邮寄时生成短期运费报价;其他去向纯预览 | 返回能力、快照和 `quote_hash` | | `CW_CHOICE_CONFIRM` | `USR-CW-006` `POST farm/cloud/order_item/:id/disposition/confirm` | 本人、整条数量、未退款/冻结;锁首次明细和目标资源 | 代销持仓,或自提凭证,或包邮履约;需补运费只建运费单不冻结最终去向 | 最终生效发 `choice.confirmed`;补运费发 `freight.created` | | `CW_FREIGHT_PAY` | `USR-CW-007` `POST farm/cloud/freight/pay/:freight_order_id` | 本人当前未支付有效运费单 | 余额渠道可同事务确认;在线渠道只建立支付请求事实 | 返回 `wait_pay_result` 或最终履约 | | `CW_FREIGHT_CANCEL` | `USR-CW-007` `POST farm/cloud/freight/cancel/:freight_order_id` | 未支付、未超时、成功回调事务未开始 | 取消当前运费单并恢复可选状态 | 返回 `choose_again` | | `CW_FREIGHT_PAID` | 支付回调内部命令 | 规范化金额/渠道交易号正确;锁运费单、明细、地址版本 | 支付事实、最终邮寄、履约和 Outbox | `farm.cloud.freight.paid`;迟到则 `late_paid` 并创建退款 | | `CW_PRIMARY_REFUND_CHECK` | `USR-CW-005` `POST farm/cloud/order_item/:id/refund/check` | 本人;仅整条;批次未开始且无不可逆履约 | 纯预检 | 返回可退额、受影响去向/运费和原因 | | `CW_PRIMARY_REFUND_APPLY` | `USR-CW-005` `POST farm/cloud/order_item/:id/refund/apply` | 预检仍有效;锁订单/明细和农业影响 | 冻结业务对象、创建退款编排和影响记录 | 返回 CRMEB 退款申请编号 | | `CW_CHOICE_REMIND` | `ADM-CW-007` `POST farm/cloud/order/remind_choice/:id` | 待选择且未在冷却期 | 通知日志/Outbox,不改变选择 | 返回发送或幂等跳过 | | `CW_PICKUP_VERIFY` | `ADM-CW-007`/`SVC-CW-002`/`SVC-PD-005` `POST farm/cloud/pickup/verify/:id` | 核销权限与点位范围;现场入口还需当前任务;凭证有效;`0 < verify_qty <= remaining_qty` | 不可变核销流水、累计/剩余量、数量级首次完成事实 | 返回 verification 和明细状态;全部闭合才发整体完成事件 | | `CW_PICKUP_OVERDUE_RESOLVE` | `ADM-CW-007` `POST farm/cloud/pickup/resolve/:id` | 已逾期且有剩余量;方案版本和用户确认/超时事实完整 | 延期、改寄、退款或按活动比例异常回购,只处理剩余量 | 返回异常/方案编号 | | `CW_FULFILLMENT_LOGISTICS_UPDATE` | `MER-CW-005` `POST farm/cloud/fulfillment/logistics/:id` | 当前商户为履约责任方;包裹未签收、未锁定售后;锁履约和包裹版本 | 更正承运商/运单号,保留变更前后快照和审计;不得改已出库数量 | 返回包裹、物流版本和风险提示 | | `CW_FULFILLMENT_EVIDENCE_ADD` | `MER-CW-005` `POST farm/cloud/fulfillment/evidence/:id` | 当前商户为履约或质量责任方;附件归属和对象版本有效 | 追加不可变质量、打包或交接证据关联和审计,不覆盖历史附件 | 返回证据版本和完整性 | | `CW_FULFILLMENT_RETURN_RECEIVE` | `MER-CW-005` `POST farm/cloud/fulfillment/return_receive/:id` | 当前商户为售后责任方;存在退回在途数量;锁履约、售后和库存关联 | 退回实收/差异、证据、待检或异常事实;数量不闭合时创建/关联统一异常,不直接恢复可售库存 | 返回退回验收状态、差异量和下一动作 | | `CW_BATCH_FREEZE` | `ADM-CW-009` `POST farm/cloud/batch/freeze/:id` | 异常原因;批次未关闭 | 冻结批次和新分配能力 | 返回受影响对象摘要 | | `CW_BATCH_RESUME` | `ADM-CW-009` `POST farm/cloud/batch/resume/:id` | 异常已处理、对账闭合、审批通过 | 恢复批次可分配状态 | 返回最新池余额 | | `CW_BATCH_RECONCILE_PREVIEW` | `ADM-CW-009` `POST farm/cloud/batch/reconcile_preview/:id` | 财务/技术权限 | 异步计算差异,不改业务汇总 | `202 operation_no` | | `CW_BATCH_RECONCILE_APPLY` | `ADM-CW-009` `POST farm/cloud/batch/reconcile_apply/:id` | 已审核差异方案、目标版本未变 | 修复/冲正步骤、流水、审计、Outbox | `202 operation_no` | | `CW_BUYBACK_PREPARE` | `ADM-CW-011` `POST farm/cloud/buyback/prepare/:batch_id` | 在途处置宽限已结束、所有权切换点和整数未售量已固化;锁批次和持仓 | 待审核预案、经济等价数量、最大余数分钱和待回购池快照 | 返回批次池与逐持仓预览 | | `CW_BUYBACK_REVIEW` | `ADM-CW-011` `POST farm/cloud/buyback/review/:batch_id` | `pending_review`;审核人与制单权限分离 | 审核结论和版本 | 通过发 `buyback.approved`,驳回发 `buyback.rejected` | | `CW_BUYBACK_EXECUTE` | `ADM-CW-011` `POST farm/cloud/buyback/execute/:batch_id` | 已审核且预检有效;锁回购、批次、持仓、平台库存 | 回购库存、用户回购账本、批次状态、流水 | 同步受理后返回 `202 operation_no` | | `CW_BUYBACK_RETRY` | `ADM-CW-011` `POST farm/cloud/buyback/retry/:batch_id` | 仅事务外可恢复步骤失败;业务事务成功不得重做 | 原结果键重投任务 | 返回同一 `operation_no` | 二次代销 FEFO 分配、支付生效、观察期转有效销售和退款冲正由 CRMEB 核心适配命令触发,不开放“手工指定某用户持仓售出”的接口。 ## 五、财务、结单和对账命令 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/响应 | | --- | --- | --- | --- | --- | | `CW_USER_LEDGER_REVIEW` | `ADM-FN-002` `POST farm/cloud/user_ledger/review` | 财务审核;只处理同一审核结论的 ID 集合 | 每笔独立审核;失败不污染其他记录 | 返回逐笔结果 | | `CW_USER_POSTING` | `ADM-FN-002` `POST farm/cloud/user_ledger/execute` | 已审核或自动阈值内;锁账本、posting、用户账户 | 用户余额、UserBill、posting、账本状态 | `farm.cloud.user_ledger.settled` | | `CW_FINANCIAL_POSTING_RETRY` | `ADM-FN-002` `POST farm/cloud/financial_posting/retry/:id` | 可恢复失败且租约可取得 | 使用原 `posting_key` 重试 | 成功返回原 CRMEB 流水 ID | | `CW_LEDGER_ADJUST_REQUEST` | `ADM-FN-002` `POST farm/cloud/user_ledger/adjust/request` | 来源记录可冲正;原因和证据完整 | 冲正申请,不直接改余额 | 返回 adjustment ID | | `CW_LEDGER_ADJUST_AUDIT` | `ADM-FN-002` `POST farm/cloud/user_ledger/adjust/audit/:id` | 审核分权;重算目标余额与后续影响 | 审核结论;通过后创建反向 posting | 余额不足进入 `recovery_pending` | | `CW_MERCHANT_STATEMENT_PREVIEW` | `ADM-FN-003` `POST farm/cloud/merchant_statement/preview` | 商户/自然日范围;候选账本未占用 | 纯预览 | 返回候选数、金额和差异 | | `CW_MERCHANT_STATEMENT_GENERATE` | `ADM-FN-003` `POST farm/cloud/merchant_statement/generate` | 锁候选账本;资格仍有效 | 结单、不可变明细、候选占用 | `farm.cloud.merchant_statement.generated` | | `CW_MERCHANT_STATEMENT_REVIEW` | `ADM-FN-003` `POST farm/cloud/merchant_statement/review/:id` | `pending_review`;版本匹配 | 审核结论 | 返回 `approved/rejected` | | `CW_MERCHANT_POSTING` | `ADM-FN-003` `POST farm/cloud/merchant_statement/execute/:id` | 已审核或自动阈值内;锁结单、明细、商户账户 | 商户余额、FinancialRecord、posting 和明细 | `farm.cloud.merchant_ledger.settled` | | `CW_MERCHANT_POSTING_RETRY` | `ADM-FN-003` `POST farm/cloud/merchant_statement/retry/:id` | 可恢复失败 | 原 `posting_key` 重试 | 返回原入账结果 | | `CW_LEDGER_DISPUTE` | `MER-FN-001` `POST farm/cloud/merchant_ledger/dispute/:id` | 当前商户、未入单记录、无重复进行中异议 | 异议及冻结标记 | 返回异议 ID | | `CW_STATEMENT_DISPUTE` | `MER-FN-002` `POST farm/cloud/merchant_statement/dispute/:id` | 当前商户;结单可异议窗口内 | 异议;已入账只生成调整候选 | 返回处理入口 | | `CW_RECONCILIATION_PREVIEW` | `ADM-FN-004` `POST farm/cloud/reconciliation/preview/:id` | 财务/技术只读证据完整 | 建立异步差异方案版本 | `202 operation_no` | | `CW_RECONCILIATION_REVIEW` | `ADM-FN-004` `POST farm/cloud/reconciliation/review/:id` | 方案待审且源版本未变 | 审核结论 | 返回 allowed actions | | `CW_RECONCILIATION_EXECUTE` | `ADM-FN-004` `POST farm/cloud/reconciliation/execute/:id` | 已审;资金/库存预检通过 | 分步修复、冲正、审计和 Outbox | `202 operation_no` | | `CW_RECONCILIATION_RETRY` | `ADM-FN-004` `POST farm/cloud/reconciliation/retry/:id` | 存在可恢复失败步骤 | 原步骤结果键重试 | 返回同一 operation | 任何财务执行命令都不接收最终金额、目标账户或余额。前端只提交记录 ID、版本、审核结论、原因和 `request_id`,服务端从锁定事实重算。 ## 六、农业主数据、套餐和分配命令 ### 1. 主数据通用命令 下列资源共用 Controller 形态,但路由、操作码和权限名逐项独立。所有 `CREATE` 都校验所属范围与业务编号唯一,`UPDATE` 都锁目标并校验 `version`,`STATUS` 都要求 `ReasonCommand`,停用只影响新业务资格且不得破坏进行中权益、任务或库存。 | 操作码 | 页面与完整路由 | 事务写集 | 结果 | | --- | --- | --- | --- | | `FARM_FARM_CREATE` | `ADM-AG-002` `POST farm/agriculture/farm/create` | 农场、点位和审计 | ID、编号、`disabled`、版本 | | `FARM_FARM_UPDATE` | `ADM-AG-002/003` `POST farm/agriculture/farm/update/:id` | 农场当前资料、点位版本和审计 | 新版本与公开影响 | | `FARM_FARM_STATUS` | `ADM-AG-002/003` `POST farm/agriculture/farm/status/:id` | 状态、原因和引用快照 | 状态与阻断/影响数量 | | `FARM_ZONE_CREATE` | `ADM-AG-004` `POST farm/agriculture/zone/create` | 区域、农场归属和审计 | ID、编号、状态、版本 | | `FARM_ZONE_UPDATE` | `ADM-AG-004` `POST farm/agriculture/zone/update/:id` | 区域当前资料和审计 | 新版本与影响 | | `FARM_ZONE_STATUS` | `ADM-AG-004` `POST farm/agriculture/zone/status/:id` | 状态、原因和引用快照 | 状态与影响数量 | | `FARM_PLOT_CREATE` | `ADM-AG-005` `POST farm/agriculture/plot/create` | 地块、区域归属和容量 | ID、编号、状态、版本 | | `FARM_PLOT_UPDATE` | `ADM-AG-005/006` `POST farm/agriculture/plot/update/:id` | 地块当前资料;历史面积快照不变 | 新版本与占用影响 | | `FARM_PLOT_STATUS` | `ADM-AG-005/006` `POST farm/agriculture/plot/status/:id` | 状态、原因和当前占用快照 | 状态与影响数量 | | `FARM_PICKUP_POINT_CREATE` | `ADM-AG-011/012` `POST farm/agriculture/pickup_point/create` | 自提点、GCJ02 点位和营业规则 | ID、编号、状态、版本 | | `FARM_PICKUP_POINT_UPDATE` | `ADM-AG-011/012` `POST farm/agriculture/pickup_point/update/:id` | 当前资料;既有凭证仍读快照 | 新版本与在途凭证影响 | | `FARM_PICKUP_POINT_STATUS` | `ADM-AG-011/012` `POST farm/agriculture/pickup_point/status/:id` | 状态、原因和在途凭证快照 | 状态与影响数量 | | `FARM_CROP_CREATE` | `ADM-LA-001` `POST farm/agriculture/crop/create` | 作物目录和审计 | ID、编号、状态、版本 | | `FARM_CROP_UPDATE` | `ADM-LA-001` `POST farm/agriculture/crop/update/:id` | 当前作物资料;套餐版本不变 | 新版本与引用提示 | | `FARM_CROP_STATUS` | `ADM-LA-001` `POST farm/agriculture/crop/status/:id` | 状态、原因和套餐引用快照 | 状态与影响数量 | | `FARM_ENCLOSURE_CREATE` | `ADM-AG-008` `POST farm/agriculture/enclosure/create` | 栏舍、区域归属和容量 | ID、编号、状态、版本 | | `FARM_ENCLOSURE_UPDATE` | `ADM-AG-008` `POST farm/agriculture/enclosure/update/:id` | 当前资料和容量版本 | 新版本与资产/批次影响 | | `FARM_ENCLOSURE_STATUS` | `ADM-AG-008` `POST farm/agriculture/enclosure/status/:id` | 状态、原因和在用资产快照 | 状态与影响数量 | | `FARM_WAREHOUSE_CREATE` | `ADM-AG-003` `POST farm/agriculture/warehouse/create` | 仓库、农场归属和审计 | ID、编号、状态、版本 | | `FARM_WAREHOUSE_UPDATE` | `ADM-AG-003` `POST farm/agriculture/warehouse/update/:id` | 仓库当前资料 | 新版本与库存影响 | | `FARM_WAREHOUSE_STATUS` | `ADM-AG-003` `POST farm/agriculture/warehouse/status/:id` | 状态、原因和当前库存快照 | 状态与影响数量 | | `FARM_WAREHOUSE_LOCATION_CREATE` | `ADM-AG-003` `POST farm/agriculture/warehouse_location/create` | 库位、仓库归属和容量 | ID、编号、状态、版本 | | `FARM_WAREHOUSE_LOCATION_UPDATE` | `ADM-AG-003` `POST farm/agriculture/warehouse_location/update/:id` | 库位当前资料 | 新版本与库存影响 | | `FARM_WAREHOUSE_LOCATION_STATUS` | `ADM-AG-003` `POST farm/agriculture/warehouse_location/status/:id` | 状态、原因和当前库存快照 | 状态与影响数量 | | `FARM_BREED_CREATE` | `ADM-AD-001` `POST farm/agriculture/breed/create` | 品种目录和审计 | ID、编号、状态、版本 | | `FARM_BREED_UPDATE` | `ADM-AD-001` `POST farm/agriculture/breed/update/:id` | 当前品种资料;历史套餐不变 | 新版本与引用提示 | | `FARM_BREED_STATUS` | `ADM-AD-001` `POST farm/agriculture/breed/status/:id` | 状态、原因和引用快照 | 状态与影响数量 | | `FARM_ANIMAL_CREATE` | `ADM-AG-009` `POST farm/agriculture/animal/create` | 动物资产、栏舍容量和审计 | ID、编号、状态、版本 | | `FARM_ANIMAL_UPDATE` | `ADM-AG-009` `POST farm/agriculture/animal/update/:id` | 当前资产资料;认养/替换历史不变 | 新版本与权益影响 | | `FARM_ANIMAL_STATUS` | `ADM-AG-009` `POST farm/agriculture/animal/status/:id` | 状态、原因和权益/健康快照 | 状态与影响数量 | | `FARM_BREEDING_BATCH_CREATE` | `ADM-AG-010` `POST farm/agriculture/breeding_batch/create` | 养殖批次、栏舍容量和份额 | ID、编号、状态、版本 | | `FARM_BREEDING_BATCH_UPDATE` | `ADM-AG-010` `POST farm/agriculture/breeding_batch/update/:id` | 当前批次资料;已售份额不变 | 新版本与容量影响 | | `FARM_BREEDING_BATCH_STATUS` | `ADM-AG-010` `POST farm/agriculture/breeding_batch/status/:id` | 状态、原因和份额/权益快照 | 状态与影响数量 | | `ANIMAL_IMPORT_VALIDATE` | `ADM-AG-009` `POST farm/agriculture/animal/import/validate` | 绑定附件到异步操作,保存文件哈希、映射、目标版本和脱敏预览;不写动物资产 | `202 operation_no` | | `ANIMAL_IMPORT_CONFIRM` | `ADM-AG-009` `POST farm/agriculture/animal/import/confirm/:operation_no` | 校验操作成功且零错误;重验文件哈希和范围;全批动物、容量、审计和 Outbox 原子写入 | `202 operation_no`;任一行失败则资产写入为零 | 补充冻结规则: - 农场和云仓自提点启用前必须有合法 `GCJ02` 点位;地块、栏舍和仓库内部精确位置不向用户公开。 - 农场详情中的仓库/库位采用标签页和抽屉维护,不新增独立一级页面。 - 在用地块、栏舍、资产、仓库和库位不得物理删除;停用只阻止新分配。 - 动物资产批量导入使用 `validate → preview → confirm` 三段异步操作,错误行不部分落库。 ### 2. 租地与认养套餐 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 结果 | | --- | --- | --- | --- | --- | | `LAND_PLAN_CREATE` | `ADM-LA-003` `POST farm/land/plan/create` | 套餐编辑权限;农场/区域在范围内 | 套餐草稿、作物/服务关系 | 返回 plan ID | | `LAND_PLAN_UPDATE` | `ADM-LA-003` `POST farm/land/plan/update/:id` | 仅草稿;版本匹配 | 新草稿版本 | 返回规则差异 | | `LAND_PLAN_PUBLISH` | `ADM-LA-003` `POST farm/land/plan/publish/:id` | 容量、价格=服务价值+交付价值、延期容忍期、交付、异常和协议预检通过 | 固化发布版本、退款基数规则和容量口径 | 返回发布版本 | | `ADOPTION_PLAN_CREATE` | `ADM-AD-003` `POST farm/adoption/plan/create` | 模式、来源资产/批次和栏舍在范围内 | 套餐草稿 | 返回 plan ID | | `ADOPTION_PLAN_UPDATE` | `ADM-AD-003` `POST farm/adoption/plan/update/:id` | 仅草稿;单体/份额模式不可混用 | 新草稿版本 | 返回规则差异 | | `ADOPTION_PLAN_PUBLISH` | `ADM-AD-003` `POST farm/adoption/plan/publish/:id` | 容量、价格=服务价值+交付价值、延期容忍期、健康、替换、产出、履约和协议完整 | 固化发布版本和退款/替换规则 | 返回发布版本 | | `LAND_ORDER_CHECK` | `USR-LA-003` `POST farm/land/order/check` | 登录用户;发布套餐、容量、作物和服务有效 | 短期 `check_key`;不分配真实地块 | 返回价格/协议/交付快照 | | `LAND_ORDER_CREATE` | `USR-LA-003` `POST farm/land/order/create` | 有效 `check_key` | CRMEB 单一商品订单、binding、租地订单、Outbox | 返回支付入口 | | `ADOPTION_ORDER_CHECK` | `USR-AD-003` `POST farm/adoption/order/check` | 登录用户;发布套餐和单体/份额容量有效 | 短期 `check_key` | 返回规则快照 | | `ADOPTION_ORDER_CREATE` | `USR-AD-003` `POST farm/adoption/order/create` | 有效 `check_key` | CRMEB 单一商品订单、binding、认养订单、Outbox | 返回支付入口 | ### 3. 真实资源预留与确认 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/结果 | | --- | --- | --- | --- | --- | | `LAND_ALLOCATION_RESERVE` | `ADM-LA-006` `POST farm/land/allocation/reserve/:order_id` | 已支付待分配;候选地块满足面积、周期、状态和范围 | 5 分钟 `reserved` 占用及令牌 | `farm.land.plot.reserved` | | `LAND_ALLOCATION_CONFIRM` | `ADM-LA-006` `POST farm/land/allocation/confirm/:order_id` | 令牌未过期;锁订单、预留、地块和占用日历 | 永久占用、订单关系、历史和 Outbox | `farm.land.plot.allocated` | | `LAND_ALLOCATION_RELEASE` | `ADM-LA-006` `POST farm/land/allocation/release/:order_id` | 当前有效预留 | 标记释放,恢复容量 | `reservation_released` | | `ADOPTION_ALLOCATION_RESERVE` | `ADM-AD-006` `POST farm/adoption/allocation/reserve/:order_id` | 已支付待分配;健康可用个体或批次份额足够 | 5 分钟资产/份额预留 | `farm.adoption.asset.reserved` | | `ADOPTION_ALLOCATION_CONFIRM` | `ADM-AD-006` `POST farm/adoption/allocation/confirm/:order_id` | 令牌未过期;锁订单、预留、资产/批次 | 分配、占用、份额扣减和历史 | `farm.adoption.asset.allocated` | | `ADOPTION_ALLOCATION_RELEASE` | `ADM-AD-006` `POST farm/adoption/allocation/release/:order_id` | 当前有效预留 | 标记释放,恢复个体/份额容量 | `reservation_released` | 分配接口不允许前端直接提交“最终可用容量”。请求只提交候选 ID、预留令牌、当前版本和 `request_id`;确认事务重新计算所有约束。 ## 七、生产、产出、履约、异常和溯源命令 ### 1. 生产批次、任务和过程记录 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/结果 | | --- | --- | --- | --- | --- | | `PRODUCTION_BATCH_CREATE` | `ADM-PD-002` `POST farm/production/batch/create` | 对象、权益、周期和类型扩展合法 | 主批次、种植/养殖一对一扩展、权益链接 | `farm.production.batch.created` | | `PRODUCTION_BATCH_UPDATE` | `ADM-PD-002` `POST farm/production/batch/update/:id` | 仅 `planned`;版本匹配 | 更新计划版本 | 返回影响预览 | | `PRODUCTION_BATCH_START` | `ADM-PD-002` `POST farm/production/batch/start/:id` | 权益、占用、必需任务、资产健康预检通过 | 开始时间、状态、迁移 | `farm.production.batch.started` | | `PRODUCTION_BATCH_PAUSE` | `ADM-PD-002` `POST farm/production/batch/pause/:id` | `in_progress`;原因与影响范围明确 | 暂停状态、待执行任务冻结标记 | `farm.production.batch.paused` | | `PRODUCTION_BATCH_RESUME` | `ADM-PD-002` `POST farm/production/batch/resume/:id` | 暂停原因已解除、异常预检通过 | 恢复状态和计划偏移 | `farm.production.batch.resumed` | | `PRODUCTION_BATCH_COMPLETE` | `ADM-PD-002` `POST farm/production/batch/complete/:id` | 必需任务、产出、异常和权益关联闭合 | 完成状态和汇总 | `farm.production.batch.completed` | | `FARM_TASK_CREATE` | `ADM-PD-002` `POST farm/task/create` | 对象在范围;要求和计划时间合法 | 任务和要求快照 | 返回 task ID | | `FARM_TASK_ASSIGN` | `ADM-PD-002` `POST farm/task/assign/:id` | 待分派;执行人职责/范围匹配 | 当前分派、分派历史 | `farm.task.assigned` | | `FARM_TASK_REASSIGN` | `ADM-PD-002` `POST farm/task/reassign/:id` | 未完成;保留原执行历史 | 关闭旧分派、新分派、版本 | `farm.task.assigned` | | `FARM_TASK_CANCEL` | `ADM-PD-002` `POST farm/task/cancel/:id` | 未完成且无不可逆执行事实 | 取消原因和状态 | 返回关联批次影响 | | `FARM_TASK_START` | `SVC-PD-001` `POST farm/task/start/:id` | 当前执行人;`assigned`;对象范围和版本仍有效 | 任务 `in_progress`、开始时间、分派历史 | `farm.task.started` | | `FARM_TASK_COMPLETE` | `SVC-PD-001` `POST farm/task/complete/:id` | 当前执行人;必需过程/产出/仓储事实和附件齐全 | 完成状态、结果快照、完成时间 | `farm.task.completed` | | `PRODUCTION_EVENT_CREATE` | `SVC-PD-003` `POST farm/production/event/create` | 执行人有对象/任务范围;附件归本人且未绑定 | 事件草稿、版本、附件绑定 | 返回 event ID | | `PRODUCTION_EVENT_SUBMIT` | `SVC-PD-003` `POST farm/production/event/submit/:id` | 本人草稿、附件上传完成、对象版本有效 | 提交版本和审核待办 | `farm.production.event.submitted` | | `PRODUCTION_EVENT_REVIEW` | `ADM-PD-003` `POST farm/production/event/review/:id`;`SVC-PD-007` `POST farm/production/review/:id` | 审核权限;审核人不得改原文 | 审核结论和版本 | 通过后仍不自动公开 | | `PRODUCTION_EVENT_PUBLISH` | `ADM-PD-003` `POST farm/production/event/publish/:id` | 已审核;独立发布权限 | 公开版本指针 | `farm.production.event.published` | | `PRODUCTION_EVENT_WITHDRAW` | `ADM-PD-003` `POST farm/production/event/withdraw/:id` | 已发布;原因必填 | 撤回状态;保留版本和引用 | 返回公开降级说明 | ### 2. 产出与履约 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/结果 | | --- | --- | --- | --- | --- | | `OUTPUT_BATCH_CREATE` | `SVC-PD-004` `POST farm/output/batch/create` | 来源批次/任务在范围;单位固定;数量方程闭合 | 产出草稿、证据、仓位候选 | 返回 output ID | | `OUTPUT_BATCH_SUBMIT` | `SVC-PD-004` `POST farm/output/batch/submit/:id` | 本人草稿、证据完整 | 提交状态 | `farm.output.batch.submitted` | | `OUTPUT_BATCH_QUALITY` | `ADM-PD-005` `POST farm/output/batch/quality/:id` | 质量权限;锁产出、库位和待检量 | 合格/损耗/待检、质量快照、库存流水 | `farm.output.batch.accepted` | | `OUTPUT_ALLOCATION_PREVIEW` | `ADM-PD-005` `POST farm/output/allocation/preview/:id` | 读取权益、已分配和合格库存 | 不写正式分配;返回 `calculation_version` | 逐权益缺口/可分量 | | `OUTPUT_ALLOCATION_CONFIRM` | `ADM-PD-005` `POST farm/output/allocation/confirm/:id` | 计算版本未变;锁产出、权益和已有分配 | 分配、库存流水、履约草稿 | `farm.output.allocated` | | `OUTPUT_ALLOCATION_RECONCILE` | `ADM-PD-005` `POST farm/output/allocation/reconcile/:id` | 财务/仓储复核权限 | 异步差异预览,不直接改汇总 | `202 operation_no` | | `FULFILLMENT_CREATE` | `ADM-PD-006` `POST farm/fulfillment/create` | 有未履约产出分配 | 履约、明细、地址待确认状态 | `farm.fulfillment.ready` | | `FULFILLMENT_ADDRESS_PREVIEW` | `USR-PD-001` `POST farm/fulfillment/address/preview/:id` | 本人待地址履约 | 纯预览 | 返回支持范围和运费规则 | | `FULFILLMENT_ADDRESS_CONFIRM` | `USR-PD-001` `POST farm/fulfillment/address/confirm/:id` | 本人;地址可达;版本匹配 | 不可变地址版本和履约引用 | `farm.fulfillment.address_confirmed` | | `FULFILLMENT_FREIGHT_CHECK` | `USR-PD-001` `POST farm/fulfillment/freight/check/:id` | 地址版本有效 | 短期报价令牌 | 返回金额、模板、期限 | | `FULFILLMENT_FREIGHT_CREATE` | `USR-PD-001` `POST farm/fulfillment/freight/create/:id` | 报价令牌有效 | 独立农业运费单,`attach=farm_output_freight` | 返回 freight order | | `FULFILLMENT_FREIGHT_PAY` | `USR-PD-001` `POST farm/fulfillment/freight/pay/:freight_order_id` | 本人有效未支付运费单 | 支付请求;回调同云仓安全适配器 | 成功发 `farm.fulfillment.freight_paid` | | `FULFILLMENT_FREIGHT_CANCEL` | `USR-PD-001` `POST farm/fulfillment/freight/cancel/:freight_order_id` | 未支付且未进入成功回调事务 | 取消运费单;履约保留待支付/重报价 | 返回下一动作 | | `FULFILLMENT_FREIGHT_PAID` | 支付回调内部命令 | 规范化金额、渠道交易号和 `attach=farm_output_freight` 正确;锁运费单、履约和地址版本 | 支付事实、履约待出库状态和 Outbox;迟到成功只创建原渠道全额退款 | `farm.fulfillment.freight_paid` 或迟到退款待办 | | `FULFILLMENT_PACKAGE` | `ADM-PD-006` `POST farm/fulfillment/package/:id` | 未发货明细;锁库存和包裹 | 包裹及明细、拣货数量 | 返回包裹列表 | | `FULFILLMENT_SHIP` | `ADM-PD-006` `POST farm/fulfillment/ship/:id`;`MER-CW-005` `POST farm/cloud/fulfillment/ship/:id`;`SVC-PD-005` `POST farm/fulfillment/ship/:task_id` | 发货权限与责任方/范围有效、运费完成、包裹可发、运单唯一 | 出库流水、包裹物流、履约状态 | `farm.fulfillment.shipped` | | `FULFILLMENT_TAKE` | `USR-PD-001` `POST farm/fulfillment/take/:id` | 本人已发货未完成履约 | 收货事实和完成汇总 | `farm.fulfillment.completed` | | `FULFILLMENT_CANCEL` | `ADM-PD-006` `POST farm/fulfillment/cancel/:id` | 仅未出库部分 | 取消明细、产出库存回退流水 | 返回剩余履约 | | `FULFILLMENT_REFUND_CHECK` | `USR-PD-001` `POST farm/fulfillment/refund/check/:id` | 本人、存在后端计算的可退未履约数量 | 纯预检;按交付退款基数计算累计应退与本次差额 | 返回基数、数量、历史/在途退款和本次金额 | | `FULFILLMENT_REFUND_APPLY` | `USR-PD-001` `POST farm/fulfillment/refund/apply/:id` | 预检版本仍有效;客户端不提交金额 | 售后申请、业务冻结和退款影响快照 | 返回 CRMEB 售后编号 | ### 3. 统一异常执行 云仓和农业异常共用以下命令语义,只是路由前缀及页面不同:`farm/cloud/exception/*` 与 `farm/exception/*`。 | 操作码 | 页面与完整路由 | 前置/锁定 | 事务写集 | 结果 | | --- | --- | --- | --- | --- | | `FARM_EXCEPTION_CREATE` | `ADM-CW-012` `POST farm/cloud/exception/create`;`MER-CW-005` `POST farm/cloud/fulfillment/exception/:id`;`ADM-PD-008`/`SVC-PD-006` `POST farm/exception/create` | 对象在范围或当前商户为责任方;事实、严重度、证据完整 | 异常主表、对象冻结建议、影响初稿;商户入口自动固化履约和责任快照 | `farm.exception.created` | | `FARM_EXCEPTION_IMPACT_RECALC` | `ADM-CW-012` `POST farm/cloud/exception/impact/recalculate/:id`;`ADM-PD-008` `POST farm/exception/impact/recalculate/:id` | 异常未关闭 | 异步建立不可变影响快照 | `202 operation_no` | | `FARM_EXCEPTION_PLAN_CREATE` | `ADM-CW-012` `POST farm/cloud/exception/plan/create/:id`;`ADM-PD-008` `POST farm/exception/plan/create/:id` | 最新影响快照存在 | 新方案版本、等价校验、比例分配、退款计算、确认截止/超时策略和有序步骤;不覆盖旧版 | 返回 plan version | | `FARM_EXCEPTION_PLAN_PRECHECK` | `ADM-CW-012` `POST farm/cloud/exception/plan/precheck/:plan_id`;`ADM-PD-008` `POST farm/exception/plan/precheck/:plan_id` | 方案待审/已审;读取当前对象版本、库存和资金 | 预检摘要和失效时间;不执行业务动作 | 返回 `pass/block` | | `FARM_EXCEPTION_PLAN_REVIEW` | `ADM-CW-012` `POST farm/cloud/exception/plan/review/:plan_id`;`ADM-PD-008` `POST farm/exception/plan/review/:plan_id` | 审核人与制单分权;预检有效 | 审核结论 | `farm.exception.plan_approved` 或驳回 | | `FARM_EXCEPTION_USER_CONFIRM` | 用户 `POST farm/exception/plan/confirm/:plan_id` | 本人受影响订单、方案待确认且版本/期限有效 | 不可变确认/拒绝事实;不修改方案金额 | 返回执行或退款下一动作 | | `FARM_EXCEPTION_PLAN_EXECUTE` | `ADM-CW-012` `POST farm/cloud/exception/plan/execute/:plan_id`;`ADM-PD-008` `POST farm/exception/plan/execute/:plan_id` | 已审核且再次预检通过 | 建立 async operation 和步骤执行租约 | `202 operation_no` | | `FARM_EXCEPTION_STEP_RETRY` | `ADM-CW-012` `POST farm/cloud/exception/step/retry/:step_id`;`ADM-PD-008` `POST farm/exception/step/retry/:step_id` | 仅可恢复失败;前序步骤满足 | 原 `result_key` 重试,不新建第二份业务结果 | 返回同一 operation | | `FARM_EXCEPTION_CLOSE` | `ADM-CW-012` `POST farm/cloud/exception/close/:id`;`ADM-PD-008` `POST farm/exception/close/:id` | 必需步骤成功、通知有结果、数量/金额/状态恒等式闭合 | 关闭状态和审计 | `farm.exception.closed` | | `FARM_EXCEPTION_PROPOSE` | `SVC-CW-002` `POST farm/cloud/exception/propose/:id`;同页自提入口 `POST farm/cloud/pickup/overdue/:id` | 服务人员有范围;只提交事实/建议;自提入口还要求逾期且有剩余量 | 建议版本和联系记录,不改金额、库存或最终去向 | 返回建议 ID | ### 4. 溯源 | 操作码 | 页面与路由 | 前置/锁定 | 事务写集 | 事件/结果 | | --- | --- | --- | --- | --- | | `TRACE_ARCHIVE_CREATE` | `ADM-TR-002` `POST farm/trace/archive/create` | 来源生产/产出对象唯一且在范围 | 档案和草稿版本 | 返回 archive ID | | `TRACE_VERSION_SAVE` | `ADM-TR-002` `POST farm/trace/version/save/:archive_id` | 当前草稿;编辑权限;版本匹配 | 新内容版本,不覆盖历史 | 返回 version ID | | `TRACE_VERSION_SUBMIT` | `ADM-TR-002` `POST farm/trace/version/submit/:id` | 公开字段、材料和敏感字段检查通过 | 待审状态 | `farm.trace.version.submitted` | | `TRACE_VERSION_REVIEW` | `ADM-TR-002` `POST farm/trace/version/review/:id` | 审核权限;审核人不改内容 | 审核结论 | 通过发 `farm.trace.version.approved` | | `TRACE_VERSION_PUBLISH` | `ADM-TR-002` `POST farm/trace/version/publish/:id` | 独立发布权限;材料仍有效 | 公开版本指针和状态 | `farm.trace.version.published` | | `TRACE_VERSION_WITHDRAW` | `ADM-TR-002` `POST farm/trace/version/withdraw/:id` | 已发布;原因必填 | 撤回状态,二维码保持稳定并展示撤回页 | `farm.trace.version.withdrawn` | | `TRACE_MATERIAL_CREATE` | `ADM-TR-003` `POST farm/trace/material/create` | 文件扫描通过;元数据和适用对象完整 | 材料记录、文件引用 | 返回 material ID | | `TRACE_MATERIAL_UPDATE` | `ADM-TR-003` `POST farm/trace/material/update/:id` | 未发布引用或仅允许安全元数据 | 新元数据版本 | 返回影响引用数 | | `TRACE_MATERIAL_STATUS` | `ADM-TR-003` `POST farm/trace/material/status/:id` | 作废/恢复原因;发布引用给出影响提示 | 状态和审计 | 返回受影响档案 | | `TRACE_LINK_CREATE` | `ADM-TR-004` `POST farm/trace/link` | 两端对象可见;无重复/循环 | 关联和有效期 | 返回 link ID | | `TRACE_LINK_REMOVE` | `ADM-TR-004` `POST farm/trace/unlink/:id` | 引用和历史订单校验通过 | 解除当前关联;历史快照保留 | 返回影响摘要 | ## 八、服务/现场端专用命令 | 操作码 | 页面与路由 | 范围与约束 | 结果 | | --- | --- | --- | --- | | `FARM_SCAN_RESOLVE` | `SVC-PD-002` `POST farm/scan/resolve` | 校验二维码签名、对象状态和当前职责范围;越界按不存在 | 返回对象摘要和允许动作,不泄露内部范围 | | `FARM_ASSET_HEALTH_CREATE` | `SVC-PD-003` `POST farm/asset/health/create` | 分配任务/资产范围、附件归属、版本匹配 | 健康记录或待审过程事件 | | `FARM_WAREHOUSE_RECEIVE` | `SVC-PD-005` `POST farm/warehouse/receive/:task_id` | 当前任务、仓库/库位范围、数量方程 | 入库流水、任务进度 | | `FARM_FULFILLMENT_PACK` | `SVC-PD-005` `POST farm/fulfillment/pack/:task_id` | 当前任务、可拣库存、包裹未发货 | 包裹、拣货流水、任务进度 | | `FARM_EXCEPTION_EVIDENCE` | `SVC-PD-006` `POST farm/exception/evidence/:id` | 本人上报或被分派异常;只补证据 | 新证据版本 | | `FARM_ATTACHMENT_UPLOAD` | `SVC-PD-003~006` `POST farm/attachment/upload` | 文件类型、大小、病毒/内容检查;当前账号 | 返回短期未绑定 attachment ID | | `FARM_PRODUCTION_REVIEW` | `SVC-PD-007` `POST farm/production/review/:id` | 审核范围;不可编辑提交内容 | 审核结论 | | `FARM_OUTPUT_REVIEW` | `SVC-PD-007` `POST farm/output/review/:id` | 审核范围;数量方程重新计算 | 审核结论 | `SVC-PD-005` 的云仓自提任务复用第五节唯一的 `CW_PICKUP_VERIFY`。除原操作约束外还需当前现场任务和点位范围;同一事务成功后推进现场任务,不产生第二套核销事实或幂等键。 未绑定现场附件由清理任务在有效期后删除;已经被业务事实引用的证据不得因任务、人员或范围变化而删除。 ## 九、前端提交与刷新规则 | 场景 | 前端固定行为 | | --- | --- | | 防重复点击 | 请求开始后禁用当前命令按钮,但仍依赖后端幂等 | | 乐观更新 | 金额、库存、状态、持仓、占用和履约均禁止仅在前端乐观完成 | | 同步成功 | 用响应中的目标对象刷新详情和摘要;不继续使用提交前对象 | | `202` | 进入统一操作进度抽屉/页;按建议间隔轮询 operation,不轮询内部表 | | 版本冲突 | 保留用户输入,重新拉取详情并展示字段差异;不得自动覆盖 | | 状态冲突 | 刷新 `allowed_actions`,说明对象已由他人/任务推进 | | 幂等重放 | 按首次结果跳转,避免再次弹成功后触发第二次业务动作 | | 部分批量失败 | 展示逐条结果;成功项刷新,失败项保留原因和重试入口 | | 网络未知 | 先用原 `request_id` 重试或查询结果,禁止生成新键盲目重提 | ## 十、开发与测试验收 - 每个表内操作码必须成为后端稳定常量、幂等记录值、审计字段和测试用例标签。 - 同一路由不同终端共享领域 Service 时仍使用终端独立权限和操作码,不共享数据范围。 - 所有高风险命令必须有:成功、幂等重放、同键异参、版本冲突、状态冲突、越权、死锁重试、事务回滚、Outbox 重投测试。 - `preview/check/precheck` 结果必须在正式命令中重新验证;不得把前端传回的金额、数量、账户或状态当作事实。 - 写接口清单、路由、Controller、Validate、Service、Repository、表和事件的逐文件映射见 `35`;任何新增操作必须同时更新 `19`、`31`、`32`、`33`、`35` 和测试矩阵。 ## 十一、关联文档 - [15-v1-data-model-draft.md](15-v1-data-model-draft) - [19-v1-api-contract-draft.md](19-v1-api-contract-draft) - [20-v1-events-jobs-permissions-notifications.md](20-v1-events-jobs-permissions-notifications) - [21-v1-code-change-blueprint.md](21-v1-code-change-blueprint) - [28-v1-requirement-traceability-matrix.md](28-v1-requirement-traceability-matrix) - [33-v1-state-exception-transaction-matrix.md](33-v1-state-exception-transaction-matrix) - [34-v1-database-field-dictionary.md](34-v1-database-field-dictionary) - [35-v1-page-api-file-trace.md](35-v1-page-api-file-trace)