From 46d1664ec8d5d037b9f354e3299b7799a51ce657 Mon Sep 17 00:00:00 2001 From: "zangch@mesnac.com" Date: Wed, 3 Sep 2025 16:09:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(wms):=20=E5=AE=9E=E7=8E=B0=E9=87=87?= =?UTF-8?q?=E8=B4=AD=E5=85=A5=E5=BA=93=E8=81=94=E5=8A=A8=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=87=87=E8=B4=AD=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在入库单保存时,针对采购类型入库单,更新对应采购订单明细的送货数量 - 根据采购订单明细的完成情况,自动更新采购订单主表的状态 - 在删除入库单时,逆向更新对应采购订单明细的送货数量及订单状态 - 优化了数据查询和更新逻辑,提高系统性能和数据一致性 --- .../impl/WmsInstockOrderServiceImpl.java | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockOrderServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockOrderServiceImpl.java index 35e46026..cf0ab6f1 100644 --- a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockOrderServiceImpl.java +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockOrderServiceImpl.java @@ -17,12 +17,15 @@ import org.dromara.wms.domain.WmsBaseWarehouse; import org.dromara.wms.domain.WmsInstockOrder; import org.dromara.wms.domain.bo.*; import org.dromara.wms.domain.vo.WmsBaseLocationVo; +import org.dromara.wms.domain.vo.WmsInstockDetailVo; import org.dromara.wms.domain.vo.WmsInstockOrderVo; +import org.dromara.wms.domain.vo.WmsPurchaseOrderDetailVo; import org.dromara.wms.mapper.WmsInstockOrderMapper; import org.dromara.wms.service.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -48,6 +51,9 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService { private final IWmsInstockRecordService wmsInstockRecordService; + private final IWmsPurchaseOrderDetailService purchaseOrderDetailService; + private final IWmsPurchaseOrderService purchaseOrderService; + public static Integer nextSequence() { return sequence.incrementAndGet(); @@ -253,6 +259,80 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService { // add.setAuditStatus(auditPass); // } +if("1".equals(bo.getInstockType())){ // 工单类型(1采购订单) + // 更新采购订单明细的deliveryQty:这是入库-采购联动的核心逻辑,确保入库数量累加到采购明细的送货数量中 + // 使用Set记录受影响的poNo,以避免重复更新主订单状态,提高效率 + Set updatedPoNos = new HashSet<>(); // 记录受影响的poNo,用于后续状态更新 + + // 遍历入库明细列表,逐个更新对应的采购订单明细 + for (WmsInstockDetailBo detail : bo.getDetailListBo()) { + // 校验poDId是否为空:采购入库必须关联采购明细ID,否则无法更新,符合数据完整性要求 + if (detail.getPoDId() == null) { + throw new ServiceException("采购入库明细缺少"); + } + // 创建更新对象,仅设置必要字段,遵循YAGNI原则 + WmsPurchaseOrderDetailBo detailBo = new WmsPurchaseOrderDetailBo(); + detailBo.setPoDId(detail.getPoDId()); + + // 查询现有采购明细:用于获取当前deliveryQty,避免直接数据库操作,增强安全性(OWASP输入验证已在上层处理) + WmsPurchaseOrderDetailVo existingDetail = purchaseOrderDetailService.queryById(detail.getPoDId()); + // 校验是否存在:如果不存在,抛出异常,防止无效更新 + if (existingDetail == null) { + throw new ServiceException("采购明细不存在" ); + } + + BigDecimal currentDeliveryQty = existingDetail.getDeliveryQty() != null ? existingDetail.getDeliveryQty() : BigDecimal.ZERO; + // 计算新deliveryQty:累加入库数量,使用BigDecimal确保精度,防止浮点错误 + BigDecimal newDeliveryQty = currentDeliveryQty.add(detail.getInstockQty()); + detailBo.setDeliveryQty(newDeliveryQty); + + // 执行更新:调用服务层方法,确保职责分离(SOLID单一职责原则) + purchaseOrderDetailService.updateByBo(detailBo); + + // 记录poNo:用于后续批量检查主订单状态 + updatedPoNos.add(existingDetail.getPoNo()); + } + + // 更新采购订单主表状态:基于所有明细的deliveryQty vs purchaseQty判断订单完成度 + // 这部分逻辑确保主订单状态实时同步,符合业务一致性 + for (String poNo : updatedPoNos) { + // 创建查询对象:用于获取该poNo的所有明细 + WmsPurchaseOrderDetailBo queryBo = new WmsPurchaseOrderDetailBo(); + queryBo.setPoNo(poNo); + + // 查询所有明细:用于计算完成状态 + List details = purchaseOrderDetailService.queryList(queryBo); + + // 初始化标志:allCompleted表示是否全部完成,partial表示是否部分完成 + boolean allCompleted = true; + boolean partial = false; + + // 遍历明细,判断每个物料的到货情况 + for (WmsPurchaseOrderDetailVo d : details) { + // 如果送货数量 < 采购数量,则未全部完成,但标记为部分完成 + if (d.getDeliveryQty().compareTo(d.getPurchaseQty()) < 0) { + allCompleted = false; + partial = true; + // 如果送货数量 > 采购数量,抛出异常,防止超入(业务约束) + } else if (d.getDeliveryQty().compareTo(d.getPurchaseQty()) > 0) { + throw new ServiceException("入库数量超过采购数量: poNo=" + poNo); + } + } + + // 根据标志计算新状态:"3"全部完成,"2"部分完成,"1"待采购 + // 此逻辑符合辩证思维,权衡多种情况 + String newStatus = allCompleted ? "3" : (partial ? "2" : "1"); + + // 创建更新对象:仅更新必要字段 + WmsPurchaseOrderBo orderBo = new WmsPurchaseOrderBo(); + orderBo.setPoNo(poNo); + orderBo.setPoStatus(newStatus); + + // 执行更新:调用服务层,确保事务内原子性 + purchaseOrderService.updateByBo(orderBo); + } +} + return orderVo; } @@ -477,6 +557,63 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService { if(isValid){ //TODO 做一些业务上的校验,判断是否需要校验 } + // 删除前处理采购类型入库单的逆向更新 + // 查询要删除的入库单 + for (Long instockId : ids) { + WmsInstockOrderVo order = queryById(instockId); + if (order != null && "1".equals(order.getInstockType())) { + // 查询子表明细 + WmsInstockDetailBo detailQuery = new WmsInstockDetailBo(); + detailQuery.setInstockId(instockId); + List details = wmsInstockDetailService.queryList(detailQuery); + + // 更新采购订单明细的deliveryQty(逆向减去instockQty) + Set updatedPoNos = new HashSet<>(); + for (WmsInstockDetailVo detail : details) { + if (detail.getPoDId() == null) { + throw new ServiceException("采购入库明细缺少poDId,无法逆向更新"); + } + WmsPurchaseOrderDetailVo existingDetail = purchaseOrderDetailService.queryById(detail.getPoDId()); + if (existingDetail == null) { + throw new ServiceException("采购明细不存在"); + } + BigDecimal currentDeliveryQty = existingDetail.getDeliveryQty() != null ? existingDetail.getDeliveryQty() : BigDecimal.ZERO; + BigDecimal newDeliveryQty = currentDeliveryQty.subtract(detail.getInstockQty()); + if (newDeliveryQty.compareTo(BigDecimal.ZERO) < 0) { + throw new ServiceException("逆向更新后送货数量为负:" ); + } + WmsPurchaseOrderDetailBo detailBo = new WmsPurchaseOrderDetailBo(); + detailBo.setPoDId(detail.getPoDId()); + detailBo.setDeliveryQty(newDeliveryQty); + purchaseOrderDetailService.updateByBo(detailBo); + updatedPoNos.add(existingDetail.getPoNo()); + } + + // 更新采购订单主表状态 + for (String poNo : updatedPoNos) { + WmsPurchaseOrderDetailBo queryBo = new WmsPurchaseOrderDetailBo(); + queryBo.setPoNo(poNo); + List poDetails = purchaseOrderDetailService.queryList(queryBo); + boolean allCompleted = true; + boolean partial = false; + for (WmsPurchaseOrderDetailVo d : poDetails) { + BigDecimal delivery = d.getDeliveryQty() != null ? d.getDeliveryQty() : BigDecimal.ZERO; + if (delivery.compareTo(d.getPurchaseQty()) < 0) { + allCompleted = false; + partial = true; + } else if (delivery.compareTo(d.getPurchaseQty()) > 0) { + throw new ServiceException("送货数量超过采购数量: poNo=" + poNo); + } + } + String newStatus = allCompleted ? "3" : (partial ? "2" : "1"); + WmsPurchaseOrderBo orderBo = new WmsPurchaseOrderBo(); + orderBo.setPoNo(poNo); + orderBo.setPoStatus(newStatus); + purchaseOrderService.updateByBo(orderBo); + } + } + } + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.in(WmsInstockOrder::getInstockId,ids); int delete = baseMapper.delete(wrapper);