ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

医院门诊药房系统:一个完整的状态机

医院门诊药房系统:一个完整的状态机 医院门诊药房系统挂号→收费→发药→退药一个完整的状态机文章目录医院门诊药房系统挂号→收费→发药→退药一个完整的状态机一、场景二、四个角色四套操作三、门诊链路一条最长状态链四、药库链路进销存管理五、住院链路更长但不复杂六、日结每天和钱对一次账七、总结不是 CRUD。是每一步都锁着上一步。一、场景一个人去医院门诊的完整路径挂号 → 看医生 → 医生开处方 → 收费处缴费 → 药房取药 → 走人。如果在任何一个环节出了问题——收错费、发错药、要退药——系统要能退回去而且要退得干净。不是因为退药就把发药记录删了是不能删只能冲正。下面拆解整条链路上的状态机设计。二、四个角色四套操作系统分四个功能域角色功能挂号处挂号、退号、日结收费处收费、作废、退费、取消作废、日结药房发药、取消发药、退药药库入库审批、出库审批、盘点、调价、药房申领每个角色的操作不是孤立的——收费锁着发药发药锁着退药退药锁着退费。前一个状态决定后一个能不能做。三、门诊链路一条最长状态链挂号 ──→ 退号只有未收费的挂号可退 │ ▼ 收费 ──→ 作废只有未发药的收费可作废 │ │ │ └──→ 取消作废作废撤销 │ ▼ 发药 ──→ 取消发药 │ ▼ 退药 ──→ 退费只有退药生成的处方才能退费每一步的约束操作前置条件做的事挂号无创建就诊记录退号未收费标记退号不删记录收费已挂号 有处方生成结算单更新费用汇总作废未发药费用撤销不删记录取消作废已作废恢复到已收费状态发药已收费 未发药更新处方发药字段 减库存取消发药已发药处方回到未发药库存加回退药已发药 有药品可退生成新处方退药处方明细插入负数库存加回退费有退药处方生成退费结算单伪代码实现// 挂号 function 挂号(患者ID, 科室ID): record INSERT INTO 就诊记录(患者ID,科室ID,状态已挂号) return record.就诊ID // 收费 function 收费(就诊ID, 处方列表): rec SELECT * FROM 就诊记录 WHERE ID就诊ID if rec.状态 ! 已挂号: return error(未挂号或已收费) sum 0 for item in 处方列表: INSERT INTO 费用明细(就诊ID, 项目, 金额, 状态未发药) sum item.金额 INSERT INTO 结算单(就诊ID, 金额sum, 状态已收费) UPDATE 就诊记录 SET 状态已收费 WHERE ID就诊ID return 收费成功 // 作废只有未发药的能作废 function 作废(就诊ID): rec SELECT * FROM 就诊记录 WHERE ID就诊ID if rec.状态 ! 已收费: return error(状态不正确) if EXISTS(SELECT 1 FROM 费用明细 WHERE 就诊ID就诊ID AND 状态已发药): return error(已有发药记录不能作废请走退药流程) UPDATE 结算单 SET 状态已作废 WHERE 就诊ID就诊ID UPDATE 就诊记录 SET 状态已作废 WHERE ID就诊ID return 作废成功 // 发药 function 发药(就诊ID, 药品列表): for drug in 药品列表: item SELECT * FROM 费用明细 WHERE 就诊ID就诊ID AND 项目drug.项目 if item.状态 ! 未发药: continue // 已发过的跳过 stock SELECT 库存 FROM 药房库存 WHERE 药品IDdrug.药品ID if stock drug.数量: return error(库存不足) UPDATE 药房库存 SET 库存库存-drug.数量 WHERE 药品IDdrug.药品ID UPDATE 费用明细 SET 状态已发药, 发药时间NOW() WHERE IDitem.ID return 发药成功 // 退药生成冲正记录不删原记录 function 退药(就诊ID, 退药列表): for drug in 退药列表: item SELECT * FROM 费用明细 WHERE 就诊ID就诊ID AND 项目drug.项目 if item.状态 ! 已发药: return error(未发药不能退) if item.数量 item.退药数量 drug.数量: return error(无可退数量) // 生成退药处方数量为负 INSERT INTO 处方汇总(就诊ID, 退药标志已退, 关联原处方号item.处方号) INSERT INTO 费用明细(处方号新处方号, 项目drug.项目, 数量-drug.数量, 状态已退药) UPDATE 药房库存 SET 库存库存drug.数量 WHERE 药品IDdrug.药品ID UPDATE 费用明细 SET 退药数量退药数量drug.数量 WHERE IDitem.ID return 退药成功 // 退费只有退药处方才能退费 function 退费(处方ID): rec SELECT * FROM 处方汇总 WHERE ID处方ID if rec.退药标志 ! 已退: return error(非退药处方不能退费) if EXISTS(SELECT 1 FROM 结算单 WHERE 处方ID处方ID AND 类型退费): return error(已退费不能重复) sum SELECT SUM(金额) FROM 费用明细 WHERE 处方ID处方ID // 金额为负 INSERT INTO 结算单(就诊IDrec.就诊ID, 金额sum, 类型退费, 状态已退费) return 退费成功关键的锁收费→发药之间只有未发药的处方可以作废。已发药的不能作废只能走退药。发药→退药退药不是把发药记录删掉是生成一条新处方明细是负数。原处方保留库存加回。审计可追溯。退药→退费只有退药生成的处方才能退费。不是随便一笔收费都能退。四、药库链路进销存管理药库管的是整批的药药房管的是发给患者的那几盒。药库入库申请 → 入库审批 → 更新库存 保存历史价格 药库出库申请 → 出库审批 → 更新库存 药库盘点录入 → 盘点确认 → 更新库存 药库调价申请 → 调价审批 → 保存历史价格 药房申领药房发起 → 药库确认 → 更新药房库存入库/出库都走申请→审批两条线。审批不通过库存不动。调价不是直接改价格——是保存新价格旧价格进历史表。历史价格永不删除。五、住院链路更长但不复杂住院比门诊多了一层病区护士入院登记 → 缴费/押金 → 分配床位 → 诊断 → 护理记录 → 体温单 → 医嘱录入 → 医嘱复核 → 医嘱提交 → 住院发药 → 医嘱执行 → 计费 → 退费 → 出院登记 → 出院结算 → 撤销结算 → 撤销出院登记 → 催款押金不够时触发 → 停止医嘱长期医嘱的终止角色分三层角色做的事住院收费处入院登记、缴费、出院结算病区护士分配床位、护理记录、体温单、医嘱执行、催款医生诊断、医嘱录入药房住院发药医嘱复合→提交→发药→执行这条线是住院的核心。医嘱不提交药房看不到药房不发药护士不能执行。六、日结每天和钱对一次账挂号处和收费处每天要做日结挂号日结 → 撤销日结 → 确认 → 查询 收费日结 → 撤销日结 → 确认 → 查询日结把当天的挂号记录和收费记录快照一份生成日结报表。报表可以撤销重做但确认后不可再撤销。日结不是业务操作是财务操作。业务系统可以崩日结数据不能丢。七、总结这套系统写了十几年状态机设计定下来之后就没大改过。为什么因为医院的业务流程是写在制度里的——挂号→收费→发药→退药不是系统决定的是医院管理规范决定的。系统只是忠实地把这些规则变成了代码。几个不变的原则不删只冲——退药不删发药记录退费不删收费记录。审计第一。状态锁状态——发药锁着退药退药锁着退费。不能跳不能倒。审批全留痕——入库审批、调价审批、日结确认每一步操作有记录、可追溯。HIS 系统的复杂度不在于算法。在于规则多、角色多、不允许出错。每次看到医院系统崩溃的新闻我都能感受到屏幕背后的 DBA 在经历什么。
返回列表