From 9717670f760ffc4770fa9f5d6d18b50701c479a6 Mon Sep 17 00:00:00 2001 From: qiankanghui Date: Fri, 7 Aug 2026 10:52:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(inspection):=20=E6=96=B0=E5=A2=9E=E9=AA=8C?= =?UTF-8?q?=E8=B4=A7=E7=94=B3=E8=AF=B7=E6=98=8E=E7=BB=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在InspectionController中添加addDetails和editDetails接口 - 创建InspectionRequestAddDetailVO和InspectionRequestEditVO数据传输对象 - 在InspectionRequestDetailMapper中增加查询最大行号的方法 - 实现新增明细的业务逻辑,支持按PO明细分组累加数量 - 实现编辑明细的业务逻辑,先回滚原数量再插入新明细 - 添加站点验证和状态校验确保操作合规性 - 完善日志记录和异常处理机制 --- .../controller/InspectionController.java | 18 ++ .../data/InspectionRequestAddDetailVO.java | 27 ++ .../data/InspectionRequestEditVO.java | 27 ++ .../mapper/InspectionRequestDetailMapper.java | 5 + .../service/InspectionRequestService.java | 10 + .../impl/InspectionRequestServiceImpl.java | 267 +++++++++++++++++- .../InspectionRequestDetailMapper.xml | 8 + 7 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/xujie/modules/inspection/data/InspectionRequestAddDetailVO.java create mode 100644 src/main/java/com/xujie/modules/inspection/data/InspectionRequestEditVO.java diff --git a/src/main/java/com/xujie/modules/inspection/controller/InspectionController.java b/src/main/java/com/xujie/modules/inspection/controller/InspectionController.java index a93a4fd..9ed971b 100644 --- a/src/main/java/com/xujie/modules/inspection/controller/InspectionController.java +++ b/src/main/java/com/xujie/modules/inspection/controller/InspectionController.java @@ -134,6 +134,24 @@ public class InspectionController { return R.ok(); } + /** + * 新增验货申请明细 + */ + @PostMapping("/addDetails") + public R addDetails(@RequestBody InspectionRequestAddDetailVO vo){ + inspectionRequestService.addDetails(vo); + return R.ok(); + } + + /** + * 编辑验货申请明细 + */ + @PostMapping("/editDetails") + public R editDetails(@RequestBody InspectionRequestEditVO vo){ + inspectionRequestService.editDetails(vo); + return R.ok(); + } + /** * 修改验货申请(仅允许修改建议验货日期、验货地址和联系人) */ diff --git a/src/main/java/com/xujie/modules/inspection/data/InspectionRequestAddDetailVO.java b/src/main/java/com/xujie/modules/inspection/data/InspectionRequestAddDetailVO.java new file mode 100644 index 0000000..2844755 --- /dev/null +++ b/src/main/java/com/xujie/modules/inspection/data/InspectionRequestAddDetailVO.java @@ -0,0 +1,27 @@ +package com.xujie.modules.inspection.data; + +import lombok.Data; + +import java.util.List; + +/** + * 新增验货申请明细VO + */ +@Data +public class InspectionRequestAddDetailVO { + + /** + * 申请单号 + */ + private String requestNo; + + /** + * 站点/工厂编码 + */ + private String site; + + /** + * 要新增的明细列表 + */ + private List items; +} diff --git a/src/main/java/com/xujie/modules/inspection/data/InspectionRequestEditVO.java b/src/main/java/com/xujie/modules/inspection/data/InspectionRequestEditVO.java new file mode 100644 index 0000000..a149c3b --- /dev/null +++ b/src/main/java/com/xujie/modules/inspection/data/InspectionRequestEditVO.java @@ -0,0 +1,27 @@ +package com.xujie.modules.inspection.data; + +import lombok.Data; + +import java.util.List; + +/** + * 编辑验货申请明细VO + */ +@Data +public class InspectionRequestEditVO { + + /** + * 申请单号(前端传入) + */ + private String requestNo; + + /** + * 站点/工厂编码(前端传入,可选) + */ + private String site; + + /** + * 新的明细列表(替换原有明细) + */ + private List items; +} diff --git a/src/main/java/com/xujie/modules/inspection/mapper/InspectionRequestDetailMapper.java b/src/main/java/com/xujie/modules/inspection/mapper/InspectionRequestDetailMapper.java index dca706a..fc69c00 100644 --- a/src/main/java/com/xujie/modules/inspection/mapper/InspectionRequestDetailMapper.java +++ b/src/main/java/com/xujie/modules/inspection/mapper/InspectionRequestDetailMapper.java @@ -104,4 +104,9 @@ public interface InspectionRequestDetailMapper extends BaseMapper poInfo = poDetailMapper.getPoDetailInspectInfo( + Map poInfo = poDetailMapper.getPoDetailInspectInfo( site, item.getOrderNo(), item.getItemNo()); int updateCount = poDetailMapper.lockInspectQty( @@ -279,6 +279,271 @@ public class InspectionRequestServiceImpl extends ServiceImpl> groupMap = + vo.getItems() + .stream() + .peek(item -> { + // 如果itemNo为null,使用poItemNo作为备选 + if (item.getItemNo() == null && item.getPoItemNo() != null) { + item.setItemNo(item.getPoItemNo()); + } + }) + .collect(Collectors.groupingBy( + item -> item.getOrderNo() + "|" + item.getItemNo(), + LinkedHashMap::new, + Collectors.toList() + )); + + // 5. 遍历分组,生成Detail和Sub + for (Map.Entry> entry : groupMap.entrySet()) { + List subList = entry.getValue(); + InspectionRequestItemVO firstItem = subList.get(0); + + // 计算该PO明细的总数量(累加) + BigDecimal totalQty = BigDecimal.ZERO; + for (InspectionRequestItemVO item : subList) { + totalQty = totalQty.add(item.getQty()); + } + + // 使用第一条数据的其他字段,但数量用累加后的总数 + InspectionRequestItemVO mergedItem = new InspectionRequestItemVO(); + mergedItem.setOrderNo(firstItem.getOrderNo()); + mergedItem.setItemNo(firstItem.getItemNo()); + mergedItem.setOrderRef1(firstItem.getOrderRef1()); + mergedItem.setOrderRef2(firstItem.getOrderRef2()); + mergedItem.setPartNo(firstItem.getPartNo()); + mergedItem.setQty(totalQty); // 使用累加后的数量 + mergedItem.setShipMethod(firstItem.getShipMethod()); + mergedItem.setCrd(firstItem.getCrd()); + + // 查询当前PO明细的待验货数量信息 + java.util.Map poInfo = poDetailMapper.getPoDetailInspectInfo( + site, mergedItem.getOrderNo(), mergedItem.getItemNo()); + + // 锁定验货数量(使用累加后的总数量) + int updateCount = poDetailMapper.lockInspectQty( + site, + mergedItem.getOrderNo(), + mergedItem.getItemNo(), + mergedItem.getQty() + ); + + if (updateCount == 0) { + log.error("锁定验货数量失败: orderNo={}, itemNo={}, qty={}", + mergedItem.getOrderNo(), mergedItem.getItemNo(), mergedItem.getQty()); + throw new RuntimeException( + "PO:" + mergedItem.getOrderNo() + + " 行:" + mergedItem.getItemNo() + + " 待验货数量不足" + ); + } + + // 保存Sub + InspectionRequestDetailSub sub = new InspectionRequestDetailSub(); + sub.setSite(site); + sub.setRequestNo(requestNo); + sub.setItemNo(requestItemNo); + sub.setPoNo(mergedItem.getOrderNo()); + sub.setPoItemNo(mergedItem.getItemNo()); + sub.setPartNo(mergedItem.getPartNo()); + sub.setQty(mergedItem.getQty()); // 使用累加后的数量 + sub.setOrderRef1(mergedItem.getOrderRef1()); + sub.setOrderRef2(mergedItem.getOrderRef2()); + sub.setShipMothod(mergedItem.getShipMethod()); + sub.setCrd(mergedItem.getCrd()); + + // 计算数量是否变更 + Object qtyObj = poInfo.get("waitInspectQty"); + BigDecimal originQty = qtyObj == null ? BigDecimal.ZERO : new BigDecimal(qtyObj.toString()); + BigDecimal reqQty = mergedItem.getQty() == null ? BigDecimal.ZERO : mergedItem.getQty(); + boolean isChanged = reqQty.compareTo(originQty) != 0; + sub.setIsChanged(isChanged ? "Y" : "N"); + + inspectionRequestDetailSubMapper.insert(sub); + + // 5.2 保存Detail汇总 + InspectionRequestDetail detail = new InspectionRequestDetail(); + detail.setSite(site); + detail.setRequestNo(requestNo); + detail.setItemNo(requestItemNo); + detail.setOrderRef1(mergedItem.getOrderRef1()); + detail.setPartNo(mergedItem.getPartNo()); + detail.setQty(totalQty); // 使用累加后的数量 + detail.setStatus("草稿"); + detail.setStatusDb("Draft"); + inspectionRequestDetailMapper.insert(detail); + + requestItemNo++; + } + + log.info("新增验货申请明细完成: site={}, requestNo={}, 新增明细数量={}", + site, requestNo, vo.getItems().size()); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void editDetails(InspectionRequestEditVO vo) { + if (vo == null || !StringUtils.hasText(vo.getRequestNo())) { + throw new RuntimeException("申请单号不能为空"); + } + if (vo.getItems() == null || vo.getItems().isEmpty()) { + throw new RuntimeException("明细列表不能为空"); + } + + String site = vo.getSite(); + if (!StringUtils.hasText(site)) { + SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal(); + site = user.getSite(); + } + String requestNo = vo.getRequestNo().trim(); + + // 1. 校验头表是否存在 + InspectionRequestHeader header = baseMapper.selectByRequestNo(site, requestNo); + if (header == null) { + throw new RuntimeException("检验申请单不存在: " + requestNo); + } + + // 2. 只有草稿和待审核状态允许编辑明细 + if (!"Draft".equals(header.getStatusDb()) && !"Confirmed".equals(header.getStatusDb())) { + throw new RuntimeException("只有草稿和待审核状态的验货申请允许编辑明细,当前状态:" + header.getStatus()); + } + + log.info("开始编辑验货申请明细: site={}, requestNo={}", site, requestNo); + + // 3. 回滚原明细数量并删除 + List oldSubList = + inspectionRequestDetailSubMapper.selectByRequestNo(site, requestNo); + + for (InspectionRequestDetailSub sub : oldSubList) { + int count = poDetailMapper.rollbackInspectQty( + site, + sub.getPoNo(), + sub.getPoItemNo(), + sub.getQty() + ); + + if (count == 0) { + throw new RuntimeException( + "回退PO待验货数量失败:" + sub.getPoNo() + + "-" + sub.getPoItemNo() + ); + } + } + + // 4. 删除原有明细记录 + int subDeleteCount = inspectionRequestDetailSubMapper.deleteByRequestNo(site, requestNo); + int detailDeleteCount = inspectionRequestDetailMapper.deleteByRequestNo(site, requestNo); + + log.info("删除原有明细完成: subDeleteCount={}, detailDeleteCount={}", subDeleteCount, detailDeleteCount); + + // 5. 插入新明细并锁定数量(不复用addDetails,避免分组合并) + int requestItemNo = 1; + for (InspectionRequestItemVO item : vo.getItems()) { + // 如果itemNo为null,使用poItemNo作为备选 + if (item.getItemNo() == null && item.getPoItemNo() != null) { + item.setItemNo(item.getPoItemNo()); + } + + // 查询当前PO明细的待验货数量信息 + java.util.Map poInfo = poDetailMapper.getPoDetailInspectInfo( + site, item.getOrderNo(), item.getItemNo()); + + // 锁定验货数量 + int updateCount = poDetailMapper.lockInspectQty( + site, + item.getOrderNo(), + item.getItemNo(), + item.getQty() + ); + + if (updateCount == 0) { + log.error("锁定验货数量失败: orderNo={}, itemNo={}, qty={}", + item.getOrderNo(), item.getItemNo(), item.getQty()); + throw new RuntimeException( + "PO:" + item.getOrderNo() + + " 行:" + item.getItemNo() + + " 待验货数量不足" + ); + } + + // 保存Sub + InspectionRequestDetailSub sub = new InspectionRequestDetailSub(); + sub.setSite(site); + sub.setRequestNo(requestNo); + sub.setItemNo(requestItemNo); + sub.setPoNo(item.getOrderNo()); + sub.setPoItemNo(item.getItemNo()); + sub.setPartNo(item.getPartNo()); + sub.setQty(item.getQty()); + sub.setOrderRef1(item.getOrderRef1()); + sub.setOrderRef2(item.getOrderRef2()); + sub.setShipMothod(item.getShipMethod()); + sub.setCrd(item.getCrd()); + + // 计算数量是否变更 + Object qtyObj = poInfo.get("waitInspectQty"); + BigDecimal originQty = qtyObj == null ? BigDecimal.ZERO : new BigDecimal(qtyObj.toString()); + BigDecimal reqQty = item.getQty() == null ? BigDecimal.ZERO : item.getQty(); + boolean isChanged = reqQty.compareTo(originQty) != 0; + sub.setIsChanged(isChanged ? "Y" : "N"); + + inspectionRequestDetailSubMapper.insert(sub); + + // 保存Detail汇总 + InspectionRequestDetail detail = new InspectionRequestDetail(); + detail.setSite(site); + detail.setRequestNo(requestNo); + detail.setItemNo(requestItemNo); + detail.setOrderRef1(item.getOrderRef1()); + detail.setPartNo(item.getPartNo()); + detail.setQty(item.getQty()); + detail.setStatus("草稿"); + detail.setStatusDb("Draft"); + inspectionRequestDetailMapper.insert(detail); + + requestItemNo++; + } + + log.info("编辑验货申请明细完成: site={}, requestNo={}, 新明细数量={}", + site, requestNo, vo.getItems().size()); + } + @Transactional(rollbackFor = Exception.class) @Override public void cancel(String requestNo) { diff --git a/src/main/resources/mapper/inspection/InspectionRequestDetailMapper.xml b/src/main/resources/mapper/inspection/InspectionRequestDetailMapper.xml index 7574e07..28b3051 100644 --- a/src/main/resources/mapper/inspection/InspectionRequestDetailMapper.xml +++ b/src/main/resources/mapper/inspection/InspectionRequestDetailMapper.xml @@ -278,4 +278,12 @@ AND item_no = #{itemNo} + + +