-
Notifications
You must be signed in to change notification settings - Fork 0
20 v1 events jobs permissions notifications
本文档定义 V1 内部事件、队列任务、定时扫描、权限、通知和审计边界。它是技术设计草案,不表示相应监听器、任务、权限记录或消息模板已经创建。
当前源码中已确认:
- 普通订单支付由
StoreOrderRepository::paySuccess()在核心事务中更新订单、商户锁定款和财务记录,事务提交后才触发order.paySuccess。 - 订单确认收货、核销、发货和整单退款等位置已预留
order.take、order.verify、order.delivery、order.refundAll等事件。 - 退款同意流程会触发
refund.agree,但不同退款完成路径没有统一、稳定的“退款最终完成”事件。 -
app/event.php已注册支付回调、定时器和部分系统监听器,但order.paySuccess等点分业务事件当前没有实际监听器。 - 定时任务由
create_timer监听器启动,TimerService只在指定 Swoole worker 上周期执行。 - 当前队列任务普遍实现
JobInterface::fire()和failed();部分任务捕获异常后直接删除,不能直接照搬到资金和库存任务。 - 当前请求锁只按具名路由和路由参数锁 8 秒,不是长期业务幂等。
因此 V1 采用“事务内薄适配器 + Outbox + 幂等消费者 + 定时对账修复”的方式接入。薄适配器只确认事实、执行必要策略分流和写 Outbox,不在 CRMEB 支付回调中计算收益或批量结算。
必须在同一数据库事务中完成:
- 云仓抢购库存条件扣减、CRMEB 订单创建、云仓首次明细创建。
- CRMEB 订单明细与
farm_order_binding创建。 - 支付成功与农业付款事实确认、财务策略分流和 Outbox。
- 退款申请冻结、拒绝/取消解冻、资金退款完成反向事实和 Outbox。
- 用户最终确认去向、库存池迁移、履约/持仓创建。
- 批次开始时冻结代销数量、持仓生效和批次状态变化。
- 二次零售 SKU 的云仓批次库存分配。
- 每次库存变化与对应不可变库存流水。
- 每次业务账本创建与其计算快照。
- 回购数量确认、平台库存取得和回购账本创建。
- 地块/认养资产条件分配与占用记录。
- 产出库存扣减与订单履约分配。
适合异步执行:
- 支付成功后的复杂云仓状态推进。
- 选择截止提醒和自动代销。
- 二次订单完成后的售后观察期扫描。
- 进度重算、节点账本生成和资金入账。
- 商户货款资格扫描和结算。
- 到期回购批量计算。
- 消息、导出、报表和第三方状态同步。
- 订单、支付、退款、库存、账本和履约表是事实来源。
- 事件用于通知其他模块“事实已发生”。
- 消费者处理前必须重新查询当前事实和版本。
- 丢事件由对账任务补发,重复事件由幂等记录消除。
V1 使用“至少一次投递 + 幂等消费 + 定时对账”:
- 每个事件有全局唯一
event_id。 - 每个消费者以
event_id + consumer_name建唯一约束。 - 每个业务结果另有业务唯一键,不能只依赖事件消费日志。
- 消费失败重试;超过上限进入失败任务列表并告警。
以下表应补入数据模型评审,不直接替代业务表:
| 表 | 用途 | 核心唯一约束 |
|---|---|---|
eb_farm_order_binding |
声明 CRMEB 订单明细的业务、财务、库存和履约策略 | order_product_id |
eb_farm_idempotency_record |
保存 HTTP 写接口首次请求摘要和结果 | operation_code + actor_type + actor_id + request_id |
eb_farm_domain_outbox |
保存待投递领域事件 | event_id |
eb_farm_event_consume_log |
消费幂等、耗时和错误 | event_id + consumer_name |
eb_farm_job_run |
定时任务游标、批次、结果和重试 | job_name + run_key |
eb_farm_notification_log |
站内信/微信/短信发送事实 | template_code + receiver + business_key |
eb_farm_audit_log |
关键业务状态和人工操作审计 | 普通索引;不可物理删除 |
幂等载体不得混用:
- HTTP 写接口使用
Idempotency-Key=request_id和eb_farm_idempotency_record。 - 支付/退款回调使用业务单号、渠道交易号、规范化金额和回调摘要;不要求客户端 Header。
- 事件消费使用
event_id + consumer_name,并由领域结果唯一键防止副作用重复。 - 定时任务使用
job_name + run_key管理一次扫描,单条记录仍以业务对象、目标状态和计算版本组成确定性结果键。
{
"event_id": "01J8M5J6TQF8M2NQJH4C5P8K3Z",
"event_type": "farm.cloud.order.paid",
"event_version": 1,
"aggregate_type": "cloud_order_item",
"aggregate_id": "42001",
"occurred_at": "2026-08-01 10:06:31",
"trace_id": "pay-98621",
"source": "crm_order_adapter",
"payload": {
"group_order_id": "98621",
"order_id": "98635",
"order_product_id": "100812",
"paid_at": "2026-08-01 10:06:30"
}
}事件 payload 只放定位和校验所需字段,不复制完整订单、用户隐私或规则快照。
- 事件名表达业务事实,不表达消费者动作。
- 增加可选字段不升级版本;删除字段或改变语义必须升级。
- 消费者声明支持的事件版本,未知版本进入告警而不是猜测处理。
- 历史事件不因当前规则修改而重写。
| 项目 | 设计 |
|---|---|
| CRMEB 原子接入点 |
StoreOrderRepository::paySuccess() 核心事务提交前 |
| 事务适配器 | FarmOrderPaymentAdapter |
| 识别方式 | 根据 group_order_id/order_id 批量读取 eb_farm_order_binding
|
| 同步动作 | 应用 finance_policy/fulfillment_policy、确认幂等付款事实并写 Outbox |
| 提交后唤醒 |
order.paySuccess 的薄监听器只补投递/唤醒,不重复制造事实 |
| 异步动作 | 推进首次明细、生成待办、尝试资产分配、发通知 |
| 缺口修复 | 扫描“核心订单已支付、业务扩展仍待付款”的记录 |
不得在支付事务适配器或监听器中直接:
- 启动完整云仓批次。
- 计算用户收益或商户货款。
- 调第三方物流。
- 批量发送通知。
- 执行耗时统计。
V1 形成统一适配事实 crm.refund.completed:
- 退款申请事务调用
FarmOrderRefundAdapter::applied(),冻结首次去向或二次分配。 - 退款拒绝和用户取消事务分别调用
rejected()、cancelled(),恢复可执行状态。 - 实际资金退款成功并执行
refundAfter()时调用completed(),按stock_policy恢复库存、跳过不适用的普通商户扣款,并写反向流水与 Outbox。 - 事件携带退款单、核心订单和订单明细 ID;复杂账本冲正由消费者处理。
- 每 5 分钟扫描已退款核心订单与业务扩展差异,修复遗漏路径。
refund.agree 只能表示部分业务路径已同意,不能在所有场景中等同资金退款最终成功;用户取消退款当前没有统一 CRMEB 事件,因此必须使用事务适配器。
StoreGroupOrderRepository::cancel() 先标记订单删除,再由 CancelGroupOrderJob 恢复库存。FarmOrderCancelAdapter 必须在该 Job 的库存事务中执行:
-
cloud_primary:跳过 CRMEB 来源商品库存恢复,释放活动抢购锁定。 -
cloud_resale:恢复 CRMEB 映射 SKU 镜像库存,并释放 FEFO 云仓分配。 -
normal:完全保持 CRMEB 现有行为。 - 所有路径以订单绑定和业务唯一键防重,并由差异任务修复队列丢失。
| CRMEB 事实 | 适配领域事件 | 云仓/农业用途 |
|---|---|---|
order.take |
crm.order.completed |
邮寄首次完成、二次零售进入观察期 |
order.verify |
crm.order.verified |
自提首次完成 |
| 自动收货调用同一完成服务 | crm.order.completed |
与用户手动收货一致 |
order.delivery |
crm.order.shipped |
履约轨迹和通知 |
order.refundAll |
crm.order.refunded_all |
辅助校验,不替代退款完成事实 |
消费者按订单明细判断业务归属,不对所有普通订单执行农业逻辑。
| 事件 | 产生条件 | 主要消费者 |
|---|---|---|
farm.product.agriculture.submitted |
平台或商户农业资料提交审核 | 商品审核待办、通知和审计投影 |
farm.product.agriculture.approved |
农业资料审核通过 | 新供货资格、商品摘要和提交方通知 |
farm.product.agriculture.rejected |
农业资料审核驳回 | 缺项展示、提交方通知 |
farm.product.material.expiring |
有效材料进入 30/7 天预警窗 | 商品运营、商户和内容审核通知 |
farm.product.material.expired |
材料到期事实确认 | 关闭新供货资格、活动来源预检告警;不改历史快照 |
farm.admin.scope.changed |
管理员农业范围全量保存成功 | 权限缓存失效、前端上下文刷新和审计投影 |
管理范围变更后的安全性仍来自每次请求实时读取当前范围;事件消费失败只能造成提示或缓存刷新延迟,不能延迟撤权本身。
| 事件 | 产生条件 | 主要消费者 |
|---|---|---|
farm.cloud.supply.submitted |
单一来源 SKU 申请提交 | 审核待办、材料检查;不改来源库存 |
farm.cloud.supply.approved |
审核事务成功并建立来源库存预留 | 交付任务、商户通知、责任快照 |
farm.cloud.supply.dispatched |
商户固化分批交付数量、物流和证据 | 在途跟踪、平台收货待办 |
farm.cloud.supply.received |
平台确认实际收货和短少 | 待检任务、收货数量流水 |
farm.cloud.supply.inspection_completed |
合格、待检、拒收和库位确认 | 合格量转云仓库存、拒收量进入退回 |
farm.cloud.supply.shortage_confirmed |
发运量与实收量差异确认 | 异常、责任协同、来源预留调整 |
farm.cloud.supply.reservation_released |
取消、超时或未交付余量释放 | 来源 SKU 库存恢复、对账 |
farm.cloud.supply.return_pending |
已入平台控制的实物决定退回 | 仓储退回任务;此时不得先增加来源可售 |
farm.cloud.supply.returned |
实物退回或等价库存移交完成 | 来源 SKU 恢复、商户通知 |
farm.cloud.supply.platform_acquired |
剩余实物经确认由平台承接 | 平台库存流水、供货闭合 |
上述事件均由同一供货事务写数量字段、库存流水和 Outbox。审核通过前不预占来源库存;责任方在审核时固化为快照,后续商品主数据变化不重写历史履约责任。
| 事件 | 产生条件 | 主要消费者 |
|---|---|---|
farm.cloud.order.created |
核心订单和云仓首次明细事务完成 | 支付超时跟踪、操作日志 |
farm.cloud.order.paid |
核心支付成功且首次明细确认 | 待选择状态、用户通知、商户首次销量 |
farm.cloud.order.pay_expired |
核心未支付订单关闭 | 库存释放、活动汇总 |
farm.cloud.choice.confirmed |
自提、包邮或代销最终生效 | 履约、持仓、批次准备 |
farm.cloud.freight.created |
需补运费 | 支付跟踪、用户通知 |
farm.cloud.freight.paid |
运费支付成功 | 邮寄去向生效、履约创建 |
farm.cloud.freight.expired |
运费单超时 | 返回待选择或自动代销 |
farm.cloud.freight.late_paid |
超时/取消/自动代销后收到渠道成功事实 | 创建全额退款、异常监控 |
farm.cloud.freight.refund_requested |
迟到支付、首次整条退款或平台取消邮寄 | 渠道退款任务 |
farm.cloud.freight.refunded |
原路或余额退款成功 | 用户通知、资金对账 |
farm.cloud.freight.refund_failed |
退款重试耗尽或渠道事实冲突 | 人工复核、告警 |
farm.cloud.choice.auto_consigned |
超过选择截止 | 创建持仓、通知 |
farm.cloud.primary.quantity_completed |
邮寄收货、每次自提核销/剩余量异常闭合或持仓入批次 | 按数量启动首次售后观察与商户结算资格 |
farm.cloud.primary.completed |
明细全部数量均已闭合 | 汇总完成状态和用户通知 |
farm.cloud.primary.refunded |
首次整条退款完成 | 释放库存、冲减商户货款 |
补运费渠道回调固定使用 CRMEB 事件 pay_success_farm_cloud_freight,由 CloudFreightPaySuccessListen 规范化为内部支付命令后调用领域服务。该监听器只确认支付事实,不计算用户收益或商户货款。
支付宝公共回调需在验签后向监听器补充 total_amount 和 trade_no;微信按 V2/V3 报文分别读取分金额。领域事务同时锁定运费单和云仓订单明细,校验订单号、金额、交易号、选择版本和超时状态。重复一致回调直接返回成功,冲突事实进入异常并告警。
| 事件 | 产生条件 | 主要消费者 |
|---|---|---|
farm.cloud.activity.published |
活动及 SKU 发布快照、库存占用和批次草稿同事务完成 | 活动预热、前台缓存、审计 |
farm.cloud.activity.closed |
未开始/异常活动经人工关闭 | 库存闭合检查、通知、审计 |
farm.cloud.activity.ended |
活动到达结束时间并停止新下单 | 关闭未支付订单、启动活动库存闭合 |
farm.cloud.activity.unpaid_closed |
活动下全部未支付订单已关闭或释放 | 允许计算真正未抢数量 |
farm.cloud.activity.inventory_released |
平台自营或可直接回源数量已释放 | 来源库存、活动汇总 |
farm.cloud.activity.return_pending |
商户实物仍在平台控制范围且需退回 | 仓储退回任务;不得先恢复商户可售 |
farm.cloud.activity.inventory_closed |
每个活动 SKU 的未抢数量均已释放、退回待办或平台承接 | 批次准备条件检查 |
farm.cloud.batch.ready |
选择窗口冻结且数量闭合 | 批次启动任务 |
farm.cloud.batch.started |
持仓全部生效 | 上架/可售库存桥接、用户通知 |
farm.cloud.resale.allocated |
普通零售明细按最早到期批次锁定 | 批次库存、订单关联 |
farm.cloud.resale.released |
普通订单未支付关闭 | 释放二次锁定 |
farm.cloud.resale.observing |
普通订单完成 | 计算观察期到期时间 |
farm.cloud.resale.effective |
完成且过二次售后期 | 有效销售、进度和节点检查 |
farm.cloud.resale.reversed |
二次退款 | 释放/冲减销售、冻结关联账本 |
farm.cloud.milestone.reached |
首次跨越尚未处理的 25/50/75/100 节点;一次跳过多个节点只发最高节点事件 | 差额账本任务、通知 |
farm.cloud.batch.sold_out |
代销数量全部有效售出 | 最终结算、提前结束 |
farm.cloud.batch.matured |
到预计到期仍有未售或在途 | 停止新分配并开始在途处置宽限 |
farm.cloud.batch.ownership_cutover |
到达在途处置宽限截止 | 固化平台承接在途、整数未售量和待审核回购预案 |
farm.cloud.buyback.approved |
人工审核回购预案通过 | 回购执行任务 |
farm.cloud.buyback.rejected |
人工审核驳回 | 冻结批次并生成重新计算待办 |
farm.cloud.buyback.completed |
平台取得剩余商品并生成回购款 | 最终账本、库存、批次关闭 |
farm.cloud.batch.closed |
数量、账本和回购全部闭合 | 报表、归档 |
farm.cloud.milestone.reached 载荷必须包含 batch_id、progress_snapshot_id、previous_progress_rate、current_progress_rate、previous_milestone、reached_milestone、crossed_milestones 和 calculation_version。结算金额按 current_progress_rate 对应的真实累计销售结果计算;reached_milestone 只作为触发与幂等边界。
| 事件 | 产生条件 | 主要消费者 |
|---|---|---|
farm.cloud.user_ledger.created |
节点/最终差额计算完成 | 自动校验、异常检测 |
farm.cloud.user_ledger.eligible |
校验通过、无冻结且在自动阈值内,或人工复核通过 | 用户余额正式入账 |
farm.cloud.user_ledger.settled |
用户资金入账完成 | 用户通知、对账 |
farm.cloud.user_ledger.frozen |
退款、差异或争议 | 财务待办 |
farm.cloud.merchant_ledger.eligible |
首次完成、验收和观察期均满足 | 商户结算 |
farm.cloud.merchant_statement.generated |
每日归集可入单供货账本 | 结单校验、自动/人工入账 |
farm.cloud.merchant_ledger.settled |
商户结单进入可用余额并回写明细 | 商户通知、对账 |
farm.financial_posting.failed |
余额、CRMEB 流水或事务处理失败 | 重试、告警、人工待办 |
farm.financial_posting.recovery_pending |
已审核的错误/重复入账或外部支付撤销需冲正,但目标余额不足 | 冻结后续农业入账、追偿待办 |
farm.cloud.ledger.adjusted |
冲正审核并执行 | 重新对账 |
eb_farm_financial_posting 使用以下状态:
pending -> processing -> succeeded
\-> failed -> processing
succeeded -> reversal_pending -> reversed
reversal_pending -> recovery_pending
-
processing必须带处理租约;任务崩溃且租约到期后可用原posting_key抢占重试。 - 用户入账事务同时锁定用户业务账本、入账记录和
eb_user行,并一起写UserBill、余额、Outbox 和成功状态。 - 商户入账事务同时锁定结单、入账记录和
eb_merchant行,并一起写FinancialRecord、余额、结单明细、Outbox 和成功状态。 - 商户供货款不进入
mer_lock_money/mer_computed_money,不受全局mer_lock_time二次等待。 - 事务回滚后不得发送成功通知;提交后的事件只负责通知、对账和修复扫描。
- 冲正只用于审核确认的错误/重复入账或外部支付最终撤销,是新的借方入账且不修改原成功记录;正常经营损失不得借记,余额不足时不做部分扣款。
“平台实际代销售出”必须来自真实普通商城订单,不能由运营手工填写一个销量。
批次开始后,将 consign_qty 中尚未锁定/售出的数量登记到 eb_farm_cloud_resale_stock:
CRMEB 普通商品 SKU
↕
云仓二次销售库存池
↕
一个或多个正在代销的云仓批次
该桥接表至少保存:
- CRMEB 来源商品和规格快照。
- 允许二次销售的商品/SKU 标识。
- 云仓可售、已锁定、有效售出数量汇总。
- 当前可参与批次范围。
- 是否允许普通商城显示与下单。
- 最后对账时间和版本。
它不能替代每个批次的库存流水,只负责把 CRMEB 普通销售入口与云仓批次连接起来。
V1 映射 SKU 的 stock_source 固定为 cloud_only。一个普通商城 SKU 不得同时混合商户普通库存和云仓库存;推荐由平台建立专用二次代销映射 SKU。活动规则和历史批次关联独立 activity_sku_id,来源 CRMEB 规格值主键只作当前同步定位。
同一 CRMEB group_order_id 不得混合普通财务商品与 cloud_only 商品。确认订单阶段应按 finance_policy 拆成不同订单组;当前端无法表达多组分别支付时返回明确错误,不能在支付后再按金额猜测拆账。
普通用户在商城购买映射 SKU 时:
- CRMEB 校验普通商品和 SKU 是否可售。
- 云仓桥接服务确认该 SKU 全量由云仓库存承担;V1 不做普通库存与云仓库存按比例混合。
- 对候选批次按
maturity_at升序、batch_id升序加锁。 - 逐批次写入
eb_farm_cloud_resale_allocation,状态为已锁定。 - 同时把批次数量从“可售”迁移到“二次锁定”并写库存流水。
- 核心订单创建失败时,同一事务回滚;未支付订单关闭时幂等释放。
一个普通订单明细可以拆给多个批次,同一批次内不直接指定某个用户持仓。
- 未支付订单期间 CRMEB 已经锁住普通商品库存。
- 如果云仓等到支付后才分配,多个未支付订单可能同时看到同一批次剩余量。
- 下单时分配才能让普通商品库存和云仓批次库存同步闭合。
- 支付事件只推进分配状态,不重新选择批次。
普通订单明细创建
→ 批次库存锁定
→ 用户支付
→ 发货/核销
→ 确认或自动收货
→ 二次售后观察期
→ 无有效退款
→ 转为有效代销售出
→ 批次内用户按持仓占比分摊
→ 检查结算节点
若完成后观察期内退款,分配进入退款/释放;若已经形成用户账本,则先冻结未结算金额,再生成反向业务账本,不直接修改历史流水。
由云仓库存承担的二次零售商品 V1 建议只参与普通商城销售:
- 不参加预售、拼团、助力、积分商品等会改变履约状态机的活动。
- 商户店铺券和商户商品优惠关闭。
- 平台券、平台补贴允许使用,由平台补足确认销售收入。
- 下单前明确商品是否由云仓池供货,避免同一明细混合普通库存和云仓库存。
如需普通库存与云仓库存混合,必须增加明确的库存来源拆分和退款分摊规则,不应在 V1 开发中临时补逻辑。
| 事件 | 产生条件 | 主要消费者 |
|---|---|---|
farm.land.order.paid |
租地交易支付成功 | 地块分配、用户通知 |
farm.land.plot.reserved |
平台锁定一个地块候选 | 5 分钟倒计时、占用日历临时容量 |
farm.land.plot.allocated |
真实地块占用成功 | 生产批次、用户详情 |
farm.land.plot.reservation_released |
主动取消、超时或确认失败 | 恢复候选容量、审计 |
farm.adoption.order.paid |
认养交易支付成功 | 个体/份额分配 |
farm.adoption.asset.reserved |
平台锁定个体或批次份额候选 | 5 分钟倒计时、临时容量 |
farm.adoption.asset.allocated |
个体或批次份额成功 | 生产关联、用户通知 |
farm.adoption.asset.reservation_released |
主动取消、超时或确认失败 | 恢复容量、审计 |
farm.adoption.asset.replaced |
已审核异常方案原子替换资产/份额 | 用户详情、生产关联、溯源 |
farm.animal.imported |
三段导入确认任务全批次原子完成 | 资产列表投影、容量摘要和操作结果通知 |
farm.production.batch.created |
计划批次和类型扩展创建 | 任务规划、占用校验 |
farm.production.batch.started |
生产周期开始 | 现场任务 |
farm.production.batch.paused |
平台因明确原因暂停 | 暂停相关待执行任务、用户告知评估 |
farm.production.batch.resumed |
预检通过后恢复 | 恢复任务和预计时间 |
farm.production.batch.completed |
产出、任务和异常闭合 | 权益和溯源汇总 |
farm.task.assigned |
任务首次分派或转派 | 现场人员待办 |
farm.task.started |
当前执行人开始任务 | 生产/履约现场进度 |
farm.task.completed |
现场任务完成 | 生产/履约进度 |
farm.production.event.submitted |
现场记录提交 | 平台审核待办 |
farm.production.event.published |
审核发布 | 用户时间线、溯源 |
farm.output.batch.submitted |
产出录入 | 质量验收 |
farm.output.batch.accepted |
合格数量确认 | 订单分配和履约 |
farm.output.allocated |
分配事务固化权益数量 | 履约创建、权益汇总 |
farm.fulfillment.ready |
用户有可邮寄产出 | 地址确认、通知 |
farm.fulfillment.address_confirmed |
用户固化本次地址版本 | 运费报价或仓储待办 |
farm.fulfillment.freight_paid |
独立农业运费支付成功 | 履约进入待出库 |
farm.fulfillment.shipped |
发货 | 物流通知 |
farm.fulfillment.completed |
收货/自动完成 | 权益履约汇总 |
farm.exception.created |
农业异常上报 | 审核、冻结、通知 |
farm.exception.plan_submitted |
不可变方案版本提交 | 平台审核待办 |
farm.exception.plan_approved |
方案审核通过且预检有效 | 需要用户确认则进入待确认,否则分步执行 |
farm.exception.plan_confirmed |
用户接受待确认方案 | 分步执行任务 |
farm.exception.plan_confirmation_timed_out |
用户确认期结束 | 完全等价方案执行;降级、减量、超期或补款方案转未履约退款 |
farm.exception.step_completed |
一个幂等执行步骤完成 | 后续步骤或闭合检查 |
farm.exception.step_failed |
一个执行步骤重试后仍失败 | 冻结、告警、人工修复 |
farm.exception.resolved |
全部必需步骤完成且恒等式闭合 | 恢复/退款/补发汇总 |
farm.exception.closed |
通知和审计闭合 | 归档、报表 |
farm.trace.version.submitted |
草稿版本提交 | 内容审核待办 |
farm.trace.version.approved |
内容审核通过 | 进入独立发布权限操作,审核通过不自动公开 |
farm.trace.version.published |
溯源版本发布 | 公开档案缓存、二维码 |
farm.trace.version.withdrawn |
发布版本撤回 | 公开状态更新 |
定时监听器只负责抢占任务和推送队列,不在 Swoole Timer 回调里批量处理业务。
| 任务 | 建议频率 | 单批上限 | 作用 |
|---|---|---|---|
CloudActivityStatusJob |
每 1 分钟 | 200 | 预热、开始、结束状态 |
CloudActivityInventoryCloseJob |
事件触发 + 每 1 分钟补偿 | 100 | 等未支付释放完成后关闭活动未抢库存并生成退回/承接 |
CloudUnpaidReleaseJob |
每 1 分钟 | 200 | 修复核心取消后未释放云仓库存 |
CloudPaidRepairJob |
每 1 分钟 | 200 | 修复已支付但业务仍待付款 |
CloudChoiceReminderJob |
每 10 分钟 | 500 | 24h/6h/1h 提醒 |
CloudChoiceExpireJob |
每 1 分钟 | 200 | 超时自动代销 |
CloudFreightExpireJob |
每 1 分钟 | 200 | 运费超时回待选择/代销,事务后请求渠道关单 |
CloudFreightPaymentRepairJob |
每 2 分钟 | 100 | 修复支付中、回调中断、迟到支付和关单失败 |
RefundCloudFreightJob |
实时队列 + 每 5 分钟补偿 | 100 | 按唯一退款单号提交在线/余额全额退款 |
CloudBatchStartJob |
每 1 分钟 | 100 | 冻结选择结果并启动批次 |
CloudPickupOverdueJob |
每 10 分钟 | 200 | 自提逾期转异常待协商 |
CloudResaleAllocationRepairJob |
每 1 分钟 | 200 | 修复普通订单未分配 |
CloudResaleReleaseJob |
每 1 分钟 | 200 | 释放未支付关闭订单 |
CloudResaleEffectiveJob |
每 5 分钟 | 200 | 二次观察期到期生效 |
CloudRefundSyncJob |
每 5 分钟 | 200 | 首次/二次退款差异修复 |
CloudMilestoneJob |
事件触发 + 每 10 分钟 | 100 | 锁批次,识别最高新节点,并按真实累计进度生成一组节点差额 |
CloudUserSettlementJob |
每 5 分钟 | 200 | 自动校验并以统一入账记录映射用户余额 |
CloudMerchantEligibilityJob |
每 10 分钟 | 200 | 商户货款资格 |
CloudMerchantStatementJob |
每日 02:00 | 按商户分片 | 归集上一自然日可入单账本并生成不可变结单 |
CloudMerchantPostingJob |
每日 02:05 + 每 10 分钟补偿 | 100 | 自动校验结单并映射商户余额和财务流水 |
FarmFinancialPostingRepairJob |
每 5 分钟 | 200 | 回收超时租约并重试可恢复失败 |
CloudMaturityJob |
每 10 分钟 | 100 | 到期批次停止新分配并固化在途处置宽限截止 |
CloudMaturityFinalizeJob |
每 10 分钟 | 100 | 宽限截止固化所有权切换、整数未售量和待人工审核回购预案 |
ExecuteCloudBuybackJob |
审核事件触发 + 每 10 分钟补偿 | 100 | 只执行状态为已审核且预检仍有效的回购 |
CloudReconciliationJob |
每日 02:10 | 分片 | 全量库存、账本、订单对账 |
CloudSupplyInventoryReconcileJob |
每 10 分钟 | 200 | 核对来源预留、送达、验收、活动占用、退回和平台承接守恒 |
FarmAllocationRepairJob |
每 5 分钟 | 100 | 已支付但未分配资产 |
FarmAllocationReservationExpireJob |
每 1 分钟 | 200 | 释放到期地块、个体资产和批次份额预留 |
FarmTaskReminderJob |
每小时 | 500 | 现场任务提醒 |
FarmOutputAllocationJob |
每 10 分钟 | 100 | 合格产出向订单分配 |
ExecuteFarmExceptionStepJob |
审核事件触发 + 每 5 分钟补偿 | 100 | 顺序执行已审核异常方案的幂等步骤 |
FarmExceptionConfirmationExpireJob |
每 10 分钟 | 200 | 处理异常方案 3 个自然日用户确认超时 |
FarmExceptionSlaJob |
每 10 分钟 | 200 | 识别即将/已经超过 SLA 的未关闭异常 |
FarmFulfillmentReminderJob |
每小时 | 500 | 地址确认、待收货提醒 |
RepairFarmFulfillmentFreightJob |
每 2 分钟 | 100 | 修复农业运费支付、超时、迟到支付和退款差异 |
ProductMaterialExpiryJob |
每 10 分钟 | 500 | 商品农业材料 30/7 天预警,到期关闭新供货资格 |
TraceMaterialExpiryJob |
每日 03:10 | 500 | 报告/证书到期预警 |
TracePublicCacheRepairJob |
每 10 分钟 | 200 | 修复发布指针与公开缓存/二维码解析差异 |
CleanupFarmUnboundAttachmentJob |
每日 03:30 | 500 | 清理超过保留期且未绑定业务对象的现场临时附件 |
PublishFarmDomainEventJob |
每 5 秒或常驻队列 | 200 | 领域事件投递 |
FarmFailedJobAlertJob |
每 5 分钟 | 200 | 失败任务告警 |
以下 Job 不按固定时间全表扫描,由事件、审核命令或上表定时任务分片投递;同名职责不得再塞进 Timer 回调:
| Job | 触发来源 | 唯一结果 |
|---|---|---|
SendFarmNotificationJob |
领域事件消费者 | 模板、接收人、业务对象和阶段唯一的通知记录 |
PostFarmUserLedgerJob |
farm.cloud.user_ledger.eligible |
唯一 posting_key 对应的一次用户正式入账 |
GenerateMerchantSupplyStatementJob |
CloudMerchantStatementJob 分片或授权人工命令 |
商户、结单日和币种唯一的不可变结单 |
PostMerchantSupplyStatementJob |
自动资格或人工审核通过 | 唯一 posting_key 对应的一次商户正式入账 |
GenerateTraceQrCodeJob |
farm.trace.version.published |
档案与公开版本唯一的二维码或静态材料 |
ValidateAnimalImportJob |
ANIMAL_IMPORT_VALIDATE |
校验操作号 + 文件哈希;只写异步操作预览/错误文件,不写资产 |
ConfirmAnimalImportJob |
ANIMAL_IMPORT_CONFIRM |
确认操作号 + 校验操作号;全批动物资产只成功一次 |
- 每类扫描任务保存
last_id或last_occurred_at + last_id。 - 禁止只用页码扫描持续变化的大表。
- 一批成功后再推进游标。
- 失败记录单独重试,不阻塞后续全部记录。
- 同一
batch_id的批次、节点和回购任务使用分布式锁。 - 同一
cloud_order_item_id的去向、退款和运费任务互斥。 - 同一
secondary_order_product_id的分配和退款互斥。 - 同一
holding_id + highest_milestone + calculation_version + ledger_type只允许一个账本结果。 - 地块、个体资产和份额预留按业务对象主行加锁;候选查询不占容量,确认只接受未过期令牌摘要。
- 地块使用时间重叠和单体资产有效分配必须由事务重查与数据库约束共同兜底。
- 同一异常方案按
exception_id + plan_version_id + step_code只产生一个执行结果;后续步骤必须观察前置步骤成功事实。
| 次数 | 延迟 |
|---|---|
| 第 1 次 | 10 秒 |
| 第 2 次 | 1 分钟 |
| 第 3 次 | 5 分钟 |
| 第 4 次 | 15 分钟 |
| 第 5 次 | 1 小时 |
超过 5 次:
- 任务进入失败状态,不再无限循环。
- 保留输入摘要、堆栈、关联业务号和最后一次错误。
- 冻结可能继续扩大差异的业务对象。
- 通知平台技术管理员和对应业务负责人。
- 平台提供“查看事实 → 预演重放 → 确认重放”,不提供直接改汇总值。
- 数据不存在且确认已删除/作废。
- 状态前置条件不满足。
- 幂等键请求摘要冲突。
- 规则快照缺失。
- 用户、商户或业务对象归属不一致。
- 金额、数量恒等式失败。
这些错误直接进入人工复核,不重复消耗队列。
- 数据库死锁、锁超时。
- Redis/队列短暂不可用。
- 支付、物流、对象存储临时超时。
- 依赖接口限流。
- 同一资源正在由其他任务处理。
| 角色 | 主要范围 |
|---|---|
| 平台超级管理员 | 全部 |
| 农业运营 | 农场、套餐、订单、生产、产出、异常 |
| 云仓运营 | 供货、活动、订单、批次、二次零售 |
| 仓储履约 | 验收、库存、自提、发货、产出入库 |
| 内容审核 | 生产记录和溯源审核发布 |
| 财务 | 用户账本、商户货款、回购、对账、冲正 |
| 客服主管 | 订单只读、异常协同、自提逾期 |
| 数据只读 | 报表和详情,不可写 |
| 权限组 | 允许操作 | 不应与之自动捆绑 |
|---|---|---|
| 云仓活动编辑 | 草稿和活动商品规则 | 发布、关闭、重算 |
| 云仓活动发布 | 发布前校验和发布 | 编辑历史快照 |
| 商品农业资料编辑 | 保存和提交资料 | 审核自己的提交、直接开启供货资格 |
| 商品农业资料审核 | 通过/驳回提交版本 | 修改提交内容 |
| 管理员农业范围授权 | 授予本人可管理范围内的对象 | 角色菜单权限、财务执行权限 |
| 供货审核 | 通过/驳回 | 入库验收、货款结算 |
| 入库验收 | 确认真实数量 | 修改供货价 |
| 批次冻结 | 暂停二次分配/结算 | 直接改库存 |
| 批次恢复 | 审核差异后恢复 | 删除异常记录 |
| 账本审核 | 查看公式并通过/驳回 | 直接入用户余额 |
| 账本执行 | 执行已审核记录 | 修改计算金额 |
| 回购审核 | 确认范围和快照 | 直接改回购比例 |
| 冲正申请 | 提交原因和证据 | 审核自己的申请 |
| 冲正审核 | 审核 | 修改原流水 |
| 溯源审核 | 审核内容 | 编辑提交内容 |
| 溯源发布/撤回 | 改公开状态 | 删除历史版本 |
- 每个平台写接口必须有唯一 ThinkPHP 路由名。
-
system_menu.route保存接口路由名,操作权限记录is_menu=0。 - 页面菜单记录
is_menu=1,其route保存前端页面路径。 - 路由组
_path指向所属前端菜单,供菜单同步和权限归类。 -
_auth=false只用于确实不需要操作权限的选项/预览,不可用于资金、库存和状态修改。 - 表单接口使用
_form映射到最终提交权限,避免“能打开表单但不能提交”或反向越权。
源码基线中的平台角色和 system_menu 主要控制路由权限,没有可直接复用的农场、仓库或农业业务对象范围。V1 使用 eb_farm_admin_scope 和 FarmAdminScopeRepository 补齐对象范围:
- 管理员先通过 CRMEB Token 和路由权限,再解析当前有效的业务域与对象范围。
- 列表 Repository 必须先套用范围再做筛选、统计和分页;禁止先取全量再在 PHP 中过滤。
- 详情和写事务按目标对象的归属链重新断言范围;越界对外返回
COMMON_NOT_FOUND,内部审计记录范围诊断。 - 超级管理员解析为版本化
all范围;业务代码不散落账号 ID 或角色名特判。 - 农场范围只控制可见对象,不自动授予财务、回购、冲正、发布或修复等高风险操作。
- 授权、撤销和全平台范围变更必须有独立权限、版本和审计;范围变化后旧页面提交仍以服务端当前关系为准。
| 角色 | 供货草稿 | 提交审核 | 验收只读 | 货款只读 | 提交异议 | 履约/售后 |
|---|---|---|---|---|---|---|
| 店铺管理员 | 是 | 是 | 是 | 是 | 是 | 是 |
| 商品运营 | 是 | 是 | 是 | 否 | 否 | 只读 |
| 仓储人员 | 否 | 否 | 是 | 否 | 否 | 是 |
| 财务人员 | 否 | 否 | 只读 | 是 | 是 | 只读 |
| 客服人员 | 否 | 否 | 只读 | 否 | 否 | 是 |
商户类型权限和商户子管理员角色均需包含新路由名;不能只在前端增加菜单。
服务端当前只有 Token 身份鉴权。V1 复用 store_service 身份,增加“职责权限码 + 对象范围”两层授权:
| 职责码 | 数据范围 | 权限码 |
|---|---|---|
platform_customer_service |
平台授权的全部或指定商户 |
farm.order.read、farm.cloud.order.read、farm.exception.read、farm.exception.propose
|
merchant_customer_service |
当前商户,不可跨租户 |
farm.order.read、farm.cloud.order.read、farm.exception.read、farm.exception.propose
|
crop_operator |
分配的农场、区域、地块、生产批次或任务 |
farm.task.read、farm.task.execute、farm.scan.resolve、farm.production.event.write、farm.output.write、farm.exception.report、farm.evidence.upload
|
livestock_operator |
分配的农场、栏舍、资产、生产批次或任务 |
farm.task.read、farm.task.execute、farm.scan.resolve、farm.production.event.write、farm.asset.health.write、farm.output.write、farm.exception.report、farm.evidence.upload
|
warehouse_operator |
分配仓库、产出批次、履约或任务 |
farm.task.read、farm.task.execute、farm.scan.resolve、farm.warehouse.receive、farm.fulfillment.pack、farm.fulfillment.ship、farm.pickup.verify、farm.exception.report、farm.evidence.upload
|
farm_reviewer |
指定农场或业务域 |
farm.production.review、farm.output.review、farm.exception.read
|
补充权限:
-
farm.user.pii.read:查看完整手机号等敏感信息,必须审计。 -
farm.workspace.access:农业工作区基础访问,由有效农业档案隐含授予。 -
farm.context.read:读取本人工作区上下文,不授予任何业务对象访问。
执行规则:
-
ServiceTokenMiddleware先确认账号仍满足is_open=1、status=1、is_del=0。 - 登录后的本人
farm/context只经过 Token 校验,用于发现工作区、职责和能力;它不授予任何业务对象访问。 - 其他农业路由由
FarmServicePermissionMiddleware根据权限码和职责配置确认动作。 -
FarmServiceScopeRepository在列表 SQL、详情读取和写事务内校验对象范围。 - 数据范围使用独立关系表,不把一组农场 ID 长期塞在 Token 中;每个写操作重新校验当前分配关系。
- 列表必须先限定范围再分页;详情越界按不存在返回,避免泄露业务编号。
- 商户账号最大边界固定为自身
mer_id;all只表示该商户内全部,不表示全平台。 - 范围变更递增
scope_version,用于通知前端刷新,不降低后端实时校验要求。
证据上传使用独立 farm.evidence.upload 权限,但还必须绑定一个当前可见、可写的业务对象或任务;上传权限不能被当成任意文件库读取权限。生产/产出审核人若只审核既有附件,无需上传权限;需要补充审核证据时再由角色显式授予。
权限码到职责的映射放在版本化代码配置中,V1 不为服务端引入平台/商户动态菜单表。权限、范围和业务状态任何一层不通过均不得执行写操作。
| 场景 | 站内信 | 微信订阅/模板 | 短信 | 发送时点 |
|---|---|---|---|---|
| 抢购支付成功 | 是 | 可选 | 否 | 支付事实确认 |
| 去向待选择 | 是 | 是 | 否 | 支付成功 |
| 选择截止前 24h/6h/1h | 去重 | 是 | 1h 可选 | 未选择且未退款 |
| 已自动转代销 | 是 | 是 | 否 | 自动代销完成 |
| 补运费待支付 | 是 | 可选 | 否 | 运费单创建 |
| 补运费超时 | 是 | 可选 | 否 | 超时处理完成 |
| 补运费迟到支付退款中 | 是 | 是 | 可选 | 迟到支付事实确认 |
| 补运费退款成功/失败 | 是 | 是 | 失败时是 | 退款状态最终变化 |
| 自提可领取 | 是 | 是 | 可选 | 自提凭证生成 |
| 自提临期/逾期 | 是 | 是 | 逾期可选 | T-24h/逾期 |
| 批次开始代销 | 是 | 可选 | 否 | 批次启动 |
| 达到结算节点 | 是 | 可选 | 否 | 账本生成/入账 |
| 批次到期 | 是 | 是 | 否 | 到期状态确认 |
| 回购完成 | 是 | 是 | 可选 | 回购款入账 |
| 账本冻结/异常 | 是 | 可选 | 重要时是 | 冻结完成 |
| 场景 | 通知内容 |
|---|---|
| 支付成功 | 套餐、下一步和预计分配时间 |
| 地块/资产分配 | 真实编号、区域、周期和查看入口 |
| 生产批次开始 | 预计周期和已发布首条记录 |
| 关键生产记录 | 仅用户可见且已审核发布的事件 |
| 预计产出延期 | 新时间、原因和处理方案 |
| 产出可邮寄 | 本次数量、地址确认截止 |
| 已发货 | 物流公司、单号和数量 |
| 农业异常 | 影响、方案、预计完成时间 |
| 溯源更新 | 新发布版本查看入口 |
| 场景 | 通知内容 |
|---|---|
| 供货提交成功 | 申请号和预计审核时间 |
| 审核通过/驳回 | 结果和原因 |
| 入库验收 | 验收数量、差异和证据 |
| 活动开始/结束 | 占用数量和首次销售汇总 |
| 首次退款 | 数量和货款影响 |
| 货款待结算/已结算 | 结算单和金额 |
| 对账异常 | 差异类型和处理入口 |
| 场景 | 接收人 |
|---|---|
| 待审核供货 | 云仓运营 |
| 活动库存不足/规则缺失 | 云仓运营、仓储 |
| 批次库存不闭合 | 云仓运营、财务、技术管理员 |
| 账本计算失败/冻结 | 财务 |
| 回购即将到期/执行失败 | 云仓运营、财务 |
| 地块/资产分配失败 | 农业运营 |
| 产出不足或异常 | 农业运营、客服 |
| 商品农业资料待审/材料到期 | 商品运营、内容审核、对应商户 |
| 溯源材料到期 | 内容审核、农业运营 |
| 队列失败超过上限 | 技术管理员和业务负责人 |
- 通知模板使用稳定
template_code,文案更新不改变业务事件。 - 同一业务对象、模板和节点建立唯一发送键。
- 发送前再次确认当前状态,已选择、已退款或已完成则取消过时提醒。
- 第三方发送失败不回滚核心业务事务。
- 微信/SMS 失败后保留站内信和发送日志。
- 消息内只放必要信息,完整金额、地址和证据进入登录后详情页。
- 用户营销订阅与履约必要通知分开管理。
- 后台 WebSocket 通知用于提示,不作为任务是否存在的事实来源。
以下操作必须写 eb_farm_audit_log:
- 活动发布、关闭和规则变更。
- 商品农业资料提交、审核、停用和材料关系变更。
- 管理员农业范围授权、撤销、全平台范围和有效期变更。
- 供货审核、入库验收和数量差异。
- 用户去向自动处理和人工异常处理。
- 批次冻结、恢复、重算预览和修复。
- 账本审核、执行、冻结和冲正。
- 回购审核和执行。
- 地块、个体资产和批次份额分配。
- 生产记录审核、溯源发布和撤回。
- 农业异常方案审核、退款、替换和补发。
- 失败任务人工重放。
审计字段至少包含:
- 操作者类型、操作者 ID、所属商户/组织。
- 业务类型、业务 ID、业务编号。
- 操作码、操作前状态、操作后状态。
- 关键字段变更摘要。
- 原因、证据附件、请求 ID、IP 和客户端。
- 创建时间。
系统自动任务使用独立系统操作者,不能伪装为某个管理员。
- 规则快照完整。
- 数量和金额恒等式通过。
- 无退款、争议、冻结和对账差异。
- 事件、账本和入账幂等键未冲突。
- 用户单笔不超过
10,000.00元、自然日累计不超过50,000.00元。 - 商户单张结单不超过
100,000.00元。
- 数据重算出现差异。
- 退款发生在用户账本已入账之后。
- 回购比例为自定义且规则快照异常。
- 用户应结算金额可能为负。
- 商户货款、供货验收和首次退款不闭合。
- 地块、资产、产出发生容量冲突。
- 任务失败超过重试上限。
- 人工冲正、补录或跨状态处理。
自动审核阈值是运营配置,不改变计算公式;大额和异常只改变是否需要人工确认。
阈值配置只允许超级管理员修改并记录审计。任务和后台人工执行必须调用同一入账服务,人工复核不能绕过来源状态、金额重算、目标账户行锁和唯一 posting_key。
至少建立:
- 已支付但仍待付款业务扩展数量。
- 已过选择截止但仍待选择数量。
- 批次库存恒等式失败数量。
- 已批准但材料已过期仍可新供货的商品数量。
- 普通二次订单未分配数量。
- 已过观察期但未生效数量。
- 达到节点但未生成账本数量。
- 待结算超时、入账失败和冻结金额。
-
financial_posting处理中租约超时数、重复幂等命中数和事务回滚数。 - 用户余额流水与成功入账记录差异、商户财务流水与结单差异。
- 借方冲正待追偿主体数和被冻结的后续农业入账金额。
- 到期未回购数量和金额。
- 商户货款资格超时数量。
- 已支付但未分配地块/资产数量。
- 已验收产出但未分配履约数量。
- Outbox 积压、队列失败和通知失败数量。
监控只展示汇总,点击进入对应异常列表和业务详情。
- 支付回调重复、乱序和延迟。
- 订单支付成功后进程立即中断,验证修复任务。
- 同一订单明细并发选择三种去向。
- 补运费成功回调、运费超时和选择截止任务并发。
- 补运费超时后迟到成功、重复回调和退款任务重复执行。
- 活动结束、未支付释放和自动代销并发。
- 普通订单一个明细跨两个云仓批次分配。
- 二次订单完成后发生部分/全量退款。
- 一次销售进度跨越多个节点。
- 到期回购与最后一笔二次订单生效并发。
- 用户账本已生成但余额入账超时。
- 商户结算与首次退款并发。
- 地块、个体资产和批次份额并发分配。
- 产出不足、替换、补发和未履约退款。
- 商品材料到期与供货提交、活动发布并发。
- 管理员农业范围并发保存和即时撤权。
- 队列停机后恢复、事件重复投递和人工重放。
- 13-cloud-warehouse-process-and-state-machines.md
- 15-v1-data-model-draft.md
- 17-v1-information-architecture.md
- 18-v1-page-and-prototype-spec.md
- 19-v1-api-contract-draft.md
- 21-v1-code-change-blueprint.md
- 31-v1-write-operation-contract-registry.md
- 32-v1-event-job-operation-registry.md
- 33-v1-state-exception-transaction-matrix.md
- 34-v1-database-field-dictionary.md
- 首页
- 项目总览
- 项目立项
- 端与角色
- 供应链经营闭环
- 模块地图
- V1 范围 PRD
- 任务拆解
- 结算与账本
- V1 结算口径
- 云仓秒杀
- CRMEB 底座能力映射
- 当前菜单页面审计
- V1 决策与术语
- 云仓流程与状态机
- 租地认养与溯源 PRD
- V1 数据模型草案
- 开发前设计计划
- V1 信息架构
- 页面与原型规格
- V1 API 契约草案
- 事件任务权限通知
- 五项目代码改造蓝图
- 测试验收发布与手册计划
- CRMEB 视觉基线审计
- G3/G4 决策登记表
- 用户端 uni-app 复用审计
- 开发前主清单
- 自主设计工作指引
- V1 需求追踪矩阵
- G3 技术专项验证报告
- V1 P0 页面矩阵
- 写操作契约注册表
- 事件任务操作注册表
- 状态异常事务矩阵
- 数据库字段字典
- 页面 API 文件追踪
- V1 ER 图
- API 字段契约注册表
- 平台管理员手册
- 商户手册
- 用户帮助
- 服务与现场手册
- 开发任务包
- 测试目录与 Fixtures
- 发布与运维手册
- 设计交付与研发交接