[开源] 药房近效期药品消耗速度-库存交叉预警系统:面向药房精细化库存管理的 CLI 工具,用双维度风险建模替代经验式盯盘
本项目是专为医院药房、社区药房及医药流通环节设计的轻量级库存风控 CLI 工具。它不依赖数据库或 Web 后台,也不要求部署服务器,而是通过「消耗速度(快/中/慢)」与「剩余效期(近/中/远)」两个业务可解释维度构建 3×3 交叉矩阵,对每种组合分别计算断货风险与报损风险,输出带严重度排序的预警清单和补货建议。核心能力包括多格式数据加载(CSV/Excel/JSON)、自动分类器训练、双预警引擎触发、HTML 可视化报告生成,以及全链路配置化,从分位数阈值、效期天数定义,到安全库存天数、报损比例红线,均可按药房实际运营节奏调整。运行于 Node.js 环境,采用 ES Module 架构,命令行交互使用 commander.js,终端输出支持 chalk 彩色高亮,Excel 解析依赖 xlsx 库,所有逻辑无外部 API 依赖,本地即可闭环运行。
定位与能力范围
我们不做通用 ERP 插件,也不做 SaaS 订阅服务。这套系统只解决药房日常最痛的两件事:一边怕断货被临床催,一边怕近效期药品过期报废。传统做法靠人工翻表、凭经验划重点,但人眼难同时盯住「哪些药卖得快却快过期」「哪些药卖得慢但库存还堆着」,这正是交叉风险的盲区。我们把问题拆成两个可量化的轴:横轴是消耗速度(基于历史日均用量按分位数自动划分快/中/慢三档),纵轴是效期等级(按剩余天数硬性切分为近/中/远三档),再在每个格子内独立评估「还能撑几天」和「效期内能不能卖完」。结果不是笼统打个标签,而是输出两类清单:断货预警(按够用天数≤7天/8–14天分级)、报损预警(按效期内预计消耗比例<30%/30%–60%分级),并附带交叉矩阵热力图,一眼锁定「快消耗+近效期」这类高优先级干预项,或「慢消耗+近效期」这类需紧急促销/调拨的红灯单元。
核心功能
系统以 CLI 为唯一交互界面,所有能力围绕「数据输入→风险识别→结果交付」三步闭环展开,不引入图形界面或后台服务,降低使用门槛与维护成本:
- 多格式数据加载
:库存、消耗、效期三类数据支持 CSV、Excel(.xlsx/.xls)、JSON 任意组合混用,无需预清洗字段名,自动映射标准字段(如
drug_id、quantity、date、expiry_date); - 消耗速度自动分类
:基于 consumption 文件中各药品 30 天内总消耗量,计算日均值后按全局分位数切分(默认 P25/P75),输出每品规归属「快/中/慢」档位,避免主观定性;
- 效期等级自动评估
:解析 expiry 文件中的
expiry_date,与当前日期比对,按配置阈值(默认 ≤30 天为近效期,31–90 天为中效期)归类,兼容不同药监效期标注习惯; - 双风险交叉矩阵
:生成 3 行(消耗速度)× 3 列(效期等级)表格,每个单元格显示该组合下药品数量、平均剩余天数、平均效期内消耗完成率,并用颜色区分风险密度;
- 双预警引擎并行触发
:断货预警依据「当前库存 ÷ 日均消耗量」推算够用天数,与配置的安全阈值比对;报损预警依据「效期内预计消耗量 ÷ 总库存」计算完成率,与报损比例阈值比对;两者独立计算、独立排序、独立导出;
- 多格式报告交付
:支持
json(默认,适合下游程序解析)、csv(适配 Excel 二次分析)、html(含交互式矩阵图、预警清单折叠面板、响应式布局,手机端可读)三种输出格式。
使用与配置
所有操作通过node bin/cli.js启动,分三个主子命令,职责清晰不重叠:
命令 | 用途 | 典型场景 |
|---|---|---|
load-data | 验证三类数据文件可读性、字段完整性、日期格式合规性,并输出标准化 JSON 结构预览 | 新接入药房系统前校验数据质量,排查 |
detect | 运行完整风险模型,终端实时输出彩色预警列表(红色=高危,黄色=中危),含药品 ID、名称、当前库存、日均消耗、剩余天数、效期完成率、风险类型与等级 | 每日晨会快速扫一遍高风险项,决定当日补货/促销/调拨优先级 |
report | 生成结构化报告文件,支持 | 向科室负责人提交周度库存风控简报,或存档备查 |
全局参数统一控制输入源与输出行为,关键参数如下:
参数 | 缩写 | 说明 | 默认值 |
|---|---|---|---|
--inventory <path> | -i | 库存数据文件路径(必须) | 无,默认报错 |
--consumption <path> | -c | 消耗记录文件路径(必须) | 无,默认报错 |
--expiry <path> | -e | 效期数据文件路径(必须) | 无,默认报错 |
--config <path> | — | 自定义配置目录路径 | config/(内置默认) |
--format <format> | -f | 输出格式: | json |
--output <path> | -o | 输出文件路径,不设则输出至终端 | stdout |
例如生成一份 HTML 报告供移动端查看:
node bin/cli.js report \ --inventory data/inventory-sample.csv \ --consumption data/consumption-sample.csv \ --expiry data/expiry-sample.csv \ --format html \ --output report.html数据与扩展
系统不绑定任何特定 HIS 或药房系统字段,仅约定最小可用字段集,便于对接各类数据源:
数据类型 | 必需字段(示例) | 说明 |
|---|---|---|
库存(inventory) | drug_id, | quantity为当前在库数量, |
消耗(consumption) | drug_id, | date为消耗发生日期,支持多条同品规跨日记录 |
效期(expiry) | drug_id, | expiry_date支持 |
配置完全外置,全部位于config/目录下,分为两类 JSON 文件:
classifier-config.json控制分类逻辑:
{
"consumptionSpeed": { "quantiles": { "fast": 0.75, "medium": 0.25 } },
"expiryThresholds": { "near": 30, "medium": 90 }
}detector-config.json控制预警红线:
{
"stockoutThresholds": { "high": 7, "medium": 14 },
"expiryThresholds": { "high": 0.3, "medium": 0.6 }
}
所有阈值均可按药房实际补货周期、药品单价、仓储条件动态调整。例如基层药房补货周期为 14 天,则应将stockoutThresholds.high改为14;若管理高价肿瘤药,则可将expiryThresholds.high从0.3收紧至0.15,提前介入。
环境与运行
零依赖安装,仅需 Node.js ≥18.0。安装命令极简:
npm install运行时无需编译或打包,直接执行 CLI 主入口。环境变量可通过.env文件预设常用路径,避免每次重复输入长路径:
变量 | 说明 | 默认值 |
|---|---|---|
INVENTORY_PATH | 库存文件路径 | data/inventory-sample.csv |
CONSUMPTION_PATH | 消耗文件路径 | data/consumption-sample.csv |
EXPIRY_PATH | 效期文件路径 | data/expiry-sample.csv |
OUTPUT_FORMAT | 默认输出格式 | json |
LOG_LEVEL | 日志级别 | info |
复制模板启用:
cp .env.example .env修改.env后,后续命令可省略全部--inventory等参数,直接运行:
node bin/cli.js detect node bin/cli.js report --format html --output daily-warning.html限制与说明
本系统明确划定能力边界:它不替代进销存系统,不处理采购订单生成,不对接电子处方,不提供用户权限管理。它的价值在于「把已有数据变成可行动的风险信号」。因此,我们不对原始数据质量负责,若消耗记录缺失某药品 30 天数据,则其消耗速度无法分类;若效期字段为空或格式错误,则整行被跳过。所有数据校验逻辑在load-data阶段透明输出,不静默容错。输出中的百分比(如“效期内消耗完成率 28%”)仅为模型推算值,用于横向比较风险程度,不构成财务报损依据;实际报损仍需结合实物盘点与院内审批流程。HTML 报告在手机 Safari、Chrome 中经实测可正常展开折叠、滑动矩阵表格,字体与间距适配小屏阅读,无需缩放即可看清药品 ID 与数字。
项目地址:
https://github.com/nexorin9/drug-expiry-warning
