Skip to content

20 v1 events jobs permissions notifications

技术老胡 edited this page Jul 30, 2026 · 2 revisions

V1 事件、任务、权限与通知设计

本文档定义 V1 内部事件、队列任务、定时扫描、权限、通知和审计边界。它是技术设计草案,不表示相应监听器、任务、权限记录或消息模板已经创建。

一、现有 CRMEB 接入事实

当前源码中已确认:

  • 普通订单支付由 StoreOrderRepository::paySuccess() 在核心事务中更新订单、商户锁定款和财务记录,事务提交后才触发 order.paySuccess
  • 订单确认收货、核销、发货和整单退款等位置已预留 order.takeorder.verifyorder.deliveryorder.refundAll 等事件。
  • 退款同意流程会触发 refund.agree,但不同退款完成路径没有统一、稳定的“退款最终完成”事件。
  • app/event.php 已注册支付回调、定时器和部分系统监听器,但 order.paySuccess 等点分业务事件当前没有实际监听器。
  • 定时任务由 create_timer 监听器启动,TimerService 只在指定 Swoole worker 上周期执行。
  • 当前队列任务普遍实现 JobInterface::fire()failed();部分任务捕获异常后直接删除,不能直接照搬到资金和库存任务。
  • 当前请求锁只按具名路由和路由参数锁 8 秒,不是长期业务幂等。

因此 V1 采用“事务内薄适配器 + Outbox + 幂等消费者 + 定时对账修复”的方式接入。薄适配器只确认事实、执行必要策略分流和写 Outbox,不在 CRMEB 支付回调中计算收益或批量结算。

二、处理原则

1. 同步与异步边界

必须在同一数据库事务中完成:

  • 云仓抢购库存条件扣减、CRMEB 订单创建、云仓首次明细创建。
  • CRMEB 订单明细与 farm_order_binding 创建。
  • 支付成功与农业付款事实确认、财务策略分流和 Outbox。
  • 退款申请冻结、拒绝/取消解冻、资金退款完成反向事实和 Outbox。
  • 用户最终确认去向、库存池迁移、履约/持仓创建。
  • 批次开始时冻结代销数量、持仓生效和批次状态变化。
  • 二次零售 SKU 的云仓批次库存分配。
  • 每次库存变化与对应不可变库存流水。
  • 每次业务账本创建与其计算快照。
  • 回购数量确认、平台库存取得和回购账本创建。
  • 地块/认养资产条件分配与占用记录。
  • 产出库存扣减与订单履约分配。

适合异步执行:

  • 支付成功后的复杂云仓状态推进。
  • 选择截止提醒和自动代销。
  • 二次订单完成后的售后观察期扫描。
  • 进度重算、节点账本生成和资金入账。
  • 商户货款资格扫描和结算。
  • 到期回购批量计算。
  • 消息、导出、报表和第三方状态同步。

2. 事件不是事实来源

  • 订单、支付、退款、库存、账本和履约表是事实来源。
  • 事件用于通知其他模块“事实已发生”。
  • 消费者处理前必须重新查询当前事实和版本。
  • 丢事件由对账任务补发,重复事件由幂等记录消除。

3. 不追求伪“恰好一次”

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 关键业务状态和人工操作审计 普通索引;不可物理删除

幂等载体不得混用:

  1. HTTP 写接口使用 Idempotency-Key=request_ideb_farm_idempotency_record
  2. 支付/退款回调使用业务单号、渠道交易号、规范化金额和回调摘要;不要求客户端 Header。
  3. 事件消费使用 event_id + consumer_name,并由领域结果唯一键防止副作用重复。
  4. 定时任务使用 job_name + run_key 管理一次扫描,单条记录仍以业务对象、目标状态和计算版本组成确定性结果键。

1. 事件信封

{
  "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 只放定位和校验所需字段,不复制完整订单、用户隐私或规则快照。

2. 事件版本

  • 事件名表达业务事实,不表达消费者动作。
  • 增加可选字段不升级版本;删除字段或改变语义必须升级。
  • 消费者声明支持的事件版本,未知版本进入告警而不是猜测处理。
  • 历史事件不因当前规则修改而重写。

四、CRMEB 适配事件

1. 支付成功

项目 设计
CRMEB 原子接入点 StoreOrderRepository::paySuccess() 核心事务提交前
事务适配器 FarmOrderPaymentAdapter
识别方式 根据 group_order_id/order_id 批量读取 eb_farm_order_binding
同步动作 应用 finance_policy/fulfillment_policy、确认幂等付款事实并写 Outbox
提交后唤醒 order.paySuccess 的薄监听器只补投递/唤醒,不重复制造事实
异步动作 推进首次明细、生成待办、尝试资产分配、发通知
缺口修复 扫描“核心订单已支付、业务扩展仍待付款”的记录

不得在支付事务适配器或监听器中直接:

  • 启动完整云仓批次。
  • 计算用户收益或商户货款。
  • 调第三方物流。
  • 批量发送通知。
  • 执行耗时统计。

2. 退款完成

V1 形成统一适配事实 crm.refund.completed

  1. 退款申请事务调用 FarmOrderRefundAdapter::applied(),冻结首次去向或二次分配。
  2. 退款拒绝和用户取消事务分别调用 rejected()cancelled(),恢复可执行状态。
  3. 实际资金退款成功并执行 refundAfter() 时调用 completed(),按 stock_policy 恢复库存、跳过不适用的普通商户扣款,并写反向流水与 Outbox。
  4. 事件携带退款单、核心订单和订单明细 ID;复杂账本冲正由消费者处理。
  5. 每 5 分钟扫描已退款核心订单与业务扩展差异,修复遗漏路径。

refund.agree 只能表示部分业务路径已同意,不能在所有场景中等同资金退款最终成功;用户取消退款当前没有统一 CRMEB 事件,因此必须使用事务适配器。

3. 未支付取消

StoreGroupOrderRepository::cancel() 先标记订单删除,再由 CancelGroupOrderJob 恢复库存。FarmOrderCancelAdapter 必须在该 Job 的库存事务中执行:

  • cloud_primary:跳过 CRMEB 来源商品库存恢复,释放活动抢购锁定。
  • cloud_resale:恢复 CRMEB 映射 SKU 镜像库存,并释放 FEFO 云仓分配。
  • normal:完全保持 CRMEB 现有行为。
  • 所有路径以订单绑定和业务唯一键防重,并由差异任务修复队列丢失。

4. 收货、核销和自动完成

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 辅助校验,不替代退款完成事实

消费者按订单明细判断业务归属,不对所有普通订单执行农业逻辑。

五、商品、管理范围与云仓领域事件

0. 商品农业资料与管理范围

事件 产生条件 主要消费者
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 管理员农业范围全量保存成功 权限缓存失效、前端上下文刷新和审计投影

管理范围变更后的安全性仍来自每次请求实时读取当前范围;事件消费失败只能造成提示或缓存刷新延迟,不能延迟撤权本身。

1. 供货与验收

事件 产生条件 主要消费者
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。审核通过前不预占来源库存;责任方在审核时固化为快照,后续商品主数据变化不重写历史履约责任。

2. 首次购买与去向

事件 产生条件 主要消费者
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_amounttrade_no;微信按 V2/V3 报文分别读取分金额。领域事务同时锁定运费单和云仓订单明细,校验订单号、金额、交易号、选择版本和超时状态。重复一致回调直接返回成功,冲突事实进入异常并告警。

3. 批次与二次零售

事件 产生条件 主要消费者
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_idprogress_snapshot_idprevious_progress_ratecurrent_progress_rateprevious_milestonereached_milestonecrossed_milestonescalculation_version。结算金额按 current_progress_rate 对应的真实累计销售结果计算;reached_milestone 只作为触发与幂等边界。

4. 结算与账本

事件 产生条件 主要消费者
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 冲正审核并执行 重新对账

5. 正式入账状态与事务

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 二次等待。
  • 事务回滚后不得发送成功通知;提交后的事件只负责通知、对账和修复扫描。
  • 冲正只用于审核确认的错误/重复入账或外部支付最终撤销,是新的借方入账且不修改原成功记录;正常经营损失不得借记,余额不足时不做部分扣款。

六、真实代销售出的技术链路

“平台实际代销售出”必须来自真实普通商城订单,不能由运营手工填写一个销量。

1. 可售库存桥接

批次开始后,将 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 拆成不同订单组;当前端无法表达多组分别支付时返回明确错误,不能在支付后再按金额猜测拆账。

2. 下单时分配

普通用户在商城购买映射 SKU 时:

  1. CRMEB 校验普通商品和 SKU 是否可售。
  2. 云仓桥接服务确认该 SKU 全量由云仓库存承担;V1 不做普通库存与云仓库存按比例混合。
  3. 对候选批次按 maturity_at 升序、batch_id 升序加锁。
  4. 逐批次写入 eb_farm_cloud_resale_allocation,状态为已锁定。
  5. 同时把批次数量从“可售”迁移到“二次锁定”并写库存流水。
  6. 核心订单创建失败时,同一事务回滚;未支付订单关闭时幂等释放。

一个普通订单明细可以拆给多个批次,同一批次内不直接指定某个用户持仓。

3. 为什么不能只在支付后分配

  • 未支付订单期间 CRMEB 已经锁住普通商品库存。
  • 如果云仓等到支付后才分配,多个未支付订单可能同时看到同一批次剩余量。
  • 下单时分配才能让普通商品库存和云仓批次库存同步闭合。
  • 支付事件只推进分配状态,不重新选择批次。

4. 完成与观察期

普通订单明细创建
→ 批次库存锁定
→ 用户支付
→ 发货/核销
→ 确认或自动收货
→ 二次售后观察期
→ 无有效退款
→ 转为有效代销售出
→ 批次内用户按持仓占比分摊
→ 检查结算节点

若完成后观察期内退款,分配进入退款/释放;若已经形成用户账本,则先冻结未结算金额,再生成反向业务账本,不直接修改历史流水。

5. V1 销售限制建议

由云仓库存承担的二次零售商品 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 失败任务告警

1. 事件或事务触发的队列 Job

以下 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 确认操作号 + 校验操作号;全批动物资产只成功一次

2. 游标

  • 每类扫描任务保存 last_idlast_occurred_at + last_id
  • 禁止只用页码扫描持续变化的大表。
  • 一批成功后再推进游标。
  • 失败记录单独重试,不阻塞后续全部记录。

3. 并发

  • 同一 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. 重试建议

次数 延迟
第 1 次 10 秒
第 2 次 1 分钟
第 3 次 5 分钟
第 4 次 15 分钟
第 5 次 1 小时

超过 5 次:

  • 任务进入失败状态,不再无限循环。
  • 保留输入摘要、堆栈、关联业务号和最后一次错误。
  • 冻结可能继续扩大差异的业务对象。
  • 通知平台技术管理员和对应业务负责人。
  • 平台提供“查看事实 → 预演重放 → 确认重放”,不提供直接改汇总值。

2. 不可重试错误

  • 数据不存在且确认已删除/作废。
  • 状态前置条件不满足。
  • 幂等键请求摘要冲突。
  • 规则快照缺失。
  • 用户、商户或业务对象归属不一致。
  • 金额、数量恒等式失败。

这些错误直接进入人工复核,不重复消耗队列。

3. 可重试错误

  • 数据库死锁、锁超时。
  • Redis/队列短暂不可用。
  • 支付、物流、对象存储临时超时。
  • 依赖接口限流。
  • 同一资源正在由其他任务处理。

十、平台端权限矩阵

1. 建议角色

角色 主要范围
平台超级管理员 全部
农业运营 农场、套餐、订单、生产、产出、异常
云仓运营 供货、活动、订单、批次、二次零售
仓储履约 验收、库存、自提、发货、产出入库
内容审核 生产记录和溯源审核发布
财务 用户账本、商户货款、回购、对账、冲正
客服主管 订单只读、异常协同、自提逾期
数据只读 报表和详情,不可写

2. 高风险权限必须拆分

权限组 允许操作 不应与之自动捆绑
云仓活动编辑 草稿和活动商品规则 发布、关闭、重算
云仓活动发布 发布前校验和发布 编辑历史快照
商品农业资料编辑 保存和提交资料 审核自己的提交、直接开启供货资格
商品农业资料审核 通过/驳回提交版本 修改提交内容
管理员农业范围授权 授予本人可管理范围内的对象 角色菜单权限、财务执行权限
供货审核 通过/驳回 入库验收、货款结算
入库验收 确认真实数量 修改供货价
批次冻结 暂停二次分配/结算 直接改库存
批次恢复 审核差异后恢复 删除异常记录
账本审核 查看公式并通过/驳回 直接入用户余额
账本执行 执行已审核记录 修改计算金额
回购审核 确认范围和快照 直接改回购比例
冲正申请 提交原因和证据 审核自己的申请
冲正审核 审核 修改原流水
溯源审核 审核内容 编辑提交内容
溯源发布/撤回 改公开状态 删除历史版本

3. 路由权限落地

  • 每个平台写接口必须有唯一 ThinkPHP 路由名。
  • system_menu.route 保存接口路由名,操作权限记录 is_menu=0
  • 页面菜单记录 is_menu=1,其 route 保存前端页面路径。
  • 路由组 _path 指向所属前端菜单,供菜单同步和权限归类。
  • _auth=false 只用于确实不需要操作权限的选项/预览,不可用于资金、库存和状态修改。
  • 表单接口使用 _form 映射到最终提交权限,避免“能打开表单但不能提交”或反向越权。

4. 平台管理员数据范围

源码基线中的平台角色和 system_menu 主要控制路由权限,没有可直接复用的农场、仓库或农业业务对象范围。V1 使用 eb_farm_admin_scopeFarmAdminScopeRepository 补齐对象范围:

  1. 管理员先通过 CRMEB Token 和路由权限,再解析当前有效的业务域与对象范围。
  2. 列表 Repository 必须先套用范围再做筛选、统计和分页;禁止先取全量再在 PHP 中过滤。
  3. 详情和写事务按目标对象的归属链重新断言范围;越界对外返回 COMMON_NOT_FOUND,内部审计记录范围诊断。
  4. 超级管理员解析为版本化 all 范围;业务代码不散落账号 ID 或角色名特判。
  5. 农场范围只控制可见对象,不自动授予财务、回购、冲正、发布或修复等高风险操作。
  6. 授权、撤销和全平台范围变更必须有独立权限、版本和审计;范围变化后旧页面提交仍以服务端当前关系为准。

十一、商户端权限矩阵

角色 供货草稿 提交审核 验收只读 货款只读 提交异议 履约/售后
店铺管理员
商品运营 只读
仓储人员
财务人员 只读 只读
客服人员 只读

商户类型权限和商户子管理员角色均需包含新路由名;不能只在前端增加菜单。

十二、服务/现场端数据范围

服务端当前只有 Token 身份鉴权。V1 复用 store_service 身份,增加“职责权限码 + 对象范围”两层授权:

职责码 数据范围 权限码
platform_customer_service 平台授权的全部或指定商户 farm.order.readfarm.cloud.order.readfarm.exception.readfarm.exception.propose
merchant_customer_service 当前商户,不可跨租户 farm.order.readfarm.cloud.order.readfarm.exception.readfarm.exception.propose
crop_operator 分配的农场、区域、地块、生产批次或任务 farm.task.readfarm.task.executefarm.scan.resolvefarm.production.event.writefarm.output.writefarm.exception.reportfarm.evidence.upload
livestock_operator 分配的农场、栏舍、资产、生产批次或任务 farm.task.readfarm.task.executefarm.scan.resolvefarm.production.event.writefarm.asset.health.writefarm.output.writefarm.exception.reportfarm.evidence.upload
warehouse_operator 分配仓库、产出批次、履约或任务 farm.task.readfarm.task.executefarm.scan.resolvefarm.warehouse.receivefarm.fulfillment.packfarm.fulfillment.shipfarm.pickup.verifyfarm.exception.reportfarm.evidence.upload
farm_reviewer 指定农场或业务域 farm.production.reviewfarm.output.reviewfarm.exception.read

补充权限:

  • farm.user.pii.read:查看完整手机号等敏感信息,必须审计。
  • farm.workspace.access:农业工作区基础访问,由有效农业档案隐含授予。
  • farm.context.read:读取本人工作区上下文,不授予任何业务对象访问。

执行规则:

  1. ServiceTokenMiddleware 先确认账号仍满足 is_open=1status=1is_del=0
  2. 登录后的本人 farm/context 只经过 Token 校验,用于发现工作区、职责和能力;它不授予任何业务对象访问。
  3. 其他农业路由由 FarmServicePermissionMiddleware 根据权限码和职责配置确认动作。
  4. FarmServiceScopeRepository 在列表 SQL、详情读取和写事务内校验对象范围。
  5. 数据范围使用独立关系表,不把一组农场 ID 长期塞在 Token 中;每个写操作重新校验当前分配关系。
  6. 列表必须先限定范围再分页;详情越界按不存在返回,避免泄露业务编号。
  7. 商户账号最大边界固定为自身 mer_idall 只表示该商户内全部,不表示全平台。
  8. 范围变更递增 scope_version,用于通知前端刷新,不降低后端实时校验要求。

证据上传使用独立 farm.evidence.upload 权限,但还必须绑定一个当前可见、可写的业务对象或任务;上传权限不能被当成任意文件库读取权限。生产/产出审核人若只审核既有附件,无需上传权限;需要补充审核证据时再由角色显式授予。

权限码到职责的映射放在版本化代码配置中,V1 不为服务端引入平台/商户动态菜单表。权限、范围和业务状态任何一层不通过均不得执行写操作。

十三、通知矩阵

1. 用户云仓

场景 站内信 微信订阅/模板 短信 发送时点
抢购支付成功 可选 支付事实确认
去向待选择 支付成功
选择截止前 24h/6h/1h 去重 1h 可选 未选择且未退款
已自动转代销 自动代销完成
补运费待支付 可选 运费单创建
补运费超时 可选 超时处理完成
补运费迟到支付退款中 可选 迟到支付事实确认
补运费退款成功/失败 失败时是 退款状态最终变化
自提可领取 可选 自提凭证生成
自提临期/逾期 逾期可选 T-24h/逾期
批次开始代销 可选 批次启动
达到结算节点 可选 账本生成/入账
批次到期 到期状态确认
回购完成 可选 回购款入账
账本冻结/异常 可选 重要时是 冻结完成

2. 用户租地/认养

场景 通知内容
支付成功 套餐、下一步和预计分配时间
地块/资产分配 真实编号、区域、周期和查看入口
生产批次开始 预计周期和已发布首条记录
关键生产记录 仅用户可见且已审核发布的事件
预计产出延期 新时间、原因和处理方案
产出可邮寄 本次数量、地址确认截止
已发货 物流公司、单号和数量
农业异常 影响、方案、预计完成时间
溯源更新 新发布版本查看入口

3. 商户

场景 通知内容
供货提交成功 申请号和预计审核时间
审核通过/驳回 结果和原因
入库验收 验收数量、差异和证据
活动开始/结束 占用数量和首次销售汇总
首次退款 数量和货款影响
货款待结算/已结算 结算单和金额
对账异常 差异类型和处理入口

4. 平台内部

场景 接收人
待审核供货 云仓运营
活动库存不足/规则缺失 云仓运营、仓储
批次库存不闭合 云仓运营、财务、技术管理员
账本计算失败/冻结 财务
回购即将到期/执行失败 云仓运营、财务
地块/资产分配失败 农业运营
产出不足或异常 农业运营、客服
商品农业资料待审/材料到期 商品运营、内容审核、对应商户
溯源材料到期 内容审核、农业运营
队列失败超过上限 技术管理员和业务负责人

十四、通知发送规则

  • 通知模板使用稳定 template_code,文案更新不改变业务事件。
  • 同一业务对象、模板和节点建立唯一发送键。
  • 发送前再次确认当前状态,已选择、已退款或已完成则取消过时提醒。
  • 第三方发送失败不回滚核心业务事务。
  • 微信/SMS 失败后保留站内信和发送日志。
  • 消息内只放必要信息,完整金额、地址和证据进入登录后详情页。
  • 用户营销订阅与履约必要通知分开管理。
  • 后台 WebSocket 通知用于提示,不作为任务是否存在的事实来源。

十五、审计日志

以下操作必须写 eb_farm_audit_log

  • 活动发布、关闭和规则变更。
  • 商品农业资料提交、审核、停用和材料关系变更。
  • 管理员农业范围授权、撤销、全平台范围和有效期变更。
  • 供货审核、入库验收和数量差异。
  • 用户去向自动处理和人工异常处理。
  • 批次冻结、恢复、重算预览和修复。
  • 账本审核、执行、冻结和冲正。
  • 回购审核和执行。
  • 地块、个体资产和批次份额分配。
  • 生产记录审核、溯源发布和撤回。
  • 农业异常方案审核、退款、替换和补发。
  • 失败任务人工重放。

审计字段至少包含:

  • 操作者类型、操作者 ID、所属商户/组织。
  • 业务类型、业务 ID、业务编号。
  • 操作码、操作前状态、操作后状态。
  • 关键字段变更摘要。
  • 原因、证据附件、请求 ID、IP 和客户端。
  • 创建时间。

系统自动任务使用独立系统操作者,不能伪装为某个管理员。

十六、自动校验与人工审核

1. 可自动通过

  • 规则快照完整。
  • 数量和金额恒等式通过。
  • 无退款、争议、冻结和对账差异。
  • 事件、账本和入账幂等键未冲突。
  • 用户单笔不超过 10,000.00 元、自然日累计不超过 50,000.00 元。
  • 商户单张结单不超过 100,000.00 元。

2. 必须人工

  • 数据重算出现差异。
  • 退款发生在用户账本已入账之后。
  • 回购比例为自定义且规则快照异常。
  • 用户应结算金额可能为负。
  • 商户货款、供货验收和首次退款不闭合。
  • 地块、资产、产出发生容量冲突。
  • 任务失败超过重试上限。
  • 人工冲正、补录或跨状态处理。

自动审核阈值是运营配置,不改变计算公式;大额和异常只改变是否需要人工确认。

阈值配置只允许超级管理员修改并记录审计。任务和后台人工执行必须调用同一入账服务,人工复核不能绕过来源状态、金额重算、目标账户行锁和唯一 posting_key

十七、监控指标

至少建立:

  • 已支付但仍待付款业务扩展数量。
  • 已过选择截止但仍待选择数量。
  • 批次库存恒等式失败数量。
  • 已批准但材料已过期仍可新供货的商品数量。
  • 普通二次订单未分配数量。
  • 已过观察期但未生效数量。
  • 达到节点但未生成账本数量。
  • 待结算超时、入账失败和冻结金额。
  • financial_posting 处理中租约超时数、重复幂等命中数和事务回滚数。
  • 用户余额流水与成功入账记录差异、商户财务流水与结单差异。
  • 借方冲正待追偿主体数和被冻结的后续农业入账金额。
  • 到期未回购数量和金额。
  • 商户货款资格超时数量。
  • 已支付但未分配地块/资产数量。
  • 已验收产出但未分配履约数量。
  • Outbox 积压、队列失败和通知失败数量。

监控只展示汇总,点击进入对应异常列表和业务详情。

十八、上线前演练

  1. 支付回调重复、乱序和延迟。
  2. 订单支付成功后进程立即中断,验证修复任务。
  3. 同一订单明细并发选择三种去向。
  4. 补运费成功回调、运费超时和选择截止任务并发。
  5. 补运费超时后迟到成功、重复回调和退款任务重复执行。
  6. 活动结束、未支付释放和自动代销并发。
  7. 普通订单一个明细跨两个云仓批次分配。
  8. 二次订单完成后发生部分/全量退款。
  9. 一次销售进度跨越多个节点。
  10. 到期回购与最后一笔二次订单生效并发。
  11. 用户账本已生成但余额入账超时。
  12. 商户结算与首次退款并发。
  13. 地块、个体资产和批次份额并发分配。
  14. 产出不足、替换、补发和未履约退款。
  15. 商品材料到期与供货提交、活动发布并发。
  16. 管理员农业范围并发保存和即时撤权。
  17. 队列停机后恢复、事件重复投递和人工重放。

十九、关联文档

Clone this wiki locally