Record agreed model for mother/father/child customer IDs on protocol parties, save-time sync, id-card merge, and customer detail relations. Co-authored-by: Cursor <cursoragent@cursor.com>
8.9 KiB
客户管理 · 协议家庭成员关联设计
日期:2026-10-07
状态:已确认(2026-10-07)
范围:市场基础信息「客户管理」+ 细胞存储采集协议单 + 科研捐赠协议单
1. 背景
biz_customer 是独立客户主数据。采集协议保存时,目前只把母亲同步进客户表,并写到当事人表唯一的 customer_id。父亲、子女姓名等信息只存在当事人子表字段上,没有客户 ID。客户详情只展示本人字段,看不到同协议其他人和关联协议。
产品要求:
- 母亲、父亲、子女只要有姓名即可写入客户管理(有证、无证均可)。
- 同一张协议上的三人通过协议当事人上的三个客户 ID 关联。
- 点开任一客户详情:上方按协议看同单其他人,下方看关联协议摘要;点协议号弹出协议只读详情。
- 一人可对应多张协议,详情按协议分组列出。
- 细胞存储与科研捐赠一起做。
2. 目标与非目标
2.1 目标
- 当事人表增加父亲、子女客户 ID;母亲继续用已有
customer_id。 - 保存细胞存储 / 科研捐赠协议时,对本单三个角色走同一套 upsert 同步(仅当前协议,不全库)。
- 上线跑一次幂等迁移,把存量当事人补建客户并回写 ID;之后保存继续同步。
- 补身份证撞到已有客户时:合并有用字段 → 全部引用改挂 → 软删临时客户。
- 客户详情提供「关联客户」「关联协议」;点协议号打开对应查看弹窗。
2.2 非目标
- 不新建「协议–客户–角色」关系表。
- 不把客户管理改成协议列表的派生视图。
- 不在客户详情内嵌完整协议表单,只弹现有只读查看。
- 不自动因协议软删而删除客户。
- 不把客户管理里的手工改名回写到协议当事人字段。
- 本期不改中试申请患者 ↔ 客户逻辑。
3. 数据模型
不改 biz_customer 结构。扩展两张当事人表:
3.1 biz_protocol_party_customer
| 字段 | 说明 |
|---|---|
customer_id |
已有,母亲客户 ID |
father_customer_id |
新增 VARCHAR(64) NULL,父亲客户 ID |
newborn_customer_id |
新增 VARCHAR(64) NULL,子女客户 ID |
3.2 biz_research_donation_party
同样增加 father_customer_id、newborn_customer_id;已有 customer_id 仍表示母亲。
不把 customer_id 改名为 mother_customer_id,避免无谓迁移;代码与 API 注释写明「母亲」。
SQL 放在 docs/sql/migrations/(例如 2026-10-07-party-father-newborn-customer-id.sql),并同步 SQLAlchemy 模型。
关联约定:同一行上的三个 ID 即同一协议家庭;查询某客户相关协议时:
customer_id = :id
OR father_customer_id = :id
OR newborn_customer_id = :id
细胞存储与科研捐赠各查一次,按租户、del_flag=0 过滤。
4. 同步规则(保存当前协议)
抽公共函数(建议 backend/app/services/party_customer_sync.py),细胞存储与科研捐赠保存当事人时调用。范围仅当前这一张协议的三个角色。
每个角色(母亲 / 父亲 / 子女)独立处理:
- 无姓名:不同步客户;该角色客户 ID 置空(不删已有
biz_customer记录)。 - 有姓名、无身份证:新建客户,回写本单对应客户 ID。不按姓名去重(允许重名)。
- 有姓名、有身份证:同租户未删除客户中按身份证查找(排除软删)。
- 未找到:若本单该角色已有客户 ID,则不换 ID,把身份证等写到该客户;若无客户 ID,则新建并回写。
- 找到且就是本单已挂的客户:更新该客户可写字段(姓名、电话等按下方合并策略)。
- 找到且是另一条客户:进入第 5 节合并改挂。
性别默认:母亲 1,父亲 0,子女用当事人 newborn_sex,缺省 2。
年龄:能从身份证推算则写入,否则空。
协议当事人上的母亲/父亲/子女姓名电话等业务字段仍照旧写入子表,客户表只存客户主数据字段。
5. 补身份证撞库:合并后软删
当本单某角色「当前挂着的客户 A」与「身份证已存在的客户 B」且 A.id != B.id:
- 把 A 的有用信息合并进 B:
phone_no、age、sex(仅当目标为空或未知2时用源值)、remark:目标为空才补,不覆盖已有。customer_tags:按逗号拆开后做并集再写回 B。customer_name:保留 B(身份证命中的已有客户为准)。
- 将细胞存储当事人、科研捐赠当事人中,三个客户 ID 字段里所有等于 A 的值,改为 B(避免 A 仍被其它协议引用)。
- 本单该角色 ID 写为 B。
- 软删 A(
del_flag=1)。 - 客户管理列表默认不展示 A。
若身份证不撞库:不换 ID,只更新当前客户。
6. 存量迁移
上线脚本(Python 或 SQL + 服务函数均可,须幂等):
- 扫描未删除的
biz_protocol_party_customer、biz_research_donation_party。 - 对已有角色姓名、却缺少对应客户 ID 的记录,调用与保存相同的同步函数。
- 已有正确客户 ID 的跳过。
- 可重复执行,结果一致。
之后日常只在保存当前协议时同步,不再全库重跑。
7. 客户详情
7.1 界面
客户管理查看弹窗自上而下:
- 基本信息:现有字段不变。
- 关联客户:按该客户出现过的协议分组(协议
create_time倒序)。每组展示:- 类型(细胞存储 / 科研捐赠)、协议号、本客户角色(母亲 / 父亲 / 子女)
- 同单已填角色(含本人,标记「本人」):角色、姓名、电话、身份证;非本人点姓名打开对方客户详情
- 未填角色不展示
- 关联协议:摘要列表字段:协议号、类型、状态、日期、本客户角色。
日期:细胞存储用register_date,科研捐赠用donation_date,接口统一字段名registerDate。
点击协议号弹出只读详情:- 细胞存储 →
ProtocolViewDialog - 科研捐赠 →
DonationViewDialog
- 细胞存储 →
无关联协议时,关联客户、关联协议区块展示空态文案。
7.2 API
GET /api/admin/customers/{id}/relations(需客户查看权限,租户隔离):
{
customer: { ...与客户详情一致 },
relatedGroups: [
{
bizType, // cell_storage | research_donation
protocolId,
protocolNo, // 细胞存储 protocol_no;科研捐赠 donation_no
protocolStatus, // protocol_status / donation_status
registerDate, // register_date / donation_date
myRole, // mother | father | newborn
members: [
{ role, customerId, name, phone, idCardNo }
]
}
],
protocols: [
{ bizType, protocolId, protocolNo, protocolStatus, registerDate, myRole }
]
}
relatedGroups 与 protocols 同源:每张相关协议一组;members 含本客户及同单其他人(有客户 ID 或至少有姓名的角色)。protocols 便于下方摘要表直接绑定。
打开协议详情:前端复用现有协议/捐赠详情接口与弹窗。无对应协议查看权限时:协议号不可点或点击后提示无权限(与现有权限码一致,不新造权限)。
8. 列表与其它入口
- 客户列表仍是
biz_customer全量未删除记录;父亲、子女会出现为独立行。 - 协议表单「选择客户」仍选自
biz_customer;保存后按第 4 节回写三个 ID。 - 客户管理手工新增/编辑/删除行为不变;删除客户不级联改协议(协议上可能留下已删 ID;详情关联客户对该 ID 显示姓名占位或「客户已删除」)。
9. 测试要点
- 无证三人保存 → 客户表 3 条,当事人三个 ID 均有值。
- 后补子女身份证撞已有客户 → 字段合并、所有引用改挂、临时户软删、详情指向 B。
- 后补身份证不撞库 → 客户 ID 不变,身份证写到原客户。
- 同一母亲两张协议 → 详情两组关联客户 + 两条协议摘要。
- 点协议号分别打开细胞存储 / 科研捐赠只读弹窗。
- 仅填母亲 → 只同步母亲;关联客户组内无父/子女行。
- 迁移脚本跑两遍结果一致。
- 科研捐赠保存与细胞存储同一套规则。
10. 已确认决策
| 项 | 结论 |
|---|---|
| 关联落点 | 当事人表三个客户 ID,不新建关系表 |
| 母亲 ID | 沿用已有 customer_id |
| 业务范围 | 细胞存储 + 科研捐赠 |
| 无证 | 有姓名即可建客户 |
| 补证撞库 | 合并后软删临时客户,协议改挂已有客户 |
| 存量 | 上线全量脚本 + 之后仅保存当前单时同步 |
| 详情布局 | 上:按协议分组的关联客户;下:协议摘要;点协议号弹详情 |
| 中试 | 本期不动 |