172 lines
10 KiB
Markdown
172 lines
10 KiB
Markdown
# 代理资金与佣金当前行为
|
||
|
||
## Purpose
|
||
|
||
描述代理充值、钱包、佣金、提现及其金额边界的当前可观察行为。
|
||
|
||
## Requirements
|
||
|
||
### Requirement: 代理钱包与提现状态门禁
|
||
|
||
系统 SHALL 仅允许正常钱包执行资金操作;冻结或关闭钱包拒绝扣款、冻结、释放或提现,提现申请按待审核、已通过、已拒绝、已到账状态推进,重复终态决定不得再次扣减或入账。
|
||
|
||
#### Scenario: 非正常钱包资金操作
|
||
|
||
- **GIVEN** 代理钱包已冻结或关闭
|
||
- **WHEN** 请求扣款、冻结、释放或提现
|
||
- **THEN** 系统返回状态错误且余额与流水不变
|
||
|
||
### Requirement: 佣金异常状态可见
|
||
|
||
系统 SHALL 将佣金记录保持为已冻结、解冻中、已发放、已失效或待人工修正;链路断裂的记录进入待人工修正而不是静默计入可提现余额。
|
||
|
||
#### Scenario: 佣金链路断裂
|
||
|
||
- **GIVEN** 佣金记录无法关联完成后续发放所需事实
|
||
- **WHEN** 系统处理该记录
|
||
- **THEN** 记录保持待人工修正状态且不增加可提现余额
|
||
|
||
### Requirement: 代理在线充值本地支付状态
|
||
|
||
系统 SHALL 将代理在线充值的本地支付投影按 0=待支付、1=已支付、2=已失败、3=已退款返回;订单和资产充值使用各自的状态集。
|
||
|
||
#### Scenario: 代理在线充值本地支付状态
|
||
|
||
- **GIVEN** 代理在线充值的本地支付记录存在
|
||
- **WHEN** 查询该充值的支付状态
|
||
- **THEN** 返回数值状态及对应中文名称
|
||
|
||
### Requirement: 充值边界
|
||
|
||
系统 SHALL 接受资产充值 100 至 10000000 分、线下代理充值 1 至 100000000 分、在线代理充值至少 10000 分。
|
||
|
||
#### Scenario: 充值边界
|
||
|
||
- **GIVEN** 请求金额位于或越过边界
|
||
- **WHEN** 创建对应充值
|
||
- **THEN** 边界内请求进入既有支付流程,越界请求返回参数或业务错误
|
||
|
||
### Requirement: 佣金待计算状态可恢复
|
||
|
||
系统 SHALL 将已支付订单的佣金待计算状态与可靠投递事实关联;投递异常不得静默遗留为无法继续处理的待计算订单。
|
||
|
||
#### Scenario: 佣金投递链路异常
|
||
|
||
- **WHEN** 佣金计算任务提交或消费链路发生可恢复异常
|
||
- **THEN** 订单维持待计算且投递状态、重试次数和失败摘要可查询,恢复投递后按既有规则得出有佣金、无佣金或待人工修正结果
|
||
|
||
### Requirement: 退款佣金回扣可靠完成
|
||
|
||
系统 SHALL 在退款审批生效时持久化佣金回扣请求;回扣请求的投递或处理异常不得静默遗留,且退款单在全部应回扣佣金失效并完成对应钱包流水前不得标记为已回扣。
|
||
|
||
#### Scenario: 已退款订单佣金回扣失败后恢复
|
||
|
||
- **WHEN** 已退款订单的佣金回扣首次处理失败或进程中断
|
||
- **THEN** 退款单保持佣金未回扣状态并保留可重试事实,后续成功处理后佣金记录失效、佣金钱包按既有规则扣减且退款单标记为已回扣
|
||
|
||
### Requirement: 退款后处理可补偿
|
||
|
||
系统 SHALL 对已退款但佣金未回扣或资产未完成后处理的退款单提供幂等补偿;重复补偿不得重复扣减佣金钱包、重复写回扣流水或重复处理资产。
|
||
|
||
#### Scenario: 遗留退款单补偿
|
||
|
||
- **WHEN** 补偿流程发现已退款且 `commission_deducted=false` 的退款单
|
||
- **THEN** 系统恢复该退款单的唯一后处理请求,并在既有回扣成功后更新其回扣完成标记
|
||
|
||
### Requirement: 代理商资金概况按店铺 ID 检索
|
||
|
||
系统 SHALL 允许通过可选的正整数 `shop_id` 查询参数精确筛选 `GET /api/admin/shops/fund-summary` 的店铺资金概况;该条件 MUST 与当前账号的店铺数据范围及其他已提供筛选条件取交集,未提供时 MUST 保持既有列表行为。
|
||
|
||
#### Scenario: 按可见店铺 ID 精确检索
|
||
|
||
- **WHEN** 当前账号请求资金概况列表并提供其数据范围内的 `shop_id`
|
||
- **THEN** 系统仅返回该 ID 且同时满足其他已提供筛选条件的店铺资金概况
|
||
|
||
#### Scenario: 店铺 ID 不匹配或超出数据范围
|
||
|
||
- **WHEN** 当前账号提供不存在、超出其数据范围或不满足其他已提供筛选条件的 `shop_id`
|
||
- **THEN** 系统返回成功的空分页结果且不披露该店铺是否存在
|
||
|
||
#### Scenario: 店铺 ID 参数无效
|
||
|
||
- **WHEN** 当前账号提供零、负数或无法解析为正整数的 `shop_id`
|
||
- **THEN** 系统返回参数错误且不执行资金概况查询
|
||
|
||
#### Scenario: 未提供店铺 ID
|
||
|
||
- **WHEN** 当前账号请求资金概况列表但未提供 `shop_id`
|
||
- **THEN** 系统继续按既有分页、数据范围、店铺名称和主账号用户名条件返回结果
|
||
|
||
### Requirement: 历史待审批线下代理充值可主动接入企业微信审批
|
||
|
||
系统 SHALL 提供 `POST /api/admin/agent-recharges/{id}/trigger-approval`,使具有既有代理充值管理访问权限的后台账号可为历史线下代理充值申请主动创建企业微信审批。系统 MUST 仅在线下充值记录处于待审批状态且 `approval_instance_id` 为空时创建审批;审批发起人 MUST 使用该充值记录的原创建账号。创建成功后,系统 MUST 原子保存唯一审批实例、审批提交请求及充值记录的审批实例关联,并返回更新后的充值申请审批摘要。
|
||
|
||
#### Scenario: 主动发起历史线下代理充值审批成功
|
||
|
||
- **GIVEN** 线下代理充值申请处于待审批状态、未关联审批实例,且其原创建账号和企业微信线下充值审批场景均可用
|
||
- **WHEN** 有既有代理充值管理访问权限的后台账号请求 `POST /api/admin/agent-recharges/{id}/trigger-approval`
|
||
- **THEN** 系统创建以原创建账号为发起人的唯一企业微信审批并返回审批摘要,后续由既有可靠提交流程提交至企业微信
|
||
|
||
#### Scenario: 在线、非待审批或已发起记录被拒绝
|
||
|
||
- **WHEN** 请求主动发起的充值记录不是线下充值、不是待审批状态或已关联审批实例
|
||
- **THEN** 系统返回状态冲突且不创建新的审批实例或提交请求
|
||
|
||
#### Scenario: 并发主动发起同一充值审批
|
||
|
||
- **WHEN** 两个请求同时为同一符合条件的线下代理充值申请主动发起审批
|
||
- **THEN** 系统至多创建一个审批实例和一个审批提交请求,未成功创建关联的请求返回冲突
|
||
|
||
#### Scenario: 原创建人或审批渠道不可用
|
||
|
||
- **WHEN** 充值申请原创建账号不可用,或企业微信线下充值审批场景不可用
|
||
- **THEN** 系统返回相应错误,充值申请保持未关联审批实例,修复条件后可再次发起
|
||
|
||
### Requirement: 代理在线充值可用支付方式按支付配置判定
|
||
|
||
系统 SHALL 按当前生效支付配置判定代理在线充值可用支付方式:微信直连(`wechat` 或 `wechat_v2`)配置完整,或富友(`fuiou`)配置完整时,返回 `wechat`;支付宝字段完整时返回 `alipay`。对外支付方式枚举 MUST 固定为 `wechat` 与 `alipay`,MUST NOT 返回 `fuiou`。代理账号以 `wechat` 创建在线充值单时,若生效配置为富友,系统 MUST 使用富友主扫统一下单并将返回的二维码链接作为支付链接。
|
||
|
||
#### Scenario: 富友配置完整时微信可用
|
||
|
||
- **GIVEN** 当前生效支付配置 `provider_type=fuiou` 且富友机构号、商户号、终端号、私钥、公钥、API 地址、通知地址均非空
|
||
- **WHEN** 代理账号查询可用支付方式
|
||
- **THEN** 系统返回包含 `wechat` 的方式列表且不包含 `fuiou`
|
||
|
||
#### Scenario: 微信直连配置完整时微信可用
|
||
|
||
- **GIVEN** 当前生效支付配置为微信直连且对应字段完整
|
||
- **WHEN** 代理账号查询可用支付方式
|
||
- **THEN** 系统返回包含 `wechat` 的方式列表
|
||
|
||
#### Scenario: 支付宝字段完整时支付宝可用
|
||
|
||
- **GIVEN** 当前生效支付配置的支付宝应用 ID、应用私钥、支付宝公钥、通知地址均非空
|
||
- **WHEN** 代理账号查询可用支付方式
|
||
- **THEN** 系统返回包含 `alipay` 的方式列表
|
||
|
||
#### Scenario: 富友配置下微信创建走主扫下单
|
||
|
||
- **GIVEN** 当前生效支付配置为富友且字段完整
|
||
- **WHEN** 代理账号以 `wechat` 创建在线充值单
|
||
- **THEN** 系统调用富友主扫统一下单并返回二维码链接作为支付链接,本地充值单支付方式为 `wechat`、支付渠道为 `fuiou`
|
||
|
||
## 可达操作索引
|
||
|
||
本节只用于入口导航,不是行为 Requirement;业务义务以上述 Requirements 为准。
|
||
|
||
### 代理预充值
|
||
|
||
`GET /api/admin/agent-recharges`(查询代理充值订单列表);`POST /api/admin/agent-recharges`(创建代理充值订单);`GET /api/admin/agent-recharges/{id}`(查询代理充值订单详情);`POST /api/admin/agent-recharges/{id}/trigger-approval`(补发历史线下代理充值审批);`POST /api/admin/agent-recharges/{id}/offline-pay`(确认线下充值);`GET /api/admin/agent-recharges/{id}/payment-status`(查询代理充值本地支付与到账状态);`POST /api/admin/agent-recharges/{id}/reject`(驳回代理充值订单);`GET /api/admin/agent-recharges/payment-methods`(查询代理在线充值可用支付方式)。
|
||
|
||
### 代理商资金管理
|
||
|
||
`POST /api/admin/commission-records/{id}/resolve`(修正待审佣金记录);`PUT /api/admin/shops/{id}/credit-limit`(调整既有店铺实际信用额度);`GET /api/admin/shops/{shop_id}/commission-daily-stats`(代理商每日佣金统计);`GET /api/admin/shops/{shop_id}/commission-records`(代理商佣金明细);`GET /api/admin/shops/{shop_id}/commission-stats`(代理商佣金统计);`GET /api/admin/shops/{shop_id}/main-wallet/transactions`(代理商预充值钱包流水);`GET /api/admin/shops/{shop_id}/withdrawal-requests`(代理商提现记录);`POST /api/admin/shops/{shop_id}/withdrawal-requests`(发起提现申请);`GET /api/admin/shops/fund-summary`(代理商资金概况)。
|
||
|
||
### 佣金提现审批
|
||
|
||
`GET /api/admin/commission/withdrawal-requests`(提现申请列表);`POST /api/admin/commission/withdrawal-requests/{id}/approve`(审批通过提现申请);`POST /api/admin/commission/withdrawal-requests/{id}/reject`(拒绝提现申请)。
|
||
|
||
### 提现配置管理
|
||
|
||
`GET /api/admin/commission/withdrawal-settings`(提现配置列表);`POST /api/admin/commission/withdrawal-settings`(新增提现配置);`GET /api/admin/commission/withdrawal-settings/current`(获取当前生效的提现配置)。
|