petstore-docs/架构决策-身份字段拆分-2026-08-01.md

71 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 架构决策:预约与报告身份字段拆分
> 日期2026-08-01
>
> 状态:已采纳,兼容迁移期
>
> 范围Backend Core、Report Media Backend、Store Miniapp、Store Admin
## 1. 决策背景
RC1 之前,`Appointment.user_id` 同时被解释为客户或创建人;门店代客预约会把操作员工写入该字段。`Report.user_id` 实际保存技师/报告提交人,但宠主报告列表又曾把它当客户归属。两处语义冲突会污染客户档案、报告可见性、回访归因和后续经营指标。
## 2. 冻结语义
| 聚合 | 字段 | 语义 |
|---|---|---|
| Appointment | `customer_user_id` | 被服务的客户账号 |
| Appointment | `created_by_user_id` | 实际创建预约的登录账号,可为 customer/boss/staff |
| Appointment | `assigned_user_id` | 服务技师API 新增语义别名 `assignedStaffId` |
| Appointment | `user_id` | legacy 兼容字段;新数据镜像 `customer_user_id` |
| Report | `customer_user_id` | 报告归属客户,从 Appointment 派生 |
| Report | `author_staff_id` | 实际提交报告的门店账号 |
| Report | `user_id` | legacy 兼容字段;新数据镜像 `author_staff_id` |
| Report | `staff_name` | 服务技师姓名快照,优先取 Appointment.assigned_user_id |
“服务技师”和“报告作者”允许不同:老板可代员工提交报告,但报告仍展示实际服务技师。
## 3. 写入规则
### 宠主自行预约
- `customerUserId = current.userId`
- `createdByUserId = current.userId`
- 忽略请求体中的身份字段
### 门店代客预约
- `createdByUserId = current.userId`
- 必须提交 `customerUserId``customerPhone`
- 手机号不存在时创建 customer 账号;若手机号已绑定 boss/staff则拒绝静默复用
- `petId` 存在时必须属于解析出的客户
### 提交报告
- `authorStaffId = current.userId`
- `customerUserId = appointment.customerUserId`
- 服务技师继续来自 `appointment.assignedUserId`
## 4. 历史回填
迁移脚本:`backend/db/migrations/20260801_split_service_identity.sql`。
预约客户按以下证据顺序回填:
1. `pet.owner_user_id`
2. legacy `user_id` 且对应账号角色为 customer
3. 无可靠证据则保持空值,进入人工修正清单
报告客户只从关联预约回填;`report.user_id` 仅用于回填 `author_staff_id`,禁止当作客户。
## 5. 兼容与退出条件
- 兼容期继续读写 legacy `userId` / `assignedUserId`,同时输出 canonical 字段。
- 客户预约查询优先 `customer_user_id`,字段为空时回退 legacy `user_id`
- 客户报告查询通过 `report.customer_user_id` 或关联预约归属,不再按 `report.user_id` 查询。
- 只有在生产回填完成、旧客户端退出、关键指标稳定后,才可另立迁移删除 legacy 字段。
## 6. 非目标
本决策不引入多角色账号、跨店客户共享、StoreCustomer 主档、订单/支付或多门店组织;这些保持在后续独立阶段。