2026-05-18-checkup-project-package-design.md 10 KB

体检机构项目套餐设计文档

日期:2026-05-18
状态:已确认
父模块:中试服务管理 §2.3.6 体检机构及项目价格
需求来源:docs/中科兴皖需求V0.3.md §2.3.6(增强)、探索结论 2026-05-18


1. 背景与目标

运营在维护各体检机构的原子项目后,常需将多项组合成固定搭配(如「基础套餐」「全面套餐」),供后续业务人员一键选用,减少逐条勾选与漏项。

目标

  • 在机构维度维护「套餐」:勾选多个本机构项目,可调整套餐内各行费用。
  • 套餐总价 = 所含项目费用之和(不单独维护打包价,口径简单、易解释)。
  • 业务落单(中试申请单体检预约等)时展开为明细行写入现有 biz_pilot_checkup_reserve_item,不引入新的结算实体。

非目标(首期不做)

  • 跨机构共用套餐模板库
  • 套餐固定优惠价(与明细之和不一致)
  • 仅保存套餐头、不展开明细的预约模型

2. 已确认业务规则

规则 说明
套餐总价 始终为明细 project_fee 之和;不存套餐头「一口价」字段
明细价格 从机构项目带入默认费用后,可在套餐内单独修改;修改仅影响该套餐行,不回写机构项目主数据
套餐归属 仅属于一个 checkup_institution_id,不跨机构
项目引用 明细行关联 checkup_institution_project_id;保存时校验项目属于同一机构且未删除
停用项目 套餐保存/启用时:若含 status=0 的项目,禁止保存或禁止启用(二选一实现,推荐禁止保存含停用项)
历史业务单 下游预约/实际明细为快照(名称+费用),套餐后续调价不影响已生成单据
名称快照 明细行冗余 project_name(与 2.3.4 项目价格体系明细一致),避免主数据改名后历史套餐展示歧义
套餐编码 必填;同一机构下未删除(del_flag=0)的套餐编码唯一(应用层校验)
删除机构项目 允许软删除,不因被套餐引用而拦截;不级联删除或修改套餐明细行
删除后展示 套餐明细仍按行内 project_name / project_fee 快照展示;源项目已删时 UI 标注「源项目已删除」,不影响历史查看与合计

2.1 机构项目软删除与套餐的关系

运营删除机构项目(del_flag=1)
        │
        ├─► 套餐明细行:保留,不自动移除
        │       展示:project_name(快照)+ 可选标签「源项目已删除」
        │       合计:仍计入该行 project_fee(套餐定义不变)
        │
        ├─► 编辑套餐:不可再「添加」已删除/停用的源项目;已有行可删除或改价
        │
        └─► Phase 2 从套餐带入预约:仅展开源项目仍有效(del_flag=0 且 status=1)的行;
            已删除源项目行跳过(快照仅用于套餐档案展示)

与中试单预约/实际明细一致:业务单落库为快照,机构项目删除不影响已生成业务单展示。


3. 数据模型

3.1 ER 关系

biz_checkup_institution
        │
        ├──1:N── biz_checkup_institution_project   (原子项目,已有)
        │
        └──1:N── biz_checkup_institution_package    (套餐头,新增)
                      │
                      └──1:N── biz_checkup_institution_package_item  (套餐明细,新增)
                                    │
                                    └──N:1── biz_checkup_institution_project

3.2 表:biz_checkup_institution_package(套餐头)

字段 类型 说明
id VARCHAR(64) 主键 UUID
checkup_institution_id VARCHAR(64) 所属体检机构
package_name VARCHAR(200) 套餐名称(必填)
package_code VARCHAR(64) 套餐编码(必填,机构内 del_flag=0 唯一)
status CHAR(1) 1 正常 / 0 停用
tenant_no … del_flag — 公共字段(见 database-conventions)

不建字段:package_fee / total_fee(总价由明细汇总计算)。

3.3 表:biz_checkup_institution_package_item(套餐明细)

字段 类型 说明
id VARCHAR(64) 主键
package_id VARCHAR(64) 套餐头 ID
checkup_institution_project_id VARCHAR(64) 来源机构项目 ID
project_name VARCHAR(200) 项目名称快照(从项目带入,可展示用)
project_fee DECIMAL(18,2) 套餐内项目费用(元),可编辑
tenant_no … del_flag — 公共字段

约束

  • 同一 package_id 下 checkup_institution_project_id 不重复。
  • project_fee ≥ 0;允许为 NULL 时按 0 参与合计(建议表单必填 ≥0)。

3.4 API 派生字段

列表/详情响应增加只读字段(不落库):

{
  "totalFee": 1280.00,
  "itemCount": 5
}

totalFee = SUM(package_item.project_fee),后端计算返回。


4. 后端设计

沿用 pilot_service.py + pilot_service.py CRUD 分段模式。

4.1 端点

方法 路径 说明
GET /checkup-institutions/{institution_id}/packages 机构下套餐列表(含 totalFee、itemCount)
POST /checkup-institutions/{institution_id}/packages 新增套餐(Body 含 items[])
GET /checkup-institution-packages/{package_id} 套餐详情 + 明细
PUT /checkup-institution-packages/{package_id} 更新套餐头 + 全量替换明细(与 2.3.4 主子表保存方式一致)
DELETE /checkup-institution-packages/{package_id} 软删除套餐及明细

权限、租户隔离、数据权限与现有中试服务接口一致。

4.2 保存逻辑(要点)

  1. 校验 package_code、package_name 非空;package_code 在同机构未删除套餐中唯一。
  2. 校验 items 非空(至少 1 项)。
  3. 新增/全量替换明细时:每项 checkup_institution_project_id 须属于当前机构、del_flag=0、status=1。
  4. 更新且明细含历史行(源项目已软删):允许保留该行(project_name / project_fee 以 Body 或库内快照为准),不允许新增指向已删项目的行。
  5. 写入明细时:project_name 默认取机构项目当前名称;project_fee 取 Body 传入值。
  6. 不写入、不校验套餐头总价字段。

4.3 机构项目删除(soft_delete_checkup_institution_project)

  • 不检查套餐引用,直接软删除机构项目。
  • 不修改 biz_checkup_institution_package_item 任意字段。
  • 列表/详情 join 源项目时附带 sourceProjectDeleted: true(源 del_flag=1 或不存在时),供前端展示标签。

4.4 Model

在 backend/app/models/models.py 追加:

  • BizCheckupInstitutionPackage
  • BizCheckupInstitutionPackageItem

5. 前端设计(web-admin)

5.1 入口

在 体检机构及项目价格 页(checkup-institution/index.vue)的「项目价格配置」弹窗内增加 Tab 或并列入口:

  • Tab 1:项目列表(现有)
  • Tab 2:套餐管理(新增)

也可采用「套餐配置」独立按钮 + 弹窗,与「项目价格配置」同级;以不挤占单弹窗高度为准。

5.2 套餐列表

列:序号、套餐名称、套餐编码、项目数、合计费用(元)、状态、备注、操作(编辑/删除)。

合计费用列展示 API 返回的 totalFee(只读)。

5.3 套餐新增/编辑弹窗

头部:套餐名称(必填)、套餐编码(必填)、状态(正常/停用)、备注。

明细区(可编辑表格,对齐 project-price-system 明细交互):

操作 说明
添加项目 从当前机构「正常」状态项目中多选/逐条添加
删除行 移除明细
项目名称 只读展示(快照);源项目已删时后缀 muted 文案「源项目已删除」
项目费用(元) 可编辑 el-input-number,默认 = 机构项目当前 projectFee
合计 弹窗底部展示「套餐合计:¥ xxx.xx」= 各行费用实时求和

保存时提交 items: [{ checkupInstitutionProjectId, projectName, projectFee }, ...],不传 totalFee。

5.4 UI 规范

  • 遵循 Fresh Mint 与 dialog-form-layout、form-grid-2、列表工具栏等既有约定。
  • 树/路径无涉;明细勾选来自 flat 项目列表。

6. 与下游业务对接(Phase 2)

中试申请单体检模块(biz_pilot_checkup + reserve_item)实现时:

  1. 选择机构后,提供 「从套餐添加」:选套餐 → 将有效 package_item 展开为预约明细行(project_name + project_fee)。
  2. 有效行:源机构项目 del_flag=0 且 status=1;源已删/停用的套餐行跳过,不写入预约明细(套餐档案仍完整展示)。
  3. 展开后各行仍可在预约单内微调(与 V0.3 明细模型一致)。
  4. 可选:明细行增加 source_package_id 字段便于统计(非首期必需)。

7. 实现分期

阶段 范围
Phase 1 表结构 + 后端 CRUD + web-admin 套餐维护(本文 §3–5)
Phase 2 中试申请单体检预约「从套餐添加」展开明细

8. SQL 增量

见 docs/sql/checkup_institution_package.sql(CREATE TABLE 两张 + 索引)。


9. 与 V0.3 / 原设计的关系

  • V0.3 §2.3.6 仅定义机构级原子项目;本设计为已确认增强,不改变下游明细表结构。
  • 模式对齐 §2.3.4「细胞产品项目价格体系」主子表,降低实现与认知成本。

10. 产品确认记录(2026-05-18 补充)

议题 结论
套餐编码 必填;机构内未删除套餐编码唯一
删除被套餐引用的机构项目 允许软删除;套餐明细不自动移除;靠快照保证历史展示;业务带入时跳过无效源项目