乡镇卫生所医用物资管理现状
乡镇卫生所作为基层医疗服务机构,普遍面临医用物资管理粗放、信息化程度低的问题。传统手工记录或简单电子表格管理易出现库存数据不准确、采购计划滞后、物资过期浪费等现象,影响医疗服务的及时性和安全性。
系统建设的核心意义
提升管理效率:通过数字化进销存流程,实现物资采购、入库、领用、盘点全链条自动化,减少人工错误和重复劳动。
保障医疗安全:实时监控库存状态和效期,避免关键物资短缺或过期使用,确保基层医疗质量。
优化资源配置:基于历史消耗数据生成智能采购建议,避免资金浪费,尤其适合财政有限的乡镇机构。
技术选型优势(SpringBoot)
快速开发:SpringBoot的约定优于配置特性适合乡镇卫生所轻量化系统需求,降低开发门槛。
集成能力:可无缝对接条码扫描设备或移动终端,适配物资管理中的多场景操作。
数据可扩展性:为未来对接区域医疗云平台预留接口,支持数据汇总分析。
社会价值体现
通过规范化物资管理,间接提升基层医疗机构服务能力,助力分级诊疗政策落地,尤其对偏远地区医疗资源均衡化具有实践意义。
乡镇卫生所医用物资进销存系统核心功能模块
系统架构
基于SpringBoot + MyBatis-Plus + MySQL,采用分层设计(Controller/Service/Dao/Entity),前端可使用Vue或Thymeleaf模板引擎。
物资管理模块代码示例
实体类设计(物资基础信息)
@Entity @Table(name = "medical_supplies") public class MedicalSupplies { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String code; // 物资编码 private String name; // 物资名称 private String spec; // 规格型号 private String unit; // 计量单位 private String category; // 分类(药品/耗材/器械) private Double price; // 单价 private Integer shelfLife; // 保质期(月) // getters/setters... }库存操作Service
@Service public class InventoryService { @Autowired private InventoryMapper inventoryMapper; // 入库操作 @Transactional public void stockIn(StockInDTO dto) { Inventory inventory = inventoryMapper.selectBySuppliesId(dto.getSuppliesId()); if (inventory == null) { inventory = new Inventory(); inventory.setSuppliesId(dto.getSuppliesId()); inventory.setQuantity(dto.getQuantity()); inventoryMapper.insert(inventory); } else { inventory.setQuantity(inventory.getQuantity() + dto.getQuantity()); inventoryMapper.updateById(inventory); } // 记录入库日志... } // 库存预警查询 public List<Inventory> getLowStockItems(int threshold) { return inventoryMapper.selectLowStock(threshold); } }进销存核心业务逻辑
采购订单生成
@RestController @RequestMapping("/api/purchase") public class PurchaseController { @PostMapping public Result createOrder(@Valid @RequestBody PurchaseOrderDTO dto) { // 校验库存阈值,生成采购清单 List<Inventory> lowStockItems = inventoryService.getLowStockItems(10); // 创建采购单逻辑... return Result.success(orderId); } }销售出库事务处理
@Service public class OutboundService { @Transactional(rollbackFor = Exception.class) public void processOutbound(OutboundRequest request) { // 校验库存是否充足 Inventory inventory = inventoryMapper.selectForUpdate(request.getSuppliesId()); if (inventory.getQuantity() < request.getQuantity()) { throw new BusinessException("库存不足"); } // 扣减库存 inventoryMapper.deductStock( request.getSuppliesId(), request.getQuantity() ); // 记录出库单 outboundMapper.insert(convertToOutboundRecord(request)); } }数据统计与分析
物资消耗统计SQL(MyBatis)
<select id="getConsumptionStats" resultType="map"> SELECT s.category, SUM(o.quantity) AS total_quantity, SUM(o.amount) AS total_amount FROM outbound_records o JOIN medical_supplies s ON o.supplies_id = s.id WHERE o.outbound_date BETWEEN #{startDate} AND #{endDate} GROUP BY s.category </select>库存周转率计算
public Double calculateTurnoverRate(Long suppliesId) { // 计算公式:周转率 = 年度出库总成本 / 平均库存价值 BigDecimal annualOutboundCost = outboundMapper.sumAnnualCost(suppliesId); BigDecimal avgInventoryValue = inventoryMapper.getAvgInventoryValue(suppliesId); return annualOutboundCost.divide(avgInventoryValue, 2, RoundingMode.HALF_UP).doubleValue(); }系统安全与验证
物资操作日志切面
@Aspect @Component public class OperationLogAspect { @AfterReturning(pointcut = "@annotation(com.xxx.annotation.OperLog)", returning = "result") public void recordLog(JoinPoint jp, Object result) { OperLog operLog = ((MethodSignature)jp.getSignature()).getMethod().getAnnotation(OperLog.class); LogEntry log = new LogEntry(); log.setOperation(operLog.value()); log.setParams(JsonUtils.toJson(jp.getArgs())); logMapper.insert(log); } }关键注意事项
- 库存操作必须加事务注解和悲观锁(
SELECT ... FOR UPDATE) - 物资编码建议采用GS1标准生成(如
69[厂商代码][商品代码]) - 效期管理需实现近效期优先出库(FIFO)逻辑
- 高并发场景考虑使用Redis缓存热点物资库存数据
以上代码需配合前端界面实现完整的进销存流程,包括采购管理、库存盘点、物资申领、报表导出等功能模块。
乡镇卫生所医用物资进销存系统设计要点
数据库设计核心表结构
物资信息表
- 字段:物资ID(主键)、名称、规格、单位、类别、生产厂家、库存预警值
- 示例SQL:
CREATE TABLE material ( material_id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, specification VARCHAR(50), unit VARCHAR(10), category VARCHAR(30), manufacturer VARCHAR(100), warning_quantity INT );
入库记录表
- 字段:入库ID、物资ID(外键)、批次号、数量、单价、供应商、入库时间、操作人
- 需建立与物资表的关联索引
出库记录表
- 字段:出库ID、物资ID(外键)、领取科室、数量、领用人、出库时间
- 需包含审批状态字段(如:待审核/已通过)
库存实时表
- 字段:物资ID(联合主键)、当前库存量、最近更新时间
- 采用触发器或定时任务同步更新
SpringBoot技术实现
- 使用JPA/Hibernate实现ORM映射
- 配置多数据源支持(如对接医保系统)
- 库存事务控制示例代码:
@Transactional public void updateStock(Long materialId, int delta) { Stock stock = stockRepo.findByMaterialId(materialId); if(stock.getQuantity() + delta < 0) { throw new InventoryException("库存不足"); } stock.setQuantity(stock.getQuantity() + delta); }
系统测试方案
功能测试重点
物资生命周期测试
- 模拟完整流程:采购入库→库存更新→申领出库→库存扣减
- 验证批次管理与先进先出规则
边界值测试
- 库存预警触发测试(达到阈值时是否提示)
- 并发出库测试(使用JMeter模拟多人同时申领)
数据一致性验证
- 检查库存总量是否等于∑入库-∑出库
- 审计日志与操作记录的匹配验证
性能测试指标
- 关键接口响应时间:入库操作<500ms(100并发)
- 数据库查询性能:库存查询<200ms(万级数据量)
- 使用Arthas进行JVM监控
安全测试要求
- 越权测试:普通员工尝试删除入库记录
- SQL注入测试:在物资搜索框输入特殊字符
- 数据加密:敏感字段如价格需AES加密存储
测试数据构造
通过SpringBootTest自动生成测试数据:
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) @SpringBootTest class InventoryTest { @Autowired private MaterialService service; @Test @Order(1) void batchInsert() { List<Material> materials = IntStream.range(0,1000) .mapToObj(i -> new Material("口罩"+i,"N95","个")) .collect(Collectors.toList()); service.batchSave(materials); } }