diff --git a/openspec/changes/svc-org-c1-elder/.openspec.yaml b/openspec/changes/archive/2026-10-15-svc-org-c1-elder/.openspec.yaml similarity index 100% rename from openspec/changes/svc-org-c1-elder/.openspec.yaml rename to openspec/changes/archive/2026-10-15-svc-org-c1-elder/.openspec.yaml diff --git a/openspec/changes/svc-org-c1-elder/design.md b/openspec/changes/archive/2026-10-15-svc-org-c1-elder/design.md similarity index 100% rename from openspec/changes/svc-org-c1-elder/design.md rename to openspec/changes/archive/2026-10-15-svc-org-c1-elder/design.md diff --git a/openspec/changes/svc-org-c1-elder/proposal.md b/openspec/changes/archive/2026-10-15-svc-org-c1-elder/proposal.md similarity index 100% rename from openspec/changes/svc-org-c1-elder/proposal.md rename to openspec/changes/archive/2026-10-15-svc-org-c1-elder/proposal.md diff --git a/openspec/changes/svc-org-c1-elder/specs/backend/elder/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c1-elder/specs/backend/elder/spec.md similarity index 100% rename from openspec/changes/svc-org-c1-elder/specs/backend/elder/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c1-elder/specs/backend/elder/spec.md diff --git a/openspec/changes/svc-org-c1-elder/specs/frontend/ad/elder/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c1-elder/specs/frontend/ad/elder/spec.md similarity index 100% rename from openspec/changes/svc-org-c1-elder/specs/frontend/ad/elder/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c1-elder/specs/frontend/ad/elder/spec.md diff --git a/openspec/changes/svc-org-c1-elder/specs/shared/api-contract/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c1-elder/specs/shared/api-contract/spec.md similarity index 100% rename from openspec/changes/svc-org-c1-elder/specs/shared/api-contract/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c1-elder/specs/shared/api-contract/spec.md diff --git a/openspec/changes/svc-org-c1-elder/specs/shared/data-model/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c1-elder/specs/shared/data-model/spec.md similarity index 100% rename from openspec/changes/svc-org-c1-elder/specs/shared/data-model/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c1-elder/specs/shared/data-model/spec.md diff --git a/openspec/changes/svc-org-c1-elder/tasks.md b/openspec/changes/archive/2026-10-15-svc-org-c1-elder/tasks.md similarity index 100% rename from openspec/changes/svc-org-c1-elder/tasks.md rename to openspec/changes/archive/2026-10-15-svc-org-c1-elder/tasks.md diff --git a/openspec/changes/svc-org-c2-plan-order/.openspec.yaml b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/.openspec.yaml similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/.openspec.yaml rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/.openspec.yaml diff --git a/openspec/changes/svc-org-c2-plan-order/design.md b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/design.md similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/design.md rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/design.md diff --git a/openspec/changes/svc-org-c2-plan-order/proposal.md b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/proposal.md similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/proposal.md rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/proposal.md diff --git a/openspec/changes/svc-org-c2-plan-order/specs/backend/order/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/backend/order/spec.md similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/specs/backend/order/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/backend/order/spec.md diff --git a/openspec/changes/svc-org-c2-plan-order/specs/backend/plan/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/backend/plan/spec.md similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/specs/backend/plan/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/backend/plan/spec.md diff --git a/openspec/changes/svc-org-c2-plan-order/specs/frontend/ad/schedule/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/frontend/ad/schedule/spec.md similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/specs/frontend/ad/schedule/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/frontend/ad/schedule/spec.md diff --git a/openspec/changes/svc-org-c2-plan-order/specs/shared/api-contract/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/shared/api-contract/spec.md similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/specs/shared/api-contract/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/shared/api-contract/spec.md diff --git a/openspec/changes/svc-org-c2-plan-order/specs/shared/data-model/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/shared/data-model/spec.md similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/specs/shared/data-model/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/specs/shared/data-model/spec.md diff --git a/openspec/changes/svc-org-c2-plan-order/tasks.md b/openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/tasks.md similarity index 100% rename from openspec/changes/svc-org-c2-plan-order/tasks.md rename to openspec/changes/archive/2026-10-15-svc-org-c2-plan-order/tasks.md diff --git a/openspec/changes/svc-org-c3-record/.openspec.yaml b/openspec/changes/archive/2026-10-15-svc-org-c3-record/.openspec.yaml similarity index 100% rename from openspec/changes/svc-org-c3-record/.openspec.yaml rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/.openspec.yaml diff --git a/openspec/changes/svc-org-c3-record/design.md b/openspec/changes/archive/2026-10-15-svc-org-c3-record/design.md similarity index 100% rename from openspec/changes/svc-org-c3-record/design.md rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/design.md diff --git a/openspec/changes/svc-org-c3-record/proposal.md b/openspec/changes/archive/2026-10-15-svc-org-c3-record/proposal.md similarity index 100% rename from openspec/changes/svc-org-c3-record/proposal.md rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/proposal.md diff --git a/openspec/changes/svc-org-c3-record/specs/backend/abnormal/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/backend/abnormal/spec.md similarity index 100% rename from openspec/changes/svc-org-c3-record/specs/backend/abnormal/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/backend/abnormal/spec.md diff --git a/openspec/changes/svc-org-c3-record/specs/backend/record/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/backend/record/spec.md similarity index 100% rename from openspec/changes/svc-org-c3-record/specs/backend/record/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/backend/record/spec.md diff --git a/openspec/changes/svc-org-c3-record/specs/frontend/ad/record/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/frontend/ad/record/spec.md similarity index 100% rename from openspec/changes/svc-org-c3-record/specs/frontend/ad/record/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/frontend/ad/record/spec.md diff --git a/openspec/changes/svc-org-c3-record/specs/shared/api-contract/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/shared/api-contract/spec.md similarity index 100% rename from openspec/changes/svc-org-c3-record/specs/shared/api-contract/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/shared/api-contract/spec.md diff --git a/openspec/changes/svc-org-c3-record/specs/shared/data-model/spec.md b/openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/shared/data-model/spec.md similarity index 100% rename from openspec/changes/svc-org-c3-record/specs/shared/data-model/spec.md rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/specs/shared/data-model/spec.md diff --git a/openspec/changes/svc-org-c3-record/tasks.md b/openspec/changes/archive/2026-10-15-svc-org-c3-record/tasks.md similarity index 100% rename from openspec/changes/svc-org-c3-record/tasks.md rename to openspec/changes/archive/2026-10-15-svc-org-c3-record/tasks.md diff --git a/openspec/specs/backend/abnormal/spec.md b/openspec/specs/backend/abnormal/spec.md new file mode 100644 index 0000000..68f5e4d --- /dev/null +++ b/openspec/specs/backend/abnormal/spec.md @@ -0,0 +1,27 @@ +# backend/abnormal Specification + +## Purpose +定义服务机构端异常上报域的后端行为——异常上报(9 宫格)与扑空(未遇)专门形态。 + +## Requirements + +### Requirement: 异常上报 +`POST /abnormal/report` MUST 仅 abnormal_type 必选,其余(desc/voice/photo/关联)可选;关联 record 或 order(扑空)。 + +#### Scenario: 分类必选其余可选 +- **WHEN** 上报异常只选分类、其余留空 +- **THEN** 允许提交(宁要一条没人名的异常也不要漏报) + +### Requirement: 扑空专门形态 +扑空(未遇)MUST:工单转 not_met(not_met_reason/not_met_at)+ 写 record_abnormal(到访时间/定位/原因必留);不产生 record、不计费。与「逾期未做」(到点无记录)严格区分。 + +#### Scenario: 扑空留证据 +- **WHEN** 护理员登记未遇(老人不在/拒绝/改期) +- **THEN** 到访时间+定位+原因必留,工单转 not_met,不产生服务记录 + +### Requirement: 异常列表 +`GET /abnormal/list` MUST 返回异常列表(后台 B4),按 abnormal_type/notify_status/handle_status/老人 筛选。 + +#### Scenario: 质控查看异常 +- **WHEN** 质控员打开异常列表 +- **THEN** 看到异常分类、状态、关联老人 diff --git a/openspec/specs/backend/elder/spec.md b/openspec/specs/backend/elder/spec.md new file mode 100644 index 0000000..f29aee1 --- /dev/null +++ b/openspec/specs/backend/elder/spec.md @@ -0,0 +1,41 @@ +# backend/elder Specification + +## Purpose +定义服务机构端待遇档案(elder)域的后端行为——老人建档、十态状态机、评估结论承载、身份证防重与掩码。 + +## Requirements + +### Requirement: 老人建档 +`POST /elder` MUST 校验身份证 18 位+校验位、出生日期由身份证带出、同机构 id_card_no 唯一、待遇止 > 起;建档后按待遇有效期置初始状态(active 或 waiting_period)。 + +#### Scenario: 身份证防重 +- **WHEN** 同机构重复录入同一 id_card_no +- **THEN** 提示「已有档案」,不创建重复档案 + +### Requirement: 等级唯一来源 +建档时 assess_level/care_level MUST 绑定评估结论副本(assess_evidence_file):有等级必须有副本,否则拒绝(ELDER_LEVEL_REQUIRES_EVIDENCE)。 + +#### Scenario: 等级绑定副本 +- **WHEN** 建档请求携带 assess_level 但无 assess_evidence_file +- **THEN** 拒绝并返回 ELDER_LEVEL_REQUIRES_EVIDENCE + +### Requirement: 十态状态机 +`elder.treat_status` MUST 支持十态;状态变更 MUST 写 elder_status_log 且 change_reason 必填。 + +#### Scenario: 状态变更留痕 +- **WHEN** 变更状态缺 change_reason +- **THEN** 拒绝并返回校验错误 + +### Requirement: 评估结论副本上传 +`POST /elder/assess-evidence` MUST 上传文件到 MinIO 并返回 file key。 + +#### Scenario: 上传成功 +- **WHEN** 上传评估结论副本 +- **THEN** 返回 file key,供建档引用 + +### Requirement: 身份证明文查看留痕 +仅 admin/qc 可查看身份证明文,且每次明文查看 MUST 落审计。 + +#### Scenario: 明文查看留痕 +- **WHEN** qc 查看老人身份证明文 +- **THEN** 写一条审计日志 diff --git a/openspec/specs/backend/order/spec.md b/openspec/specs/backend/order/spec.md new file mode 100644 index 0000000..0a9ed5c --- /dev/null +++ b/openspec/specs/backend/order/spec.md @@ -0,0 +1,34 @@ +# backend/order Specification + +## Purpose +定义服务机构端工单域的后端行为——八态工单、派单/调单/取消、时间冲突硬拦、批量推荐。 + +## Requirements + +### Requirement: 派单前置校验 +`POST /order/assign` MUST 按序校验:工单态 → 老人态(treat_status ∈ {active, waiting_period},否则 1001)→ 有计划(否则 1002)→ 护理员当班 → 时间冲突(2001 硬拦)→ 资质(1006 提示)。 + +#### Scenario: 无有效待遇不可派单 +- **WHEN** 派单时老人 treat_status 非 active/waiting_period +- **THEN** 返回 1001 拒绝 + +### Requirement: 时间冲突硬拦 +同 assignee_id 且 time_slot 重叠 MUST 拒绝(2001)。 + +#### Scenario: 同时段重叠 +- **WHEN** 同一护理员已有 09:00-10:00 工单,再派 09:30-10:30 +- **THEN** 返回 2001,拒绝保存 + +### Requirement: 调单与批量推荐 +`POST /order/:id/reassign` MUST 记 reschedule_log(改前改后/时间/操作人);`GET /order/batch-recommend` MUST 只返回推荐(权重:同资质→历史服务过→距离近→负荷低),不自动派单。 + +#### Scenario: 调单留痕 +- **WHEN** 调单改派护理员 +- **THEN** 写 reschedule_log 并通知新护理员 + +### Requirement: 工单八态 +order_status MUST 支持 to_assign/assigned/serving/done/abnormal/cancelled/overdue/not_met;取消必填 cancel_reason。 + +#### Scenario: 取消需原因 +- **WHEN** 取消工单缺 cancel_reason +- **THEN** 拒绝 diff --git a/openspec/specs/backend/plan/spec.md b/openspec/specs/backend/plan/spec.md new file mode 100644 index 0000000..cacef9d --- /dev/null +++ b/openspec/specs/backend/plan/spec.md @@ -0,0 +1,27 @@ +# backend/plan Specification + +## Purpose +定义服务机构端服务计划与老人个人项目库的后端行为——制定/变更计划、属地项数校验、个人项目库带入。 + +## Requirements + +### Requirement: 制定服务计划 +`POST /plan` MUST 校验:老人存在、项目从本机构 L4 选、属地项数(昆明校验/州市提示)、care_mode×care_level 规则。plan_status 置 active。 + +#### Scenario: 制定计划 +- **WHEN** 质控员制定计划并选够项目 +- **THEN** 创建 active 计划,item_count 与 item_count_rule 快照记录 + +### Requirement: 计划变更不原地改 +`POST /plan/change` MUST 新建计划 + change_from_plan_id 指向旧计划,旧计划转 changed。 + +#### Scenario: 变更留旧版 +- **WHEN** 变更计划 +- **THEN** 旧计划转 changed、新计划 active,历史工单仍指向旧计划 + +### Requirement: 老人个人项目库 +`PUT /elder-svc/:elderId` MUST 整表覆盖(svc_id 必须落在本机构 L4、care_mode 变更=重制、旧库留档);制定计划可一键带入。 + +#### Scenario: 带入计划 +- **WHEN** 制定计划时选择「从个人项目库带入」 +- **THEN** 自动生成 plan_item 初稿,可修改 diff --git a/openspec/specs/backend/record/spec.md b/openspec/specs/backend/record/spec.md new file mode 100644 index 0000000..7d7a105 --- /dev/null +++ b/openspec/specs/backend/record/spec.md @@ -0,0 +1,63 @@ +# backend/record Specification + +## Purpose +定义服务机构端履约留痕域的后端行为——签到/签退/项目执行/照片/离线补传/垫付台账与结转。 + +## Requirements + +### Requirement: 签到 +`POST /record/checkin` MUST 校验 L3(order 存在、order_status ∈ {assigned, serving}、elder/assignee 匹配);checkin_time 服务器取时(不接受客户端传入);定位失败 3002 不阻塞(locate_status=failed/denied);建 record(serving)并返回 record_id。 + +#### Scenario: 服务器取时 +- **WHEN** 签到 +- **THEN** checkin_time 由服务端生成,客户端传入被忽略 + +#### Scenario: 定位失败不阻塞 +- **WHEN** 签到但定位失败 +- **THEN** 标记 locate_status=failed,照常提交(3002) + +### Requirement: 签退提交 +`POST /record/checkout` MUST 校验必拍未拍(3001 硬拒 + 拒拍出路 is_refused_photo=1);checkout_time/duration_min 服务器取时;record_status 转 submitted;waiting_period 老人 is_prepaid=1、billable=0(3004 仅标记)。 + +#### Scenario: 必拍未拍硬拒 +- **WHEN** 必拍项未拍照且未走拒拍出路 +- **THEN** 返回 3001 拒绝签退 + +#### Scenario: 垫付标记 +- **WHEN** 等待期老人签退 +- **THEN** record.is_prepaid=1、billable=0,不计费 + +### Requirement: 项目执行 +`POST /record/item/save` MUST exec_result ∈ {done, undo_not_done, undo_refused};svc_id 落本机构 L4;photo_required 快照自 order.item_list。 + +#### Scenario: 措辞纪律 +- **WHEN** 项目未执行 +- **THEN** exec_result 用 undo_not_done(非 not_done) + +### Requirement: 照片上传 +`POST /record/photo/upload` MUST 校验文件 ≤500KB;visible_to_family=0;keep_until 补传后 ≥7 天。 + +#### Scenario: 超限拒绝 +- **WHEN** 上传超过 500KB 的照片 +- **THEN** 拒绝并提示压缩 + +### Requirement: 离线补传 +`POST /record/offline/sync` MUST 按 client_md5 幂等去重(重复提交返回已存在,静默不弹窗)。 + +#### Scenario: 去重 +- **WHEN** 同 client_md5 重复补传 +- **THEN** 幂等返回,不重复落库 + +### Requirement: 垫付台账与结转 +`waiting_period` 老人留痕 MUST `is_prepaid=1`、`billable=0`;`POST /record/prepaid/carryover` MUST 勾选若干 is_prepaid=1 记录 → 生成对应正式记录(复制、is_prepaid=0、source_prepaid_of=原 id),原记录保留只读、不改原始时间戳(签到时间/定位/照片仍是原始值)。 + +#### Scenario: 结转不改原始时间戳 +- **WHEN** 结转垫付记录 +- **THEN** 新记录签到时间/定位/照片仍为原始值,仅标记来源 + +### Requirement: 留痕列表与详情 +`GET /record/list`(admin B3,按 elder/assignee/日期/状态筛选)与 `GET /record/detail` MUST 返回留痕列表/详情(含项目、照片、异常、定位、垫付标记)。 + +#### Scenario: 质控查看留痕 +- **WHEN** 质控员查询留痕列表与详情 +- **THEN** 返回时间/项目/照片/异常/定位/垫付标记 diff --git a/openspec/specs/frontend/ad/elder/spec.md b/openspec/specs/frontend/ad/elder/spec.md new file mode 100644 index 0000000..b5a9ce4 --- /dev/null +++ b/openspec/specs/frontend/ad/elder/spec.md @@ -0,0 +1,27 @@ +# frontend/ad/elder Specification + +## Purpose +定义服务机构端「服务对象」页面——老人档案列表、建档表单、详情与状态变更的交互。 + +## Requirements + +### Requirement: 服务对象列表 +列表 MUST 显示姓名/护理等级(带「(最高级)」)/状态/计划/下次服务,支持状态筛选。 + +#### Scenario: 状态筛选 +- **WHEN** 按「住院暂停」筛选 +- **THEN** 只显示该状态的老人 + +### Requirement: 建档表单 +建档表单 MUST 含身份证校验、出生日期自动带出、参保地默认取机构属地、参保核验字段、评估结论副本上传与等级录入(等级必须绑定评估结论副本)。 + +#### Scenario: 等级绑定副本 +- **WHEN** 填了等级但未上传评估结论副本 +- **THEN** 拦截提交,提示先上传副本 + +### Requirement: 状态变更 +详情页 MUST 支持十态状态变更(原因必填)+ 状态日志时间线。 + +#### Scenario: 变更需原因 +- **WHEN** 变更状态未填原因 +- **THEN** 不允许提交 diff --git a/openspec/specs/frontend/ad/record/spec.md b/openspec/specs/frontend/ad/record/spec.md new file mode 100644 index 0000000..492653d --- /dev/null +++ b/openspec/specs/frontend/ad/record/spec.md @@ -0,0 +1,27 @@ +# frontend/ad/record Specification + +## Purpose +定义服务机构端「工单留痕」「异常列表」页面与服务对象页结转入口的交互。 + +## Requirements + +### Requirement: 工单留痕页 +admin「工单留痕」页 MUST 提供记录列表 + 详情(签到/签退时间、时长、项目 exec_result、照片、异常、定位、垫付标记);质控员/院长可见,护理员看自己。 + +#### Scenario: 查看留痕 +- **WHEN** 质控员打开工单留痕 +- **THEN** 看到记录列表与详情(时间/项目/照片/异常/定位) + +### Requirement: 异常列表页 +admin「异常列表」页 MUST 展示异常(分类、状态、关联老人、语音/照片入口)。 + +#### Scenario: 查看异常 +- **WHEN** 质控员打开异常列表 +- **THEN** 看到异常分类与状态 + +### Requirement: 结转入口 +服务对象页 MUST 在待遇转「正常享受」后提供「结转垫付期服务」按钮:勾选 is_prepaid=1 记录 → 生成正式记录,原记录保留只读。 + +#### Scenario: 结转垫付 +- **WHEN** 待遇已生效,点「结转垫付期服务」 +- **THEN** 勾选垫付记录生成正式记录,原记录保留只读 diff --git a/openspec/specs/frontend/ad/schedule/spec.md b/openspec/specs/frontend/ad/schedule/spec.md new file mode 100644 index 0000000..12a099c --- /dev/null +++ b/openspec/specs/frontend/ad/schedule/spec.md @@ -0,0 +1,20 @@ +# frontend/ad/schedule Specification + +## Purpose +定义服务机构端「排班派单」页面与「服务对象」页扩展的交互。 + +## Requirements + +### Requirement: 排班派单页 +日视图(横轴时间段/纵轴护理员)MUST 显示工单卡片、空缺橙框、冲突红框;调单面板 ≤3 步;批量推荐需人工确认。 + +#### Scenario: 调单三步 +- **WHEN** 点击卡片→选目标护理员→确认 +- **THEN** 生效并自动通知 + +### Requirement: 服务对象页扩展 +档案页 MUST 提供「个人项目库」区块(勾选 L4 项目、可空)与「制定计划」入口(一键带入、可改、校验项数)。 + +#### Scenario: 从个人项目库带入 +- **WHEN** 制定计划并点「从个人项目库带入」 +- **THEN** 自动生成计划项初稿,可修改 diff --git a/openspec/specs/shared/api-contract/spec.md b/openspec/specs/shared/api-contract/spec.md index 619e928..7f80b53 100644 --- a/openspec/specs/shared/api-contract/spec.md +++ b/openspec/specs/shared/api-contract/spec.md @@ -18,3 +18,56 @@ #### Scenario: 资质不匹配提示级 - **WHEN** 派单时护理员资质不匹配 - **THEN** 返回 1006,前端仅提示、允许继续(本期不拦截,二期改硬拒) + +### Requirement: 老人档案接口 +`GET /elder`、`POST /elder`、`GET /elder/:id`、`POST /elder/:id/status`、`GET /elder/:id/status/log`、`POST /elder/assess-evidence` MUST 存在,遵循统一响应 `{code,message,data,hint}`。 + +#### Scenario: 状态变更必填原因 +- **WHEN** 调用 `/elder/:id/status` 且缺 change_reason +- **THEN** 返回校验错误,拒绝变更 + +### Requirement: 身份证服务端掩码 +`/elder/list` MUST 返回掩码后的身份证(如 `5301**********1234`);明文仅在 `/elder/detail` 且 admin/qc 授权时返回,并 MUST 落审计。 + +#### Scenario: 列表掩码 +- **WHEN** 调用 `/elder/list` +- **THEN** id_card_no 返回掩码值,非明文 + +### Requirement: 计划与工单接口 +`POST /plan`、`POST /plan/change`、`GET /plan/:id`、`POST /plan/:id/confirm`、`GET /plan/by-elder/:elderId`、`POST /order/generate`、`POST /order/assign`、`POST /order/:id/reassign`、`GET /order/batch-recommend`、`GET /order/today`、`POST /order/:id/cancel`、`GET /order/:id`、`GET /elder-svc/:elderId`、`PUT /elder-svc/:elderId` MUST 存在,遵循统一响应。 + +#### Scenario: 时间冲突硬拒 +- **WHEN** 派单时同护理员时间重叠 +- **THEN** 返回 2001,拒绝保存 + +### Requirement: 属地项数校验 +制定计划时,昆明按 care_mode×care_level 校验项数(一级≥18/二级≥15/三级≥13,附加≤5),不满足返回 2002(提示级);州市只提示不拦。 + +#### Scenario: 昆明项数不满足 +- **WHEN** 昆明一级护理计划项数 < 18 +- **THEN** 返回 2002 提示,不硬拦 + +### Requirement: 履约留痕接口 +`POST /record/checkin`、`POST /record/item/save`、`POST /record/photo/upload`、`POST /record/checkout`、`POST /record/offline/sync`、`GET /record/:id`、`GET /record`、`GET /record/prepaid-list`、`POST /record/prepaid/carryover` MUST 存在,遵循统一响应。 + +#### Scenario: 签退必拍未拍硬拒 +- **WHEN** 必拍项未拍照且未走拒拍出路时签退 +- **THEN** 返回 3001,拒绝签退 + +#### Scenario: 签到服务器取时 +- **WHEN** 签到 +- **THEN** checkin_time 由服务端生成,客户端传入被忽略 + +### Requirement: 异常接口 +`POST /abnormal`、`GET /abnormal` MUST 存在,遵循统一响应。 + +#### Scenario: 扑空 +- **WHEN** 护理员登记未遇(扑空) +- **THEN** 工单转 not_met、到访时间/定位/原因必留、不产生 record + +### Requirement: 垫付结转接口 +`GET /record/prepaid-list` MUST 返回老人垫付台账(is_prepaid=1);`POST /record/prepaid/carryover` MUST 勾选垫付记录生成正式记录,原记录保留只读。 + +#### Scenario: 结转不改原始时间戳 +- **WHEN** 结转垫付记录 +- **THEN** 新记录签到时间/定位/照片仍为原始值,仅标记来源=垫付台账 diff --git a/openspec/specs/shared/data-model/spec.md b/openspec/specs/shared/data-model/spec.md index 0a10f2a..d2d425e 100644 --- a/openspec/specs/shared/data-model/spec.md +++ b/openspec/specs/shared/data-model/spec.md @@ -53,3 +53,77 @@ #### 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 表存在且无业务数据