From 3b8b92942a75bb48240a85dc46dc9a5723b84d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=B9=E9=B9=8F=E9=A3=9E?= Date: Tue, 3 Mar 2026 17:56:54 +0800 Subject: [PATCH] =?UTF-8?q?refactor(storage):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=82=A8=E4=BD=8D=E7=AE=A1=E7=90=86=E5=92=8C=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=B1=82=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将getBinNos方法改为getBinNo,统一返回单个储位编号 - 移除SAP服务集成相关的代码逻辑 - 更新InCostCenterBackController中的储位获取逻辑 - 添加仓库位置启用状态检查功能 - 重构入库记录中的二维码处理流程 - 引入条码处理阶段常量进行状态管理 - 优化InProduceBackController中的储位设置逻辑 - 更新生产订单控制器中的入库处理逻辑 - 调整物料扫描记录中的储位字段为单一值 - 修改多个控制器中的资源注入方式 - 更新物料退料提交对象的数据结构 - 优化条码主数据的状态更新机制 - 调整物料清单控制器中的删除操作事务处理 - 修复Excel导入验证条件的逻辑错误 - 优化包装数量计算使用统一工具类方法 --- .../InCostCenterBackController.java | 100 +++++++++------ .../controller/InProduceBackController.java | 121 +++++++++++------- .../controller/InProduceOrderController.java | 99 +++++++++----- .../InProduceOrderSurplusController.java | 66 +++++----- .../controller/OutPurchaseController.java | 2 +- .../StructuralPackageOrderController.java | 2 +- .../controller/TransferCompanyController.java | 4 +- .../controller/TransferFactoryController.java | 13 +- .../nflg/wms/admin/service/BinService.java | 19 +-- .../pojo/document/InMaterialScanRecord.java | 4 +- .../pojo/qo/InCostcenterBackSubmitItemQO.java | 10 +- .../qo/InCostcenterBackSubmitItemQRQO.java | 21 +++ .../common/pojo/qo/InProduceBackSubmitQO.java | 4 +- .../qo/InProduceOrderReceiveMaterialQO.java | 11 +- .../pojo/qo/InProduceOrderReceiveQO.java | 2 +- .../common/pojo/vo/InProduceOrderItemVO.java | 2 +- .../wms/common/pojo/vo/OutProduceItemVO.java | 6 + .../repository/mapper/WmsStorageMapper.java | 2 +- .../repository/mapper/WmsWarehouseMapper.java | 2 + .../service/IWmsStorageService.java | 2 +- .../service/IWmsWarehouseService.java | 2 + .../service/impl/WmsStorageServiceImpl.java | 4 +- .../service/impl/WmsWarehouseServiceImpl.java | 5 + .../resources/mapper/WmsStorageMapper.xml | 2 +- .../resources/mapper/WmsWarehouseMapper.xml | 7 + .../controller/MaterialCodeController.java | 73 +++++++---- .../template/物料码打印导出模板.xlsx | Bin 12638 -> 12727 bytes 27 files changed, 365 insertions(+), 220 deletions(-) create mode 100644 nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InCostcenterBackSubmitItemQRQO.java diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InCostCenterBackController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InCostCenterBackController.java index 6d86354b..988691fe 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InCostCenterBackController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InCostCenterBackController.java @@ -13,6 +13,7 @@ import com.nflg.wms.admin.util.NoUtil; import com.nflg.wms.admin.util.PdfGeneratorUtil; import com.nflg.wms.admin.util.QRCodeUtil; import com.nflg.wms.admin.util.ThymeleafUtil; +import com.nflg.wms.common.constant.BarCodeProcessStage; import com.nflg.wms.common.pojo.ApiResult; import com.nflg.wms.common.pojo.PageData; import com.nflg.wms.common.pojo.document.InMaterialScanRecord; @@ -24,10 +25,7 @@ import com.nflg.wms.common.pojo.qo.*; import com.nflg.wms.common.pojo.vo.*; import com.nflg.wms.common.util.UserUtil; import com.nflg.wms.common.util.VUtil; -import com.nflg.wms.repository.entity.WmsInCostcenterBack; -import com.nflg.wms.repository.entity.WmsInCostcenterBackItem; -import com.nflg.wms.repository.entity.WmsInCostcenterBackTicket; -import com.nflg.wms.repository.entity.WmsInCostcenterBackTicketItem; +import com.nflg.wms.repository.entity.*; import com.nflg.wms.repository.service.*; import com.nflg.wms.starter.BaseController; import jakarta.annotation.Resource; @@ -80,6 +78,12 @@ public class InCostCenterBackController extends BaseController { @Resource private BasdeSerialNumberControllerService serialNumberControllerService; + @Resource + private IWmsWarehouseService warehouseService; + + @Resource + private IWmsQrCodeMasterService qrCodeMasterService; + /** * 查询SAP领料订单数据 */ @@ -181,9 +185,8 @@ public class InCostCenterBackController extends BaseController { if (StrUtil.isBlank(vo.getLgort2())) { vo.setLgort2(CollectionUtil.get(storageService.getWarehouseNo(order.getWerks(), item.getMatnr()), 0)); } - if (StrUtil.isNotBlank(vo.getLgort2()) && StrUtil.isBlank(vo.getLgpbe())) { - vo.setLgpbe(StrUtil.join("/", storageService.getBinNos(item.getMatnr(), order.getWerks(), vo.getLgort2()))); - } + vo.setLgpbe(storageService.getBinNo(item.getMatnr(), order.getWerks(), vo.getLgort2())); + vo.setIsDisableLocation(warehouseService.isEnableLocation(order.getWerks(), vo.getLgort2())); return vo; }).toList() ) @@ -208,8 +211,17 @@ public class InCostCenterBackController extends BaseController { .setCreateTime(LocalDateTime.now()); List datas = inCostcenterBackItemService.getList(order.getId()); List records = new ArrayList<>(); -// List dtos = new ArrayList<>(); List ticketItems = new ArrayList<>(); + Set allQrCodes = new HashSet<>(); + request.getItems().forEach(it -> { + it.getItems().forEach(item -> { + allQrCodes.addAll(item.getQrCodes()); + }); + }); + List qrCodeMasters = qrCodeMasterService.lambdaQuery() + .lt(WmsQrCodeMaster::getProcessStage, BarCodeProcessStage.InBound.getState()) + .in(WmsQrCodeMaster::getBarcodeCode, allQrCodes) + .list(); request.getItems().forEach(it -> { WmsInCostcenterBackItem item = datas.stream().filter(d -> Objects.equals(it.getOrderItemId(), d.getId())).findFirst().orElse(null); VUtil.trueThrowBusinessError(Objects.isNull(item)).throwMessage("订单项无效"); @@ -217,40 +229,52 @@ public class InCostCenterBackController extends BaseController { .setId(IdUtil.getSnowflakeNextId()) .setTicketId(ticket.getId()) .setOrderItemId(item.getId()) - .setLgpbe(StrUtil.join(",", it.getBinNos())) + .setLgpbe(StrUtil.join(",", it.getItems().stream().map(InCostcenterBackSubmitItemQRQO::getBinNo).toList())) .setNum(BigDecimal.ZERO); ticketItems.add(ti); - it.getQrCodes().forEach(qrCode -> { - MaterialQRCodeContentDTO qrCodeContent = NoUtil.getMaterialQRCodeContent(qrCode); -// dtos.add(qrCodeContent); - String materialNo = qrCodeContent.getMaterialNo(); - VUtil.trueThrowBusinessError(!StrUtil.equals(materialNo, item.getMatnr())) - .throwMessage("订单项与物料不符"); - item.setLeft(item.getLeft().subtract(qrCodeContent.getNum())); - VUtil.trueThrowBusinessError(item.getLeft().compareTo(BigDecimal.ZERO) < 0) - .throwMessage("物料" + materialNo + "的入库数量超出申请数量"); - ti.setNum(ti.getNum().add(qrCodeContent.getNum())); - records.add(new InMaterialScanRecord() - .setSource(2) - .setSourceId(order.getId()) - .setSourceItemId(item.getId()) - .setTicketItemId(ti.getId()) - .setMaterialNo(materialNo) - .setContent(qrCode) - .setBatchNo(qrCodeContent.getBatchNo()) - .setSerialNo(qrCodeContent.getSerialNo()) - .setFactoryNo(order.getWerks()) - .setWarehouseNo(request.getLgort()) - .setBinNos(StrUtil.split(it.getBinNos(), "/")) - .setUniqNo(qrCodeContent.getUniqNo()) - .setNum(qrCodeContent.getNum()) - .setCreateBy(UserUtil.getUserName()) - .setCreateTime(Instant.now()) - ); + it.getItems().forEach(iit -> { + iit.getQrCodes().forEach(qrCode -> { + MaterialQRCodeContentDTO qrCodeContent = NoUtil.getMaterialQRCodeContent(qrCode); + String materialNo = qrCodeContent.getMaterialNo(); + VUtil.trueThrowBusinessError(!StrUtil.equals(materialNo, item.getMatnr())) + .throwMessage("订单项与物料不符"); + item.setLeft(item.getLeft().subtract(qrCodeContent.getNum())); + VUtil.trueThrowBusinessError(item.getLeft().compareTo(BigDecimal.ZERO) < 0) + .throwMessage("物料" + materialNo + "的入库数量超出申请数量"); + ti.setNum(ti.getNum().add(qrCodeContent.getNum())); + records.add(new InMaterialScanRecord() + .setSource(2) + .setSourceId(order.getId()) + .setSourceItemId(item.getId()) + .setTicketItemId(ti.getId()) + .setMaterialNo(materialNo) + .setContent(qrCode) + .setBatchNo(qrCodeContent.getBatchNo()) + .setSerialNo(qrCodeContent.getSerialNo()) + .setFactoryNo(order.getWerks()) + .setWarehouseNo(request.getLgort()) + .setBinNo(iit.getBinNo()) + .setUniqNo(qrCodeContent.getUniqNo()) + .setNum(qrCodeContent.getNum()) + .setCreateBy(UserUtil.getUserName()) + .setCreateTime(Instant.now()) + ); + WmsQrCodeMaster qrCodeMaster = qrCodeMasters.stream() + .filter(q -> StrUtil.equals(q.getBarcodeCode(), qrCode)) + .findFirst() + .orElse(null); + VUtil.trueThrowBusinessError(Objects.isNull(qrCodeMaster)).throwMessage("二维码" + qrCode + "无效"); + qrCodeMaster.setProcessStage(BarCodeProcessStage.InBound.getState()); + qrCodeMaster.setFactoryCode(order.getWerks()); + qrCodeMaster.setStorageLocation(request.getLgort()); + qrCodeMaster.setBinLocation(iit.getBinNo()); + qrCodeMaster.setLastScanBy(UserUtil.getUserId()); + qrCodeMaster.setLastScanByname(UserUtil.getUserName()); + qrCodeMaster.setLastScanTime(LocalDateTime.now()); + }); }); }); inCostcenterBackItemService.updateBatchById(datas); - inMaterialScanRecordRespository.saveAll(records); inCostcenterBackTicketItemService.saveBatch(ticketItems); inCostcenterBackService.lambdaUpdate() .set(WmsInCostcenterBack::getSapStatus, true) @@ -260,6 +284,7 @@ public class InCostCenterBackController extends BaseController { .set(WmsInCostcenterBack::getState, datas.stream().map(WmsInCostcenterBackItem::getLeft).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(BigDecimal.ZERO) > 0 ? 1 : 2) .eq(WmsInCostcenterBack::getId, order.getId()) .update(); + qrCodeMasterService.updateBatchById(qrCodeMasters); inventoryService.in(records.stream() .collect(Collectors.groupingBy(InMaterialScanRecord::getKey)) .values() @@ -299,6 +324,7 @@ public class InCostCenterBackController extends BaseController { ticket.setDocYear(vo.getEMJahr()); ticket.setMatDoc(vo.getEMblnr()); inCostcenterBackTicketService.save(ticket); + inMaterialScanRecordRespository.saveAll(records); return ApiResult.success(); } diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceBackController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceBackController.java index 14b3c628..3b16960b 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceBackController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceBackController.java @@ -15,6 +15,7 @@ import com.nflg.wms.admin.util.NoUtil; import com.nflg.wms.admin.util.PdfGeneratorUtil; import com.nflg.wms.admin.util.QRCodeUtil; import com.nflg.wms.admin.util.ThymeleafUtil; +import com.nflg.wms.common.constant.BarCodeProcessStage; import com.nflg.wms.common.pojo.ApiResult; import com.nflg.wms.common.pojo.PageData; import com.nflg.wms.common.pojo.document.InMaterialScanRecord; @@ -23,10 +24,7 @@ import com.nflg.wms.common.pojo.qo.*; import com.nflg.wms.common.pojo.vo.*; import com.nflg.wms.common.util.UserUtil; import com.nflg.wms.common.util.VUtil; -import com.nflg.wms.repository.entity.WmsInProduceBack; -import com.nflg.wms.repository.entity.WmsInProduceBackItem; -import com.nflg.wms.repository.entity.WmsInProduceBackTicket; -import com.nflg.wms.repository.entity.WmsInProduceBackTicketItem; +import com.nflg.wms.repository.entity.*; import com.nflg.wms.repository.service.*; import com.nflg.wms.starter.BaseController; import jakarta.annotation.Resource; @@ -76,6 +74,15 @@ public class InProduceBackController extends BaseController { @Resource private BasdeSerialNumberControllerService serialNumberControllerService; + @Resource + private IWmsQrCodeMasterService qrCodeMasterService; + + @Resource + private IWmsStorageService storageService; + + @Resource + private IWmsWarehouseService warehouseService; + /** * 查询SAP领料订单数据 */ @@ -185,10 +192,11 @@ public class InProduceBackController extends BaseController { .map(item -> new OutProduceItemVO() .setId(item.getId()) .setLgort2(order.getLgort2()) - .setLgpbe(item.getLgpbe()) + .setLgpbe(storageService.getBinNo(item.getMatnr(), order.getDwerk(), order.getLgort2())) .setMaktx2(item.getMaktx2()) .setMatnr(item.getMatnr()) .setNum(item.getSqsl().subtract(item.getNum())) + .setIsDisableLocation(warehouseService.isEnableLocation(order.getDwerk(), order.getLgort2())) ).toList() ) ); @@ -213,55 +221,77 @@ public class InProduceBackController extends BaseController { // List dtos = new ArrayList<>(); List ticketItems = new ArrayList<>(); Multimap input2 = ArrayListMultimap.create(); - request.getQrCodes().forEach(qrCode -> { - MaterialQRCodeContentDTO qrCodeContent = NoUtil.getMaterialQRCodeContent(qrCode); + Set allQrCodes = new HashSet<>(); + request.getItems().forEach(it -> { + allQrCodes.addAll(it.getQrCodes()); + }); + List qrCodeMasters = qrCodeMasterService.lambdaQuery() + .lt(WmsQrCodeMaster::getProcessStage, BarCodeProcessStage.InBound.getState()) + .in(WmsQrCodeMaster::getBarcodeCode, allQrCodes) + .list(); + request.getItems().forEach(iit -> { + iit.getQrCodes().forEach(qrCode -> { + MaterialQRCodeContentDTO qrCodeContent = NoUtil.getMaterialQRCodeContent(qrCode); // dtos.add(qrCodeContent); - String materialNo = qrCodeContent.getMaterialNo(); - WmsInProduceBackItem item = datas.stream().filter(d -> StrUtil.equals(d.getMatnr(), materialNo)).findFirst().orElse(null); - VUtil.trueThrowBusinessError(Objects.isNull(item)).throwMessage("物料" + materialNo + "不需要退料"); + String materialNo = qrCodeContent.getMaterialNo(); + WmsInProduceBackItem item = datas.stream().filter(d -> StrUtil.equals(d.getMatnr(), materialNo)).findFirst().orElse(null); + VUtil.trueThrowBusinessError(Objects.isNull(item)).throwMessage("物料" + materialNo + "不需要退料"); // VUtil.trueThrowBusinessError(List.of("3","4").contains(item.getLbprt()) && StrUtil.isBlank(qrCodeContent.getSerialNo())) // .throwMessage("物料" + materialNo + "必须有序列号"); // if (List.of("3","4").contains(item.getLbprt())){ // input2.put(item.getRspos(),qrCodeContent.getSerialNo()); // } - input2.put(item.getRspos(), qrCodeContent.getSerialNo()); - WmsInProduceBackTicketItem pti = ticketItems.stream() - .filter(ti -> Objects.equals(ti.getProduceBackItemId(), item.getId())) - .findFirst() - .orElseGet(() -> { - WmsInProduceBackTicketItem ti = new WmsInProduceBackTicketItem() - .setId(IdUtil.getSnowflakeNextId()) - .setTicketId(ticket.getId()) - .setProduceBackItemId(item.getId()) - .setNum(BigDecimal.ZERO); - ticketItems.add(ti); - return ti; - }); - BigDecimal num = item.getSqsl().subtract(item.getNum()); - VUtil.trueThrowBusinessError(num.compareTo(qrCodeContent.getNum()) < 0) - .throwMessage("物料" + materialNo + "的入库数量超出申请数量"); - item.setNum(item.getNum().add(qrCodeContent.getNum())); - pti.setNum(pti.getNum().add(qrCodeContent.getNum())); - records.add(new InMaterialScanRecord() - .setSource(1) - .setSourceId(order.getId()) - .setSourceItemId(item.getId()) - .setTicketItemId(pti.getId()) - .setMaterialNo(materialNo) - .setContent(qrCode) - .setBatchNo(qrCodeContent.getBatchNo()) - .setSerialNo(qrCodeContent.getSerialNo()) - .setUniqNo(qrCodeContent.getUniqNo()) - .setFactoryNo(order.getDwerk()) - .setWarehouseNo(request.getLgort()) + input2.put(item.getRspos(), qrCodeContent.getSerialNo()); + WmsInProduceBackTicketItem pti = ticketItems.stream() + .filter(ti -> Objects.equals(ti.getProduceBackItemId(), item.getId())) + .findFirst() + .orElseGet(() -> { + WmsInProduceBackTicketItem ti = new WmsInProduceBackTicketItem() + .setId(IdUtil.getSnowflakeNextId()) + .setTicketId(ticket.getId()) + .setProduceBackItemId(item.getId()) + .setNum(BigDecimal.ZERO); + ticketItems.add(ti); + return ti; + }); + BigDecimal num = item.getSqsl().subtract(item.getNum()); + VUtil.trueThrowBusinessError(num.compareTo(qrCodeContent.getNum()) < 0) + .throwMessage("物料" + materialNo + "的入库数量超出申请数量"); + item.setNum(item.getNum().add(qrCodeContent.getNum())); + pti.setNum(pti.getNum().add(qrCodeContent.getNum())); + records.add(new InMaterialScanRecord() + .setSource(1) + .setSourceId(order.getId()) + .setSourceItemId(item.getId()) + .setTicketItemId(pti.getId()) + .setMaterialNo(materialNo) + .setContent(qrCode) + .setBatchNo(qrCodeContent.getBatchNo()) + .setSerialNo(qrCodeContent.getSerialNo()) + .setUniqNo(qrCodeContent.getUniqNo()) + .setFactoryNo(order.getDwerk()) + .setWarehouseNo(request.getLgort()) // .setBinNos(StrUtil.split(it.getBinNos(), "/")) - .setNum(qrCodeContent.getNum()) - .setCreateBy(UserUtil.getUserName()) - .setCreateTime(Instant.now()) - ); + .setNum(qrCodeContent.getNum()) + .setCreateBy(UserUtil.getUserName()) + .setCreateTime(Instant.now()) + ); + WmsQrCodeMaster qrCodeMaster = qrCodeMasters.stream() + .filter(q -> StrUtil.equals(q.getBarcodeCode(), qrCode)) + .findFirst() + .orElse(null); + VUtil.trueThrowBusinessError(Objects.isNull(qrCodeMaster)).throwMessage("二维码" + qrCode + "无效"); + qrCodeMaster.setProcessStage(BarCodeProcessStage.InBound.getState()); + qrCodeMaster.setFactoryCode(order.getDwerk()); + qrCodeMaster.setStorageLocation(request.getLgort()); + qrCodeMaster.setBinLocation(iit.getBinNo()); + qrCodeMaster.setLastScanBy(UserUtil.getUserId()); + qrCodeMaster.setLastScanByname(UserUtil.getUserName()); + qrCodeMaster.setLastScanTime(LocalDateTime.now()); + }); }); inProduceBackItemService.updateBatchById(datas); - inMaterialScanRecordRespository.saveAll(records); + qrCodeMasterService.updateBatchById(qrCodeMasters); inProduceBackTicketItemService.saveBatch(ticketItems); inventoryService.in(records.stream() .collect(Collectors.groupingBy(InMaterialScanRecord::getKey)) @@ -310,6 +340,7 @@ public class InProduceBackController extends BaseController { .set(WmsInProduceBack::getState, inNum.compareTo(totalNum) >= 0 ? 2 : 1) .eq(WmsInProduceBack::getId, order.getId()) .update(); + inMaterialScanRecordRespository.saveAll(records); return ApiResult.success(); } diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceOrderController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceOrderController.java index 4f5de08f..ecaec29d 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceOrderController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceOrderController.java @@ -108,6 +108,12 @@ public class InProduceOrderController extends BaseController { @Resource private IWmsQrCodeMasterService qrCodeMasterService; + @Resource + private IWmsStorageService storageService; + + @Resource + private IWmsWarehouseService warehouseService; + /** * 从SAP查询生产订单信息 * @param no 生产订单号 @@ -367,21 +373,21 @@ public class InProduceOrderController extends BaseController { if (Objects.equals(type, 0)) { child.setMustScan(false); } - child.setBinNos(binService.getBinNos(child.getMaterialNo(), child.getFactoryNo(), child.getWarehouseNo())); + child.setBinNo(binService.getBinNo(child.getMaterialNo(), child.getFactoryNo(), child.getWarehouseNo())); }); datas.addAll(children); }); return ApiResult.success(datas); } else { list.forEach(it -> { - it.setBinNos(binService.getBinNos(it.getMaterialNo(), it.getFactoryNo(), it.getWarehouseNo())); + it.setBinNo(binService.getBinNo(it.getMaterialNo(), it.getFactoryNo(), it.getWarehouseNo())); }); return ApiResult.success(list); } } /** - * 收货(PDA使用) + * 入库(PDA使用) * @param request 请求参数 */ @Transactional @@ -413,8 +419,18 @@ public class InProduceOrderController extends BaseController { List materialNos = new ArrayList<>(); List records = new ArrayList<>(); Map warehouseNoChange = new HashMap<>(); + Set allQrCodes = new HashSet<>(); + request.getMaterials().forEach(it -> { + it.getItems().forEach(item -> { + allQrCodes.addAll(item.getQrCodes()); + }); + }); + List qrCodeMasters = CollectionUtil.isEmpty(allQrCodes) ? Collections.emptyList() : qrCodeMasterService.lambdaQuery() + .lt(WmsQrCodeMaster::getProcessStage, BarCodeProcessStage.InBound.getState()) + .in(WmsQrCodeMaster::getBarcodeCode, allQrCodes) + .list(); datas.forEach(it -> { - InProduceOrderReceiveMaterialQO materialQO = request.getItems() + InProduceOrderReceiveMaterialQO materialQO = request.getMaterials() .stream() .filter(q -> StrUtil.equals(q.getMaterialNo(), it.getMaterialNo())) .findFirst() @@ -422,7 +438,7 @@ public class InProduceOrderController extends BaseController { if (Objects.isNull(materialQO)) { materialNos.add(it.getMaterialNo()); } else { - VUtil.trueThrowBusinessError(it.isMustScan() && CollectionUtil.isEmpty(materialQO.getQrCodes())) + VUtil.trueThrowBusinessError(it.isMustScan() && CollectionUtil.isEmpty(materialQO.getItems())) .throwMessage(materialQO.getMaterialNo() + "需要提供扫码信息"); if (!StrUtil.equals(it.getWarehouseNo(), materialQO.getWarehouseNo())) { warehouseNoChange.put(it.getId(), materialQO.getWarehouseNo()); @@ -437,34 +453,48 @@ public class InProduceOrderController extends BaseController { } } if (it.isMustScan()) { - BigDecimal num = BigDecimal.ZERO; - for (String qrCode : materialQO.getQrCodes()) { - MaterialQRCodeContentDTO content = NoUtil.getMaterialQRCodeContent(qrCode); - if (Objects.nonNull(content.getNum())) { - num = num.add(content.getNum()); + materialQO.getItems().forEach(item -> { + BigDecimal num = BigDecimal.ZERO; + for (String qrCode : item.getQrCodes()) { + MaterialQRCodeContentDTO content = NoUtil.getMaterialQRCodeContent(qrCode); + if (Objects.nonNull(content.getNum())) { + num = num.add(content.getNum()); + } + records.add(new InMaterialScanRecord() + .setSource(4) + .setSourceId(order.getId()) + .setSourceItemId(it.getId()) + .setTicketItemId(it.getId()) + .setMaterialNo(it.getMaterialNo()) + .setContent(qrCode) + .setBatchNo(content.getBatchNo()) + .setSerialNo(content.getSerialNo()) + .setUniqNo(content.getUniqNo()) + .setFactoryNo(it.getFactoryNo()) + .setWarehouseNo(it.getWarehouseNo()) + .setBinNo(item.getBinNo()) + .setNum(content.getNum()) + .setUnit(it.getUnit()) + .setCreateBy(UserUtil.getUserName()) + .setCreateTime(Instant.now()) + ); + WmsQrCodeMaster qrCodeMaster = qrCodeMasters.stream() + .filter(q -> StrUtil.equals(q.getBarcodeCode(), qrCode)) + .findFirst() + .orElse(null); + VUtil.trueThrowBusinessError(Objects.isNull(qrCodeMaster)).throwMessage("二维码" + qrCode + "无效"); + qrCodeMaster.setProcessStage(BarCodeProcessStage.InBound.getState()); + qrCodeMaster.setFactoryCode(it.getFactoryNo()); + qrCodeMaster.setStorageLocation(it.getWarehouseNo()); + qrCodeMaster.setBinLocation(item.getBinNo()); + qrCodeMaster.setLastScanBy(UserUtil.getUserId()); + qrCodeMaster.setLastScanByname(UserUtil.getUserName()); + qrCodeMaster.setLastScanTime(LocalDateTime.now()); } - records.add(new InMaterialScanRecord() - .setSource(4) - .setSourceId(order.getId()) - .setSourceItemId(it.getId()) - .setTicketItemId(it.getId()) - .setMaterialNo(it.getMaterialNo()) - .setContent(qrCode) - .setBatchNo(content.getBatchNo()) - .setSerialNo(content.getSerialNo()) - .setUniqNo(content.getUniqNo()) - .setFactoryNo(it.getFactoryNo()) - .setWarehouseNo(it.getWarehouseNo()) - .setBinNos(StrUtil.split(materialQO.getBinNos(), "/")) - .setNum(content.getNum()) - .setUnit(it.getUnit()) - .setCreateBy(UserUtil.getUserName()) - .setCreateTime(Instant.now()) - ); - } - if (num.compareTo(it.getNum()) != 0) { - materialNos.add(it.getMaterialNo()); - } + if (num.compareTo(it.getNum()) != 0) { + materialNos.add(it.getMaterialNo()); + } + }); } // if (!order.getList()) { // //是否更改了储位 @@ -511,6 +541,9 @@ public class InProduceOrderController extends BaseController { .map(InMaterialScanRecord::getSerialNo) .toList(); } + if (CollectionUtil.isNotEmpty(qrCodeMasters)) { + qrCodeMasterService.updateBatchById(qrCodeMasters); + } inventoryService.in(list.stream() .filter(it -> Objects.equals(it.getParentId(), 0L)) .map(it -> new InventoryDTO() @@ -522,7 +555,6 @@ public class InProduceOrderController extends BaseController { .setSerialNo(it.getSernr()) ).toList() ); - inMaterialScanRecordRespository.saveAll(records); if (CollectionUtil.isNotEmpty(warehouseNoChange)) { produceOrderItemService.updateBatchById( warehouseNoChange.entrySet() @@ -541,6 +573,7 @@ public class InProduceOrderController extends BaseController { order.setUpdateBy(UserUtil.getUserName()); order.setUpdateTime(LocalDateTime.now()); produceOrderService.updateById(order); + inMaterialScanRecordRespository.saveAll(records); return ApiResult.success(); } diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceOrderSurplusController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceOrderSurplusController.java index 25fd1ce5..871ba93e 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceOrderSurplusController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InProduceOrderSurplusController.java @@ -21,7 +21,6 @@ import com.nflg.wms.common.pojo.dto.MaterialQRCodeContentDTO; import com.nflg.wms.common.pojo.dto.QrCodeMasterPrintDTO; import com.nflg.wms.common.pojo.qo.*; import com.nflg.wms.common.pojo.vo.*; -import com.nflg.wms.common.util.NumberUtil; import com.nflg.wms.common.util.UserUtil; import com.nflg.wms.common.util.VUtil; import com.nflg.wms.repository.entity.*; @@ -47,7 +46,6 @@ import java.time.Instant; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; -import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -243,39 +241,41 @@ public class InProduceOrderSurplusController extends BaseController { .setId(IdUtil.getSnowflakeNextId()) .setTicketId(ticket.getId()) .setOrderItemId(item.getId()) - .setLgpbe(StrUtil.join(",", it.getBinNos())) + .setLgpbe(StrUtil.join(",", it.getItems().stream().map(InCostcenterBackSubmitItemQRQO::getBinNo).toList())) .setNum(BigDecimal.ZERO); ticketItems.add(ti); - it.getQrCodes().forEach(qrCode -> { - MaterialQRCodeContentDTO qrCodeContent = NoUtil.getMaterialQRCodeContent(qrCode); - String materialNo = qrCodeContent.getMaterialNo(); - VUtil.trueThrowBusinessError(!StrUtil.equals(materialNo, item.getMatnr())) - .throwMessage("订单项与物料不符"); - item.setLeftNum(item.getLeftNum().subtract(qrCodeContent.getNum())); - VUtil.trueThrowBusinessError(item.getLeftNum().compareTo(BigDecimal.ZERO) < 0) - .throwMessage("物料" + materialNo + "的入库数量超出申请数量"); - ti.setNum(ti.getNum().add(qrCodeContent.getNum())); - records.add(new InMaterialScanRecord() - .setSource(7) - .setSourceId(order.getId()) - .setSourceItemId(item.getId()) - .setTicketId(ticket.getId()) - .setTicketItemId(ti.getId()) - .setMaterialNo(materialNo) - .setMaterialDesc(qrCodeContent.getMaterialDesc()) - .setUnit(item.getMeins()) - .setContent(qrCode) - .setBatchNo(qrCodeContent.getBatchNo()) - .setSerialNo(qrCodeContent.getSerialNo()) - .setFactoryNo(order.getDwerk()) - .setWarehouseNo(ticket.getLgort()) - .setBinNos(StrUtil.split(it.getBinNos(), "/")) - .setUniqNo(qrCodeContent.getUniqNo()) - .setRspos(item.getRspos()) - .setNum(qrCodeContent.getNum()) - .setCreateBy(UserUtil.getUserName()) - .setCreateTime(Instant.now()) - ); + it.getItems().forEach(iit -> { + iit.getQrCodes().forEach(qrCode -> { + MaterialQRCodeContentDTO qrCodeContent = NoUtil.getMaterialQRCodeContent(qrCode); + String materialNo = qrCodeContent.getMaterialNo(); + VUtil.trueThrowBusinessError(!StrUtil.equals(materialNo, item.getMatnr())) + .throwMessage("订单项与物料不符"); + item.setLeftNum(item.getLeftNum().subtract(qrCodeContent.getNum())); + VUtil.trueThrowBusinessError(item.getLeftNum().compareTo(BigDecimal.ZERO) < 0) + .throwMessage("物料" + materialNo + "的入库数量超出申请数量"); + ti.setNum(ti.getNum().add(qrCodeContent.getNum())); + records.add(new InMaterialScanRecord() + .setSource(7) + .setSourceId(order.getId()) + .setSourceItemId(item.getId()) + .setTicketId(ticket.getId()) + .setTicketItemId(ti.getId()) + .setMaterialNo(materialNo) + .setMaterialDesc(qrCodeContent.getMaterialDesc()) + .setUnit(item.getMeins()) + .setContent(qrCode) + .setBatchNo(qrCodeContent.getBatchNo()) + .setSerialNo(qrCodeContent.getSerialNo()) + .setFactoryNo(order.getDwerk()) + .setWarehouseNo(ticket.getLgort()) + .setBinNo(iit.getBinNo()) + .setUniqNo(qrCodeContent.getUniqNo()) + .setRspos(item.getRspos()) + .setNum(qrCodeContent.getNum()) + .setCreateBy(UserUtil.getUserName()) + .setCreateTime(Instant.now()) + ); + }); }); }); inProduceOrderSurplusItemService.updateBatchById(datas); diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/OutPurchaseController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/OutPurchaseController.java index b4e9a857..fa18f4b3 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/OutPurchaseController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/OutPurchaseController.java @@ -78,7 +78,7 @@ public class OutPurchaseController extends BaseController { public ApiResult searchSAP(@Valid @RequestBody @NotNull zwm3A05QO request) { ZWM3A05VO result = sapService.zwm3A05(request); result.getItems().parallelStream().forEach(it -> { - it.setBinNos(binService.getBinNos(it.getMatnr(), result.getWerks(), it.getLgort())); + it.setBinNos(binService.getBinNo(it.getMatnr(), result.getWerks(), it.getLgort())); }); return ApiResult.success(result); } diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/StructuralPackageOrderController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/StructuralPackageOrderController.java index 5846b7a4..82b6fde6 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/StructuralPackageOrderController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/StructuralPackageOrderController.java @@ -881,7 +881,7 @@ public class StructuralPackageOrderController extends BaseController { log.error("{},{},{}未从SAP的ZIM_004接口查询仓库为空", it.getExternalOrderNo(), it.getSupplierCode(), it.getPackageNo()); } else { it.setWarehouseNo(dto.getWarehouseNo()); - it.setBinNos(binService.getBinNos(it.getPackageNo(), dto.getWerks(), dto.getWarehouseNo())); + it.setBinNos(binService.getBinNo(it.getPackageNo(), dto.getWerks(), dto.getWarehouseNo())); // if (dto.getTransportNum().compareTo(new BigDecimal(it.getNum()))<0){ // it.setNum(dto.getTransportNum().intValue()); // } diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/TransferCompanyController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/TransferCompanyController.java index 65beec02..769936c7 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/TransferCompanyController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/TransferCompanyController.java @@ -484,7 +484,7 @@ public class TransferCompanyController extends BaseController { .setMatnr(item.getMatnr()) .setMaktx(item.getMaktx()) .setNum(item.getNum()) - .setBinIn(StrUtil.join("/", storageService.getBinNos(item.getMatnr(), ticket.getWerks(), ticket.getLgort()))) + .setBinIn(StrUtil.join("/", storageService.getBinNo(item.getMatnr(), ticket.getWerks(), ticket.getLgort()))) ).toList() ) ); @@ -515,7 +515,7 @@ public class TransferCompanyController extends BaseController { .setSerialNo(record.getSerialNo()) .setFactoryNo(ticket.getWerks()) .setWarehouseNo(qo.getLgort1()) - .setBinNos(Objects.isNull(itemQo) ? Collections.emptyList() : StrUtil.split(itemQo.getBinNos(), "/")) + .setBinNo(Objects.isNull(itemQo) ? "" : itemQo.getBinNos()) .setUniqNo(record.getUniqNo()) .setRspos(record.getRspos()) .setNum(record.getNum()) diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/TransferFactoryController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/TransferFactoryController.java index 4a8f4ac0..90b089d2 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/TransferFactoryController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/TransferFactoryController.java @@ -212,8 +212,8 @@ public class TransferFactoryController extends BaseController { .setLgort(order.getLgort()) .setNum(item.getLeft()) .setMeins(item.getMeins()) - .setBinIn(StrUtil.join("/", storageService.getBinNos(item.getMatnr(), order.getWerks(), order.getUmlgo()))) - .setBinOut(StrUtil.join("/", storageService.getBinNos(item.getMatnr(), order.getWerks(), order.getLgort()))); + .setBinIn(StrUtil.join("/", storageService.getBinNo(item.getMatnr(), order.getWerks(), order.getUmlgo()))) + .setBinOut(StrUtil.join("/", storageService.getBinNo(item.getMatnr(), order.getWerks(), order.getLgort()))); vo.setQiTao(type > 0); if (Objects.equals(type, 1)) { vo.setChildren(bomService.getChildrenVO(item.getMatnr())); @@ -446,8 +446,8 @@ public class TransferFactoryController extends BaseController { .setLgort(ticket.getLgort()) .setLgort1(ticket.getUmlgo()) .setNum(it.getNum()) - .setBinIn(StrUtil.join("/", storageService.getBinNos(it.getMatnr(), ticket.getWerks(), ticket.getUmlgo()))) - .setBinOut(StrUtil.join("/", storageService.getBinNos(it.getMatnr(), ticket.getWerks(), ticket.getLgort()))) + .setBinIn(StrUtil.join("/", storageService.getBinNo(it.getMatnr(), ticket.getWerks(), ticket.getUmlgo()))) + .setBinOut(StrUtil.join("/", storageService.getBinNo(it.getMatnr(), ticket.getWerks(), ticket.getLgort()))) ).toList()) ); } @@ -479,12 +479,13 @@ public class TransferFactoryController extends BaseController { .setSerialNo(record.getSerialNo()) .setFactoryNo(ticket.getWerks()) .setWarehouseNo(qo.getLgort1()) - .setBinNos(StrUtil.split(qo.getItems() + .setBinNo(qo.getItems() .stream() .filter(it -> Objects.equals(it.getId(), record.getTicketItemId())) .findFirst() .orElse(new InSubmitItemQO()) - .getBinNos(), "/")) + .getBinNos() + ) .setUniqNo(record.getUniqNo()) .setRspos(record.getRspos()) .setNum(record.getNum()) diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/BinService.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/BinService.java index 6854517f..ba398fae 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/BinService.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/BinService.java @@ -17,22 +17,7 @@ public class BinService { @Resource private IWmsStorageService storageService; - @Resource - private SapService sapService; - - public String getBinNos(String materialNo, String factory, String warehouseNo) { - Set bins = storageService.getBinNos(materialNo, factory, warehouseNo); -// if (CollectionUtil.isNotEmpty(bins)){ -// return String.join("/",bins); -// }else { -// List dtos = sapService.zwm3A01(factory, List.of(warehouseNo), List.of(materialNo), null, null); -// if (CollectionUtil.isEmpty(dtos)){ -// log.error("{},{},{}未从SAP的ZWM3A01接口查询到数据", factory, warehouseNo, materialNo); -// return null; -// }else { -// return dtos.get(0).getBinNos(); -// } -// } - return String.join("/",bins); + public String getBinNo(String materialNo, String factory, String warehouseNo) { + return storageService.getBinNo(materialNo, factory, warehouseNo); } } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/document/InMaterialScanRecord.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/document/InMaterialScanRecord.java index 0e75b981..a6ea32d1 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/document/InMaterialScanRecord.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/document/InMaterialScanRecord.java @@ -45,9 +45,9 @@ public class InMaterialScanRecord { private String warehouseNo; /** - * 储位列表 + * 储位 */ - private List binNos; + private String binNo; /** * 二维码内容 diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InCostcenterBackSubmitItemQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InCostcenterBackSubmitItemQO.java index 9f91d91a..e291b744 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InCostcenterBackSubmitItemQO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InCostcenterBackSubmitItemQO.java @@ -1,5 +1,6 @@ package com.nflg.wms.common.pojo.qo; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -16,15 +17,10 @@ public class InCostcenterBackSubmitItemQO { @NotNull private Long orderItemId; - /** - * 实际入库储位编号列表 - */ - @NotBlank - private String binNos; - /** * 二维码列表 */ + @Valid @NotEmpty - private List qrCodes; + private List items; } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InCostcenterBackSubmitItemQRQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InCostcenterBackSubmitItemQRQO.java new file mode 100644 index 00000000..bd357d7a --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InCostcenterBackSubmitItemQRQO.java @@ -0,0 +1,21 @@ +package com.nflg.wms.common.pojo.qo; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.util.List; + +@Data +public class InCostcenterBackSubmitItemQRQO { + + /** + * 实际入库储位编号列表 + */ + private String binNo; + + /** + * 二维码列表 + */ + @NotEmpty + private List qrCodes; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceBackSubmitQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceBackSubmitQO.java index 667259c9..630a1749 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceBackSubmitQO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceBackSubmitQO.java @@ -1,5 +1,6 @@ package com.nflg.wms.common.pojo.qo; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import lombok.Data; @@ -21,6 +22,7 @@ public class InProduceBackSubmitQO { /** * 二维码列表 */ + @Valid @NotEmpty - private List qrCodes; + private List items; } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceOrderReceiveMaterialQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceOrderReceiveMaterialQO.java index 68c5e985..5f3a39b2 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceOrderReceiveMaterialQO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceOrderReceiveMaterialQO.java @@ -1,6 +1,8 @@ package com.nflg.wms.common.pojo.qo; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; import lombok.Data; import java.util.List; @@ -17,15 +19,12 @@ public class InProduceOrderReceiveMaterialQO { /** * 仓库编号 */ + @NotBlank private String warehouseNo; - /** - * 储位编号列表 - */ - private String binNos; - /** * 二维码列表 */ - private List qrCodes; + @Valid + private List items; } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceOrderReceiveQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceOrderReceiveQO.java index 1bcd7677..75374f16 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceOrderReceiveQO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/InProduceOrderReceiveQO.java @@ -21,5 +21,5 @@ public class InProduceOrderReceiveQO { */ @Valid @NotEmpty - private List items; + private List materials; } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/InProduceOrderItemVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/InProduceOrderItemVO.java index c439e679..391cf1b8 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/InProduceOrderItemVO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/InProduceOrderItemVO.java @@ -55,7 +55,7 @@ public class InProduceOrderItemVO { /** * 储位 */ - private String binNos; + private String binNo; /** * 批次号 diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/OutProduceItemVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/OutProduceItemVO.java index 3dd2666b..6c873de3 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/OutProduceItemVO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/OutProduceItemVO.java @@ -76,4 +76,10 @@ public class OutProduceItemVO { public boolean getUseChildren() { return CollectionUtil.isNotEmpty(children); } + + /** + * 是否启用储位管理 + */ + @JsonProperty("isDisableLocation") + private Boolean isDisableLocation; } diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsStorageMapper.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsStorageMapper.java index e99c9333..33772e0b 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsStorageMapper.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsStorageMapper.java @@ -29,7 +29,7 @@ public interface WmsStorageMapper extends BaseMapper { List getWarehouseNo(String factoryNo, String materialNo); - String getBinNos(String materialNo, String factoryNo, String warehouseNo); + String getBinNo(String materialNo, String factoryNo, String warehouseNo); List searchNonSync(); diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsWarehouseMapper.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsWarehouseMapper.java index f4026ab9..408ccc95 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsWarehouseMapper.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsWarehouseMapper.java @@ -32,4 +32,6 @@ public interface WmsWarehouseMapper extends BaseMapper { List getListByIds(List list); WarehouseVO getInfo(Long id); + + Boolean isEnableLocation(String factoryNo, String warehouseNo); } diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsStorageService.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsStorageService.java index 7c331183..e040c0dd 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsStorageService.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsStorageService.java @@ -39,7 +39,7 @@ public interface IWmsStorageService extends IService { List getWarehouseNo(String factoryNo, String materialNo); - Set getBinNos(String materialNo, @NotBlank String factoryNo, String warehouseNo); + String getBinNo(String materialNo, @NotBlank String factoryNo, String warehouseNo); List searchNonSync(); diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsWarehouseService.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsWarehouseService.java index 9eb699a6..f41e75ba 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsWarehouseService.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsWarehouseService.java @@ -43,4 +43,6 @@ public interface IWmsWarehouseService extends IService { List getListByIds(List list); WarehouseVO getInfo(Long id); + + Boolean isEnableLocation(String factoryNo, String warehouseNo); } diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsStorageServiceImpl.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsStorageServiceImpl.java index 91e39219..4c3047ed 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsStorageServiceImpl.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsStorageServiceImpl.java @@ -102,8 +102,8 @@ public class WmsStorageServiceImpl extends ServiceImpl getBinNos(String materialNo, String factoryNo, String warehouseNo) { - return new HashSet<>(StrUtil.split(baseMapper.getBinNos(materialNo,factoryNo,warehouseNo), ",")); + public String getBinNo(String materialNo, String factoryNo, String warehouseNo) { + return baseMapper.getBinNo(materialNo,factoryNo,warehouseNo); } @Override diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsWarehouseServiceImpl.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsWarehouseServiceImpl.java index 4d3c30b3..69c8d651 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsWarehouseServiceImpl.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsWarehouseServiceImpl.java @@ -120,4 +120,9 @@ public class WmsWarehouseServiceImpl extends ServiceImpl - SELECT bin.no FROM wms_storage s INNER JOIN wms_bin bin ON s.bin_id = bin.id diff --git a/nflg-wms-repository/src/main/resources/mapper/WmsWarehouseMapper.xml b/nflg-wms-repository/src/main/resources/mapper/WmsWarehouseMapper.xml index 8813f998..13801df3 100644 --- a/nflg-wms-repository/src/main/resources/mapper/WmsWarehouseMapper.xml +++ b/nflg-wms-repository/src/main/resources/mapper/WmsWarehouseMapper.xml @@ -77,4 +77,11 @@ left join dictionary_item di on w.factory_id = di.id where w.id = #{id} + + diff --git a/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/controller/MaterialCodeController.java b/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/controller/MaterialCodeController.java index e8d7cf73..4a1c1e6c 100644 --- a/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/controller/MaterialCodeController.java +++ b/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/controller/MaterialCodeController.java @@ -11,6 +11,7 @@ import com.nflg.wms.common.pojo.qo.*; import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeQRVO; import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeItemVO; import com.nflg.wms.common.util.EecExcelUtil; +import com.nflg.wms.common.util.NumberUtil; import com.nflg.wms.common.util.UserUtil; import com.nflg.wms.common.util.VUtil; import com.nflg.wms.repository.entity.*; @@ -113,12 +114,35 @@ public class MaterialCodeController extends BaseController { /** * 清单-删除 */ + @Transactional @PostMapping("delete") public ApiResult delete(@RequestBody @NotEmpty List ids) { - materialCodeService.lambdaUpdate() + List idsForDelete = materialCodeService.lambdaQuery() + .select(WmsShipmentMaterialCode::getId) .eq(WmsShipmentMaterialCode::getStatus, 0) .in(WmsShipmentMaterialCode::getId, ids) - .remove(); + .list() + .stream() + .map(WmsShipmentMaterialCode::getId) + .toList(); + if (CollectionUtil.isNotEmpty(idsForDelete)) { + materialCodeService.removeByIds(idsForDelete); + materialCodeForwardService.lambdaUpdate() + .in(WmsShipmentMaterialCodeForward::getMaterialCodeId) + .remove(); + idsForDelete = materialCodeItemService.lambdaQuery() + .in(WmsShipmentMaterialCodeItem::getMaterialCodeId, idsForDelete) + .list() + .stream() + .map(WmsShipmentMaterialCodeItem::getId) + .toList(); + if (CollectionUtil.isNotEmpty(idsForDelete)) { + materialCodeItemService.removeByIds(idsForDelete); + materialCodeItemQrService.lambdaUpdate() + .in(WmsShipmentMaterialCodeItemQr::getItemId, idsForDelete) + .remove(); + } + } return ApiResult.success(); } @@ -193,21 +217,21 @@ public class MaterialCodeController extends BaseController { log.debug("第{}行:{}", row.getRowNum(), row); if (row.getRowNum() == 1) { materialCode.setCustomerName(row.getString(2)); - VUtil.trueThrowBusinessError(StrUtil.isNotBlank(materialCode.getCustomerName())) + VUtil.trueThrowBusinessError(StrUtil.isBlank(materialCode.getCustomerName())) .throwMessage("客户名称不能为空"); } else if (row.getRowNum() == 2) { materialCode.setDeviceNo(row.getString(2)); - VUtil.trueThrowBusinessError(StrUtil.isNotBlank(materialCode.getDeviceNo())) + VUtil.trueThrowBusinessError(StrUtil.isBlank(materialCode.getDeviceNo())) .throwMessage("设备编号不能为空"); materialCode.setOrderDate(row.getLocalDate(6).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); - VUtil.trueThrowBusinessError(StrUtil.isNotBlank(materialCode.getOrderDate())) + VUtil.trueThrowBusinessError(StrUtil.isBlank(materialCode.getOrderDate())) .throwMessage("订单日期不能为空"); } else if (row.getRowNum() == 3) { materialCode.setSoNo(row.getString(2)); - VUtil.trueThrowBusinessError(StrUtil.isNotBlank(materialCode.getSoNo())) + VUtil.trueThrowBusinessError(StrUtil.isBlank(materialCode.getSoNo())) .throwMessage("销售订单号不能为空"); materialCode.setMaterialNo(row.getString(6)); - VUtil.trueThrowBusinessError(StrUtil.isNotBlank(materialCode.getMaterialNo())) + VUtil.trueThrowBusinessError(StrUtil.isBlank(materialCode.getMaterialNo())) .throwMessage("设备料号不能为空"); } else if (row.getRowNum() > 4 && StrUtil.isNotBlank(row.getString(1))) { WmsShipmentMaterialCodeItem item = new WmsShipmentMaterialCodeItem(); @@ -225,6 +249,8 @@ public class MaterialCodeController extends BaseController { item.setBoxNo(row.getString(9)); item.setCreateBy(UserUtil.getUserName()); item.setCreateTime(LocalDateTime.now()); + item.setPackingNum(NumberUtil.calculateLabelNum(item.getNum(), item.getMinPackagingNum())); + item.setPackingLeft(item.getPackingNum()); items.add(item); qrs.add(new WmsShipmentMaterialCodeItemQr() .setItemId(item.getId()) @@ -271,18 +297,20 @@ public class MaterialCodeController extends BaseController { item.setId(IdUtil.getSnowflakeNextId()); item.setCreateBy(UserUtil.getUserName()); item.setCreateTime(LocalDateTime.now()); - BigDecimal result = item.getNum().divide(item.getMinPackagingNum(), 3, RoundingMode.HALF_UP); - BigDecimal decimalValue = result.remainder(BigDecimal.ONE); - item.setPackingNum(decimalValue.compareTo(BigDecimal.ZERO) > 0 ? result.intValue() + 1 : result.intValue()); +// BigDecimal result = item.getNum().divide(item.getMinPackagingNum(), 3, RoundingMode.HALF_UP); +// BigDecimal decimalValue = result.remainder(BigDecimal.ONE); +// item.setPackingNum(decimalValue.compareTo(BigDecimal.ZERO) > 0 ? result.intValue() + 1 : result.intValue()); + item.setPackingNum(NumberUtil.calculateLabelNum(item.getNum(), item.getMinPackagingNum())); item.setPackingLeft(item.getPackingNum()); - int count = decimalValue.compareTo(BigDecimal.ZERO) > 0 ? result.intValue() + 1 : result.intValue(); +// int count = decimalValue.compareTo(BigDecimal.ZERO) > 0 ? result.intValue() + 1 : result.intValue(); for (int i = 1; i <= item.getPackingNum(); i++) { materialCodeItemQrService.save(new WmsShipmentMaterialCodeItemQr() - .setItemId(item.getId()) - .setNo(KeyUtil.next()) - .setNum(i == count && decimalValue.compareTo(BigDecimal.ZERO) > 0 ? decimalValue : item.getMinPackagingNum()) - .setCreateBy(UserUtil.getUserName()) - .setCreateTime(LocalDateTime.now()) + .setItemId(item.getId()) + .setNo(KeyUtil.next()) +// .setNum(i == count && decimalValue.compareTo(BigDecimal.ZERO) > 0 ? decimalValue : item.getMinPackagingNum()) + .setNum(NumberUtil.getPackageNum(item.getNum(), item.getMinPackagingNum(), item.getPackingNum(), i)) + .setCreateBy(UserUtil.getUserName()) + .setCreateTime(LocalDateTime.now()) ); } materialCodeItemService.save(item); @@ -318,16 +346,17 @@ public class MaterialCodeController extends BaseController { materialCodeItemQrService.lambdaUpdate() .eq(WmsShipmentMaterialCodeItemQr::getItemId, item.getId()) .remove(); - BigDecimal result = item.getNum().divide(item.getMinPackagingNum(), 3, RoundingMode.HALF_UP); - BigDecimal decimalValue = result.remainder(BigDecimal.ONE); - item.setPackingNum(decimalValue.compareTo(BigDecimal.ZERO) > 0 ? result.intValue() + 1 : result.intValue()); +// BigDecimal result = item.getNum().divide(item.getMinPackagingNum(), 3, RoundingMode.HALF_UP); +// BigDecimal decimalValue = result.remainder(BigDecimal.ONE); +// item.setPackingNum(decimalValue.compareTo(BigDecimal.ZERO) > 0 ? result.intValue() + 1 : result.intValue()); + item.setPackingNum(NumberUtil.calculateLabelNum(item.getNum(), item.getMinPackagingNum())); item.setPackingLeft(item.getPackingNum()); - int count = decimalValue.compareTo(BigDecimal.ZERO) > 0 ? result.intValue() + 1 : result.intValue(); +// int count = decimalValue.compareTo(BigDecimal.ZERO) > 0 ? result.intValue() + 1 : result.intValue(); for (int i = 1; i <= item.getPackingNum(); i++) { materialCodeItemQrService.save(new WmsShipmentMaterialCodeItemQr() .setItemId(item.getId()) .setNo(KeyUtil.next()) - .setNum(i == count && decimalValue.compareTo(BigDecimal.ZERO) > 0 ? decimalValue : item.getMinPackagingNum()) + .setNum(NumberUtil.getPackageNum(item.getNum(), item.getMinPackagingNum(), item.getPackingNum(), i)) .setCreateBy(UserUtil.getUserName()) .setCreateTime(LocalDateTime.now()) ); @@ -551,7 +580,7 @@ public class MaterialCodeController extends BaseController { return exportItemZip(datas); } - private ResponseEntity exportItemZip(List datas) throws Exception{ + private ResponseEntity exportItemZip(List datas) throws Exception { Map iamges = materialService.lambdaQuery() .select(WmsShipmentMaterial::getNo, WmsShipmentMaterial::getImage) .in(WmsShipmentMaterial::getNo, datas.stream().map(ShipmentMaterialCodeQRVO::getMaterialNo).collect(Collectors.toSet())) diff --git a/nflg-wms-shipment/src/main/resources/template/物料码打印导出模板.xlsx b/nflg-wms-shipment/src/main/resources/template/物料码打印导出模板.xlsx index bd2eb79ede39506ae0f3c816272e57fa8792f0eb..f4c5fd9477fea5789a79eaa53b38510eda21d522 100644 GIT binary patch delta 7921 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 Tii-A634ZRN=LDrW|4IJ^5vIc3