Files
dukang/docs/杜康好客-v4.0.20-开发文档.md
T

5.7 KiB
Raw Blame History

杜康好客 · v4.0.20 开发文档

2026-09-16 / 09-17 · promo / city-scope / store / admin-web / h5-partner / shared-types
主题:推广码渠道负责人(多选主合伙人)+ 关联合伙人(扫码 first-lock)
2026-09-17 修订:HQ 渠道负责人 / 关联合伙人下拉与表格展示为「公司(如有)-人名」


1. 版本目标

# 任务 类型 交付
1 渠道负责人 需求 HQ 创建/编辑推广码可多选主合伙人;被指定主账号在合伙人 H5 只看扫码人数、归因人数、订单数量
2 关联合伙人 需求 HQ 可单选绑定主合伙人;登录用户扫该码且尚未关联任何人时 first-lock;已关联他人静默跳过;不回刷历史

不做:把推广码改成关联码(仍用数字 scene,不复用 pa_ / sa_);回刷历史归因用户;已关联他人换绑;合伙人 H5 开放用户/订单/核销/手机号明细;历史 ownerUserId(C 端用户)迁成合伙人;子账号推广码数据入口。


2. 规则

规则事实源:杜康好客-v4-PRD.md §2.1。

flowchart TD
  scan[C端扫推广码] --> touch["POST /promo/touch"]
  touch --> scanInc[scanCount++ 未登录也计]
  touch --> login{已登录?}
  login -->|否| done[结束]
  login -->|是| attr[首次归因 UserPromoAttribution]
  attr --> src[ORGANIC 才标 PROMO_CODE 来源]
  src --> hasAssoc{码上有关联合伙人?}
  hasAssoc -->|否| done
  hasAssoc -->|是| bound{用户已有 assoc?}
  bound -->|无| lock["PartnerCityService.tryBindIfUnbound"]
  bound -->|已是同一人| skipSame[noop]
  bound -->|已是他人| skipOther[静默跳过]
  lock --> users[合伙人H5 关联用户可见]
  • 渠道负责人:可空、多选 ACTIVE 主合伙人(isPrimary=1)。只授权看三项汇总,不绑用户。
  • 关联合伙人:可空、单选 ACTIVE 主合伙人。登录 touch 后 tryBindIfUnbound:无关联则写 assoc_partner_account_id + assoc_bound_at(不写 assoc_sub_account_id、不改 sourceType、不增加关联码 assoc_scan_count);已是同一人 noop;已是他人不抛错。只绑以后扫进来的用户。
  • 两字段独立:只配渠道负责人 ≠ 绑用户;只配关联合伙人也会把用户写入该合伙人「关联用户」,并允许看三项汇总。
  • HQ 原 ownerUserId 列保留、创建/编辑不再暴露。
  • 展示:渠道负责人、关联合伙人(筛选/创建/编辑下拉、列表列、详情)统一为「公司-人名」;无公司则只显示人名。多人用顿号拼接。

3. API

3.1 HQ(promo 模块)

POST /admin/promo-codes、PUT /admin/promo-codes/:id 增加:

  • channelOwnerPartnerIds: string[](可空)
  • assocPartnerAccountId: string | null(可空;空串/null 解绑)

列表/详情返回 channelOwners[]、assocPartner(id / companyName / name / phone)。列表筛:channelOwnerPartnerId、assocPartnerAccountId。

3.2 C 端扫码

POST /promo/touch:登录后、归因与来源标记之后,若码上有 assocPartnerAccountId,调用 PartnerCityService.tryBindIfUnbound(不 import StoreModule,避免 Nest 循环依赖)。

3.3 合伙人 H5(仅主账号,PartnerPrimaryGuard)

方法 路径 返回
GET /partner/promo-codes { items: [{ id, name, code, status, scanCount, attributionCount, orderCount }] }

可见范围:当前主账号是渠道负责人 或 关联合伙人。订单数 = status=COMPLETED。禁止 HQ 的 users / metrics / timeline / 订单快链。


4. 变更面

层 路径
Prisma CommonPromoCode.assocPartnerAccountId;PromoCodeChannelOwner(promo_code_channel_owner)
迁移 server/dukang-api/prisma/migrate-promo-partner-fields.sql(Review 后生产执行)
shared-types promo.ts:PromoCodePartnerBrief、PromoCodeItem.channelOwners/assocPartner、PartnerPromoCodeItem
API promo promo-code.service.ts、dto/promo-code.dto.ts、partner-promo-code.controller.ts;PromoModule import CityScopeModule
API city-scope PartnerCityService.tryBindIfUnbound
API store PartnerAssocService.tryBindIfUnbound 转调 city-scope
admin-web PromoCodesPage.tsx、promo/PromoCodeDetailPage.tsx:渠道负责人多选 / 关联合伙人单选;去掉关联用户 ID;展示「公司-人名」(lib/promo-partner-label.ts)
h5-partner CenterPage.tsx 运营管理「推广码数据」;/center/promo-codes;PromoCodesPage.tsx
本地代理 admin/partner/shop Vite 默认 VITE_API_TARGET → http://127.0.0.1:3010(Windows 上 localhost 可能打到占用 ::3010 的其他进程)

5. 验收

  • HQ 创建/编辑推广码可多选渠道负责人、可清空单选关联合伙人;下拉与列表/详情展示「公司-人名」(无公司则人名);可按两字段筛选
  • 只配渠道负责人:扫码不写用户关联;该主账号 H5「推广码数据」能看到三项数字,点不开用户/订单/核销
  • 只配关联合伙人:未关联的登录用户扫码后出现在该合伙人「关联用户」;该主账号也能看三项汇总
  • 用户已关联他人:扫带关联合伙人的码不换绑、流程不中断、不报「无法更换」
  • 为已有码补关联合伙人:不回刷历史归因用户
  • 子账号中心无「推广码数据」入口
  • 关联码 pa_ / sa_ 行为不变;已付佣金快照不回刷
  • 执行迁移后 API 可启动(PromoModule 不得再 import StoreModule)
  • shared-types 构建通过;相关 lint 过