Ship customer portal and marketing pages, user edit drawer with employee archive, IDE employee numbers, channel config refactor, and related nginx/route updates. Co-authored-by: Cursor <cursoragent@cursor.com>
970 lines
44 KiB
Markdown
970 lines
44 KiB
Markdown
# 客户裂变与营销体系设计方案
|
||
|
||
> **文档状态**:产品 + 表结构 + 接口 + 页面交互(**评审通过后再开发**)
|
||
> **编写日期**:2026-07-23
|
||
> **关联系统**:OMS 业务(`docs/oms系统设计-050801.md`)、客户域 / RBAC(`docs/rbac系统设计-060801.md`)
|
||
> **关联规范**:`docs/oms系统设计-050801.md` **§3**(表/接口模板)、`docs/前端页面设计规范.md`
|
||
> **DDL 脚本**:`oms0414-back/sql/migrate_marketing_module.sql`
|
||
> **目标读者**:产品、运营、研发、测试
|
||
|
||
---
|
||
|
||
## 1 背景与目标
|
||
|
||
### 1.1 业务背景
|
||
|
||
跨境物流 OMS 以 **客户下单 → 余额支付 → 渠道履约** 为主链路。当前 `t_customer` 已有 **客户分组(CustomerGroup / VIP)**、**余额与资金流水**、**主子客户(ParentCustomerId)** 等基础能力,但缺少:
|
||
|
||
- 可传播的 **获客归因**(谁引荐了谁);
|
||
- 与下单行为绑定的 **成长体系**(积分 / 等级);
|
||
- 下单时可用的 **营销工具**(优惠券);
|
||
- 对引荐人可见的 **业绩与分成** 闭环。
|
||
|
||
### 1.2 建设目标
|
||
|
||
| 维度 | 目标 |
|
||
| --- | --- |
|
||
| **获客** | 老客户成为分销节点,注册链接 + 二维码降低分享门槛,新客可追踪来源 |
|
||
| **留存** | 积分等级让高频客户有可见成长路径,与 VIP 权益挂钩 |
|
||
| **转化** | 优惠券在查价 / 下单环节直接抵扣,提高首单与复购 |
|
||
| **激励** | 引荐人可查看下级客户订单成交额,按规则获得分成 |
|
||
| **可运营** | 管理端可配置规则,无需改代码即可调整活动 |
|
||
|
||
### 1.3 设计原则
|
||
|
||
1. **与现有 ID 体系一致**:业务归属一律使用 `t_customer.Id`(CustomerId),不用 JWT `mapId` 直接落库。
|
||
2. **与资金体系一致**:余额变动走 **`t_customer_account_flow`**;佣金走 **`CommissionBalance`**,扩展 `BizType` 枚举。
|
||
3. **与订单计费一致**:优惠券、等级折扣在 **查价 / 下单 / 支付** 链路上统一计算,前端只展示 `priceBreakdown`。
|
||
4. **主子客户边界清晰**:营销权益一律归 **主客户**;子账号仅做业务数据隔离,不参与营销。
|
||
5. **规则可见、误操作可拦**:页面须讲清业务规则,高危操作二次确认 + 服务端双保险(见 §16)。
|
||
|
||
---
|
||
|
||
## 2 已确认业务规则
|
||
|
||
| # | 决策 | 设计落点 |
|
||
| --- | --- | --- |
|
||
| 1 | **子账号不参与营销** | 积分/券/分成/引荐码/等级均挂在 **主客户**;`ResolveMarketingMainCustomerId` |
|
||
| 2 | **MemberLevel 替换 CustomerGroup** | 计价读 `t_member_level.PriceTierKey`;`CustomerGroup` 只读保留后废弃 |
|
||
| 3 | **分成独立账户** | `t_customer.CommissionBalance`;可 **提现** 或 **转入余额** |
|
||
| 4 | **默认分成** | 实付每 **1000 元 → 2 元**(floor 整段),`BaseAmount=1000, CommissionAmount=2` |
|
||
| 5 | **等级与券可叠加** | 见 §11 叠加计费公式 |
|
||
| 6 | **分成触发条件** | 订单 **`deliverySuccess`(派送成功)** 后计算;支付成功 **不** 最终入账 |
|
||
| 7 | **引荐层级** | 首版 **仅一级**;注册后 **不可** 自助改绑(运营可人工修正 + 审计) |
|
||
| 8 | **1 单 1 券** | 下单仅可选用一张券;未支付锁定 **30 分钟** 后自动释放 |
|
||
| 9 | **子账号下单** | 计价/券/积分/分成均归 **主客户**;子账号下单页须提示可能消耗主账号券 |
|
||
| 10 | **在途不展示分成金额** | 派送成功前仅展示下级订单与实付,**不展示预估分成** |
|
||
| 11 | **分成规则快照** | 写 `commission_detail` 时快照规则参数,改规则不追溯 |
|
||
| 12 | **PayableAmount=0** | 不发积分、不产生分成 |
|
||
| 13 | **Salesman 与 Referrer** | **分开统计**;分成 **仅认 ReferrerCustomerId** |
|
||
|
||
---
|
||
|
||
## 3 现状与可复用能力
|
||
|
||
### 3.1 已有能力
|
||
|
||
| 能力 | 现状 | 营销方案中的用法 |
|
||
| --- | --- | --- |
|
||
| 客户主数据 | `t_customer`:Balance、CustomerGroup、ParentCustomerId | 扩展引荐、积分、等级、CommissionBalance |
|
||
| 个人中心 | `views/user/profile` | 邀请、等级、券、佣金入口 |
|
||
| 客户门户 | `customerPortalOnly`、`loginType=1` | 裂变分享、券包、收益看板 |
|
||
| 订单与支付 | 订单创建、余额扣款、`BizType=orderPay` | 积分发放、券核销、分成统计 |
|
||
| 充值 | `t_recharge_record` | 佣金转余额与充值体系衔接 |
|
||
| 字典 | `t_dict_type` / `t_dict` | 券类型、积分、分成模式 |
|
||
| 微信 | `/wechat/customer/*` | 注册链接 H5 / 小程序 scene |
|
||
|
||
### 3.2 新建能力域
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 客户营销域(Marketing) │
|
||
├──────────────┬──────────────┬──────────────┬────────────────────┤
|
||
│ 裂变归因 │ 积分等级 │ 优惠券 │ 推荐分成 │
|
||
│ Referral │ Points/Tier │ Coupon │ Commission │
|
||
└──────┬───────┴──────┬───────┴──────┬───────┴─────────┬──────────┘
|
||
└──────────────┴──────────────┴─────────────────┘
|
||
│
|
||
订单查价 / 下单 / 支付 / 派送成功
|
||
│
|
||
t_customer + t_customer_account_flow
|
||
```
|
||
|
||
---
|
||
|
||
## 4 整体玩法架构
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[客户 A 个人中心] -->|生成链接/二维码| B[客户 B 注册]
|
||
B -->|写入引荐关系| C[归因库]
|
||
B -->|首单/下单| D[订单]
|
||
D -->|实付金额| E[积分发放]
|
||
E -->|累计积分| F[等级升级]
|
||
F -->|等级权益| G[运费折扣/专属券]
|
||
D -->|选券| H[优惠券核销]
|
||
D -->|派送成功| I[引荐分成]
|
||
I -->|结算| J[客户 A 佣金账户]
|
||
C --> I
|
||
```
|
||
|
||
| 角色 | 端 | 主要能力 |
|
||
| --- | --- | --- |
|
||
| **主客户(引荐人)** | 客户门户 | 分享链接/二维码、下级列表、等级积分、券包、收益明细 |
|
||
| **被引荐客户** | 注册页 / 门户 | 注册绑定引荐人;下单获积分、用券 |
|
||
| **运营 / 管理员** | 管理后台 | 等级、券、分成规则、发券、数据报表 |
|
||
| **财务** | 管理后台 | 分成审核、提现审核、对账 |
|
||
|
||
---
|
||
|
||
## 5 模块一:裂变推荐
|
||
|
||
### 5.1 功能
|
||
|
||
**个人中心** 提供:
|
||
|
||
1. **专属注册链接**:`https://{domain}/wechat/register?ref={inviteCode}`(公众号 OAuth 注册;PC 备用 `/register?ref=`)
|
||
2. **注册二维码**:前端本地生成 PNG;小程序码 `scene` 同码(若启用)
|
||
3. **归因**:`ReferrerCustomerId`、`ReferralBindTime`、`ReferralChannel`(微信注册为 `wechat`)
|
||
4. **ref 暂存**:`localStorage` **7 天 last-touch** + OAuth `state` 双保险
|
||
|
||
### 5.2 规则
|
||
|
||
| 规则项 | 默认值 | 说明 |
|
||
| --- | --- | --- |
|
||
| 绑定时机 | 注册成功一次性写入 | 未登录访问 cookie/localStorage 暂存 ref |
|
||
| 是否可改绑 | **否**(客户侧) | 运营后台可人工修正 + 审计;**只影响改绑后的新订单**(见 §24.5) |
|
||
| 老客点链接 | **不覆盖** | 已有 `ReferrerCustomerId` 的客户再次访问 ref 链接 **不更新** 归因 |
|
||
| ref 归因策略 | **last-touch** | cookie 7 天内以 **最后一次** 有效 ref 为准(仅对新注册生效) |
|
||
| 自引荐 | **禁止** | 同手机/同主体注册小号需风控拦截(见 §19) |
|
||
| 层级 | **一级** | |
|
||
| 链接有效期 | 长期;cookie 7 天 | |
|
||
| 注册页展示 | 校验 ref 后展示 | 「您由 {昵称/编号} 邀请注册」,增强确认、减少错绑纠纷 |
|
||
| 与 Salesman | 并存 | 内部销售与客户引荐 **分开统计**;**分成只认 Referrer** |
|
||
| 引荐人停用 | 邀请码 Disabled | 已绑定下级关系保留;该码 **不可再带来新注册** |
|
||
|
||
### 5.3 拓展玩法
|
||
|
||
邀请海报、话术模板、邀请排行榜、邀请任务、渠道参数 `utm_source`。
|
||
|
||
---
|
||
|
||
## 6 模块二:积分等级
|
||
|
||
### 6.1 功能
|
||
|
||
**管理员**:等级 CRUD(名称、累计积分门槛、价区键、额外折扣率、权益文案)。
|
||
**客户侧**:支付成功后发积分;累计达标自动升级(首版 **不自动降级**)。
|
||
|
||
### 6.2 积分规则(建议默认)
|
||
|
||
| 规则 | 示例 |
|
||
| --- | --- |
|
||
| 按实付 | 1 元 = 1 积分(基数 = `PayableAmount`) |
|
||
| 首单加倍 | 可配置 ×2 |
|
||
| 单笔上限 | 10 000 分 |
|
||
| 过期 | 首版可不做过期 |
|
||
|
||
### 6.3 与 CustomerGroup 关系
|
||
|
||
**已确认**:`MemberLevel` **替换** `CustomerGroup`。计价入口改为 `PriceTierKey`;管理端客户编辑用等级下拉。
|
||
|
||
| 原 CustomerGroup | MemberLevel | PriceTierKey |
|
||
| --- | --- | --- |
|
||
| Normal | 普通会员 | `普通客户` |
|
||
| Vip1 | 银卡 | `VIP1` |
|
||
| Vip2 | 金卡 | `VIP2` |
|
||
| Vip3+ | 钻石 | `VIP3` |
|
||
|
||
---
|
||
|
||
## 7 模块三:优惠券
|
||
|
||
### 7.1 券模板配置
|
||
|
||
| 配置项 | 说明 |
|
||
| --- | --- |
|
||
| 券类型 | 满减、折扣、无门槛立减、运费券 |
|
||
| 面额/折扣 | 满 100 减 10、9.5 折等 |
|
||
| 库存 | 全站上限 + 每客户领取上限 |
|
||
| 有效期 | 固定日期 / 领取后 N 天 |
|
||
| 适用范围 | 最低金额、产品/渠道/国家 |
|
||
| 状态 | 草稿 / 进行中 / 已结束 |
|
||
|
||
### 7.2 券类型枚举
|
||
|
||
| 类型 | 计算 |
|
||
| --- | --- |
|
||
| `fixed_off` | 满足 `minAmount` 减 `faceValue` |
|
||
| `percent_off` | 应付 × 折扣率,可封顶 |
|
||
| `direct_off` | 直接减 `faceValue` |
|
||
| `shipping_off` | 仅抵扣运费(P1 可简化为比例) |
|
||
|
||
### 7.3 生命周期
|
||
|
||
```
|
||
创建模板 → 领取/发放 → 实例 Available
|
||
→ 下单 Locked(30 分钟)→ 支付成功 Used
|
||
→ 取消/超时未支付 → 释放 Available(定时 Job)
|
||
```
|
||
|
||
**用券约束**:
|
||
|
||
| 规则 | 说明 |
|
||
| --- | --- |
|
||
| 每单张数 | **1 单 1 券**(首版不可叠加多张) |
|
||
| 满减门槛 | 按 **`AmountAfterLevel`(等级折后金额)** 判断 `MinOrderAmount` |
|
||
| 锁定超时 | 下单预占后 **30 分钟** 未支付自动释放;改单/重新查价须重新校验 |
|
||
| 应付为 0 | 允许下单时,**不发积分、不产生分成**(§2 #12) |
|
||
| 批量发券 | 目标为子账号编号时 **自动归并主客户** 并记入操作日志 |
|
||
|
||
订单记录:`CouponInstanceId`、`CouponDiscountAmount`、`MemberLevelDiscountAmount` 等快照,便于退款。
|
||
|
||
---
|
||
|
||
## 8 模块四:推荐分成
|
||
|
||
### 8.1 客户侧
|
||
|
||
- 下级列表、订单笔数/实付汇总
|
||
- 分成明细:**待派送 / 待结算 / 已结算** 三分(见 §16);**派送成功前不展示分成金额**
|
||
- 佣金转余额 / 提现申请
|
||
|
||
### 8.2 统计口径
|
||
|
||
| 指标 | 口径 |
|
||
| --- | --- |
|
||
| 成交金额 | 实付(已扣券),不含全额退款 |
|
||
| 有效订单(分成) | **`OrderStatus = deliverySuccess`** |
|
||
| 分成基数 | 剩余实付;**派送成功时** 计算 |
|
||
| 归因范围 | 仅直接下级 |
|
||
| 单月封顶 | `MonthlyCap`(可 NULL=不限);自然月累计达顶后 **超出部分不计**(§24.4) |
|
||
| 零元单 | `PayableAmount=0` **不产生** 分成 |
|
||
|
||
### 8.3 结算流程
|
||
|
||
```
|
||
支付成功 → 门户仅展示下级订单与实付(不展示分成金额)
|
||
→ deliverySuccess → 写 commission_detail Pending + 规则快照,EligibleTime
|
||
→ EligibleTime + FreezeDays 且无退款
|
||
→ Settled,CommissionBalance += 金额,写 referralCommission 流水
|
||
```
|
||
|
||
**不触发**:派送失败、问题件、已删除、全额退款、未达派送成功。
|
||
|
||
### 8.4 默认公式(floor 整段)
|
||
|
||
```
|
||
CommissionAmount = floor(BasePayableAmount / 1000) × 2
|
||
```
|
||
|
||
例:实付 2500 → 4 元。结算服务入口:`ReferralCommissionService.OnOrderDeliverySuccessAsync(orderId)`;**禁止**在支付回调写最终分成。
|
||
|
||
### 8.5 佣金提现 / 转余额
|
||
|
||
| WithdrawType | 行为 |
|
||
| --- | --- |
|
||
| `2` 转余额 | 审核通过 → CommissionBalance 减、Balance 增,`commissionToBalance` |
|
||
| `1` 提现 | 审核通过 → CommissionBalance 减,`commissionWithdraw`;线下打款 |
|
||
|
||
---
|
||
|
||
## 9 组合营销策略
|
||
|
||
**新客裂变闭环**:A 分享 → B 注册 → 新人券包 → B 首单双倍积分 → A 首单分成 + 感谢券 → B 升级复购。
|
||
**老客唤醒**:保级提醒、沉睡客户发券。
|
||
**大促**:限时券 + 等级折扣(配置叠加或取最优)。
|
||
**与销售协同**:ReferrerCustomerId 与 Salesman 分开统计。
|
||
|
||
---
|
||
|
||
## 10 主客户解析
|
||
|
||
```
|
||
sessionCustomer = OmsSessionHelper.ResolveSessionCustomerAsync(...)
|
||
marketingCustomer =
|
||
sessionCustomer.ParentCustomerId == null
|
||
? sessionCustomer
|
||
: 查 ParentCustomerId 对应主客户
|
||
```
|
||
|
||
| 场景 | 使用 Id |
|
||
| --- | --- |
|
||
| 引荐码、积分、券、佣金 | 主客户 Id |
|
||
| 订单 CustomerId | **不变**(可为子账号,数据隔离) |
|
||
| 营销计价、快照 | 下单时用 **主客户** 等级/券 |
|
||
|
||
**Helper**:`Oms.Application/Shared/MarketingCustomerHelper.cs`
|
||
子账号调用营销 API 归并主客户;前端 `ParentCustomerId != null` **隐藏** 全部营销入口。
|
||
|
||
**子账号下单(须写进下单页提示)**:
|
||
|
||
| 项 | 规则 |
|
||
| --- | --- |
|
||
| 计价等级/价区 | 用 **主客户** `MemberLevelId` / `PriceTierKey` |
|
||
| 可用券 | 主客户券包;核销记主客户 |
|
||
| 积分 | 支付成功后记 **主客户** |
|
||
| 引荐分成 | 订单 `CustomerId` 解析到主客户 → 取其 `ReferrerCustomerId` 作为引荐人 |
|
||
| 门户 UI | 隐藏营销中心;下单页 **须提示**「本单将使用主账号会员价/优惠券(如有)」 |
|
||
|
||
---
|
||
|
||
## 11 等级 + 优惠券叠加计费
|
||
|
||
### 11.1 计算步骤
|
||
|
||
| 步骤 | 字段 | 公式 |
|
||
| --- | --- | --- |
|
||
| ① 价区 | `PriceTierKey` | 主客户等级 → 卖价 JSON 键 |
|
||
| ② 等级价小计 | `ReceivableSubtotal` | 按价区计价后的合计 |
|
||
| ③ 等级额外折 | `LevelDiscountAmount` | `round(ReceivableSubtotal × ExtraDiscountRate, 2)` |
|
||
| ④ 券前金额 | `AmountAfterLevel` | `ReceivableSubtotal - LevelDiscountAmount` |
|
||
| ⑤ 券抵扣 | `CouponDiscountAmount` | 按券类型,且 ≤ AmountAfterLevel |
|
||
| ⑥ 应付 | `PayableAmount` | `max(0, AmountAfterLevel - CouponDiscountAmount)` |
|
||
|
||
### 11.2 示例
|
||
|
||
金卡 VIP2 + 额外 1%:价区价 90 → 等级折 0.9 → 89.1 → 满 80 减 10 → **应付 79.1 元**。
|
||
|
||
### 11.3 积分与分成基数
|
||
|
||
| 用途 | 基数 | 时机 |
|
||
| --- | --- | --- |
|
||
| 积分 | `PayableAmount` | 支付成功 |
|
||
| 引荐分成 | 下级 `PayableAmount` | **派送成功** |
|
||
|
||
### 11.4 退款
|
||
|
||
| 对象 | 规则 |
|
||
| --- | --- |
|
||
| 券 | 全额退款退回 Available;部分不退 |
|
||
| 积分 | 按比例扣回 |
|
||
| 分成 | 未派送成功不产生;Pending **按剩余实付重算**;已 Settled **负向流水扣回**(§24.3) |
|
||
|
||
### 11.5 priceBreakdown 出参
|
||
|
||
```json
|
||
{
|
||
"receivableSubtotal": 90.00,
|
||
"levelDiscountAmount": 0.90,
|
||
"couponDiscountAmount": 10.00,
|
||
"payableAmount": 79.10,
|
||
"memberLevelId": 3,
|
||
"memberLevelName": "金卡会员",
|
||
"priceTierKey": "VIP2",
|
||
"couponInstanceId": 1001
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 12 数据表结构与实体规范
|
||
|
||
> **必须遵循** `docs/oms系统设计-050801.md` **§3.1~§3.2**;DDL 脚本:`oms0414-back/sql/migrate_marketing_module.sql`。
|
||
|
||
### 12.1 必备字段(聚合根 / 业务单据表)
|
||
|
||
凡 C# 实体继承 **`OmsAuditedAggregateRoot`** 的表,建表 **必须** 包含:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `Id` | INT AUTO_INCREMENT | 主键 |
|
||
| `IsDeleted` | TINYINT DEFAULT 0 | 软删除:0-否,1-是 |
|
||
| `ConcurrencyStamp` | CHAR(36) | 并发戳;默认 **`'00000000-0000-0000-0000-000000000000'`**(**禁止** `DEFAULT (UUID())`,见 OMS §3.1.2) |
|
||
| `CreateUserId` | INT DEFAULT 0 | 创建人(`CurrentUser.GetId<int>()`,禁止前端传入) |
|
||
| `CreateTime` | DATETIME | 创建时间 |
|
||
| `UpdateUserId` | INT NULL | 更新人 |
|
||
| `UpdateTime` | DATETIME NULL | 更新时间 |
|
||
|
||
**流水 / 审计类**(如 `t_customer_points_flow`、`t_marketing_audit_log`)对齐 **`t_customer_account_flow`**:同样继承 `OmsAuditedAggregateRoot`,含 `ConcurrencyStamp` 与完整审计列。
|
||
|
||
**逻辑外键**:不设物理 FK,仅索引 + 注释(与 `db.sql` 一致)。
|
||
|
||
### 12.2 实体基类映射
|
||
|
||
| 表 | C# 实体 | 基类 | 聚合 |
|
||
| --- | --- | --- | --- |
|
||
| `t_member_level` | `MemberLevel` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_member_points_rule` | `MemberPointsRule` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_customer_referral_code` | `CustomerReferralCode` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_coupon_template` | `CouponTemplate` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_coupon_instance` | `CouponInstance` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_referral_commission_rule` | `ReferralCommissionRule` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_referral_commission_detail` | `ReferralCommissionDetail` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_commission_withdraw_request` | `CommissionWithdrawRequest` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_customer_points_account` | `CustomerPointsAccount` | `OmsAuditedAggregateRoot` | Marketing(含 `Version` 乐观锁) |
|
||
| `t_customer_points_flow` | `CustomerPointsFlow` | `OmsAuditedAggregateRoot` | Marketing |
|
||
| `t_marketing_audit_log` | `MarketingAuditLog` | `OmsAuditedAggregateRoot` | Marketing |
|
||
|
||
路径:`Oms.Domain/MarketingAggregate/Entities/*`、`Repositories/I*Repository.cs`。
|
||
|
||
### 12.3 业务字段与编号规范
|
||
|
||
| 表 | 业务必填 / 特征字段 |
|
||
| --- | --- |
|
||
| `t_customer`(扩展) | `ReferrerCustomerId`、`MemberLevelId`、`CommissionBalance`;扩展列 **无** ConcurrencyStamp(主表已有) |
|
||
| `t_customer_referral_code` | `CustomerId` UNIQUE、`InviteCode` UNIQUE、`Status` |
|
||
| `t_member_level` | `LevelCode` UNIQUE、`PriceTierKey`、`MinPoints`、`Sort`、`Status`(EnableStatus) |
|
||
| `t_coupon_template` | `TemplateCode` UNIQUE、`CouponType`、`Status`;`IssuedQuantity` ≤ `TotalQuantity` |
|
||
| `t_coupon_instance` | `CouponCode` UNIQUE、`TemplateId`、`CustomerId`、`ValidStartTime/EndTime`、`LockExpireTime` |
|
||
| `t_referral_commission_detail` | `OrderId+ReferrerCustomerId` UNIQUE、`RuleSnapshotJson`、`EligibleTime` |
|
||
| `t_commission_withdraw_request` | `SerialNumber` UNIQUE(规则 **`CMW{yyyyMMddHHmmss}{6位随机}`**)、`AuditBy`/`AuditTime`(对齐充值审核) |
|
||
| `t_customer_points_flow` | `BizType`、`BizId`、`BizNo`(订单号);**无** SerialNumber,以 Id + Biz 索引 |
|
||
| `t_order`(扩展) | 营销快照:`MemberLevelId`、`PriceTierKey`、`ReceivableSubtotal`、`LevelDiscountAmount`、`CouponInstanceId`、`CouponDiscountAmount`、`PayableAmount` |
|
||
|
||
**佣金入账**:`CommissionBalance` 变动须同步写 **`t_customer_account_flow`**,`BizType` = `referralCommission` / `commissionToBalance` / `commissionWithdraw` / `marketingAdjust`(与 §11 资金体系一致)。
|
||
|
||
### 12.4 表清单与 ER
|
||
|
||
| 表 | 说明 |
|
||
| --- | --- |
|
||
| `t_customer`(扩展) | Referrer*、MemberLevelId、CommissionBalance |
|
||
| `t_customer_referral_code` | 主客户邀请短码 |
|
||
| `t_member_level` / `t_member_points_rule` | 等级与积分规则 |
|
||
| `t_customer_points_account` / `_flow` | 积分账户与流水 |
|
||
| `t_coupon_template` / `t_coupon_instance` | 券模板与实例 |
|
||
| `t_referral_commission_rule` / `_detail` | 分成规则与明细 |
|
||
| `t_commission_withdraw_request` | 提现/转余额(对齐 `t_recharge_record` 审核字段) |
|
||
| `t_marketing_audit_log` | 高危操作审计 |
|
||
| `t_order`(扩展) | 营销快照 |
|
||
|
||
```mermaid
|
||
erDiagram
|
||
t_customer ||--o| t_customer_referral_code : "主客户 1:1"
|
||
t_customer ||--o| t_customer_points_account : "主客户 1:1"
|
||
t_customer }o--|| t_member_level : MemberLevelId
|
||
t_customer ||--o{ t_coupon_instance : CustomerId
|
||
t_coupon_template ||--o{ t_coupon_instance : TemplateId
|
||
t_customer ||--o{ t_referral_commission_detail : ReferrerCustomerId
|
||
t_order ||--o| t_referral_commission_detail : OrderId
|
||
```
|
||
|
||
---
|
||
|
||
## 13 关键业务流程
|
||
|
||
### 13.1 注册带引荐
|
||
|
||
```
|
||
/register?ref=ABC123 → 缓存 ref → 提交注册
|
||
→ 校验 InviteCode → ReferrerCustomerId
|
||
→ 创建客户 → (可选)新人券
|
||
```
|
||
|
||
### 13.2 下单用券 + 积分 + 分成
|
||
|
||
```
|
||
查价 + availableCoupons → 选券重算
|
||
→ 支付成功 → 核销券 → 积分 → 检查升级
|
||
→ (分成)等 deliverySuccess
|
||
→ OnOrderDeliverySuccessAsync → Pending
|
||
→ Job 冻结期满 → Settled
|
||
```
|
||
|
||
### 13.3 退款
|
||
|
||
回退积分、取消/调整 Pending 分成、按规则退券。
|
||
|
||
---
|
||
|
||
## 14 接口设计
|
||
|
||
> **必须遵循** `docs/oms系统设计-050801.md` **§3.2~§3.3** 与现有 Service 模板(如 `KpiAreaService`、`RechargeService`、`CustomerAccountFlowService`)。
|
||
|
||
### 14.0 公共约定
|
||
|
||
| 项 | 约定 |
|
||
| --- | --- |
|
||
| 暴露方式 | Fake 框架:`ApplicationService` + `[HttpPost]` / `[HttpGet]`,**无手写 Controller** |
|
||
| Swagger 分组 | `[ApiExplorerSettings(GroupName = "OMS-Marketing")]` |
|
||
| 管理端路由 | **`POST /marketing/{resource}/{action}`**(list / create / update / delete),与 `/channel/kpi-area/*` 一致 |
|
||
| 门户读接口 | **`GET /marketing/{resource}/{action}`** + `[FromQuery]`(对齐 `/customer/account-flow/list`) |
|
||
| 门户写接口 | **`POST /marketing/{resource}/{action}`** + JSON Body |
|
||
| 分页入参 | `Page`(从 1)、`PageSize`;`OmsDocHelper.NormalizePage` / `NormalizePageSize`(上限 200) |
|
||
| 分页出参 | **`OmsPageResult<T>`**:`Items` + **`Total`**(long,非 `totalCount`) |
|
||
| 主键操作 | 删除/详情用 **`IdInput`**(`Dtos/Shared/IdInput.cs`) |
|
||
| 保存 | **`*SaveInput`**:`Id?` 为空 create,有值 update(对齐 `KpiAreaSaveInput`) |
|
||
| 审计 | Create/Update/Delete 写 `CreateUserId`/`UpdateUserId`;**禁止**信任前端传操作人 |
|
||
| 客户会话 | 门户须 `loginType=1`;`MarketingCustomerHelper.ResolveMarketingMainCustomerIdAsync` |
|
||
| 管理端 | `loginType=0`;列表 **不** 注入单一 CustomerId;门户列表 **强制** 主客户 Id |
|
||
| 权限码 | 见 §20;前端 `meta.permission` 对齐(后端细粒度拦截待 RBAC 完善,Service 内仍须校验) |
|
||
|
||
**DTO 目录**(`Oms.Application/Dtos/Marketing/`):
|
||
|
||
```
|
||
MemberLevelListInput / MemberLevelSaveInput / MemberLevelOutput
|
||
CouponTemplateListInput / CouponTemplateSaveInput / CouponTemplateOutput
|
||
CouponGrantInput / CouponInstanceListInput / CouponInstanceOutput
|
||
ReferralCommissionRuleSaveInput / CommissionDetailListInput / ...
|
||
MarketingReferralMyInviteOutput / MarketingMemberOverviewOutput / ...
|
||
```
|
||
|
||
**Service 目录**(`Oms.Application/Services/Marketing/`):
|
||
|
||
| 类 | 职责 |
|
||
| --- | --- |
|
||
| `MarketingMemberLevelService` | 等级 CRUD |
|
||
| `MarketingPointsRuleService` | 积分规则、调账、流水查询 |
|
||
| `MarketingCouponTemplateService` | 券模板 CRUD、停发 |
|
||
| `MarketingCouponGrantService` | 批量发券 |
|
||
| `MarketingCommissionRuleService` | 分成规则 |
|
||
| `MarketingCommissionAdminService` | 分成明细、提现审核 |
|
||
| `MarketingReferralAdminService` | 引荐树、改绑 |
|
||
| `MarketingPortalReferralService` | 门户:邀请、下级 |
|
||
| `MarketingPortalMemberService` | 门户:等级、积分 |
|
||
| `MarketingPortalCouponService` | 门户:券包、领取 |
|
||
| `MarketingPortalCommissionService` | 门户:收益、提现 |
|
||
|
||
### 14.1 客户门户接口
|
||
|
||
| 方法 | 路径 | 入参 | 出参 |
|
||
| --- | --- | --- | --- |
|
||
| GET | `/marketing/referral/my-invite` | — | `ReferralMyInviteOutput` |
|
||
| GET | `/marketing/referral/referees` | `ReferralRefereeListInput`(Page, PageSize) | `OmsPageResult<ReferralRefereeOutput>` |
|
||
| GET | `/marketing/referral/validate-code` | `code`(**AllowAnonymous**) | `ReferralValidateCodeOutput` |
|
||
| GET | `/marketing/member/overview` | — | `MemberOverviewOutput` |
|
||
| GET | `/marketing/member/points-flow` | `PointsFlowListInput` | `OmsPageResult<PointsFlowOutput>` |
|
||
| GET | `/marketing/coupon/my-list` | `CouponMyListInput`(status) | `OmsPageResult<CouponInstanceOutput>` |
|
||
| GET | `/marketing/coupon/available-for-order` | `CouponAvailableInput` | `List<CouponAvailableOutput>` |
|
||
| POST | `/marketing/coupon/receive` | `IdInput`(templateId) | `CouponInstanceOutput` |
|
||
| GET | `/marketing/commission/overview` | — | `CommissionOverviewOutput` |
|
||
| GET | `/marketing/commission/details` | `CommissionDetailListInput` | `OmsPageResult<CommissionDetailOutput>` |
|
||
| GET | `/marketing/commission/withdraw/list` | `CommissionWithdrawListInput` | `OmsPageResult<CommissionWithdrawOutput>` |
|
||
| POST | `/marketing/commission/transfer-to-balance` | `CommissionTransferInput` | — |
|
||
| POST | `/marketing/commission/withdraw/apply` | `CommissionWithdrawApplyInput` | `CommissionWithdrawOutput` |
|
||
|
||
**注册扩展**(`/customer/*` 或 Auth):`CustomerCreateInput` 增加 `InviteCode?` → `ReferrerCustomerId`。
|
||
|
||
### 14.2 管理端接口
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
| --- | --- | --- | --- |
|
||
| POST | `/marketing/member-level/list` | 分页列表 | `Marketing.Level.View` |
|
||
| POST | `/marketing/member-level/create` | 新增 | `.Create` |
|
||
| POST | `/marketing/member-level/update` | 更新 | `.Update` |
|
||
| POST | `/marketing/member-level/delete` | 软删 | `.Delete` |
|
||
| POST | `/marketing/points-rule/get` | 当前规则 | `Marketing.PointsRule.Edit` |
|
||
| POST | `/marketing/points-rule/update` | 更新规则 | 同上 |
|
||
| POST | `/marketing/points-flow/list` | 积分流水 | `Marketing.Points.View` |
|
||
| POST | `/marketing/points/adjust` | 人工调账 | `Marketing.Points.Adjust` |
|
||
| POST | `/marketing/coupon-template/list` | 券模板列表 | `Marketing.Coupon.Template.View` |
|
||
| POST | `/marketing/coupon-template/create` | 创建 | `.Create` |
|
||
| POST | `/marketing/coupon-template/update` | 更新 | `.Update` |
|
||
| POST | `/marketing/coupon-template/publish` | Draft→Active | `.Update` |
|
||
| POST | `/marketing/coupon-template/end` | 停发 | `.Update` |
|
||
| POST | `/marketing/coupon/grant` | 批量发券 | `Marketing.Coupon.Grant` |
|
||
| POST | `/marketing/coupon-instance/list` | 券实例查询 | `Marketing.Coupon.Template.View` |
|
||
| POST | `/marketing/commission-rule/get` | 当前分成规则 | `Marketing.Commission.Rule.Edit` |
|
||
| POST | `/marketing/commission-rule/update` | 更新规则 | 同上 |
|
||
| POST | `/marketing/commission-detail/list` | 分成明细 | `Marketing.Commission.View` |
|
||
| POST | `/marketing/commission-detail/adjust` | 人工调整 | `Marketing.Commission.Adjust` |
|
||
| POST | `/marketing/commission-withdraw/list` | 提现列表 | `Marketing.Commission.Withdraw.View` |
|
||
| POST | `/marketing/commission-withdraw/approve` | 审核通过 | `.Audit` |
|
||
| POST | `/marketing/commission-withdraw/reject` | 驳回 | `.Audit` |
|
||
| POST | `/marketing/referral/tree` | 一级引荐关系 | `Marketing.Referral.View` |
|
||
| POST | `/marketing/referral/rebind` | 改绑 | `Marketing.Referral.Rebind` |
|
||
|
||
### 14.3 订单扩展(OrderService,非 Marketing Service)
|
||
|
||
| 方法 | 路径 | 变更 |
|
||
| --- | --- | --- |
|
||
| POST | `/order/price-check` | 入参 `couponInstanceId?`;出参 `priceBreakdown`、`availableCoupons` |
|
||
| POST | `/order/parcel/create` 等 | 营销快照;支付成功写积分;**不含**分成结算 |
|
||
| 内部 | 订单 → `deliverySuccess` | `ReferralCommissionService.OnOrderDeliverySuccessAsync` |
|
||
|
||
---
|
||
|
||
## 15 枚举与字典
|
||
|
||
补充 `docs/itfx枚举说明.md` 与 `t_dict`:
|
||
|
||
| 字典/枚举 | 值 |
|
||
| --- | --- |
|
||
| `coupon_type` | fixed_off, percent_off, direct_off, shipping_off |
|
||
| `coupon_template_status` | 0 Draft, 1 Active, 2 Ended |
|
||
| `coupon_instance_status` | 1 Available, 2 Locked, 3 Used, 4 Expired |
|
||
| `commission_status` | 1 Pending, 2 Settled, 3 Cancelled |
|
||
| `commission_withdraw_type` | 1 External, 2 ToBalance |
|
||
| `points_change_type` | 1 Earn, 2 Consume, 3 Adjust, 4 RefundClawback |
|
||
|
||
---
|
||
|
||
## 16 页面交互与防误操作
|
||
|
||
营销涉及资金与折扣,页面 **必须** 讲清规则并防止误操作。
|
||
|
||
### 16.1 交互设计原则
|
||
|
||
| 原则 | 说明 |
|
||
| --- | --- |
|
||
| **规则可见** | 每页顶部固定区域说明规则、适用对象、生效时机 |
|
||
| **后果可预期** | 保存/发放前展示影响范围 + 数量/金额估算 |
|
||
| **误操作可拦** | 高危操作二次确认;批量操作输入确认词 `确认发放` |
|
||
| **前后端双保险** | UI + 服务端校验库存、状态、主客户归属 |
|
||
| **可审计** | 关键操作写 `t_marketing_audit_log` |
|
||
|
||
布局遵循 `docs/前端页面设计规范.md`:`table-toolbar`、`FormPro`/`ModalPro`、`var(--app-primary-color)`。
|
||
|
||
### 16.2 规则说明组件
|
||
|
||
**页面级**(必选):容器顶部 `.marketing-page-tip`:
|
||
|
||
```vue
|
||
<a-alert type="info" :show-icon="true" class="marketing-page-tip">
|
||
{{ t('marketing.pageTip.xxx') }}
|
||
</a-alert>
|
||
```
|
||
|
||
- 文案 3~5 行,写清主客户/子账号、生效时机、不可撤销项
|
||
- 资金风险用 `warning`;不要只写「请谨慎操作」
|
||
|
||
**弹窗内**:`ModalPro` 顶部 `a-alert`(同渠道配置 `modal-form-tip`)。
|
||
**字段级**:价区键、额外折扣率、冻结天数用 tooltip 或 `extra` 说明。
|
||
|
||
**状态标签**(分成/券/提现):
|
||
|
||
| 状态 | 颜色 | 说明 |
|
||
| --- | --- | --- |
|
||
| 待派送成功 | `arcoblue` | 未达派送成功,**不展示分成金额**,仅展示订单与实付 |
|
||
| 待结算 Pending | `orange` | 已派送成功,冻结期内 |
|
||
| 已结算 Settled | `green` | 已入佣金账户 |
|
||
| 已取消 Cancelled | `gray` | 退款/派送失败/人工取消 |
|
||
|
||
### 16.3 页面须展示的业务规则(i18n:`marketing.rule.*`)
|
||
|
||
**全局**:营销权益归主客户;等级替换客户组且不追溯历史订单;叠加顺序见 §11;引荐仅一级、不可自助改绑。
|
||
|
||
**裂变**:链接绑定主客户;注册数 ≠ 下单数;以下级实付为准。
|
||
|
||
**积分等级**:支付成功后发积分;自动升级不自动降级;改 MinPoints/价区键只影响之后。
|
||
|
||
**优惠券**:不可转让;停发不影响已领券;改面额不影响已发券;批量发券受库存与上限约束。
|
||
|
||
**分成(重点)**:**仅 `deliverySuccess` 后计算**;默认 1000→2 元 floor(999 元 = 0 分成,页内须举例);Pending → 冻结 → CommissionBalance;支付成功 **不展示分成金额**;单月可有封顶 `MonthlyCap`。
|
||
|
||
**下单**:展示完整 `priceBreakdown` 四行;选券必须重新查价;不可用券展示原因。
|
||
|
||
### 16.4 管理端分页面要求
|
||
|
||
| 页面 | 要点 |
|
||
| --- | --- |
|
||
| **等级配置** | tip 说明价区键;改价区/额外折扣 Modal 摘要;禁止删已用等级 |
|
||
| **积分规则** | tip 支付成功发放;改比例不追溯;人工调账必填原因 ≥10 字 |
|
||
| **券模板** | 分步向导;发布二次确认;停发说明已领券仍有效;总量只允许增大 |
|
||
| **批量发券(高危)** | warning tip;预览 N/M 人、库存 X;超 100 人或 >5000 元输入 `确认发放` |
|
||
| **分成规则** | tip 加粗派送成功条件;保存新旧对比;禁止一键重算历史 |
|
||
| **分成明细** | 列 EligibleTime;禁止 Pending 直接改 Settled |
|
||
| **提现审核** | 展示余额与申请额;拒绝必填原因;禁止一键全部通过 |
|
||
| **引荐改绑(高危)** | 仅管理员;原因 ≥20 字;警告不影响已结算;写审计日志 |
|
||
|
||
### 16.5 客户门户分页面要求
|
||
|
||
| 页面 | 要点 |
|
||
| --- | --- |
|
||
| **子账号** | 隐藏全部营销入口 |
|
||
| **邀请好友** | tip:一级、不可改绑、**派送成功** 才有分成 |
|
||
| **我的等级** | 价区对人话翻译;进度条 + 积分规则 tooltip |
|
||
| **我的优惠券** | Tab 三分;≤3 天过期 orange |
|
||
| **推荐收益** | tip 三分待派送/待结算/已结算;**待派送不展示分成金额**;派送成功后显示金额 |
|
||
| **下单选券** | priceBreakdown 默认展开;换券 Toast + 金额高亮;提交确认券抵扣;**子账号须提示消耗主账号券** |
|
||
|
||
### 16.6 高危操作分级
|
||
|
||
| 级别 | 操作 | UI |
|
||
| --- | --- | --- |
|
||
| L1 | 查看、导出 | 无 |
|
||
| L2 | 单条发券、编辑草稿、小额转余额 | popconfirm / Modal |
|
||
| L3 | 批量发券、发布模板、改分成规则、改价区键 | Modal + 摘要;超阈值确认词 |
|
||
| L4 | 引荐改绑、强制入账、大额调账 | L3 + 原因 + 审计 |
|
||
|
||
### 16.7 后端防线(与 UI 配套)
|
||
|
||
| 场景 | 校验 |
|
||
| --- | --- |
|
||
| 发券 | 库存、PerCustomerLimit、Active、主客户 |
|
||
| 核销 | 归属、有效期、门槛;Locked 防并发 |
|
||
| 改等级 | 禁止删已引用;不 retroactive |
|
||
| 分成 | 必须 deliverySuccess;EligibleTime + FreezeDays;MonthlyCap;规则快照;退款扣回 |
|
||
| 佣金转出 | 余额足够;无冲突申请;进行中申请冻结可用额 |
|
||
| 引荐改绑 | 禁自引荐、禁环、审计;不 retroactive 历史单 |
|
||
|
||
**审计表 `t_marketing_audit_log`**:Action、OperatorId、TargetType/Id、BeforeJson/AfterJson、Remark。
|
||
|
||
### 16.8 典型营销事故与防护
|
||
|
||
| 事故 | 防护 |
|
||
| --- | --- |
|
||
| 误发大量无门槛券 | 确认词 + 库存硬顶 + Job 限流 |
|
||
| 改错价区键 | 保存前受影响客户数 + 试算 |
|
||
| 支付后显示「已赚分成」 | 门户三分状态 + 文案 |
|
||
| 券重复核销 | Locked + 释放 Job |
|
||
| 子账号看到佣金 | 前端隐藏 + API 主客户解析 |
|
||
| 派送失败仍分成 | 仅 deliverySuccess 写 Pending |
|
||
| 以为改规则会追溯 | 每页 tip + 保存 Modal |
|
||
|
||
### 16.9 i18n 与验收
|
||
|
||
- 文案走 `marketing.*`,确认框含具体数字
|
||
- 示例:`marketing.confirm.grantCoupon` = 「将向 {count} 个客户发放「{templateName}」共 {total} 张,预估最大抵扣 {amount} 元,发放后不可撤回。」
|
||
|
||
**验收 checklist**:
|
||
|
||
- [ ] 每页有 `marketing-page-tip`
|
||
- [ ] Modal 有规则 tip
|
||
- [ ] L2+ 二次确认;L3 含摘要/确认词
|
||
- [ ] 下单完整 priceBreakdown + 选券重查价
|
||
- [ ] 子账号无营销入口;下单有「使用主账号价/券」提示
|
||
- [ ] 推荐收益 **待派送不展示分成金额**;待结算/已结算区分清晰
|
||
- [ ] 关键操作有审计日志
|
||
- [ ] 遵循 §24 边界规则
|
||
|
||
---
|
||
|
||
## 17 管理端功能清单
|
||
|
||
| 菜单 | 功能 |
|
||
| --- | --- |
|
||
| 营销 · 等级配置 | CRUD 等级、价区键、额外折扣 |
|
||
| 营销 · 积分规则 | 获取比例、上限、调账 |
|
||
| 营销 · 券模板 | 创建/停发/库存 |
|
||
| 营销 · 手动发券 | 按客户编号批量发放 |
|
||
| 营销 · 分成规则 | 1000/2、冻结期、封顶 |
|
||
| 营销 · 分成明细 | 查询、人工调整 |
|
||
| 营销 · 引荐关系 | 一级关系、改绑 |
|
||
| 营销 · 数据看板 | 注册来源、券核销、分成支出 |
|
||
|
||
---
|
||
|
||
## 18 客户门户功能清单
|
||
|
||
| 入口 | 功能 |
|
||
| --- | --- |
|
||
| 邀请好友 | 链接、二维码、邀请记录 |
|
||
| 我的等级 | 等级、积分、进度、权益 |
|
||
| 积分明细 | 流水(含订单号) |
|
||
| 我的优惠券 | 可用/已用/过期 |
|
||
| 推荐收益 | 下级、汇总、分成(在途/待结算/已结算) |
|
||
| 下单/查价 | 选券、priceBreakdown |
|
||
|
||
---
|
||
|
||
## 19 风控与合规
|
||
|
||
| 风险 | 措施 |
|
||
| --- | --- |
|
||
| 刷单骗积分/券 | 延迟发放、异常审核、IP 频率限制 |
|
||
| 自引荐/小号 | 手机唯一、同 IP 阈值 |
|
||
| 券囤积 | 领取上限、短有效期 |
|
||
| 分成套利 | **仅派送成功后计算**、冻结期、退款扣回、MonthlyCap、PayableAmount=0 不计 |
|
||
| 运营误操作 | §16 确认词、tip、审计 |
|
||
| 人工刷派送成功 | `ForceTrigger` + L4;默认仅轨迹入口 |
|
||
| 子账号误用主账号券 | 下单页提示 + API 主客户解析 |
|
||
| 多级分销 | 首版仅一级 |
|
||
| 金额一致性 | 服务端计费为准 |
|
||
| 主子账号 | 权益归主客户;子账号隐藏入口 |
|
||
|
||
---
|
||
|
||
## 20 权限码
|
||
|
||
```
|
||
Marketing.Level.View / .Create / .Update / .Delete
|
||
Marketing.PointsRule.Edit
|
||
Marketing.Points.View / .Adjust
|
||
Marketing.Coupon.Template.View / .Create / .Update
|
||
Marketing.Coupon.Grant
|
||
Marketing.Commission.Rule.Edit
|
||
Marketing.Commission.View
|
||
Marketing.Commission.Adjust
|
||
Marketing.Commission.ForceTrigger
|
||
Marketing.Commission.Withdraw.View / .Audit
|
||
Marketing.Referral.View / .Rebind
|
||
Marketing.Emergency.Disable
|
||
```
|
||
|
||
门户接口:无 Permission,仅 `loginType=1` + 主客户解析。
|
||
|
||
---
|
||
|
||
## 21 涉及改动清单
|
||
|
||
### 21.1 后端(oms0414-back)
|
||
|
||
| 模块 | 路径 | 说明 |
|
||
| --- | --- | --- |
|
||
| SQL | `sql/migrate_marketing_module.sql` | 遵循 §12.1 必备字段 |
|
||
| Domain | `Oms.Domain/MarketingAggregate/` | Entities + Enums + Repositories |
|
||
| Domain | `CustomersAggregate/Customer.cs`、`OrdersAggregate/Order.cs` | 扩展字段 |
|
||
| Application | `Shared/MarketingCustomerHelper.cs` | 主客户解析 |
|
||
| Application | `Services/Marketing/*.cs` | 见 §14.0 Service 清单 |
|
||
| Application | `Dtos/Marketing/*.cs` | ListInput / SaveInput / Output |
|
||
| Application | `Services/Orders/*` | 查价、支付、派送成功钩子 |
|
||
| Application | `Jobs/CommissionSettleJob.cs` | 冻结期结算 |
|
||
| Auth/Customer | 注册 `InviteCode` | 归因 |
|
||
|
||
**实体与仓储命名**:与渠道模块一致,如 `IMemberLevelRepository`、`MemberLevelRepository`(SqlSugar 实现放 Infrastructure 层)。
|
||
|
||
### 21.2 前端(oms0414)
|
||
|
||
| 模块 | 改动 |
|
||
| --- | --- |
|
||
| 门户 | `views/user/profile/**`、注册页 `?ref=` |
|
||
| 管理端 | `views/marketing/**`(遵循 §16) |
|
||
| 下单 | 选券 UI、priceBreakdown |
|
||
| API/路由/i18n | `api/marketing/**`、`router/.../marketing.ts` |
|
||
|
||
### 21.3 文档
|
||
|
||
| 文件 | 改动 |
|
||
| --- | --- |
|
||
| `docs/itfx枚举说明.md` | 营销枚举 |
|
||
| `docs/oms系统设计-050801.md` | 营销模块索引(可选) |
|
||
|
||
---
|
||
|
||
## 22 分阶段实施
|
||
|
||
| 阶段 | 交付 | 依赖 |
|
||
| --- | --- | --- |
|
||
| **M1** | DDL + MarketingCustomerHelper + MemberLevel 替换 CustomerGroup 计价 | SQL |
|
||
| **M2** | 引荐码、注册归因、邀请页(§16.5) | M1 |
|
||
| **M3** | 券模板/发券/核销 + 查价 breakdown(§16.4 券相关) | M1 |
|
||
| **M4** | 积分发放 + 等级升级 | M3 |
|
||
| **M5** | 分成 + 结算 Job + 佣金账户 + 提现(§16 分成文案) | M2,M3 |
|
||
| **M6** | 管理端营销菜单 + 报表 + 审计 | M2–M5 |
|
||
|
||
**建议顺序**:M1 → M2 → M3 → M4 → M5 → M6。
|
||
|
||
---
|
||
|
||
## 23 待实现细节(编码时再定)
|
||
|
||
1. **floor 整段** vs **比例分成** — 当前默认 floor(999 元 = 0 分成,已在 §24.4 说明)。
|
||
2. **shipping_off** 首版是否简化为整单比例抵扣。
|
||
3. **转余额** 是否 ≤500 元免审;**最低提现额** 与手续费。
|
||
4. **CustomerGroup 列** 何时物理删除(建议运行 2 版本后)。
|
||
5. **积分是否可消耗**(首版仅升级用,不抵扣运费)。
|
||
6. **注册入口** PC / 微信 H5 / 小程序范围与 ref 跨端一致性。
|
||
7. **销售店铺单、代客下单** 是否一律参与营销(建议:仅客户余额支付的业务订单,见 §24.8)。
|
||
8. **价区键缺失** 时降级普通价还是报错(建议:降级普通价 + 管理端告警)。
|
||
|
||
---
|
||
|
||
## 24 边界与争议规则
|
||
|
||
本节为 §2 已确认规则的 **展开说明**,开发与客户/管理端文案 **必须一致**。
|
||
|
||
### 24.1 优惠券
|
||
|
||
| # | 规则 |
|
||
| --- | --- |
|
||
| 1 | **1 单 1 券**;不可叠加多张 |
|
||
| 2 | 下单预占 `Locked`,**30 分钟** 未支付由 Job 释放为 `Available` |
|
||
| 3 | 满减/折扣门槛基数 = **`AmountAfterLevel`**(等级价 + 额外折扣后) |
|
||
| 4 | 改产品/重量/国家后 **重新查价**,券可能失效,须返回不可用原因 |
|
||
| 5 | 全额退款 → 券退回;**部分退款不退券** |
|
||
| 6 | 运营批量发券:客户编号为子账号 → **解析到主客户** 再发放 |
|
||
| 7 | `PayableAmount=0` → 允许支付则 **不发积分、不产生分成** |
|
||
|
||
### 24.2 引荐归因
|
||
|
||
| # | 规则 |
|
||
| --- | --- |
|
||
| 1 | **仅新注册** 写入 `ReferrerCustomerId`;老客户点链接 **不覆盖** |
|
||
| 2 | cookie **last-touch**,有效期 7 天;链接本身长期有效 |
|
||
| 3 | 注册页校验 ref 成功后展示邀请人信息 |
|
||
| 4 | 禁止自引荐;同手机号/同证件(若采集)/异常 IP 频率限制 |
|
||
| 5 | 后台创建客户可手工录入引荐人,`ReferralChannel=manual` |
|
||
| 6 | 引荐人账号停用 → 邀请码 Disabled;**已有下级关系保留** |
|
||
| 7 | **Salesman 与 Referrer 分开统计**;分成 **只认 ReferrerCustomerId** |
|
||
|
||
### 24.3 分成、退款与状态机
|
||
|
||
| # | 规则 |
|
||
| --- | --- |
|
||
| 1 | **门户**:派送成功前 **不展示分成金额**,只展示下级订单列表与实付 |
|
||
| 2 | 触发:`OrderStatus → deliverySuccess`;`OnOrderDeliverySuccessAsync` **幂等**(一单一引荐人一条明细) |
|
||
| 3 | 写 Pending 时 **快照规则**:`BaseAmount`、`CommissionAmount`、`FreezeDays`、`MonthlyCap`(JSON 或冗余列) |
|
||
| 4 | **部分退款**:冻结期内 Pending **按剩余实付重算**;已 Settled → **`marketingAdjust` 负向流水** 扣减 CommissionBalance(不足扣到 0,记欠账备注) |
|
||
| 5 | 状态回退(`deliverySuccess` → 其他):Pending → `Cancelled`;已 Settled → 走扣回 |
|
||
| 6 | **人工改状态为派送成功**:默认 **与轨迹回写同一入口**;若管理端强改须 `Marketing.Commission.ForceTrigger` + L4 审计 |
|
||
| 7 | floor 整段:实付 999 元 → **0 分成**;邀请页/规则页须举例说明 |
|
||
|
||
**MonthlyCap(单月封顶)**:
|
||
|
||
- 统计维度:引荐人主客户 + **自然月**(EligibleTime 所在月)
|
||
- 结算 Job 入账前:若 `本月已 Settled + 本笔 > MonthlyCap`,则本笔 **按剩余额度截断或整笔 Cancelled**(实现时二选一,推荐 **截断入账**)
|
||
- `MonthlyCap=NULL` 表示不限;管理端配置页与门户 tip 须说明
|
||
|
||
### 24.4 积分与等级
|
||
|
||
| # | 规则 |
|
||
| --- | --- |
|
||
| 1 | 积分在 **支付成功** 后发放;基数 `PayableAmount`;**升级即时生效**(同一支付回调内检查) |
|
||
| 2 | 首版 **不自动降级**;运营调高 `MinPoints` **不批量降级** 存量客户 |
|
||
| 3 | 运营 **手动改客户等级**:只改 `MemberLevelId`,**不修改** `TotalPoints` |
|
||
| 4 | 禁用某等级:禁止 **新分配**,存量客户 **沿用到下次升级** |
|
||
| 5 | `TotalPoints` 用于定级;`AvailablePoints` 首版与 Total 同步(仅升级用时不消耗) |
|
||
| 6 | 产品卖价 JSON **无对应 PriceTierKey** 时:回退 **普通客户** 价并记告警(§23 #8) |
|
||
|
||
### 24.5 引荐改绑
|
||
|
||
| # | 规则 |
|
||
| --- | --- |
|
||
| 1 | 仅管理端、`Marketing.Referral.Rebind`、原因 ≥20 字、审计日志 |
|
||
| 2 | **不影响** 已 Settled 分成 |
|
||
| 3 | **Pending / 未产生分成** 的订单:以 **下单时** 订单快照的 `RefereeCustomerId → ReferrerCustomerId` 为准;改绑 **不 retroactive 改历史单** |
|
||
| 4 | 改绑后 **新订单** 按新引荐关系计算 |
|
||
|
||
### 24.6 佣金提现与转余额
|
||
|
||
| # | 规则 |
|
||
| --- | --- |
|
||
| 1 | 进行中提现/转余额申请 **冻结** 对应 `CommissionBalance` 可用额度 |
|
||
| 2 | 拒绝须填原因,客户门户可见 |
|
||
| 3 | 转余额:`commissionToBalance` 流水,与充值记录 **分开对账** |
|
||
| 4 | 最低提现额、手续费见 §23(编码前产品确认) |
|
||
|
||
### 24.7 隐私与展示
|
||
|
||
| # | 规则 |
|
||
| --- | --- |
|
||
| 1 | 引荐人看下级:默认展示 **客户编号 + 注册时间 + 是否首单/是否已有派送成功单**;姓名/手机 **脱敏**(如编号完整、手机中间四位 `*`) |
|
||
| 2 | 下级订单列表:运单号、状态、实付可见;**不展示** 下级收件人 PII |
|
||
|
||
### 24.8 参与范围与应急
|
||
|
||
| # | 规则 |
|
||
| --- | --- |
|
||
| 1 | 默认参与:客户门户 **余额支付** 的业务订单(parcel 主链路);草稿/已删除不参与 |
|
||
| 2 | 销售店铺单、代客下单:若 `CustomerId` 指向真实客户且走同一支付链路则 **参与**,否则首版 **排除**(以订单类型字段为准,编码时落枚举) |
|
||
| 3 | **全局应急开关** `Marketing.Emergency.Disable`:停发券、停新分成 Pending(已 Pending 仍走冻结结算),管理端一键 + 审计 |
|
||
|
||
### 24.9 管理端须补充的页面说明
|
||
|
||
- 分成规则页:MonthlyCap、floor 举例(999=0)、派送成功条件
|
||
- 批量发券:子账号编号自动归主客户
|
||
- 引荐改绑:仅影响新单
|
||
- 客户编辑:手动改等级不碰积分
|
||
|
||
---
|
||
|
||
## 25 附录:名词对照
|
||
|
||
| 名词 | 说明 |
|
||
| --- | --- |
|
||
| 引荐人 | 分享链接的主客户 A |
|
||
| 被引荐人/下级 | 通过 A 注册的客户 B |
|
||
| 实付 / PayableAmount | 等级折扣、券抵扣后应付金额 |
|
||
| 核销 | 券标记已用并绑定订单 |
|
||
| 冻结期 | 派送成功后至佣金入账的等待期 |
|
||
| 待派送 | 已支付、未达派送成功;**不展示分成金额** |
|
||
| 待结算 | 已派送成功、冻结期内 |
|
||
| 已结算 | 已入 CommissionBalance |
|
||
| 规则快照 | 写分成明细时固化的 BaseAmount/CommissionAmount 等,改配置不追溯 |
|
||
| MonthlyCap | 引荐人自然月分成上限,NULL=不限 |
|
||
|
||
---
|
||
|
||
**文档结束。** 评审通过后按 **M1→M6** 开工;页面开发须满足 **§16** 交互与 **§24** 边界规则。
|