# 红人客户与寄样订单实现方案

## 需求背景

需求原文：

| 模块 | 功能 | 说明 |
| --- | --- | --- |
| 红人管理 | 红人管理 | 管理员创建红人后，可以给红人下单赠送红人产品。创建红人的时候需要根据红人的主页地址等信息去重。在红人页面可以查看给红人的寄样订单。红人有负责人，只有负责人可以查看红人的所有信息，所有人不允许导出客户列表。可以给某个红人赠送产品，支持新建产品或选择已收到的产品，要记录产品成本、佣金、合作费用。 |
| 红人订单 | 红人订单 | 将员工发起的红人订单展示出来。 |

## 核心结论

红人不应独立成一套人员主数据，应作为 `customer` 的一种客户属性。

推荐做法：

```text
customer.type = 3  红人
```

红人相关的订单仍复用现有 `sale_order` / `sale_order_detail`，通过现有 `sale_order.type` 区分普通销售订单和红人寄样订单，不新增订单类型字段。

这样可以复用现有能力：

- 客户基础信息。
- 客户负责人 `owner_admin_id`。
- 客户地址。
- 销售订单、订单明细。
- 库存、出库、发货计划。
- 费用记录 `cost`。
- 操作日志、跟进记录、附件。

不建议新增 `influencer` 主表，也不建议把现有 `sample` 表作为红人寄样订单主表。现有 `sample` 更偏样品库存或项目样品语境，不能自然承载红人主页去重、负责人数据权限、订单履约和营销成本闭环。

## 客户类型

在 `config/autoload/variable.php` 的 `CUSTOMER_TYPE` 中增加红人类型：

```php
'CUSTOMER_TYPE' => [
    1 => 'variable.零售',
    2 => 'variable.批发',
    3 => 'variable.红人',
],
```

建议新增常量，避免业务代码中直接写 `3`：

```php
class CustomerSet
{
    public const TYPE_RETAIL = 1;
    public const TYPE_WHOLESALE = 2;
    public const TYPE_INFLUENCER = 3;
}
```

## Customer 字段扩展

红人是 `customer` 的属性，应优先沿用 `Customer` 现有字段，只补充现有字段无法可靠承载的红人专用字段。

### 可沿用字段

| 红人含义 | 沿用字段 | 说明 |
| --- | --- | --- |
| 红人名称/昵称 | `title` | 客户名称，红人列表主显示字段 |
| 红人简称/别名 | `short_title` | 可用于备注账号昵称、简称 |
| 红人主页地址 | `website` | 例如 TikTok、Instagram、YouTube 主页 |
| 平台账号 ID | `third_id` | 可保存平台 user id、handle 或第三方账号 ID |
| 红人平台/来源 | `customer_source_id` / `channel_id` | 平台可作为客户来源或渠道配置，如 TikTok、Instagram |
| 客户类型 | `type` | `type = 3` 表示红人 |
| 负责人 | `owner_admin_id` | 控制红人可见范围 |
| 联系人 | `contact` | 红人本人或商务联系人 |
| 电话/手机 | `telephone` / `mobile` | 联系方式 |
| WhatsApp | `whats_app` | 跨境联系常用 |
| 邮箱 | `email` | 商务联系邮箱 |
| 微信 | `wechat` | 国内联系字段 |
| 地址 | `address` | 寄样地址 |
| 国家/省/市/区域 | `country_id` / `state_id` / `city_id` / `area_id` / `district` | 地址结构化字段 |
| 快递地址快照 | `express_address_info` | 可用于保存收件人、电话、完整地址等快递信息 |
| 备注 | `remark` | 合作说明、注意事项 |
| 重要程度 | `important_star` | 可用于红人优先级 |
| 图片/视频素材 | `avatar` / `images` / `video` | 红人头像、主页截图、合作素材 |
| 跟进时间 | `next_follow_id` / `next_follow_time` / `last_follow_time` | 复用客户跟进能力 |

### 字段扩展结论

红人基础资料优先沿用现有 `customer` 字段，当前阶段不新增红人字段。

粉丝数、合作状态如果需要结构化筛选，有两种处理方式：

1. 短期可放在客户扩展字段或 `remark` 中，避免改表。
2. 如果后续需要按粉丝数范围、合作状态频繁筛选，再新增 `influencer_fans_count`、`influencer_status`。

建议索引：

```sql
ALTER TABLE hg_customer
ADD KEY idx_customer_type_owner (company_id, type, owner_admin_id);
```

## 主页去重

创建或编辑红人客户时，如果 `customer.type = 3`，必须执行主页去重。

### 规范化规则

输入主页地址后，对 `customer.website` 做简单规范化，再进行业务层比对：

```text
1. trim 空格。
2. scheme 统一处理，去掉 http:// 和 https://。
3. 域名转小写。
4. 去掉 URL 末尾 /。
5. 去掉常见跟踪参数，如 utm_source、utm_medium、utm_campaign、fbclid、gclid。
6. 对 TikTok / Instagram / YouTube 等平台尽量提取账号 handle。
```

### 去重规则

创建时：

```text
同公司下，查找 type = 3 的客户，将已有 customer.website 与当前输入 website 规范化后比较，相同则禁止创建。
```

编辑时：

```text
同公司下，排除当前 customer.id 后，查找 type = 3 的客户，将已有 customer.website 与当前输入 website 规范化后比较，相同则禁止保存。
```

如果主页为空，但提供了平台账号 ID，可以按：

```text
company_id + customer_source_id/channel_id + third_id
```

做业务层查重。

## 红人负责人与数据权限

红人的负责人复用：

```text
customer.owner_admin_id
```

权限规则：

| 用户类型 | 可见范围 |
| --- | --- |
| 普通员工 | 只能看 `owner_admin_id = 当前用户` 的红人客户 |
| 红人订单发起员工 | 可看自己发起的红人订单 |
| 主管/管理员 | 可看全部红人客户和红人订单 |

后端必须强制校验，不能只依赖前端菜单隐藏。

红人详情、编辑、删除、创建寄样订单时都需要校验当前用户是否有权操作该红人客户。

## 红人管理页面

红人管理本质是客户管理的一个专用视图。

查询条件固定：

```text
customer.type = 3
```

列表建议字段：

```text
红人名称
平台
主页地址
账号ID
粉丝数
负责人
合作状态
最近寄样订单
寄样订单数
累计产品成本
累计佣金
累计合作费用
创建时间
```

详情页建议展示：

```text
客户基础信息
红人平台信息
负责人
联系信息
地址
寄样订单列表
费用记录
跟进记录
附件
备注
```

## 红人订单模型

红人订单应复用 `sale_order`。

红人寄样订单直接沿用现有字段：

```text
sale_order.type
```

建议在订单类型常量中补充红人寄样类型，避免业务代码中直接写数字：

```php
class SaleOrderSet
{
    public const TYPE_NORMAL = 1;
    public const TYPE_INFLUENCER_SAMPLE = 2;
}
```

红人订单查询条件：

```sql
customer.type = 3
AND sale_order.type = 2
```

红人订单仍然走现有：

```text
sale_order
sale_order_detail
repository_receipt
delivery_plan
delivery_plan_detail
express_task
```

## 红人订单金额与成本

红人寄样通常销售金额为 0，但必须记录营销成本。

建议规则：

| 场景 | 处理 |
| --- | --- |
| 选择已有产品 | 产品正常进入 `sale_order_detail`，成本取产品成本价或手动覆盖 |
| 新建产品 | 先创建 `product`，再创建 `sale_order_detail` |
| 选择已收到产品 | 明细成本为 0 |
| 佣金 | 写入 `cost`，关联 `sale_order_id` 和 `customer_id` |
| 合作费用 | 写入 `cost`，关联 `sale_order_id` 和 `customer_id` |

如果 `sale_order_detail` 当前没有单行成本字段，可选择：

1. 给 `sale_order_detail` 增加 `cost_price`、`cost_amount`。
2. 或先只汇总到 `sale_order.cost_amount`，明细成本放到扩展字段。

推荐增加明细成本字段，便于后续统计每次寄样的产品成本构成。

```sql
ALTER TABLE hg_sale_order_detail
ADD COLUMN cost_price decimal(10,2) unsigned NOT NULL DEFAULT 0 COMMENT '成本单价',
ADD COLUMN cost_amount decimal(10,2) unsigned NOT NULL DEFAULT 0 COMMENT '成本金额';
```

## 费用类型

复用 `cost` 表记录红人营销费用。

建议扩展费用类型：

```text
红人佣金
红人合作费用
红人其他费用
```

费用记录字段使用：

```text
cost.customer_id = 红人 customer.id
cost.sale_order_id = 红人寄样订单 sale_order.id
cost.amount = 费用金额
cost.currency = 币种
cost.admin_remark = 说明
```

订单利润或营销成本统计时：

```text
红人订单总成本 = 产品成本 + 佣金 + 合作费用 + 其他费用
```

## 创建红人寄样订单流程

入口：红人详情页。

```text
红人详情
  -> 创建寄样订单
  -> 添加产品
      -> 选择已有产品
      -> 快速新建产品
      -> 选择已收到产品
  -> 填写产品成本、佣金、合作费用
  -> 保存草稿或提交审核
```

审核通过后：

```text
1. sale_order.type = 红人寄样
2. sale_order.customer_id = 红人 customer.id
3. sale_order.amount / real_amount 可为 0
4. sale_order.cost_amount 汇总产品成本和营销费用
5. 生成 sale_order_detail
6. 按现有订单逻辑生成库存锁定、发货计划或出库单
```

如果红人订单无需收款：

```text
pay_status 可直接设为无需收款或已付款
```

如果现有系统没有“无需收款”状态，建议保留 `real_amount = 0`，并在 `sale_order.type = 红人寄样` 时跳过收款校验。

## 红人订单列表

新增菜单：

```text
营销 / 红人订单
```

列表数据来自 `sale_order`，筛选：

```text
customer.type = 3
sale_order.type = 2
```

展示字段：

```text
订单号
红人名称
平台
主页
发起员工
负责人
订单状态
审核状态
发货状态
产品成本
佣金
合作费用
总成本
物流单号
创建时间
```

## 导出限制

需求明确要求：

```text
所有人不允许导出客户列表
```

针对红人客户，建议后端强制限制：

1. 红人管理页面不提供导出按钮。
2. `CustomerController` 的导出接口如果查询条件包含 `type = 3`，直接拒绝。
3. 普通客户导出默认排除 `type = 3`。
4. 如果用户通过手工构造接口参数试图导出红人客户，也必须返回错误。

示例规则：

```text
if module = customer export and query.type = 红人:
    throw EXPORT_NOT_SUPPORTED
```

如需导出红人订单，可以只允许导出订单级数据，不导出红人的联系方式、主页以外的敏感客户信息。

## 接口建议

红人客户和红人订单沿用现有接口，通过传参实现，不新增红人专用 Controller。

红人客户沿用客户接口：

```text
GET    /admin/customer/index?type=3
GET    /admin/customer/detail?id={customer_id}
POST   /admin/customer/add
POST   /admin/customer/edit
POST   /admin/customer/delete
```

创建或编辑红人客户时传入：

```text
type = 3
influencer_platform
influencer_homepage_url
influencer_account_id
influencer_fans_count
influencer_status
owner_admin_id
```

红人订单沿用销售订单接口：

```text
GET    /admin/sale-order/index?customer_type=3&type={红人寄样订单类型}
GET    /admin/sale-order/detail?id={sale_order_id}
POST   /admin/sale-order/add
POST   /admin/sale-order/edit
POST   /admin/sale-order/audit
POST   /admin/sale-order/delete
```

创建红人寄样订单时传入：

```text
customer_id = 红人 customer.id
type = 红人寄样订单类型
amount = 0
real_amount = 0
detail_list = 赠送产品明细
```

如需在红人详情页一键创建寄样订单，前端仍调用销售订单新增接口，只是预填 `customer_id`、`type`、金额、费用和明细。

## 实施步骤

1. 增加客户类型 `红人`。
2. 复用 `customer.website` 做主页地址，创建/编辑时做简单规范化比对去重。
3. 扩展现有 `sale_order.type` 枚举，增加红人寄样订单类型。
4. 视成本统计需要，给 `sale_order_detail` 增加成本字段。
5. 扩展 `cost` 类型，支持红人佣金、合作费用、其他费用。
6. 在 `Customer` 保存前增加红人主页规范化和去重。
7. 增加红人列表和详情接口，固定 `customer.type = 红人`。
8. 增加红人负责人数据权限。
9. 增加创建红人寄样订单服务，复用 `SaleOrder`。
10. 增加红人订单列表，基于 `sale_order.type = 红人寄样`。
11. 限制红人客户导出，普通客户导出默认排除红人。
12. 补充菜单、权限点和前端页面。

## 后续扩展

后续可增加红人投放效果记录：

```text
发帖链接
发帖时间
曝光量
点赞数
评论数
带来订单数
带来销售额
ROI
```

这部分可以后续新增 `customer_influencer_post` 或类似表，不影响当前红人作为 `Customer` 属性的主设计。
