Files
huangjingfen/docs/project-shaoyaoju/secondary-development-guide.md

1472 lines
57 KiB
Markdown
Raw Normal View History

# 芍药居项目二次开发详细说明文档
> 文档日期2026-05-02
> 面向对象:后端研发
> 技术底座CRMEB Pro v3.5.1 + 当前 fsgx/HJF 二开代码
> 业务依据:`docs/project-shaoyaoju/PRD_shaoyaoju_V1.0.md`
> 差异依据:`docs/project-shaoyaoju/syj-fsgx-diff.md`
> 代码根目录:`pro_v3.5.1`
---
## 1. 开发目标
芍药居项目不是重写一套商城、分销、积分或会员系统,而是在当前项目代码基础上增加一层“推四免一有效推广任务”的业务适配层。
核心目标:
1. 用户有效消费金额每满 `4333` 元,自动生成 `1` 个“推四免一有效推广任务”。
2. 每个推广任务在系统侧等价当前代码中的 `1``is_queue_goods=1` 报单商品订单触发基准。
3. 推广任务创建后,继续复用当前代码的分销返佣、积分奖励、分销等级、后台分销等级任务、积分日志和佣金流水。
4. 推广任务自身负责记录推四免一进度、4 单完成结算、1-3 单提前兑现、后台审核和追溯。
5. 返佣时机不为芍药居单独固定,复用当前代码的 `brokerage_timing` 配置。
一句话落地口径:
```text
有效消费金额 floor(amount / 4333)
-> 生成 N 个推四免一有效推广任务
-> 每个任务等价当前 1 个报单商品订单触发单位
-> 复用分销奖金、积分奖励、分销等级任务
-> 任务自身记录推四免一进度和结算
```
---
## 2. 术语边界
| 术语 | 本项目含义 | 不等同于 |
|---|---|---|
| 推广任务 | 推四免一有效推广任务维度,由用户有效消费累计满 4333 元生成 | 后台分销等级任务 |
| 等价报单触发单位 | 为复用当前代码,将 1 个推广任务视为当前 1 个 `is_queue_goods=1` 报单商品订单触发基准 | 必须真实创建商城订单 |
| 分销等级 | 当前代码 `eb_agent_level``eb_user.agent_level` 体系 | 新建会员等级表 |
| 分销等级任务 | 当前后台配置的 `eb_agent_level_task` 升级任务 | 推四免一任务本身 |
| 积分奖励 | 当前 HJF/FSGX 的冻结积分、积分日志、释放逻辑 | 新建独立积分账户 |
| 返佣时机 | 当前 `brokerage_timing` 配置决定的发放节点 | 芍药居固定支付或固定确认收货 |
开发时必须避免把“推四免一有效推广任务”写成新的分销等级任务。二者关系是:推广任务作为业务来源,按等价报单触发单位计入当前后台配置的分销等级任务。
---
## 3. 当前代码能力地图
### 3.1 订单支付主链路
| 链路 | 当前代码 | 说明 |
|---|---|---|
| 支付成功入口 | `app/services/order/StoreOrderSuccessServices.php` | `paySuccess()` 更新支付状态后触发 `event('order.pay')` |
| 支付事件监听 | `app/listener/order/Pay.php` | 处理佣金发放、等级检查、积分奖励、订单后置任务 |
| 确认收货 | `app/services/order/StoreOrderTakeServices.php` | `storeProductOrderUserTakeDelivery()` 内处理赠送积分、返佣、经验等 |
| 建单与佣金计算 | `app/services/order/StoreOrderCreateServices.php` | 标记 `is_queue_goods`,计算 `one_brokerage``two_brokerage` |
当前支付事件中已经存在 HJF/FSGX 报单商品处理逻辑:
- `is_queue_goods=1` 订单会进入报单商品相关处理。
- `hjf_queue_pool_enable=1` 时走 `HjfOrderPayJob` 异步处理。
- `hjf_queue_pool_enable=0` 时在 `Pay.php` 中同步执行等级检查和积分奖励。
芍药居二开应尽量把新逻辑挂在订单生命周期的明确节点上,不直接改散在页面层或支付回调层。
### 3.2 分销返佣能力
| 能力 | 当前代码 | 说明 |
|---|---|---|
| 返佣计算 | `StoreOrderCreateServices.php` | 根据商品、推荐人、周期配置计算订单佣金 |
| 返佣发放 | `StoreOrderTakeServices::backOrderBrokerage()` | 写佣金账户、佣金流水,并处理二级返佣 |
| 支付即返 | `listener/order/Pay.php` | 当 `brokerage_timing=on_pay` 时支付后立即调用返佣 |
| 确认后返 | `StoreOrderTakeServices.php` | 当 `brokerage_timing=on_confirm` 时确认收货后返佣 |
| 返佣配置 | `app/services/system/config/SystemConfigServices.php` | `brokerage_cycle_count``brokerage_cycle_rates``brokerage_scope``brokerage_timing` |
当前返佣时机已由配置控制:
| 配置值 | 行为 |
|---|---|
| `brokerage_timing=on_pay` | 支付成功后发放佣金,确认收货时跳过返佣 |
| `brokerage_timing=on_confirm` | 支付成功后不发佣金,确认收货后发放佣金 |
芍药居不新增独立返佣时机配置,只复用该逻辑。
### 3.3 积分奖励能力
| 能力 | 当前代码 | 说明 |
|---|---|---|
| 积分奖励计算 | `app/services/hjf/PointsRewardServices.php` | 按 `eb_agent_level.direct_reward_points``umbrella_reward_points` 计算 |
| 积分释放 | `app/services/hjf/PointsReleaseServices.php` | 使用 `hjf_release_rate` 释放冻结积分 |
| 冻结积分日志 | `app/model/hjf/PointsReleaseLog.php` | 对应 `eb_points_release_log` |
| 营销后台积分日志 | `app/services/user/UserBillServices.php` | 已有 `hjf_reward_direct_integral``hjf_reward_umbrella_integral` 类型 |
| 补发工具 | `app/command/HjfPatchMissingRewards.php` | 用于缺失奖励补发场景 |
当前积分奖励已经具备幂等检查:`points_release_log` 中同一订单、同类奖励存在时跳过重复发放。芍药居推广任务接入时,应保留相同幂等策略,推荐使用 `syj_task_id` 或等价来源单号参与幂等。
### 3.4 分销等级与等级任务能力
| 能力 | 当前代码 | 说明 |
|---|---|---|
| 分销等级 | `app/services/agent/AgentLevelServices.php` | 使用 `eb_agent_level` |
| 等级任务 | `app/services/agent/AgentLevelTaskServices.php` | 后台配置的升级任务 |
| HJF 会员等级包装 | `app/services/hjf/MemberLevelServices.php` | 薄封装,底层仍复用分销等级 |
| 后台等级配置 | `app/controller/admin/v1/agent/AgentLevel.php``AgentLevelTask.php` | 原分销等级与任务配置 |
| HJF 等级后台 | `app/controller/admin/v1/hjf/MemberController.php` | 读取和保存 `eb_agent_level` 的积分奖励字段 |
芍药居会员等级继续使用 `eb_user.agent_level`。升级任务继续走后台分销等级任务配置,不新增独立会员等级任务表。
### 3.5 队列与公排能力
当前代码存在 HJF 公排池能力:
| 能力 | 当前代码 |
|---|---|
| 公排入队 | `app/services/hjf/QueuePoolServices.php` |
| 支付后异步处理 | `app/jobs/hjf/HjfOrderPayJob.php` |
| 退款任务 | `app/jobs/hjf/QueueRefundJob.php` |
| 用户端接口 | `app/controller/api/v1/hjf/QueueController.php` |
| 后台接口 | `app/controller/admin/v1/hjf/QueueController.php` |
| 数据表 | `eb_queue_pool` |
芍药居 PRD 明确首版不做公排池/排队退款机制。该能力可保留代码但默认关闭,确保 `hjf_queue_pool_enable=0`。推四免一任务不要复用 `eb_queue_pool` 作为主任务表,否则业务含义会混淆。
---
## 4. 芍药居目标架构
### 4.1 推荐分层
```text
订单生命周期
-> 芍药居消费累计服务
-> 推四免一任务服务
-> 等价报单触发适配服务
-> 当前分销返佣 / 积分奖励 / 分销等级任务
-> 任务进度与结算服务
```
建议新增 `syj` 命名空间,避免继续扩散在 `hjf` 命名空间中。
| 层 | 建议服务 | 职责 |
|---|---|---|
| 消费累计 | `SyjPromoteAmountServices` | 统计有效订单金额,生成金额流水,计算可生成任务数 |
| 任务核心 | `SyjPromoteTaskServices` | 创建任务、分配推荐订单、完成任务、提前兑现 |
| 奖励适配 | `SyjPromoteRewardTriggerServices` | 将任务映射为当前报单商品订单触发单位 |
| 结算 | `SyjPromoteSettlementServices` | 处理 4 单完成结算、提前兑现扣费、账单关联 |
| 后台查询 | `SyjPromoteAdminServices` | 任务列表、详情、异常、导出、审核 |
### 4.2 推广任务生成规则
有效金额计算:
```text
valid_amount = pay_price - refunded_amount
task_count = floor((user_pending_amount + valid_amount) / 4333)
remaining_amount = (user_pending_amount + valid_amount) % 4333
```
首版口径:
- 以订单实际支付金额 `pay_price` 为基础。
- 积分抵扣、优惠券抵扣不计入有效消费金额。
- 运费默认不计入,除非业务另行确认。
- 发生退款后,未生成任务的累计金额应回滚;已生成任务的订单进入异常或人工处理。
推荐挂载节点:
| 节点 | 推荐动作 | 原因 |
|---|---|---|
| 支付成功 | 不生成任务,最多记录待处理标识 | 避免未确认收货、退款导致任务提前生效 |
| 确认收货 | 生成消费累计和推广任务 | 与“有效订单”口径一致 |
| 售后退款 | 回滚未结算金额或标记任务异常 | 保证金额与任务可追溯 |
若业务最终要求支付即生成任务,也应通过配置控制,并明确退款回滚策略。
### 4.3 等价报单触发规则
每个推广任务创建成功后,调用奖励适配服务生成一次“等价报单触发”。
触发参数至少包含:
| 参数 | 说明 |
|---|---|
| `task_id` | 推广任务 ID |
| `uid` | 任务归属用户 |
| `source_order_id` | 生成任务的来源订单 |
| `amount` | 固定或配置为 4333 |
| `trigger_no` | 等价触发单号,建议使用 `SYJ-TASK-{task_id}` |
| `trigger_type` | `syj_promote_task` |
| `qty` | 固定为 1若一次消费生成多个任务每个任务独立触发 |
适配服务职责:
1. 记录任务触发状态,防止重复触发。
2. 以等价报单触发单位调用当前分销返佣逻辑。
3. 调用当前积分奖励逻辑,确保 `points_release_log``user_bill` 仍有记录。
4. 调用当前分销等级任务统计逻辑,让后台配置的任务继续生效。
5. 记录当前任务与佣金流水、积分流水、等级任务记录的关联。
注意:如果现有返佣服务强依赖真实 `store_order.id`,不要直接伪造不完整订单数组。应优先抽出统一的“奖励触发上下文”方法,或创建完整可追溯的等价触发记录,再由适配层组装当前服务所需字段。
### 4.4 推荐进度规则
推广任务生成后,推荐人分享给下级,下级有效订单计入推荐人的任务进度。
匹配规则:
1. 下级订单必须为参与规则商品订单,通常为 `is_queue_goods=1`
2. 下级订单达到当前后台返佣设置中的佣金发放时机后才计入任务进度,复用 `brokerage_timing``on_pay` 表示支付成功后计入,`on_confirm` 表示确认收货后计入。
3. 根据订单上的 `spread_uid` 找到推荐人。
4. 推荐人必须存在未完成、未关闭、未提前兑现的推广任务。
5. 若推荐人有多个进行中任务,按创建时间从早到晚填充。
6. 单个下级有效订单默认只能计入一个任务一次。
7. 同一购买人是否可重复计入多个任务,建议首版允许按订单计入,若运营要求按用户去重再增加配置。
任务进度:
| 计入第几单 | 推荐奖励比例 | 完成状态 |
|---:|---:|---|
| 1 | 10% | 可申请提前兑现 |
| 2 | 20% | 可申请提前兑现 |
| 3 | 30% | 可申请提前兑现 |
| 4 | 40% | 任务完成,结算 4333 元,不扣 7% |
### 4.5 结算规则
完成 4 单:
- 任务状态改为 `completed`
- 结算金额为 `4333` 元。
- 不扣 `7%`
- 入账到当前 CRMEB 佣金账户或业务确认的奖励账户。
- 写入任务结算流水,关联 `user_bill``user_brokerage`
提前兑现 1-3 单:
- 用户发起提前兑现申请。
- 后台审核通过后关闭任务。
- 按当前已完成档位计算可兑现奖励。
- 扣除 `7%` 手续费或税费。
- 入账后任务状态改为 `cashed_out`
- 审核拒绝后任务保持进行中。
建议公式:
```text
gross_amount = 4333 * current_rate
fee_amount = gross_amount * 7%
net_amount = gross_amount - fee_amount
```
其中 `current_rate` 为当前已完成档位对应比例:`10%``20%``30%`
---
## 5. 建议新增数据表
### 5.1 `eb_syj_promote_task`
用于保存推四免一有效推广任务。
| 字段 | 类型建议 | 说明 |
|---|---|---|
| `id` | int | 主键 |
| `uid` | int | 任务归属用户 |
| `task_no` | varchar(64) | 任务编号 |
| `source_order_id` | int | 来源订单主键 |
| `source_order_no` | varchar(64) | 来源订单号 |
| `base_amount` | decimal(10,2) | 任务基准金额,默认 4333 |
| `status` | tinyint | 0 进行中1 已完成2 提前兑现3 已关闭4 异常 |
| `progress_count` | tinyint | 已完成推荐单数 |
| `target_count` | tinyint | 目标单数,默认 4 |
| `reward_trigger_status` | tinyint | 等价报单触发状态 |
| `reward_trigger_no` | varchar(64) | 等价触发单号 |
| `finish_time` | int | 完成时间 |
| `cashout_time` | int | 提前兑现时间 |
| `add_time` | int | 创建时间 |
| `update_time` | int | 更新时间 |
建议索引:
- `idx_uid_status (uid, status)`
- `idx_source_order (source_order_id)`
- `uniq_task_no (task_no)`
- `uniq_reward_trigger_no (reward_trigger_no)`
### 5.2 `eb_syj_promote_amount_log`
用于记录用户待推广金额累计与扣减。
| 字段 | 类型建议 | 说明 |
|---|---|---|
| `id` | int | 主键 |
| `uid` | int | 用户 |
| `order_id` | int | 来源订单 |
| `amount` | decimal(10,2) | 本次变动金额 |
| `before_amount` | decimal(10,2) | 变动前待推广金额 |
| `after_amount` | decimal(10,2) | 变动后待推广金额 |
| `type` | varchar(32) | `income``consume_task``refund_rollback``manual_adjust` |
| `link_id` | int | 关联任务或退款记录 |
| `mark` | varchar(255) | 说明 |
| `add_time` | int | 创建时间 |
用户当前待推广金额可放在独立余额表,也可通过流水聚合。考虑查询效率,建议增加用户扩展字段或独立汇总表。
### 5.3 `eb_syj_promote_task_record`
用于记录推荐订单计入任务进度。
| 字段 | 类型建议 | 说明 |
|---|---|---|
| `id` | int | 主键 |
| `task_id` | int | 推广任务 |
| `uid` | int | 推荐人 |
| `order_uid` | int | 下单用户 |
| `order_id` | int | 下级订单 |
| `order_no` | varchar(64) | 下级订单号 |
| `source_type` | varchar(32) | 来源类型:`order_pay``order_confirm``task_created``manual` |
| `trigger_timing` | varchar(32) | 推荐订单计入时使用的 `brokerage_timing` 快照 |
| `step_no` | tinyint | 第几单1-4 |
| `reward_rate` | decimal(5,2) | 对应比例 |
| `status` | tinyint | 1 有效2 已退款失效 |
| `add_time` | int | 创建时间 |
建议增加唯一索引 `uniq_order_task (order_id, task_id)``uniq_order (order_id)`,避免同一订单重复计入。
### 5.4 `eb_syj_promote_settlement`
用于任务完成或提前兑现结算。
| 字段 | 类型建议 | 说明 |
|---|---|---|
| `id` | int | 主键 |
| `task_id` | int | 推广任务 |
| `uid` | int | 用户 |
| `settle_type` | varchar(32) | `complete``early_cashout` |
| `gross_amount` | decimal(10,2) | 应结算金额 |
| `fee_rate` | decimal(5,2) | 手续费/税费比例 |
| `fee_amount` | decimal(10,2) | 扣费金额 |
| `net_amount` | decimal(10,2) | 实到账 |
| `bill_id` | int | 关联账单 |
| `brokerage_id` | int | 关联佣金流水 |
| `audit_status` | tinyint | 0 待审核1 通过2 拒绝 |
| `audit_uid` | int | 审核管理员 |
| `audit_remark` | varchar(255) | 审核说明 |
| `audit_time` | int | 审核时间 |
| `add_time` | int | 创建时间 |
### 5.5 `eb_syj_promote_reward_trigger`
用于记录推广任务触发现有奖励链路的结果。
| 字段 | 类型建议 | 说明 |
|---|---|---|
| `id` | int | 主键 |
| `task_id` | int | 推广任务 |
| `uid` | int | 任务用户 |
| `trigger_no` | varchar(64) | 等价触发单号 |
| `trigger_amount` | decimal(10,2) | 触发金额,默认 4333 |
| `brokerage_status` | tinyint | 分销返佣触发状态 |
| `points_status` | tinyint | 积分奖励触发状态 |
| `level_task_status` | tinyint | 分销等级任务触发状态 |
| `brokerage_link_id` | varchar(255) | 关联佣金流水,可存 JSON |
| `points_link_id` | varchar(255) | 关联积分流水,可存 JSON |
| `level_task_link_id` | varchar(255) | 关联等级任务记录,可存 JSON |
| `error_msg` | varchar(500) | 失败原因 |
| `add_time` | int | 创建时间 |
| `update_time` | int | 更新时间 |
---
## 6. 配置项
### 6.1 继续复用当前配置
| 配置 | 当前含义 | 芍药居口径 |
|---|---|---|
| `brokerage_cycle_count` | 周期人数 | 建议设为 `4` |
| `brokerage_cycle_rates` | 周期比例 JSON | 建议设为 `[10,20,30,40]` |
| `brokerage_scope` | 返佣范围 | 默认 `queue_only` 或按运营确定 |
| `brokerage_timing` | 佣金发放时机 | 继续复用,支持 `on_pay``on_confirm` |
| `hjf_release_rate` | 积分释放比例 | 继续用于当前积分释放 |
| `hjf_umbrella_reward_enable` | 伞下积分奖励开关 | 继续复用 |
### 6.2 建议新增芍药居配置
| 配置 | 默认值 | 说明 |
|---|---:|---|
| `syj_task_base_amount` | `4333` | 每满多少有效消费生成 1 个推广任务 |
| `syj_task_target_count` | `4` | 推四免一目标单数 |
| `syj_task_reward_rates` | `[10,20,30,40]` | 任务进度比例 |
| `syj_early_cashout_fee_rate` | `7` | 提前兑现扣费比例 |
| `syj_task_generate_timing` | `on_confirm` | 任务生成节点,首版建议确认收货 |
| `syj_task_order_dedupe` | `order` | 推荐订单计入方式,首版按订单 |
| `syj_reward_trigger_enable` | `1` | 是否启用任务等价报单触发 |
### 6.3 必须关闭或谨慎使用的配置
| 配置 | 建议 | 原因 |
|---|---|---|
| `hjf_queue_pool_enable` | `0` | 芍药居首版不做公排池/排队退款 |
| `hjf_trigger_multiple` | 保留 | 仅 HJF 公排使用,不作为芍药居推四免一主配置 |
| `hjf_withdraw_fee_rate` | 不直接复用 | 芍药居提前兑现扣 7% 应放入任务结算配置 |
---
## 7. 后端开发落点
### 7.1 订单确认收货接入
推荐在 `StoreOrderTakeServices::storeProductOrderUserTakeDelivery()` 成功完成原逻辑后,触发芍药居消费累计。
接入原则:
1. 原有赠送积分、返佣、经验、事业部逻辑保持不变。
2. 只对 `is_queue_goods=1` 的有效订单累计。
3. 使用事务或幂等记录,避免确认收货重复调用导致重复生成任务。
4. 订单退款、售后状态不满足时不生成任务。
建议伪流程:
```text
确认收货成功
-> 判断订单 is_queue_goods=1
-> 判断订单未生成过 syj 消费累计流水
-> 计算有效金额
-> 写入 syj_promote_amount_log
-> floor(累计金额 / 4333) 生成任务
-> 每个任务调用 SyjPromoteRewardTriggerServices
```
### 7.2 支付事件接入
当前 `listener/order/Pay.php` 已经处理 `brokerage_timing=on_pay` 的返佣。芍药居不应破坏这个逻辑。
如任务生成节点为 `on_confirm`,支付事件只需要保留现状。如后续配置为支付即生成任务,可在 `Pay.php` 中增加独立开关判断,但必须保证:
- 同一订单只触发一次。
- 售后退款能回滚或标记异常。
- `brokerage_timing=on_pay` 不导致同一等价任务重复返佣。
### 7.3 返佣适配
当前返佣逻辑主要依赖订单字段:
| 字段 | 用途 |
|---|---|
| `uid` | 下单用户 |
| `spread_uid` | 一级推荐人 |
| `spread_two_uid` | 二级推荐人 |
| `pay_price` | 订单金额 |
| `one_brokerage` | 一级佣金 |
| `two_brokerage` | 二级佣金 |
| `is_queue_goods` | 是否报单商品 |
| `id` | 账单关联 ID |
| `order_id` | 订单号 |
芍药居任务触发返佣时有两种实现路径:
| 路径 | 说明 | 推荐度 |
|---|---|---|
| 抽出统一奖励触发上下文 | 将当前订单返佣逻辑改造成可接收 `order``syj_task` 上下文 | 推荐 |
| 构造完整虚拟订单数组 | 由适配服务组装当前方法所需字段 | 可用,但必须完整追溯 |
| 创建真实商城订单 | 为任务创建系统订单 | 不推荐,容易污染订单统计和财务 |
必须做到:
- `brokerage_timing` 仍决定发放节点。
- 同一 `task_id` 不重复发放佣金。
- 佣金流水能追溯到任务和来源订单。
- 返佣失败可重试,不影响任务主记录创建。
### 7.4 积分奖励适配
当前 `PointsRewardServices::reward()` 参数为:
```php
reward(int $orderUid, string $orderId, int $orderDbId = 0, array $preUpgradeLevels = [], int $qty = 1)
```
芍药居推广任务可以按以下方式复用:
- `orderUid` 使用任务归属用户。
- `orderId` 使用等价触发单号,例如 `SYJ-TASK-10001`
- `orderDbId` 若没有真实订单,可传来源订单 ID或扩展为支持任务来源。
- `qty` 固定为 `1`
- `preUpgradeLevels` 仍在触发前快照推荐链路用户等级。
建议增强:
1. `points_release_log` 增加或通过 `order_id` 标记任务来源。
2. `UserBillServices` 写入积分日志时保留任务编号。
3. 幂等条件从 `order_id + type` 扩展为 `trigger_no + type`,避免补偿任务重复发放。
### 7.5 分销等级任务适配
当前等级任务统计位于 `AgentLevelTaskServices`。代码里已有对 `is_queue_goods` 报单商品订单数量的统计能力。
芍药居二开要实现:
- 推广任务创建后,按 1 个等价报单触发单位计入后台分销等级任务。
- 后台仍由运营配置分销等级任务,不新增独立会员等级任务。
- 若当前统计完全从 `store_order` 查询,需要补充统计来源,让 `syj_promote_task` 也能计入。
推荐改造方式:
| 方式 | 说明 |
|---|---|
| 统计服务抽象 | 将“报单订单数”改为“有效任务触发数”,内部合并真实订单与 syj 任务 |
| 增加任务来源查询 | 在 `AgentLevelTaskServices` 中增加 syj 任务计数 |
| 数据镜像 | 将 syj 任务写入一个统一触发表,等级任务统一查该表 |
首选“统一触发表”或“统计服务抽象”,避免在多处 SQL 中重复拼接任务逻辑。
### 7.6 推荐订单计入任务
推荐订单计入任务进度的节点复用当前代码后台返佣设置中的佣金发放时机配置项 `brokerage_timing`
| 配置 | 推荐订单计入任务节点 | 复用代码节点 |
|---|---|---|
| `on_pay` | 下级订单支付成功后计入 | `listener/order/Pay.php` 的支付成功事件 |
| `on_confirm` | 下级订单确认收货后计入 | `StoreOrderTakeServices::storeProductOrderUserTakeDelivery()` |
执行任务进度匹配:
```text
下级订单达到 brokerage_timing 对应节点
-> 订单 is_queue_goods=1
-> 读取 order.spread_uid
-> 查询推荐人最早的进行中 syj_promote_task
-> 写 syj_promote_task_record
-> task.progress_count + 1
-> progress_count = 4 时完成结算
```
需要注意:
- 同一订单不能重复计入。
- 任务计入节点必须与当前 `brokerage_timing` 一致,不为芍药居单独固定支付成功或确认收货。
- 推荐人没有进行中任务时,不创建任务进度。
- 订单退款时,若任务未结算应回滚进度;若已结算应进入异常处理或人工复核。
- 多任务并行时,优先填充最早任务。
### 7.7 提前兑现与后台审核
用户端:
- 展示当前进行中任务。
-`progress_count` 为 1-3 时允许发起提前兑现。
- 已完成 4 单的任务不走提前兑现,直接完成结算。
后台:
- 待审核列表。
- 任务详情。
- 审核通过:扣 7%,入账,关闭任务。
- 审核拒绝:任务继续进行。
审核通过必须使用事务:
```text
锁定任务
-> 校验状态仍为进行中
-> 校验进度为 1-3
-> 计算 gross / fee / net
-> 写入佣金或账单
-> 写 settlement
-> 更新任务状态
```
---
## 8. 接口建议
### 8.1 用户端接口
建议新增 `/api/syj/promote/*`
| 接口 | 方法 | 说明 |
|---|---|---|
| `/api/syj/promote/overview` | GET | 我的推广任务概览 |
| `/api/syj/promote/task/list` | GET | 我的任务列表 |
| `/api/syj/promote/task/:id` | GET | 任务详情 |
| `/api/syj/promote/task/:id/records` | GET | 推荐订单进度 |
| `/api/syj/promote/task/:id/cashout` | POST | 发起提前兑现 |
| `/api/syj/promote/amount/log` | GET | 待推广金额流水 |
| `/api/syj/promote/settlement/list` | GET | 结算记录 |
任务概览建议返回:
```json
{
"pending_amount": "866.00",
"base_amount": "4333.00",
"active_task_count": 2,
"completed_task_count": 3,
"cashout_task_count": 1,
"available_cashout_amount": "1299.90"
}
```
### 8.2 后台接口
建议新增 `/adminapi/syj/promote/*`
| 接口 | 方法 | 说明 |
|---|---|---|
| `/adminapi/syj/promote/task/list` | GET | 任务列表 |
| `/adminapi/syj/promote/task/:id` | GET | 任务详情 |
| `/adminapi/syj/promote/task/:id/records` | GET | 任务进度 |
| `/adminapi/syj/promote/cashout/list` | GET | 提前兑现审核列表 |
| `/adminapi/syj/promote/cashout/:id/audit` | POST | 审核提前兑现 |
| `/adminapi/syj/promote/settlement/list` | GET | 结算流水 |
| `/adminapi/syj/promote/config` | GET/POST | 任务配置 |
| `/adminapi/syj/promote/retry-trigger/:task_id` | POST | 重试奖励触发 |
后台列表筛选建议:
- 用户 ID / 手机号 / 昵称
- 任务编号
- 来源订单号
- 状态
- 创建时间
- 是否触发奖励成功
- 是否存在异常
---
## 9. 管理端与用户端页面影响
### 9.1 用户端
建议新增或改造:
| 页面 | 功能 |
|---|---|
| 我的推广任务 | 展示进行中、已完成、已兑现、异常任务 |
| 任务详情 | 展示 4 单进度、每单订单、奖励比例、可兑现信息 |
| 提前兑现 | 用户确认提前兑现,展示扣 7% 后到账金额 |
| 资产页 | 继续展示佣金、积分、等级,文案改为芍药居 |
| 推广中心 | 增加任务入口,继续复用分享关系能力 |
页面文案要避免出现 fsgx 旧口径例如“推三免一”“20/30/50”“公排退款”等。
### 9.2 管理后台
建议新增:
| 页面 | 功能 |
|---|---|
| 推广任务列表 | 查询任务状态、用户、来源订单、进度 |
| 推广任务详情 | 查看任务进度、等价奖励触发记录、积分/佣金流水 |
| 提前兑现审核 | 审核通过/拒绝,展示扣费计算 |
| 任务配置 | 4333、4 单、10/20/30/40、7% 等配置 |
| 异常任务 | 奖励触发失败、退款冲突、重复计入等问题处理 |
继续复用:
- 商品管理
- 订单管理
- 分销等级与分销等级任务配置
- 分销员管理
- 积分日志
- 佣金流水
- 提现审核
---
## 10. 数据迁移与初始化
当前项目已有迁移参考:
| 文件 | 说明 |
|---|---|
| `database/hjf_migration.sql` | HJF/FSGX 表和字段迁移 |
| `help/migrations/fsgx_v1.sql` | fsgx 初始迁移参考 |
| `database/hjfshop.sql` | 包含部分 HJF 表结构 |
芍药居应新增独立迁移文件,例如:
```text
database/syj_migration.sql
```
迁移内容:
1. 创建 `eb_syj_promote_task`
2. 创建 `eb_syj_promote_amount_log`
3. 创建 `eb_syj_promote_task_record`
4. 创建 `eb_syj_promote_settlement`
5. 创建 `eb_syj_promote_reward_trigger`
6. 插入 `syj_*` 配置项。
7. 确保 `brokerage_cycle_count=4``brokerage_cycle_rates=[10,20,30,40]` 可由后台配置覆盖。
8. 确保 `hjf_queue_pool_enable=0`
数据初始化建议:
- 新增商品默认 `is_queue_goods=1`
- 旧商品是否批量设为 `1` 由运营确认。
- 已有用户等级继续使用 `eb_user.agent_level`,不迁移到新表。
- 已有积分奖励字段继续使用 `eb_agent_level.direct_reward_points``umbrella_reward_points`
---
## 11. 幂等、事务与异常处理
### 11.1 幂等点
| 场景 | 幂等键 |
|---|---|
| 订单消费累计 | `order_id + type=income` |
| 任务生成 | `source_order_id + split_index` |
| 等价奖励触发 | `task_id``reward_trigger_no` |
| 积分奖励 | `reward_trigger_no + reward_type` |
| 推荐订单计入 | `order_id``order_id + task_id` |
| 完成结算 | `task_id + settle_type=complete` |
| 提前兑现 | `task_id + settle_type=early_cashout` |
### 11.2 事务边界
必须使用事务的场景:
- 确认收货后累计金额并生成任务。
- 任务创建后写奖励触发记录。
- 推荐订单计入任务进度。
- 第 4 单完成任务并结算。
- 提前兑现审核通过。
- 退款导致任务回滚或异常标记。
### 11.3 异常处理
| 异常 | 处理建议 |
|---|---|
| 奖励触发失败 | 任务保留,`reward_trigger_status=failed`,后台允许重试 |
| 积分发放失败 | 记录失败原因,允许按任务重试 |
| 返佣失败 | 不重复生成任务,单独重试返佣触发 |
| 推荐订单退款 | 未结算任务回滚进度,已结算任务进入异常 |
| 来源订单退款 | 未触发任务回滚累计,已生成任务标记异常或人工处理 |
| 并发确认收货 | 使用唯一索引和事务锁避免重复生成任务 |
| 并发推荐订单 | 锁定任务行,按最早任务顺序写入进度 |
---
## 12. 测试与验收场景
### 12.1 任务生成
| 场景 | 期望 |
|---|---|
| 订单有效金额 `4332` | 不生成推广任务,不触发任务维度奖励 |
| 订单有效金额 `4333` | 生成 1 个推广任务,剩余待推广金额为 0 |
| 订单有效金额 `8666` | 生成 2 个推广任务 |
| 订单有效金额 `9000` | 生成 2 个推广任务,剩余 334 |
| 多个小额订单累计满 4333 | 在达到阈值的确认收货节点生成任务 |
| 同一订单重复确认收货回调 | 不重复生成任务 |
### 12.2 奖励触发
| 场景 | 期望 |
|---|---|
| 生成 1 个推广任务 | 触发一次等价报单奖励 |
| 生成 2 个推广任务 | 触发两次等价报单奖励 |
| 积分奖励重复调用 | `points_release_log``user_bill` 不重复写入 |
| 分销等级任务 | 推广任务计入当前后台配置的分销等级任务 |
| 任务触发失败后重试 | 不重复创建任务,只补触发失败部分 |
### 12.3 返佣时机
| 配置 | 验收 |
|---|---|
| `brokerage_timing=on_pay` | 支付后返佣,确认收货不重复返佣 |
| `brokerage_timing=on_confirm` | 支付后不返佣,确认收货后返佣 |
### 12.4 推荐进度
| 场景 | 期望 |
|---|---|
| 推荐人无进行中任务 | 下级订单不计入推四免一进度 |
| 推荐人有 1 个任务 | 下级有效订单计入该任务 |
| 推荐人有多个任务 | 优先计入最早创建的进行中任务 |
| `brokerage_timing=on_pay` | 下级订单支付成功后匹配并计入任务进度 |
| `brokerage_timing=on_confirm` | 下级订单确认收货后匹配并计入任务进度 |
| 第 4 单达到计入节点 | 任务完成,结算 4333不扣 7% |
| 已计入订单退款 | 未结算任务回滚进度,已结算任务标记异常 |
### 12.5 提前兑现
| 场景 | 期望 |
|---|---|
| 进度 0 单 | 不允许提前兑现 |
| 进度 1-3 单 | 允许申请提前兑现 |
| 审核通过 | 扣 7%,入账,任务关闭 |
| 审核拒绝 | 任务继续进行 |
| 已完成 4 单 | 不走提前兑现,按完成结算 |
### 12.6 配置与后台
| 场景 | 期望 |
|---|---|
| 修改 4333 基准金额 | 新任务按新配置生成,旧任务保留原基准 |
| 修改 10/20/30/40 比例 | 新任务按新配置,旧任务按创建时快照 |
| 后台查看任务详情 | 能看到来源订单、推荐订单、奖励触发、积分/佣金流水 |
| 后台重试奖励触发 | 只补失败部分,不重复发放成功部分 |
---
## 13. 按功能拆分开发清单
本章用于把开发说明拆成可排期、可验收的功能包。每个功能包均包含前端、后端、数据库、配置/权限、Checklist。实施时建议按功能包建任务后端先完成接口契约和测试数据前端再并行联调。
### 13.1 基础配置与初始化
**功能目标**
建立芍药居二开所需的基础配置、菜单、权限和默认数据,保证后续任务生成、奖励触发、结算审核都能读取统一配置。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| Admin | 新增芍药居配置页 | 管理 `4333` 基准金额、目标单数、奖励比例、提前兑现扣费、任务生成节点 |
| Admin | 菜单与权限 | 增加“芍药居/推广任务/任务配置”菜单,按当前后台权限体系挂载 |
| 用户端 | 暂无独立页面 | 用户端读取配置展示由任务页统一处理 |
**后端**
| 模块 | 开发项 | 说明 |
|---|---|---|
| 配置服务 | `SyjPromoteConfigServices` | 封装 `syj_*` 配置读取,统一默认值和类型转换 |
| 后台接口 | `GET/POST /adminapi/syj/promote/config` | 获取和保存配置 |
| 校验 | 配置保存校验 | 金额大于 0目标单数大于 0比例数组长度与目标单数一致扣费比例 0-100 |
**数据库**
| 项 | 说明 |
|---|---|
| `eb_system_config` | 插入 `syj_task_base_amount``syj_task_target_count``syj_task_reward_rates``syj_early_cashout_fee_rate``syj_task_generate_timing``syj_reward_trigger_enable` |
| 后台权限表 | 按当前系统菜单/权限表增加芍药居配置和任务管理权限 |
**配置/默认值**
| 配置 | 默认值 |
|---|---|
| `syj_task_base_amount` | `4333` |
| `syj_task_target_count` | `4` |
| `syj_task_reward_rates` | `[10,20,30,40]` |
| `syj_early_cashout_fee_rate` | `7` |
| `syj_task_generate_timing` | `on_confirm` |
| `syj_reward_trigger_enable` | `1` |
| `hjf_queue_pool_enable` | `0` |
**Checklist**
- [ ] 新增 `syj_*` 配置项迁移脚本。
- [ ] 配置读取服务能返回正确默认值。
- [ ] 后台配置页保存后立即生效。
- [ ] `hjf_queue_pool_enable` 默认关闭。
- [ ] 配置保存有边界校验和错误提示。
- [ ] 后台菜单和权限能控制配置页访问。
### 13.2 消费累计与推广任务生成
**功能目标**
订单达到有效节点后,将用户有效消费金额计入待推广金额;每满 `4333` 元自动生成 1 个推四免一有效推广任务。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| 用户端 | 任务概览展示 | 展示待推广金额、距下一个任务差额、已生成任务数 |
| 用户端 | 订单支付/确认提示 | 支付成功页或订单详情提示“确认收货后计入推广任务” |
| Admin | 任务详情来源展示 | 后台任务详情展示来源订单、生成金额和拆分序号 |
**后端**
| 模块 | 开发项 | 说明 |
|---|---|---|
| 订单接入 | 确认收货后触发累计 | 推荐接入 `StoreOrderTakeServices::storeProductOrderUserTakeDelivery()` 成功后 |
| 金额服务 | `SyjPromoteAmountServices::recordOrderAmount()` | 计算有效金额,写累计流水 |
| 任务服务 | `SyjPromoteTaskServices::generateByAmount()` | 根据累计金额拆分生成任务 |
| 幂等 | 订单累计幂等 | 同一订单只能写一次 `income` 流水 |
| 并发 | 用户维度锁 | 同一用户多个订单并发确认时,串行计算待推广金额 |
**数据库**
| 表 | 用途 |
|---|---|
| `eb_syj_promote_amount_log` | 记录订单计入、任务扣减、退款回滚、人工调整 |
| `eb_syj_promote_task` | 保存推广任务主体 |
| 用户汇总字段或汇总表 | 保存当前待推广金额,避免每次聚合流水 |
建议在任务表保存配置快照:
| 字段 | 说明 |
|---|---|
| `base_amount` | 创建任务时的基准金额 |
| `target_count` | 创建任务时的目标单数 |
| `reward_rates` | 创建任务时的奖励比例 JSON |
| `fee_rate` | 创建任务时的提前兑现扣费比例 |
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| `syj_task_base_amount` | 控制每个任务的消费金额门槛 |
| `syj_task_generate_timing` | 首版建议 `on_confirm`,若改为 `on_pay` 必须补退款回滚 |
| 订单状态依赖 | 依赖订单已支付、未删除、达到有效节点 |
| 商品依赖 | 订单或商品需满足 `is_queue_goods=1` |
**Checklist**
- [ ] `4332` 元有效金额不生成任务。
- [ ] `4333` 元有效金额生成 1 个任务。
- [ ] `8666` 元有效金额生成 2 个任务。
- [ ] 多笔小额订单累计满额后能生成任务。
- [ ] 同一订单重复确认收货不重复累计。
- [ ] 并发确认收货不会重复生成或扣减待推广金额。
- [ ] 任务保存创建时的配置快照。
- [ ] 来源订单、来源金额、任务编号可在后台追溯。
### 13.3 等价报单奖励触发
**功能目标**
推广任务创建后,按当前代码的 1 个 `is_queue_goods=1` 报单商品订单触发基准,复用分销返佣、积分奖励和分销等级任务。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| 用户端 | 任务详情奖励状态 | 展示“奖励触发中/已触发/触发失败待处理” |
| 用户端 | 积分/佣金入口 | 继续跳转当前积分日志、佣金记录页面 |
| Admin | 奖励触发详情 | 展示分销、积分、等级任务触发结果和失败原因 |
| Admin | 重试按钮 | 对失败任务提供“重试奖励触发” |
**后端**
| 模块 | 开发项 | 说明 |
|---|---|---|
| 适配服务 | `SyjPromoteRewardTriggerServices` | 统一处理推广任务到现有奖励链路的映射 |
| 返佣 | 调用当前返佣入口 | 必须尊重 `brokerage_timing`,不绕开现有时机 |
| 积分 | 调用 `PointsRewardServices::reward()` | 使用等价触发单号作为幂等来源 |
| 等级任务 | 调用或扩展 `AgentLevelTaskServices` | 推广任务按 1 个有效报单触发单位计入 |
| 补偿 | 重试接口/命令 | 只补失败部分,成功部分不可重复 |
**数据库**
| 表 | 用途 |
|---|---|
| `eb_syj_promote_reward_trigger` | 保存任务触发分销、积分、等级任务的状态 |
| `eb_points_release_log` | 继续保存冻结积分奖励日志 |
| `eb_user_bill` | 继续保存后台可见积分日志 |
| 佣金流水表 | 继续保存现有分销佣金记录 |
| 分销等级任务记录表 | 继续保存现有任务完成记录 |
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| `syj_reward_trigger_enable` | 控制推广任务是否触发现有奖励链路 |
| `brokerage_timing` | 控制佣金发放节点,必须完全复用当前逻辑 |
| `hjf_umbrella_reward_enable` | 控制伞下积分奖励是否发放 |
| 后台权限 | 重试奖励触发必须限制为运营/管理员权限 |
**Checklist**
- [ ] 1 个任务只触发 1 次等价报单奖励。
- [ ] 2 个任务触发 2 次等价报单奖励。
- [ ] 积分奖励幂等,不重复写 `points_release_log`
- [ ] 后台积分日志能看到任务触发的积分记录。
- [ ] 分销等级任务按推广任务计数。
- [ ] `brokerage_timing=on_pay` 时不出现确认收货重复返佣。
- [ ] `brokerage_timing=on_confirm` 时不出现支付后提前返佣。
- [ ] 奖励触发失败可后台重试。
- [ ] 重试不会重复发放已成功的佣金或积分。
### 13.4 推荐订单计入任务进度
**功能目标**
下级有效订单按推荐关系计入推荐人的推四免一任务进度,计入节点复用当前后台返佣设置中的 `brokerage_timing``on_pay` 支付成功后计入,`on_confirm` 确认收货后计入,满 4 单完成任务。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| 用户端 | 任务进度条 | 展示 1/4、2/4、3/4、4/4 状态 |
| 用户端 | 推荐订单列表 | 展示下级昵称、订单时间、有效金额、当前档位 |
| 用户端 | 分享入口 | 复用当前推广二维码/分享海报能力 |
| Admin | 进度明细 | 后台任务详情展示每一单来源、订单号、下级用户 |
**后端**
| 模块 | 开发项 | 说明 |
|---|---|---|
| 订单接入 | 按 `brokerage_timing` 匹配任务 | `on_pay` 接支付成功事件,`on_confirm` 接确认收货流程 |
| 任务分配 | 最早任务优先 | 推荐人多个进行中任务时,按创建时间填充 |
| 进度记录 | `SyjPromoteTaskRecordServices` | 写入任务进度明细 |
| 状态推进 | 任务进度 +1 | 进度达到目标单数后触发完成结算 |
| 幂等 | 订单计入幂等 | 同一订单默认只能计入一次 |
**数据库**
| 表 | 用途 |
|---|---|
| `eb_syj_promote_task_record` | 保存下级订单计入任务进度的明细 |
| `eb_syj_promote_task` | 更新 `progress_count` 和任务状态 |
| `eb_store_order` | 读取订单、推荐人、支付状态、确认状态 |
任务进度明细需保存 `source_type``trigger_timing`,用于区分 `brokerage_timing=on_pay` 的支付成功计入与 `brokerage_timing=on_confirm` 的确认收货计入。
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| `syj_task_target_count` | 控制任务目标单数,首版为 4 |
| `syj_task_order_dedupe` | 控制按订单或按用户去重,首版建议按订单 |
| `brokerage_timing` | 控制推荐订单计入任务进度的节点,复用后台返佣设置 |
| 推荐关系依赖 | 依赖订单 `spread_uid` 或当前推荐关系快照 |
| 任务状态依赖 | 仅进行中任务可接收推荐订单 |
**Checklist**
- [ ] 推荐人无进行中任务时,下级订单不计入进度。
- [ ] 推荐人有 1 个任务时,下级订单计入该任务。
- [ ] 推荐人有多个任务时,优先计入最早进行中任务。
- [ ] `brokerage_timing=on_pay` 时,下级订单支付成功后计入任务进度。
- [ ] `brokerage_timing=on_confirm` 时,下级订单确认收货后计入任务进度。
- [ ] 同一订单重复支付回调或重复确认收货时不重复计入。
- [ ] 第 4 单计入后自动完成任务。
- [ ] 任务进度在用户端和后台一致。
- [ ] 推荐订单退款后能回滚或标记异常。
### 13.5 任务完成结算
**功能目标**
推广任务完成 4 单后,结算 `4333` 元,不扣 `7%`,并复用当前佣金/账单/提现链路。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| 用户端 | 完成状态 | 任务详情展示“已完成”与到账金额 |
| 用户端 | 结算记录 | 展示结算时间、结算金额、到账账户 |
| 用户端 | 资产入口 | 跳转当前佣金账户或提现页 |
| Admin | 结算流水 | 后台查看完成结算记录和关联账单 |
**后端**
| 模块 | 开发项 | 说明 |
|---|---|---|
| 结算服务 | `SyjPromoteSettlementServices::complete()` | 第 4 单后自动结算 |
| 入账 | 复用佣金账户/账单服务 | 写入当前可提现账户 |
| 状态 | 更新任务为 `completed` | 写完成时间,禁止再次计入 |
| 幂等 | 完成结算幂等 | 同一任务只能完成结算一次 |
**数据库**
| 表 | 用途 |
|---|---|
| `eb_syj_promote_settlement` | 保存完成结算记录 |
| `eb_syj_promote_task` | 保存任务完成状态 |
| `eb_user_bill` 或佣金流水表 | 保存资金入账流水 |
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| `syj_task_reward_rates` | 完成 4 单时不按提前兑现比例扣费,直接按任务基准结算 |
| 资金账户依赖 | 首版复用当前佣金账户和提现链路 |
| 任务状态依赖 | 只有进行中且进度达到目标单数的任务可完成结算 |
**Checklist**
- [ ] 第 4 单计入后自动结算。
- [ ] 完成结算金额为任务 `base_amount`
- [ ] 完成 4 单不扣 7%。
- [ ] 同一任务不会重复结算。
- [ ] 结算流水能关联任务、用户和账单。
- [ ] 用户资产页能看到到账变化。
- [ ] 已完成任务不能再申请提前兑现。
### 13.6 提前兑现申请与审核
**功能目标**
任务进度为 1-3 单时,用户可申请提前兑现;后台审核通过后扣 7%,入账并关闭任务。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| 用户端 | 提前兑现按钮 | 仅进度 1-3 且任务进行中时展示 |
| 用户端 | 兑现确认弹窗 | 展示应结算、扣费、预计到账 |
| 用户端 | 审核状态 | 展示待审核、已通过、已拒绝 |
| Admin | 审核列表 | 展示用户、任务、进度、金额、申请时间 |
| Admin | 审核操作 | 通过/拒绝,填写备注 |
**后端**
| 模块 | 开发项 | 说明 |
|---|---|---|
| 用户申请 | `POST /api/syj/promote/task/:id/cashout` | 创建待审核结算记录 |
| 后台审核 | `POST /adminapi/syj/promote/cashout/:id/audit` | 审核通过后入账并关闭任务 |
| 金额计算 | 按当前进度比例 | `gross=base_amount*rate``net=gross-fee` |
| 状态机 | 任务和审核记录联动 | 防止审核期间任务继续完成导致重复结算 |
**数据库**
| 表 | 用途 |
|---|---|
| `eb_syj_promote_settlement` | 保存提前兑现申请、审核和入账结果 |
| `eb_syj_promote_task` | 审核中可增加锁定状态,审核通过后改为提前兑现 |
| `eb_user_bill` 或佣金流水表 | 保存到账流水 |
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| `syj_early_cashout_fee_rate` | 首版默认 7 |
| 后台审核权限 | 审核通过/拒绝必须限制后台权限 |
| 资金账户依赖 | 审核通过后复用当前佣金账户/账单服务入账 |
| 状态依赖 | 审核中任务需避免继续完成结算造成双重入账 |
**Checklist**
- [ ] 进度 0 单不能申请提前兑现。
- [ ] 进度 1-3 单可以申请提前兑现。
- [ ] 已完成、已关闭、异常任务不能申请提前兑现。
- [ ] 审核通过扣 7% 后入账。
- [ ] 审核拒绝后任务继续进行。
- [ ] 审核通过后任务不能继续计入推荐订单。
- [ ] 审核中并发第 4 单时有明确状态处理,不重复结算。
- [ ] 用户端和后台金额计算一致。
### 13.7 用户端推广任务中心
**功能目标**
为用户提供待推广金额、任务列表、任务详情、推荐进度、提前兑现和结算记录入口。
**前端**
| 页面/文件建议 | 开发项 | 说明 |
|---|---|---|
| `view/uniapp/api/syjPromote.js` | API 封装 | 任务概览、列表、详情、兑现、流水 |
| `pages/syj/promote_task/index.vue` | 我的任务列表 | 进行中、已完成、已兑现、异常筛选 |
| `pages/syj/promote_task/detail.vue` | 任务详情 | 进度、推荐订单、奖励触发、结算 |
| 推广中心 | 增加入口 | 从现有推广中心进入“我的推广任务” |
| 资产页 | 文案联动 | 佣金、积分、等级继续复用当前页面 |
**后端**
| 接口 | 说明 |
|---|---|
| `GET /api/syj/promote/overview` | 概览 |
| `GET /api/syj/promote/task/list` | 任务列表 |
| `GET /api/syj/promote/task/:id` | 任务详情 |
| `GET /api/syj/promote/task/:id/records` | 推荐进度 |
| `POST /api/syj/promote/task/:id/cashout` | 提前兑现申请 |
| `GET /api/syj/promote/amount/log` | 待推广金额流水 |
| `GET /api/syj/promote/settlement/list` | 结算记录 |
**数据库**
用户端接口主要读取:
- `eb_syj_promote_task`
- `eb_syj_promote_task_record`
- `eb_syj_promote_amount_log`
- `eb_syj_promote_settlement`
- 现有用户、订单、佣金、积分日志表
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| 登录态 | 所有用户端任务接口必须登录后访问 |
| 数据权限 | 用户只能查看自己的任务、流水和结算 |
| 分享依赖 | 分享二维码/海报复用当前推广能力 |
| 文案依赖 | 页面统一使用芍药居口径 |
**Checklist**
- [ ] 未登录访问被拦截。
- [ ] 任务列表分页正常。
- [ ] 状态筛选正确。
- [ ] 任务详情只允许本人查看。
- [ ] 提前兑现按钮按状态展示。
- [ ] 空状态、异常状态、加载失败状态完整。
- [ ] 页面文案不出现 fsgx 旧口径。
- [ ] 金额、比例、小数位显示一致。
### 13.8 管理后台任务管理
**功能目标**
运营和财务能查看推广任务、推荐进度、奖励触发、结算流水、提前兑现审核和异常重试。
**前端**
| 页面/文件建议 | 开发项 | 说明 |
|---|---|---|
| `view/admin/src/api/syjPromote.js` | 后台 API 封装 | 任务、配置、审核、重试 |
| `view/admin/src/router/modules/syj.js` | 后台路由 | 芍药居菜单 |
| `pages/syj/promoteTask/index.vue` | 任务列表 | 搜索、筛选、导出入口 |
| `pages/syj/promoteTask/detail.vue` | 任务详情 | 来源订单、进度、奖励、结算 |
| `pages/syj/cashout/index.vue` | 提前兑现审核 | 审核通过/拒绝 |
| `pages/syj/config/index.vue` | 规则配置 | 基准金额、比例、扣费等 |
**后端**
| 接口 | 说明 |
|---|---|
| `GET /adminapi/syj/promote/task/list` | 任务列表 |
| `GET /adminapi/syj/promote/task/:id` | 任务详情 |
| `GET /adminapi/syj/promote/task/:id/records` | 进度明细 |
| `GET /adminapi/syj/promote/cashout/list` | 审核列表 |
| `POST /adminapi/syj/promote/cashout/:id/audit` | 审核 |
| `GET /adminapi/syj/promote/settlement/list` | 结算流水 |
| `GET/POST /adminapi/syj/promote/config` | 配置 |
| `POST /adminapi/syj/promote/retry-trigger/:task_id` | 重试奖励触发 |
**数据库**
后台需要支持组合筛选索引:
| 索引建议 | 用途 |
|---|---|
| `task_no` | 按任务号搜索 |
| `uid,status` | 按用户和状态筛选 |
| `source_order_no` | 按来源订单搜索 |
| `add_time` | 按创建时间筛选 |
| `audit_status,add_time` | 提前兑现审核列表 |
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| 后台菜单权限 | 任务列表、详情、配置、审核、重试分别授权 |
| 导出权限 | 结算和财务导出建议单独授权 |
| 操作审计 | 审核、重试、人工处理必须写操作人和备注 |
| 数据权限 | 若后台存在门店/供应商隔离,需按当前后台规则过滤 |
**Checklist**
- [ ] 后台任务列表支持状态、时间、用户、订单号筛选。
- [ ] 任务详情展示来源订单和 4 单进度。
- [ ] 奖励触发结果能看到成功/失败和失败原因。
- [ ] 重试奖励触发有权限控制。
- [ ] 提前兑现审核操作有二次确认。
- [ ] 审核通过/拒绝写管理员和备注。
- [ ] 列表导出字段满足财务核对。
- [ ] 页面权限与当前后台权限体系一致。
### 13.9 积分、分销等级与资产展示
**功能目标**
用户通过推广任务获得的积分、等级成长、佣金资产,都继续在当前积分、等级、资产页面可查,不新建平行资产体系。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| 用户端 | 积分记录文案 | 显示任务来源,例如“推广任务积分奖励” |
| 用户端 | 等级展示 | 继续使用当前分销等级/会员等级展示 |
| 用户端 | 佣金资产 | 继续复用当前佣金账户和提现入口 |
| Admin | 积分日志筛选 | 可按 HJF/SYJ 类型查任务积分 |
| Admin | 分销等级任务 | 保持原后台配置入口 |
**后端**
| 模块 | 开发项 | 说明 |
|---|---|---|
| 积分日志 | 扩展 mark/source | 明确写入推广任务编号 |
| 资产概览 | 复用或包装现有资产接口 | 可增加任务统计字段 |
| 等级任务 | 保持 `AgentLevelTaskServices` 为唯一升级逻辑 | 不新增会员等级任务 |
**数据库**
| 表 | 说明 |
|---|---|
| `eb_agent_level` | 继续保存等级和奖励积分配置 |
| `eb_user.agent_level` | 继续保存用户当前等级 |
| `eb_points_release_log` | 保存冻结积分明细 |
| `eb_user_bill` | 后台积分日志 |
| `eb_syj_promote_reward_trigger` | 关联任务与积分/等级触发结果 |
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| 分销等级配置 | 继续由当前 `agent/level` 后台维护 |
| 分销等级任务配置 | 继续由当前 `agent/level_task` 后台维护 |
| 积分释放配置 | 继续复用 `hjf_release_rate` |
| 数据展示权限 | 积分、佣金、等级页面沿用当前权限体系 |
**Checklist**
- [ ] 任务触发积分后,用户端积分相关页面可查。
- [ ] 后台积分日志可查到任务来源。
- [ ] 用户等级仍取 `eb_user.agent_level`
- [ ] 分销等级后台配置不被替换。
- [ ] 推广任务计入后台配置的等级任务。
- [ ] 资产页面没有出现独立新账户造成口径冲突。
### 13.10 售后退款、异常与补偿
**功能目标**
处理来源订单退款、推荐订单退款、奖励触发失败、积分或佣金补发等异常场景,避免资金和任务状态失真。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| 用户端 | 异常状态展示 | 任务异常时提示联系客服或等待处理 |
| Admin | 异常任务列表 | 展示退款冲突、触发失败、结算冲突 |
| Admin | 人工处理入口 | 标记已处理、重试触发、备注 |
**后端**
| 模块 | 开发项 | 说明 |
|---|---|---|
| 售后接入 | 监听退款成功 | 判断来源订单或推荐订单影响 |
| 回滚服务 | `SyjPromoteExceptionServices` | 回滚未结算任务或标记异常 |
| 补偿命令 | `syj:promote:retry-trigger` | 批量重试奖励触发失败任务 |
| 审计日志 | 记录人工处理 | 保留管理员、原因、前后状态 |
**数据库**
| 表 | 说明 |
|---|---|
| `eb_syj_promote_task` | 增加异常状态和异常原因 |
| `eb_syj_promote_task_record` | 推荐订单退款后标记失效 |
| `eb_syj_promote_amount_log` | 来源订单退款后写回滚流水 |
| `eb_syj_promote_reward_trigger` | 保存触发失败和重试次数 |
| 异常处理日志表 | 可新增,也可复用系统日志 |
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| 售后状态依赖 | 需明确退款成功、部分退款、撤销售后的处理节点 |
| 人工处理权限 | 仅运营/管理员可标记异常处理结果 |
| 补偿命令权限 | 只能由运维或管理员执行 |
| 日志依赖 | 关键异常必须写业务日志,便于财务追溯 |
**Checklist**
- [ ] 来源订单未生成任务前退款,待推广金额正确回滚。
- [ ] 来源订单已生成任务后退款,任务进入异常或人工处理。
- [ ] 推荐订单未结算前退款,任务进度回滚。
- [ ] 推荐订单已完成结算后退款,任务进入异常。
- [ ] 奖励触发失败可后台重试。
- [ ] 补偿命令不会重复发放已成功奖励。
- [ ] 所有人工处理都有备注和操作人。
### 13.11 测试、命令与上线检查
**功能目标**
为芍药居二开提供可重复执行的测试、补偿命令和上线前检查清单。
**前端**
| 端 | 开发项 | 说明 |
|---|---|---|
| 用户端 | 联调测试账号 | 准备普通用户、推荐人、下级用户 |
| Admin | 联调账号权限 | 准备运营、财务、超级管理员权限 |
| 前端构建 | 页面路由检查 | 确认新增页面能在 H5/小程序/Admin 正常访问 |
**后端**
| 类型 | 开发项 | 说明 |
|---|---|---|
| 单元测试 | 金额累计、任务生成、结算公式 | 覆盖 4332/4333/8666 |
| 集成测试 | 支付/确认收货/推荐计入 | 覆盖订单生命周期 |
| 命令 | `syj:promote:retry-trigger` | 重试奖励触发失败 |
| 命令 | `syj:promote:verify` | 检查配置、表结构、任务异常 |
| 日志 | 关键节点日志 | 任务生成、奖励触发、结算、退款 |
**数据库**
上线前检查:
- 表结构和索引已执行。
- 配置项已初始化。
- `hjf_queue_pool_enable=0`
- 旧商品 `is_queue_goods` 口径已由运营确认。
- 后台菜单和权限已初始化。
**配置/权限/依赖**
| 项 | 说明 |
|---|---|
| 测试环境 | 需准备可支付或可模拟支付的测试链路 |
| 队列依赖 | 若奖励触发异步化,需确认队列 worker 正常 |
| 定时任务 | 若积分释放依赖定时任务,需确认计划任务开启 |
| 日志权限 | 上线后需要能查看业务日志和异常日志 |
**Checklist**
- [ ] 后端测试覆盖 4332、4333、8666、9000。
- [ ] 返佣时机 `on_pay``on_confirm` 都通过验收。
- [ ] 积分奖励幂等测试通过。
- [ ] 等级任务计数测试通过。
- [ ] 提前兑现审核测试通过。
- [ ] 退款异常测试通过。
- [ ] 用户端任务列表和详情联调通过。
- [ ] 后台任务管理、配置、审核联调通过。
- [ ] 上线前配置检查命令通过。
---
## 14. 开发顺序建议
1. 新增数据库迁移和配置项。
2. 新增 `syj` 模型、DAO、核心服务。
3. 接入确认收货后的消费累计和任务生成。
4. 实现等价报单奖励触发适配,先打通积分和等级任务,再打通佣金。
5. 实现推荐订单计入任务进度。
6. 实现 4 单完成结算。
7. 实现提前兑现申请和后台审核。
8. 增加用户端接口和后台接口。
9. 补充管理端、用户端页面。
10. 补齐测试、补偿命令、后台重试能力。
建议优先打通最小闭环:
```text
确认收货生成任务
-> 任务触发积分和等级任务
-> 推荐 4 单完成
-> 结算入账
```
返佣、提前兑现、后台页面可在最小闭环稳定后并行完善。
---
## 15. 风险与注意事项
1. 不要新建独立会员等级体系,避免和 `eb_user.agent_level` 冲突。
2. 不要把推四免一任务直接写成后台分销等级任务。
3. 不要默认启用 HJF 公排池,芍药居首版不做排队退款。
4. 不要用不完整的虚拟订单直接调用返佣方法,容易造成账单、统计和幂等问题。
5. 不要绕开 `brokerage_timing`,否则会出现支付和确认收货重复返佣。
6. 不要让积分奖励只写 `points_release_log`,后台积分日志还需要通过 `user_bill` 可查。
7. 不要把旧 fsgx 文案带到芍药居页面尤其是“推三免一”“20/30/50”“公排退款”。
8. 退款、重复回调、并发确认收货是主要风险点,必须用唯一索引、事务和状态机兜住。
---
## 16. 与现有文档关系
| 文档 | 用途 |
|---|---|
| `docs/project-shaoyaoju/prd-require.md` | 原始需求整理与业务补充 |
| `docs/project-shaoyaoju/PRD_shaoyaoju_V1.0.md` | 产品需求主文档 |
| `docs/project-shaoyaoju/syj-fsgx-diff.md` | 芍药居与 fsgx 当前代码差异 |
| `docs/project-shaoyaoju/secondary-development-guide.md` | 面向后端工程师的二次开发说明 |
研发实施时,以 PRD 确认业务口径,以差异文档确认复用边界,以本文档确认代码落点、数据结构、接口和验收方式。