1. 项目背景与核心需求
东方红食品公司作为一家中型食品加工企业,其采购管理长期面临三大痛点:手工台账导致数据滞后、多部门协作效率低下、供应商评估缺乏量化依据。传统Excel表格管理方式已无法满足日均50+采购订单的处理需求,经常出现库存信息不同步、审批流程超时、供应商交货延迟等问题。
这个采购管理系统需要实现四个核心目标:
- 建立从采购申请到付款结算的全流程数字化闭环
- 实现与现有ERP系统的库存数据实时同步
- 构建供应商KPI动态评估体系
- 支持移动端审批与异常预警
2. 技术架构设计
2.1 SpringBoot框架选型考量
选择SpringBoot 2.7.x版本主要基于:
- 约定优于配置的特性大幅减少XML配置(相比传统Spring MVC可减少约70%的配置代码)
- 内嵌Tomcat容器简化部署,配合健康检查端点便于k8s集群管理
- 完善的Starter生态:特别是Spring Data JPA对多数据源的支持,满足同时连接ERP数据库和业务库的需求
java复制// 典型的多数据源配置示例
@Configuration
@EnableJpaRepositories(
basePackages = "com.dfh.procurement.erp",
entityManagerFactoryRef = "erpEntityManager",
transactionManagerRef = "erpTransactionManager"
)
public class ErpDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.erp")
public DataSource erpDataSource() {
return DataSourceBuilder.create().build();
}
}
2.2 前后端分离架构
采用Vue3+Element Plus前端框架,通过以下设计解决常见问题:
- 接口幂等性:为所有POST/PUT请求增加X-Request-Id头
- 大文件上传:采购合同采用分片上传+MD5校验
- 数据权限:通过自定义指令v-permission控制按钮级权限
3. 核心功能实现
3.1 采购流程状态机设计
使用Spring StateMachine实现采购单状态流转:
mermaid复制stateDiagram
[*] --> DRAFT
DRAFT --> APPROVING : 提交审批
APPROVING --> APPROVED : 部门经理通过
APPROVING --> REJECTED : 审批驳回
APPROVED --> ORDERED : 生成采购单
ORDERED --> PART_RECEIVED : 部分到货
PART_RECEIVED --> FULL_RECEIVED : 全部到货
FULL_RECEIVED --> INSPECTING : 质检中
INSPECTING --> COMPLETED : 质检通过
INSPECTING --> RETURNING : 退货处理
关键实现技巧:
- 使用Redis持久化状态机上下文,解决服务重启后状态丢失问题
- 通过@WithStateMachine注解实现监听器与业务逻辑解耦
- 状态变更记录采用AOP统一入库,满足审计要求
3.2 供应商评估模型
构建包含5个维度的评估体系:
java复制public class SupplierEvaluation {
private Double qualityScore; // 质检合格率
private Double deliveryScore; // 准时交货率
private Double priceScore; // 价格竞争力
private Double serviceScore; // 售后服务
private Double financialScore;// 财务健康度
public Double getTotalScore() {
return qualityScore*0.3 + deliveryScore*0.25
+ priceScore*0.2 + serviceScore*0.15
+ financialScore*0.1;
}
}
4. 特殊场景处理
4.1 并发采购申请控制
针对热门原料的抢购场景,采用Redisson分布式锁实现:
java复制public PurchaseOrder createUrgentOrder(PurchaseRequest request) {
RLock lock = redissonClient.getLock("MATERIAL_" + request.getMaterialId());
try {
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
// 检查实时库存
Inventory inventory = erpService.getRealTimeInventory(
request.getMaterialId());
if (inventory.getAvailable() < request.getQuantity()) {
throw new BusinessException("库存不足");
}
return orderRepository.save(convertToOrder(request));
}
} finally {
lock.unlock();
}
}
4.2 定时任务设计
使用Spring Scheduler实现两个关键任务:
- 每日凌晨1点执行的供应商评分重算:
java复制@Scheduled(cron = "0 0 1 * * ?")
public void recalculateSupplierScores() {
supplierService.recalculateAllScores();
log.info("已完成{}家供应商评分更新", supplierCount);
}
- 每30分钟检查未支付订单(配合RabbitMQ延迟队列):
java复制@RabbitListener(queues = "order.timeout.check")
public void checkOrderPayment(OrderTimeoutCheck check) {
Order order = orderService.getById(check.getOrderId());
if (order.getStatus() == OrderStatus.UNPAID) {
orderService.cancelOrder(order.getId(), "超时未支付");
}
}
5. 部署与监控方案
5.1 容器化部署
Dockerfile关键配置:
dockerfile复制FROM adoptopenjdk:11-jre-hotspot
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar",
"-Dspring.profiles.active=prod",
"-Djava.security.egd=file:/dev/./urandom",
"/app.jar"]
5.2 监控体系搭建
- Prometheus采集指标:
yaml复制# application.yml配置示例
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
- 关键业务指标埋点:
java复制@GetMapping("/orders")
public Page<OrderVO> listOrders(OrderQuery query) {
Metrics.counter("procurement.orders.query",
"type", query.getType().name())
.increment();
return orderService.queryOrders(query);
}
6. 项目演进中的经验总结
- JPA优化实践:
- 对于关联查询N+1问题,采用@EntityGraph注解替代fetchType.EAGER
- 批量插入使用spring.jpa.properties.hibernate.jdbc.batch_size=50
- 审计字段通过@CreatedDate自动填充
- 缓存策略调整:
- 采购品类等基础数据使用Caffeine本地缓存(5分钟过期)
- 供应商详情采用Redis缓存(1小时过期+主动刷新)
- 接口兼容性处理:
- 为所有API添加/api/v1前缀
- 使用@ControllerAdvice统一处理Feign调用异常
- 重要接口实现RequestRateLimiter限流
这个系统上线后,采购审批周期从平均3天缩短至4小时,供应商交货准时率提升27%,年度采购成本降低约15%。后续计划接入区块链技术实现合同存证,并开发供应商门户完善协同生态。
