4bdb09068c
C 端门店列表拼接省市区县地址;门店多银行账户与默认打款账户;子账号独立 sa_ 关联码及统计维度;同步 v4.0.18 开发文档。 Co-authored-by: Cursor <cursoragent@cursor.com>
6.8 KiB
6.8 KiB
杜康好客 · 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/单测过