Files
dukang/docs/杜康好客-v4.0.18-开发文档.md
T
jacy 4bdb09068c feat(store): v4.0.18 门店多收款账户与子账号继承二维码
C 端门店列表拼接省市区县地址;门店多银行账户与默认打款账户;子账号独立 sa_ 关联码及统计维度;同步 v4.0.18 开发文档。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 15:56:16 +08:00

6.8 KiB
Raw Blame History

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

2026-09-07 · mini-user / store / settlement / iam / h5-shop / admin-web / h5-partner / shared-types
主题:C 端门店列表省市区县地址;门店多收款账户;子账号独立继承二维码


1. 版本目标

# 任务 类型 交付
1 C 端门店列表地址 需求 「省市区县 + 详细地址」拼接展示,搜索同步匹配完整地址
2 门店多银行账号 需求 门店级收款账户列表;设「默认」账户用于打款;切换无需重启
3 子账号二维码 需求 子账号独立继承码 sa_{subId};新增一级子账号维度统计

不做:银行账号历史打款回刷;子账号佣金独立归属(佣金仍归主账号);按承运商维度的收款账户。


2. 规则

2.1 门店列表地址

接口已返回 province / cityName / district / address,纯前端拼接。复用助手 fullStoreAddress(store)(province + (cityName ?? city) + district + address trim,空回退「地址待完善」),与门店详情页逻辑一致。

2.2 门店多银行账号

  • 表 store_bank_account 挂在 storeId:一门店多账户;is_default=1 为打款默认账户(每店至多一个)。
  • 迁移时按现有主账号银行字段(StoreAccount.bank_account_name/no/branch)为每店回填一条默认账户。
  • 打款/结算/提现导出统一读取默认账户(无默认则取第一个 ACTIVE;再退回旧主账号字段,兼容未迁移数据)。
  • 切换/新增/删除账户不需要重启服务器:全仓无进程内缓存,StoreAccount/PartnerAccount/FulfillmentProvider 银行字段与酒厂 system_config WINERY_BANK_* 均每次请求实时查库。唯一「改后需重启」的是微信支付商户号 WX_MCH_ID(system-config.registry.ts,requiresRestart: true),属微信支付、非银行账号。
  • 权限:门店主账号可维护本店账户(子账号只读);总部可维护任意门店账户。

2.3 子账号继承二维码

flowchart LR
  scanC[C端扫码 sa_subId] --> touch[touchScan 子账号 assocScanCount+1]
  scanC --> bind[bindUser]
  bind -->|first-lock| setAssoc[user.assocPartnerAccountId=主账号, assocSubAccountId=子账号]
  setAssoc --> main[主账号聚合统计: 关联用户/订单]
  setAssoc --> sub[子账号统计: 已扫码/已关联/订单]
  • 复用 partner_account.assoc_qrcode_id / assoc_qrcode_resource_id / assoc_scan_count:子账号行存自己的 sa_{subId} 码(assoc_qrcode_id 为 @unique,sa_ 与 pa_ 前缀、id 均不同,不冲突)。
  • 新增 user_user.assoc_sub_account_id:记录带来该用户的子账号(主账号码扫码则为空)。
  • touchScan:sa_ 场景对子账号行 assocScanCount 自增;主账号已扫码在读取时聚合 own+children。
  • bindUser:sa_ 场景解析子账号 → 主账号;first-lock 仍校验主账号,写入 assocPartnerAccountId=主账号 + assocSubAccountId=子账号。
  • getSummary/getStats/listUsers/listAssocOrders:子账号调用时返回自己维度数据(assocSubAccountId=子账号);activityPosterId 恒为空;主账号保持聚合行为不变。
  • 佣金仍归主账号,不因扫码来源为子账号而改变归属。

3. API

3.1 门店收款账户(store 模块)

方法 路径 Guard 说明
GET /shop/store/bank-accounts 门店 本店账户列表
POST /shop/store/bank-accounts 门店主账号 新增账户(首条自动默认)
PUT /shop/store/bank-accounts/:id 门店主账号 编辑账户
DELETE /shop/store/bank-accounts/:id 门店主账号 删除(默认账户不可删)
POST /shop/store/bank-accounts/:id/default 门店主账号 设为默认
GET /admin/stores/:storeId/bank-accounts HQ 指定门店账户列表
POST / PUT / DELETE / POST :id/default /admin/stores/:storeId/bank-accounts HQ 总部维护

入参:{ bankAccountName, bankAccountNo, bankBranch? };bankAccountNo 校验 ^\d{8,32}$。

3.2 关联码(store 模块)

  • POST /user/partner-assoc/touch:scene 支持 pa_{id} 与 sa_{subId};sa_ 对子账号行计数,返回 { partnerId, subAccountId, scanCounted, scanCount }。
  • POST /user/partner-assoc/bind:scene 支持 sa_;返回 { bound, alreadyBound, partnerId, subAccountId, partnerName }。
  • GET /partner/assoc(summary):子账号返回 { partnerId, primaryAccountId, isSubAccount, qrcodeUrl, userCount, scanCount }。
  • GET /partner/assoc/stats、GET /partner/assoc/users、GET /partner/assoc/orders:子账号返回自己维度。
  • GET /partner/assoc/qrcode:子账号下载自己的码。

4. 变更面

层 路径
Prisma schema.prisma(新增 StoreBankAccount;User.assocSubAccountId)
迁移 migrate-store-bank-account-v4018.sql、migrate-user-assoc-sub-account-v4018.sql
shared-types settlement.ts(StoreBankAccountDto);partner-assoc.ts(summary/touch/bind 增 subAccountId/isSubAccount)
API store store-bank.service.ts、store-bank.controller.ts(新增);store.module.ts;store-bank.util.ts(loadStoreBankAccounts/loadStoreDefaultBank);partner-assoc.service.ts(sa_ 解析/生成/touch/bind/统计)
API settlement settlement.service.ts(summary/withdraw/admin-withdrawal/export 改读默认账户)
API ops admin-redeem.service.ts(默认账户)
mini-user stores/index.tsx、lib/store-display.ts(fullStoreAddress)、lib/promo.ts(放行 sa_)
h5-shop BankAccountsPage.tsx(新增)、App.tsx、MinePage.tsx、styles.css
admin-web StoreBankAccountsPanel.tsx(新增)、StoresPage.tsx(收款账户页签)
h5-partner AssocQrcodePage.tsx、UsersManagePage.tsx(子账号提示)

5. 验收

  • C 端门店列表地址显示「省市区县 + 详细地址」;空值回退「地址待完善」;搜索「省/市/区县」关键词可命中
  • 门店可新增/编辑/删除/设默认收款账户;默认账户用于提现打款与账单导出
  • 切换默认账户后(无需重启)提现 summary 与打款信息即时生效
  • 子账号可生成并下载自己的二维码(scene sa_{subId}),与主账号 pa_{id} 不冲突
  • 扫子账号码:用户仍锁定主账号(佣金归主账号),并写入 assoc_sub_account_id
  • 子账号用户管理/关联码页展示自己维度的已扫码/已关联/订单统计;主账号聚合 own+children 不变
  • 主账号码扫码:assoc_sub_account_id 为空,行为与 v4.0.9 一致
  • shared-types 构建通过;相关 lint/单测过