liuyun 2792dc7e34 chore(openspec): 归档 C4 质控闸门 change
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-15 07:25:19 +08:00

144 lines
7.9 KiB
Markdown
Raw Permalink 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.

# shared/data-model Specification
## Purpose
定义服务机构端 C0 的数据模型字段字典——机构/人员/服务目录四层/字典/属地配置的实体、字段、枚举与多租户键约定,作为前后端字段命名的唯一锚点。
## Requirements
### Requirement: 多租户键约定
服务机构端所有业务实体 MUST 携带 `tenant_code` 字段作为多租户隔离键,其值为机构唯一标识(= 脚手架租户 code)。
#### Scenario: 跨机构隔离
- **WHEN** 业务表写入一条记录
- **THEN** 该记录 MUST 带 `tenant_code`,且读操作按当前租户自动过滤,不返回其他租户数据
### Requirement: 机构实体 org
`org` 表 MUST 存在,主键为机构 code(与 `tenant_code` 同值),承载机构业务字段:org_name、org_type、credit_code、loc_code、loc_name、svc_source、license_no、address、contact_name、contact_phone、bed_count、sign_date。
#### Scenario: 机构唯一标识
- **WHEN** 创建一个机构
- **THEN** 其 code 与脚手架的 tenant code 一致且全局唯一
### Requirement: 人员实体 staff
`staff` 表 MUST 存在,承载人员/资质字段(name、id_card_no、phone、job_type、work_type、employ_status、cert_type/cert_no/cert_level/cert_expire/cert_status、group_leader_id),并 MUST 带 `user_id` 关联脚手架 `user.id`(可空、1:1)。
#### Scenario: 账号关联人员
- **WHEN** 护理员登录并定位本人 staff
- **THEN** 通过 `staff.user_id = user.id` 唯一定位到一条 staff 记录
### Requirement: 软删约定
服务机构端业务实体 MUST 采用脚手架 `deleted_at`(时间戳)软删,不物理删除。
#### Scenario: 软删保留
- **WHEN** 删除一条业务记录
- **THEN** 记录置 `deleted_at`,读操作默认排除,物理数据保留
### Requirement: 主键约定
业务实体主键 MUST 采用脚手架 UUID v7;业务码(机构 code、项目代码)MUST 建唯一索引。
#### Scenario: 主键唯一
- **WHEN** 新增业务记录
- **THEN** 生成 UUID v7 主键,业务码唯一索引防重复
### Requirement: 目录四层实体
`svc_national`(L1)、`svc_local`(L2)、`svc_mapping`(L3)、`svc_org`(L4) 四表 MUST 存在,字段按 PRD §7.2 定义;L3 映射表不提供机构侧接口。
#### Scenario: 目录分层
- **WHEN** 加载某机构属地目录
- **THEN** 按 L1/L2 取目录、L4 取机构勾选与配价、L3 仅内部映射
### Requirement: 字典与属地配置实体
`dict_abnormal_type`、`dict_photo_tier`、`loc_config` 三表 MUST 存在,承载异常分类、拍照分档、属地目录来源与项数规则配置。
#### Scenario: 属地配置驱动目录
- **WHEN** 新增一个州市
- **THEN** 插入一条 `loc_config` + 一批 `svc_local` 即生效,无需改代码
### Requirement: 老人档案实体 elder
`elder` 表 MUST 存在,承载老人档案字段(tenant_code、loc_code、name、gender、birth_date、id_card_no、insur_no/type、assess_level/care_level、assess_date/org、assess_evidence_file、benefit_start/end、treat_status、hosp_start/end、note 等),主键 UUID v7,`tenant_code` 多租户隔离,`tenant_code + id_card_no` 唯一。
#### Scenario: 老人档案归属机构
- **WHEN** 创建一条老人档案
- **THEN** 带 tenant_code,读操作按当前租户自动过滤
#### Scenario: 同机构身份证唯一
- **WHEN** 同机构重复录入同一 id_card_no
- **THEN** 命中唯一约束,提示「已有档案」
### Requirement: 待遇状态日志实体 elder_status_log
`elder_status_log` 表 MUST 存在;每次待遇状态变更 MUST 写一条日志,含 from_status/to_status/change_reason(必填)/operator_id/changed_at。
#### Scenario: 状态变更留痕
- **WHEN** 变更老人待遇状态
- **THEN** 写入一条 elder_status_log,change_reason 非空
### Requirement: 服务计划实体 svc_plan / svc_plan_item
`svc_plan` 表 MUST 存在(plan_period_start/end、care_level、care_mode、item_count、item_count_rule、plan_status、change_from_plan_id 等);`svc_plan_item` MUST 存在(svc_id 引 L4、svc_name_snapshot、freq_type/value、duration_min、photo_tier、caution_note 等)。计划变更 MUST 新建 + change_from_plan_id 指向旧计划,不原地改。
#### Scenario: 计划变更留旧版
- **WHEN** 变更某老人的服务计划
- **THEN** 生成新计划并指向旧计划,旧计划保留
### Requirement: 工单实体 svc_order
`svc_order` 表 MUST 存在(plan_id、service_date、time_slot_start/end、assignee_id、order_status、item_list(json)、reschedule_log(json)、not_met_reason/at 等)。
#### Scenario: 工单关联计划
- **WHEN** 生成一张工单
- **THEN** 工单带 plan_id,item_list 为计划项目快照
### Requirement: 老人个人项目库实体 ltc_elder_svc
`ltc_elder_svc` 表 MUST 存在(elder_id、svc_id 引 L4、svc_name_snapshot、care_mode、is_active),一人一份;svc_id 必须落在本机构 L4。
#### Scenario: 项目只能从 L4 选
- **WHEN** 保存个人项目库
- **THEN** svc_id 必须在本机构 svc_org 内,否则拒绝
### Requirement: 履约留痕实体 ho_record
`ho_record` 表 MUST 存在(order_id、elder_id、assignee_id、checkin_time、checkout_time、duration_min、checkin_lat/lng、locate_status、record_status、voice_file、offline_flag、client_md5、submit_time、actual_duration_tier、biz_line、is_prepaid、billable、source_prepaid_of)。`record_status` MUST ∈ {serving, submitted}(returned/passed 留 C4)。签到签退时间与时长由系统生成,不接受客户端传入。
#### Scenario: 留痕关联有效工单
- **WHEN** 创建一条留痕
- **THEN** 必须带 order_id 且工单有效(L3 硬锁)
### Requirement: 留痕项目明细 ho_record_item
`ho_record_item` 表 MUST 存在(record_id、svc_id 引 L4、svc_name_snapshot、exec_result、undo_reason、extra_flag、photo_required、is_refused_photo、refuse_reason)。`exec_result` MUST ∈ {done, undo_not_done, undo_refused}。
#### Scenario: 项目只能从 L4 选
- **WHEN** 保存留痕项目
- **THEN** svc_id 必须在本机构 svc_org 内,否则拒绝
### Requirement: 留痕照片 ho_record_photo
`ho_record_photo` 表 MUST 存在(record_id、svc_id、file_path、file_size、visible_to_family、upload_batch、keep_until)。`visible_to_family` 本期恒 0;文件压缩后 ≤500KB。
#### Scenario: 家属端不可见
- **WHEN** 上传留痕照片
- **THEN** visible_to_family = 0
### Requirement: 异常上报 ho_record_abnormal
`ho_record_abnormal` 表 MUST 存在(record_id 可空、order_id 可空、elder_id、reporter_id、abnormal_type、abnormal_desc、voice_file、has_photo、notify_status、handle_status、handle_result、link_plan_change)。`abnormal_type` MUST 必填,其余可选。
#### Scenario: 扑空无留痕
- **WHEN** 登记未遇(扑空)
- **THEN** record_id 为空、order_id 指向工单、abnormal_type 为扑空分类
### Requirement: 二期预留表 settlement / report
`settlement`/`report` 表 MUST 建空表不写业务数据(settlement 含 amount_fund/amount_self_pay 个人自付拆分字段)。
#### Scenario: 预留表空建
- **WHEN** 迁移完成后
- **THEN** settlement/report 表存在且无业务数据
### Requirement: 质控记录实体 qc
`qc` 表 MUST 存在(record_id、qc_type、push_reason、qc_result、qc_note、qc_staff_id、qc_time、pass_time、first_qc_id)。`qc_result` MUST ∈ {pending, passed, returned};退回时 `qc_note` 必填;recheck 时 `first_qc_id` 指向首次 qc。
#### Scenario: 全量生成
- **WHEN** 一条留痕 submitted 且无 qc 记录
- **THEN** 定时任务生成一条 qc(qc_result=pending)
### Requirement: 补正实体 ho_record_correction
`ho_record_correction` 表 MUST 存在(record_id、qc_id、correction_note、corrected_by、corrected_at)。补正 MUST 新增说明、不直接改原记录。
#### Scenario: 补正留痕
- **WHEN** 退回后护理员补正
- **THEN** 写一条更正说明,原记录保留不动