10 KiB
体检机构项目套餐设计文档
日期: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 保存逻辑(要点)
- 校验
package_code、package_name非空;package_code在同机构未删除套餐中唯一。 - 校验
items非空(至少 1 项)。 - 新增/全量替换明细时:每项
checkup_institution_project_id须属于当前机构、del_flag=0、status=1。 - 更新且明细含历史行(源项目已软删):允许保留该行(
project_name/project_fee以 Body 或库内快照为准),不允许新增指向已删项目的行。 - 写入明细时:
project_name默认取机构项目当前名称;project_fee取 Body 传入值。 - 不写入、不校验套餐头总价字段。
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 追加:
BizCheckupInstitutionPackageBizCheckupInstitutionPackageItem
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)实现时:
- 选择机构后,提供 「从套餐添加」:选套餐 → 将有效
package_item展开为预约明细行(project_name+project_fee)。 - 有效行:源机构项目
del_flag=0且status=1;源已删/停用的套餐行跳过,不写入预约明细(套餐档案仍完整展示)。 - 展开后各行仍可在预约单内微调(与 V0.3 明细模型一致)。
- 可选:明细行增加
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 补充)
| 议题 | 结论 |
|---|---|
| 套餐编码 | 必填;机构内未删除套餐编码唯一 |
| 删除被套餐引用的机构项目 | 允许软删除;套餐明细不自动移除;靠快照保证历史展示;业务带入时跳过无效源项目 |