2.9 KiB
2.9 KiB
架构决策:预约与报告身份字段拆分
日期: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.userIdcreatedByUserId = current.userId- 忽略请求体中的身份字段
门店代客预约
createdByUserId = current.userId- 必须提交
customerUserId或customerPhone - 手机号不存在时创建 customer 账号;若手机号已绑定 boss/staff,则拒绝静默复用
petId存在时必须属于解析出的客户
提交报告
authorStaffId = current.userIdcustomerUserId = appointment.customerUserId- 服务技师继续来自
appointment.assignedUserId
4. 历史回填
迁移脚本:backend/db/migrations/20260801_split_service_identity.sql。
预约客户按以下证据顺序回填:
pet.owner_user_id- legacy
user_id且对应账号角色为 customer - 无可靠证据则保持空值,进入人工修正清单
报告客户只从关联预约回填;report.user_id 仅用于回填 author_staff_id,禁止当作客户。
5. 兼容与退出条件
- 兼容期继续读写 legacy
userId/assignedUserId,同时输出 canonical 字段。 - 客户预约查询优先
customer_user_id,字段为空时回退 legacyuser_id。 - 客户报告查询通过
report.customer_user_id或关联预约归属,不再按report.user_id查询。 - 只有在生产回填完成、旧客户端退出、关键指标稳定后,才可另立迁移删除 legacy 字段。
6. 非目标
本决策不引入多角色账号、跨店客户共享、StoreCustomer 主档、订单/支付或多门店组织;这些保持在后续独立阶段。