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 cc72fc11..ccd3fb81 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 @@ -3,10 +3,8 @@ package com.nflg.wms.admin.controller; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Pair; -import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.*; import cn.hutool.core.util.NumberUtil; -import cn.hutool.core.util.RandomUtil; -import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; @@ -176,47 +174,106 @@ public class StructuralPackageOrderController extends BaseController { */ @PostMapping("generateTray") public ApiResult generateTray(@Valid @RequestBody @NotNull GenerateTrayQO request) { - return ApiResult.success(generateTray(request.getPackageId(), request.getNum(), request.getPlanNum())); + return ApiResult.success(generateTray(request.getPackageId(), request.getSupplierCode(), request.getNum(), request.getPlanNum())); } - private GenerateTrayVO generateTray(Long packageId, BigDecimal num, BigDecimal orderNum) { + private GenerateTrayVO generateTray(Long packageId, String supplierCode, BigDecimal num, BigDecimal orderNum) { PackageVO packageVO = structuralPackageService.getInfo(packageId); VUtil.trueThrowBusinessError(Objects.isNull(packageVO)).throwMessage("钢构包不存在"); - List materials = packageVO.getMaterialList(); - VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(materials)).throwMessage("物料清单为空"); - List trays = new ArrayList<>(); - List items = new ArrayList<>(); - BigDecimal totalWeight = BigDecimal.ZERO; - for (PackageMaterialDTO material : materials) { - TrayVO tray = trays.stream().filter(it -> StrUtil.equals(it.getTray(), material.getTray()) && StrUtil.equals(it.getStation(), material.getStation())).findFirst().orElse(null); - if (Objects.isNull(tray)) { - tray = new TrayVO() - .setNo("S" + RandomUtil.randomNumbers(10)) - .setTray(material.getTray()) - .setStation(material.getStation()) - .setMaterialNo(packageVO.getNo()) - .setMaterialDesc(packageVO.getName()) - .setTotalWeight(BigDecimal.ZERO); - trays.add(tray); - } - BigDecimal itemNum = material.getNum(); - items.add(new TrayItemVO() - .setNo(tray.getNo()) - .setMaterialNo(material.getNo()) - .setMaterialDesc(material.getName()) - .setVersion(material.getVersion()) - .setWeight(material.getWeight()) - .setPlanNum(itemNum.multiply(orderNum)) - .setShipmentNum(itemNum.multiply(num)) - .setImage(material.getImage()) - .setDrawingNo(material.getDrawingNo()) - ); - if (Objects.nonNull(material.getWeight())) { - BigDecimal itemWeight = itemNum.multiply(material.getWeight()); - tray.setTotalWeight(tray.getTotalWeight().add(itemWeight)); - totalWeight = totalWeight.add(itemWeight); + + // 获取托盘数量 + Integer trayNum = packageVO.getTrayNum() != null ? packageVO.getTrayNum().intValue() : 0; + VUtil.trueThrowBusinessError(trayNum <= 0).throwMessage("托盘数量必须大于0"); + + return generateTrayWithTrayNum(packageVO, supplierCode, num, orderNum, trayNum); + } + + /** + * 生成托盘(指定托盘数量) + */ + private GenerateTrayVO generateTrayWithTrayNum(PackageVO packageVO, String supplierCode, BigDecimal num, BigDecimal orderNum, Integer trayNum) { + VUtil.trueThrowBusinessError(trayNum <= 0).throwMessage("托盘数量必须大于0"); + + // 生成日期部分:年后2位+月2位+日2位 + LocalDate now = LocalDate.now(); + String datePart = String.format("%02d%02d%02d", + now.getYear() % 100, + now.getMonthValue(), + now.getDayOfMonth()); + + // 供应商代码后4位(supplierCode是6位数字) + String supplierSuffix = ""; + if (StrUtil.isNotBlank(supplierCode)) { + supplierSuffix = supplierCode.length() >= 4 + ? supplierCode.substring(supplierCode.length() - 4) + : supplierCode; + } + + // 构建托盘号前缀:S+供应商代码后4位+年后2位+月2位+日2位 + String trayPrefix = "S" + supplierSuffix + datePart; + + // 查询数据库中该前缀的最新托盘号,获取当前最大流水号 + int startSeq = 1; + String lastTrayNo = structuralPackageOrderTrayService.getLast(trayPrefix); + if (StrUtil.isNotBlank(lastTrayNo)) { + // 从托盘号中提取流水号(格式:Sxxxxxx-序号) + int lastDashIndex = lastTrayNo.lastIndexOf('-'); + if (lastDashIndex > 0 && lastDashIndex < lastTrayNo.length() - 1) { + try { + String seqStr = lastTrayNo.substring(lastDashIndex + 1); + startSeq = Integer.parseInt(seqStr) + 1; + } catch (NumberFormatException e) { + // 如果解析失败,从1开始 + startSeq = 1; + } } } + + List trays = new ArrayList<>(); + + // 根据托盘数量生成托盘,使用数据库最新流水号+1开始 + for (int i = 0; i < trayNum; i++) { + int currentSeq = startSeq + i; + // 生成托盘号:S+供应商代码后4位+年后2位+月2位+日2位-序号 + String generatedTrayNo = trayPrefix + "-" + currentSeq; + + TrayVO tray = new TrayVO() + .setNo(generatedTrayNo) + .setTray("") // 托盘序号设置为空 + .setStation("") + .setMaterialNo(packageVO.getNo()) + .setMaterialDesc(packageVO.getName()) + .setTotalWeight(BigDecimal.ZERO); + trays.add(tray); + } + + // 处理物料清单,生成TrayItemVO + List items = new ArrayList<>(); + BigDecimal totalWeight = BigDecimal.ZERO; + List materials = packageVO.getMaterialList(); + if (CollectionUtil.isNotEmpty(materials)) { + for (PackageMaterialDTO material : materials) { + BigDecimal itemNum = material.getNum(); + TrayItemVO item = new TrayItemVO() + .setNo("") // 托盘号设置为空 + .setMaterialNo(material.getNo()) + .setMaterialDesc(material.getName()) + .setVersion(material.getVersion()) + .setWeight(material.getWeight()) + .setPlanNum(itemNum.multiply(orderNum)) + .setShipmentNum(itemNum.multiply(num)) + .setImage(material.getImage()) + .setDrawingNo(material.getDrawingNo()); + items.add(item); + + // 计算总重量 + if (Objects.nonNull(material.getWeight())) { + BigDecimal itemWeight = itemNum.multiply(material.getWeight()); + totalWeight = totalWeight.add(itemWeight); + } + } + } + return new GenerateTrayVO().setTrays(trays).setItems(items).setTotalWeight(totalWeight); } @@ -251,6 +308,14 @@ public class StructuralPackageOrderController extends BaseController { } List ordersForAdd = new ArrayList<>(); List ordersForUpdate = new ArrayList<>(); + // 预先获取所有供应商信息 + Set supplierIds = request.getItems().stream() + .map(PackageDeliverOrderSaveItemQO::getSupplierId) + .collect(Collectors.toSet()); + List suppliers = userSupplierService.listByIds(supplierIds); + Map supplierCodeMap = suppliers.stream() + .collect(Collectors.toMap(UserSupplier::getId, UserSupplier::getSupplierCode)); + request.getItems().forEach(orderQO -> { WmsStructuralPackageOrder order = Convert.convert(WmsStructuralPackageOrder.class, orderQO); order.setOrderNo(orderNo); @@ -264,7 +329,9 @@ public class StructuralPackageOrderController extends BaseController { order.setUpdateTime(LocalDateTime.now()); ordersForUpdate.add(order); } - GenerateTrayVO trayVO = generateTray(orderQO.getPackageId(), orderQO.getNum(), orderQO.getPlanNum()); + // 获取供应商代码 + String supplierCode = supplierCodeMap.get(orderQO.getSupplierId()); + GenerateTrayVO trayVO = generateTray(orderQO.getPackageId(), supplierCode, orderQO.getNum(), orderQO.getPlanNum()); if (Objects.nonNull(orderQO.getId())) { WmsStructuralPackageOrder o = structuralPackageOrderService.getById(orderQO.getId()); VUtil.trueThrowBusinessError(Objects.isNull(o)).throwMessage("订单不存在"); @@ -283,19 +350,13 @@ public class StructuralPackageOrderController extends BaseController { .setNum(BigDecimal.ZERO) .setStation(it.getStation()) .setTray(it.getTray())).toList(); - List items = new ArrayList<>(); - trays.forEach(tray -> { - List itemVOS = trayVO.getItems().stream().filter(it -> StrUtil.equals(it.getNo(), tray.getNo())).toList(); - items.addAll(itemVOS.stream().map(it -> { - WmsStructuralPackageOrderTrayItem item = Convert.convert(WmsStructuralPackageOrderTrayItem.class, it); - item.setOrderId(order.getId()); - item.setTrayId(tray.getId()); - tray.setNum(tray.getNum().add(item.getShipmentNum())); - tray.setWeight(tray.getWeight().add(NumberUtil.mul(it.getWeight(), item.getShipmentNum()))); - return item; - }).toList() - ); - }); + List items = trayVO.getItems().stream().map(it -> { + WmsStructuralPackageOrderTrayItem item = Convert.convert(WmsStructuralPackageOrderTrayItem.class, it); + item.setOrderId(order.getId()); + // 不再设置 trayId,断开与托盘的关联 + item.setTrayId(-1L); + return item; + }).toList(); structuralPackageOrderTrayService.saveBatch(trays); structuralPackageOrderTrayItemService.deleteByOrderId(order.getId()); structuralPackageOrderTrayItemService.saveBatch(items); @@ -305,7 +366,6 @@ public class StructuralPackageOrderController extends BaseController { List packages = structuralPackageService.lambdaQuery() .in(WmsStructuralPackage::getId, request.getItems().stream().map(PackageDeliverOrderSaveItemQO::getPackageId).toList()) .list(); - List suppliers = userSupplierService.listByIds(ordersForAdd.stream().map(WmsStructuralPackageOrder::getSupplierId).collect(Collectors.toSet())); qrCodeMasterService.saveBatch( ordersForAdd.stream() .map(it -> { @@ -313,6 +373,7 @@ public class StructuralPackageOrderController extends BaseController { .filter(pt -> pt.getId().equals(it.getPackageId())) .findFirst() .get(); + String supplierCode = supplierCodeMap.get(it.getSupplierId()); UserSupplier supplier = suppliers.stream() .filter(pt -> pt.getId().equals(it.getSupplierId())) .findFirst() @@ -391,11 +452,15 @@ public class StructuralPackageOrderController extends BaseController { ); List items = structuralPackageOrderTrayItemService.getList(id); vo.setItems(items.stream().map(item -> { - WmsStructuralPackageOrderTray tray = trays.stream().filter(it -> Objects.equals(it.getId(), item.getTrayId())).findFirst().get(); TrayItemVO ivo = Convert.convert(TrayItemVO.class, item); - ivo.setNo(tray.getNo()); - if (Objects.equals(tray.getState(), (short) 3)) { - ivo.setStoreNum(item.getStoreNum()); + // 由于断开了与托盘的关联,托盘号设置为空 + ivo.setNo(""); + // 获取订单下的任意一个托盘状态(如果有托盘的话) + if (CollectionUtil.isNotEmpty(trays)) { + WmsStructuralPackageOrderTray firstTray = trays.get(0); + if (Objects.equals(firstTray.getState(), (short) 3)) { + ivo.setStoreNum(item.getStoreNum()); + } } return ivo; }).toList()); @@ -451,38 +516,47 @@ public class StructuralPackageOrderController extends BaseController { /** * 获取托盘零件列表 * - * @param id 托盘id + * @param id 订单id */ @GetMapping("getItems") public ApiResult> getItems(@Valid @RequestParam @NotNull Long id) { - return ApiResult.success(structuralPackageOrderTrayItemService.getListVOByTrayId(id)); + // 直接根据订单ID获取物料项列表,不再依赖托盘关联 + List result = structuralPackageOrderTrayItemService.getListVOByOrderId(id); + return ApiResult.success(result); } /** * 导出托盘零件列表 * - * @param id 托盘id + * @param id 订单id */ @PostMapping("exportItems") public void exportItems(HttpServletResponse response, @Valid @RequestParam @NotNull Long id) throws IOException { - List list = structuralPackageOrderTrayItemService.getListVOByTrayId(id); + // 直接根据订单ID获取物料项列表,不再依赖托盘关联 + List list = structuralPackageOrderTrayItemService.getListVOByOrderId(id); EecExcelUtil.export("零件信息", "sheet1", list, response); } /** * 导出老鼠图PDF * - * @param id 托盘id + * @param id 订单id */ @GetMapping("exportPdf") public ApiResult exportPdf(HttpServletResponse response, @Valid @RequestParam @NotNull Long id) throws Exception { - DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(id); + // 根据订单ID获取第一个托盘信息用于生成PDF + List trays = structuralPackageOrderTrayService.getList(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("数据不存在"); + + // 使用第一个托盘的信息 + WmsStructuralPackageOrderTray firstTray = trays.get(0); + DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(firstTray.getId()); VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); + PackageVO vo = new PackageVO() .setNo(trayVO.getPackageNo()) .setExternalOrderNo(trayVO.getExternalOrderNo()) .setRowNo(trayVO.getRowNo()) - .setTrayNo(trayVO.getTrayNo()) .setSupplierName(trayVO.getSupplierName()) .setModelNos(trayVO.getModelNo()) .setVersion(trayVO.getPackageVersion()) @@ -492,8 +566,11 @@ public class StructuralPackageOrderController extends BaseController { .setDrawingNo(trayVO.getPackageDrawingNo()) .setName(trayVO.getPackageDesc()) .setQrCode(QRCodeUtil.generateQRCodeBase64(trayVO.getPackageNo(), 100, 100)); - List list = structuralPackageOrderTrayItemService.getListVOByTrayId(id); - List items = list.stream().map(item -> new PackageMaterialDTO() + + // 获取该订单下的所有物料项,不再依赖托盘关联 + List allItems = structuralPackageOrderTrayItemService.getListVOByOrderId(id); + + List items = allItems.stream().map(item -> new PackageMaterialDTO() .setImage(item.getImage()) .setNo(item.getMaterialNo()) .setDrawingNo(item.getDrawingNo()) @@ -509,19 +586,27 @@ public class StructuralPackageOrderController extends BaseController { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PdfGeneratorUtil.generatePdf(vo.getExternalOrderNo() + "-" + vo.getWorkbenchCode() + "老鼠图", html, outputStream); InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); - return ApiResult.success(fileUploadService.upload("tmp/sp/" + RandomUtil.randomString(10) + "/" + vo.getTrayNo() + "老鼠图.pdf", inputStream, MediaType.APPLICATION_PDF_VALUE)); + return ApiResult.success(fileUploadService.upload("tmp/sp/" + RandomUtil.randomString(10) + "/" + "老鼠图.pdf", inputStream, MediaType.APPLICATION_PDF_VALUE)); } /** * 导出零件标签PDF * - * @param id 托盘id + * @param id 订单id */ @GetMapping("exportItemPdf") public void exportItemPdf(HttpServletResponse response, @Valid @RequestParam @NotNull Long id) throws Exception { - DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(id); + // 根据订单ID获取第一个托盘信息 + List trays = structuralPackageOrderTrayService.getList(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("数据不存在"); + + WmsStructuralPackageOrderTray firstTray = trays.get(0); + DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(firstTray.getId()); VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); - List list = structuralPackageOrderTrayItemService.getListVOByTrayId(id); + + // 获取该订单下的所有物料项,不再依赖托盘关联 + List list = structuralPackageOrderTrayItemService.getListVOByOrderId(id); + List datas = new ArrayList<>(); for (DeliverStructuralPackageOrderTrayItemVO it : list) { String code = Base62Util.encode(it.getId()); @@ -550,13 +635,22 @@ public class StructuralPackageOrderController extends BaseController { /** * 导出零件标签图片ZIP - * @param id 托盘id + * + * @param id 订单id */ @GetMapping(value = "exportItemImageZip", produces = "application/zip") public ResponseEntity exportItemImageZip(HttpServletResponse response, @Valid @RequestParam @NotNull Long id) throws Exception { - DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(id); - VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); - List list = structuralPackageOrderTrayItemService.getListVOByTrayId(id); + // 获取订单信息 + DeliverStructuralPackageOrderVO orderVO = structuralPackageOrderService.getInfo(id); + VUtil.trueThrowBusinessError(Objects.isNull(orderVO)).throwMessage("数据不存在"); + + // 获取第一个托盘信息用于生成标签 + List trays = structuralPackageOrderTrayService.getList(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("数据不存在"); + DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(trays.get(0).getId()); + + // 直接根据订单ID获取物料项列表,不再依赖托盘关联 + List list = structuralPackageOrderTrayItemService.getListVOByOrderId(id); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (ZipOutputStream zos = new ZipOutputStream(baos)) { int index = 0; @@ -602,34 +696,67 @@ public class StructuralPackageOrderController extends BaseController { /** * 导出托盘标签PDF * - * @param id 托盘id + * @param id 订单id */ @GetMapping("exportTrayPdf") public void exportTrayPdf(HttpServletResponse response, @Valid @RequestParam @NotNull Long id) throws Exception { - DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(id); - VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); - trayVO.setQrCode(QRCodeUtil.generateQRCodeBase64(trayVO.getTrayNo(), 100, 100)); - Map variables = new HashMap<>(); - variables.put("info", trayVO); - String html = ThymeleafUtil.generator("/template/qrcode/", "tray", ".html", variables); - URL baseUrl = new ClassPathResource("template/qrcode/").getURL(); - PdfGeneratorUtil.generatePdf("托盘标签" + trayVO.getTrayNo(), html, baseUrl.toString(), response); + // 根据订单ID获取所有托盘,为每个托盘生成标签 + List trays = structuralPackageOrderTrayService.getList(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("数据不存在"); + + // 收集所有托盘的HTML内容 + List htmlList = new ArrayList<>(); + + // 遍历所有托盘,生成每个托盘的HTML内容 + for (WmsStructuralPackageOrderTray tray : trays) { + DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(tray.getId()); + VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); + trayVO.setQrCode(QRCodeUtil.generateQRCodeBase64(trayVO.getTrayNo(), 100, 100)); + Map variables = new HashMap<>(); + variables.put("info", trayVO); + String html = ThymeleafUtil.generator("/template/qrcode/", "tray", ".html", variables); + htmlList.add(html); + } + + // 将所有托盘标签合并成一个PDF文件,每页一个标签 + PdfGeneratorUtil.generatePdf("托盘标签", htmlList, response); } /** - * 导出托盘标签图片 + * 导出托盘标签图片(多个托盘合并为一张长图) * - * @param id 托盘id + * @param id 订单id */ @GetMapping(value = "exportTrayImage", produces = MediaType.IMAGE_PNG_VALUE) public ResponseEntity exportTrayImage(@Valid @RequestParam @NotNull Long id) throws Exception { - DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(id); - VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); - trayVO.setQrCode(QRCodeUtil.generateQRCodeBase64(trayVO.getTrayNo(), 200, 200)); - Map variables = new HashMap<>(); - variables.put("info", trayVO); - String html = ThymeleafUtil.generator("/template/qrcode/", "tray-label", ".html", variables); - byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 600); + // 根据订单ID获取所有托盘 + List trays = structuralPackageOrderTrayService.getList(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("数据不存在"); + + // 为每个托盘生成HTML内容,并拼接成一个完整的HTML + StringBuilder mergedHtml = new StringBuilder(); + mergedHtml.append(""); + + for (WmsStructuralPackageOrderTray tray : trays) { + DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(tray.getId()); + VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); + trayVO.setQrCode(QRCodeUtil.generateQRCodeBase64(trayVO.getTrayNo(), 200, 200)); + Map variables = new HashMap<>(); + variables.put("info", trayVO); + String html = ThymeleafUtil.generator("/template/qrcode/", "tray-label", ".html", variables); + // 提取body内容并追加 + int bodyStart = html.indexOf("", bodyStart) + 1; + int bodyEnd = html.lastIndexOf(""); + if (bodyStart != -1 && bodyEnd != -1) { + mergedHtml.append(html.substring(bodyEndStart, bodyEnd)); + } + } + + mergedHtml.append(""); + + // 将合并后的HTML转换为图片 + byte[] imageBytes = HtmlToImageUtil.convertToPng(mergedHtml.toString(), 600); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.IMAGE_PNG); headers.setContentLength(imageBytes.length); @@ -639,33 +766,57 @@ public class StructuralPackageOrderController extends BaseController { /** * 导出齐套标签PDF * - * @param id 托盘id + * @param id 订单id */ @GetMapping("exportQiTaoPdf") public void exportQiTaoPdf(HttpServletResponse response, @Valid @RequestParam @NotNull Long id) throws Exception { - DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(id); + // 根据订单ID获取所有托盘 + List trays = structuralPackageOrderTrayService.getList(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("数据不存在"); + + // 获取订单信息用于生成二维码 + WmsStructuralPackageOrder order = structuralPackageOrderService.getById(id); + VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在"); + + List codes = qrCodeMasterService.getByExtendId(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(codes)).throwMessage("未找到二维码信息"); + + // 注意:齐套标签内容基于订单信息(外部订单号、行号、包号),同一订单下所有托盘的标签内容相同 + // 因此只需取第一个托盘生成一个标签即可 + DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(trays.get(0).getId()); VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); String temp = trayVO.getExternalOrderNo() + "$" + trayVO.getRowNo() + "$" + trayVO.getPackageNo(); - List codes = qrCodeMasterService.getByExtendId(trayVO.getOrderId()); trayVO.setQrCode(QRCodeUtil.generateQRCodeBase64(codes.get(0).getBarcodeCode() + "$" + temp, 100, 100)); Map variables = new HashMap<>(); variables.put("info", trayVO); String html = ThymeleafUtil.generator("/template/qrcode/", "qitao", ".html", variables); - URL baseUrl = new ClassPathResource("template/qrcode/").getURL(); - PdfGeneratorUtil.generatePdf("齐套标签" + trayVO.getTrayNo(), html, baseUrl.toString(), response); + + PdfGeneratorUtil.generatePdf("齐套标签", html, response); } /** * 导出齐套标签图片 * - * @param id 托盘id + * @param id 订单id */ @GetMapping(value = "exportQiTaoImage", produces = MediaType.IMAGE_PNG_VALUE) public ResponseEntity exportQiTaoImage(@Valid @RequestParam @NotNull Long id) throws Exception { - DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(id); + // 根据订单ID获取所有托盘 + List trays = structuralPackageOrderTrayService.getList(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("数据不存在"); + + // 获取订单信息用于生成二维码 + WmsStructuralPackageOrder order = structuralPackageOrderService.getById(id); + VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在"); + + List codes = qrCodeMasterService.getByExtendId(id); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(codes)).throwMessage("未找到二维码信息"); + + // 注意:齐套标签内容基于订单信息(外部订单号、行号、包号),同一订单下所有托盘的标签内容相同 + // 因此只需取第一个托盘生成一个标签即可 + DeliverStructuralPackageOrderExtendVO trayVO = structuralPackageOrderTrayService.getInfo(trays.get(0).getId()); VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在"); String temp = trayVO.getExternalOrderNo() + "$" + trayVO.getRowNo() + "$" + trayVO.getPackageNo(); - List codes = qrCodeMasterService.getByExtendId(trayVO.getOrderId()); trayVO.setQrCode(QRCodeUtil.generateQRCodeBase64(codes.get(0).getBarcodeCode() + "$" + temp, 100, 100)); Map variables = new HashMap<>(); variables.put("info", trayVO); @@ -685,7 +836,16 @@ public class StructuralPackageOrderController extends BaseController { DeliverStructuralPackageOrderTrayVO vo = structuralPackageOrderTrayService.getInfoByNo(trayNo); VUtil.trueThrowBusinessError(Objects.isNull(vo)).throwMessage("无效的托盘号"); VUtil.trueThrowBusinessError(!Objects.equals(vo.getState(), 0)).throwMessage("该托盘已打包"); - vo.setItems(structuralPackageOrderTrayItemService.getSimpleListByTrayNo(trayNo)); + + // 通过托盘的订单ID获取该订单下的所有物料项 + List items = structuralPackageOrderTrayItemService.getListVOByOrderId(vo.getOrderId()); + vo.setItems(items.stream().map(item -> { + DeliverStructuralPackageOrderTrayItemSimpleVO simpleVO = new DeliverStructuralPackageOrderTrayItemSimpleVO(); + simpleVO.setMaterialNo(item.getMaterialNo()); + simpleVO.setMaterialDesc(item.getMaterialDesc()); + simpleVO.setShipmentNum(item.getShipmentNum()); + return simpleVO; + }).toList()); return ApiResult.success(vo); } @@ -777,56 +937,121 @@ public class StructuralPackageOrderController extends BaseController { /** * 退回到未打包 * - * @param id 托盘id + * @param orderId 订单id */ + @Transactional @GetMapping("backToUnpackaged") - public ApiResult backToUnpackaged(@Valid @RequestParam @NotNull Long id) { - WmsStructuralPackageOrderTray tray = structuralPackageOrderTrayService.getById(id); - VUtil.trueThrowBusinessError(Objects.isNull(tray)).throwMessage("数据不存在"); - VUtil.trueThrowBusinessError(!Objects.equals(tray.getState(), OrderState.Packaged.getState())) - .throwMessage("托盘状态不正确"); + public ApiResult backToUnpackaged(@Valid @RequestParam @NotNull Long orderId) { + // 根据订单ID获取所有托盘 + List trays = structuralPackageOrderTrayService.getList(orderId); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("数据不存在"); + + // 检查所有托盘的状态是否都是已打包 + VUtil.trueThrowBusinessError(trays.stream().anyMatch(tray -> !Objects.equals(tray.getState(), OrderState.Packaged.getState()))) + .throwMessage("托盘状态不正确,只有已打包的托盘才能退回"); + + // 将所有托盘状态更新为未打包 VUtil.trueThrowBusinessError(!structuralPackageOrderTrayService.lambdaUpdate() .set(WmsStructuralPackageOrderTray::getState, OrderState.Unpackaged.getState()) .set(WmsStructuralPackageOrderTray::getPackBy, null) .set(WmsStructuralPackageOrderTray::getPackTime, null) - .eq(WmsStructuralPackageOrderTray::getId, id) + .eq(WmsStructuralPackageOrderTray::getOrderId, orderId) .eq(WmsStructuralPackageOrderTray::getState, OrderState.Packaged.getState()) .update()).throwMessage("退回到未打包失败,请重试"); - packageMaterialScanRecordRepository.removeByTrayNo(tray.getNo()); + + // 删除所有托盘的扫描记录 + trays.forEach(tray -> packageMaterialScanRecordRepository.removeByTrayNo(tray.getNo())); + return ApiResult.success(); } /** * 创建送货单 * - * @param ids 托盘id + * @param orderIds 订单id集合 */ @Transactional @PostMapping("createDeliverOrder") - public ApiResult createDeliverOrder(@Valid @RequestBody @NotEmpty List ids) { - List trays = structuralPackageOrderTrayService.getListByIds(ids); - VUtil.trueThrowBusinessError(trays.stream().map(DeliverStructuralPackageOrderExtendVO::getOrderId).collect(Collectors.toSet()).size() > 1) - .throwMessage("订单号必须一致"); - Long orderId = trays.get(0).getOrderId(); - Long supplierId = trays.get(0).getSupplierId(); - List tids = structuralPackageOrderTrayService.getIdsByOrderId(orderId); - VUtil.trueThrowBusinessError(tids.size() != ids.size()).throwMessage("数据未齐套"); + public ApiResult createDeliverOrder(@Valid @RequestBody @NotEmpty List orderIds) { + // 验证所有订单是否存在 + List orders = structuralPackageOrderService.listByIds(orderIds); + VUtil.trueThrowBusinessError(orders.size() != orderIds.size()).throwMessage("部分订单不存在"); + + // 获取所有订单的供应商ID,确保是同一个供应商 + Set supplierIds = orders.stream().map(WmsStructuralPackageOrder::getSupplierId).collect(Collectors.toSet()); + VUtil.trueThrowBusinessError(supplierIds.size() > 1).throwMessage("订单必须属于同一个供应商"); + Long supplierId = supplierIds.iterator().next(); + + // 检查所有订单下的托盘状态 + for (Long orderId : orderIds) { + List trays = structuralPackageOrderTrayService.getList(orderId); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("订单" + orderId + "没有托盘数据"); + + // 获取该订单下所有已打包的托盘项,找出关联的托盘ID + List trayItems = structuralPackageOrderTrayItemService.getList(orderId); + Set packedTrayIds = trayItems.stream() + .filter(i -> ObjectUtil.isNotEmpty(i.getTrayId()) && i.getTrayId() != -1L) + .map(WmsStructuralPackageOrderTrayItem::getTrayId) + .collect(Collectors.toSet()); + + // 检查是否有已关联托盘项但未打包的托盘 + boolean hasUnpackagedWithItems = trays.stream() + .filter(tray -> packedTrayIds.contains(tray.getId())) + .anyMatch(tray -> Objects.equals(tray.getState(), OrderState.Unpackaged.getState())); + VUtil.trueThrowBusinessError(hasUnpackagedWithItems) + .throwMessage("订单" + orderId + "存在已关联物料但未打包的托盘"); + + // 检查是否有已发货的托盘 + VUtil.trueThrowBusinessError(trays.stream().anyMatch(tray -> Objects.equals(tray.getState(), OrderState.InTransit.getState()) || Objects.equals(tray.getState(), OrderState.Received.getState()))) + .throwMessage("订单" + orderId + "存在已发货或已收货的托盘"); + } + + // 生成送货单号 String deliverOrderNo = serialNumberControllerService.generateSerialNumber(7); + + // 检查是否有缺料情况 + boolean hasQuehuo = orders.stream().anyMatch(order -> { + List items = structuralPackageOrderTrayItemService.getList(order.getId()); + return items.stream().anyMatch(item -> item.getOfflineReceived() != null && !item.getOfflineReceived()); + }); + + // 创建送货单 WmsStructuralPackageDeliverOrder deliverOrder = new WmsStructuralPackageDeliverOrder() .setNo(deliverOrderNo) .setSupplierId(supplierId) - .setQuehuo(trays.stream().anyMatch(DeliverStructuralPackageOrderVO::getQuehuo)) + .setQuehuo(hasQuehuo) .setQuehuoReceived(false) .setCreateBy(UserUtil.getUserName()) .setCreateTime(LocalDateTime.now()); structuralPackageDeliverOrderService.save(deliverOrder); - structuralPackageDeliverOrderMapService.saveBatch(trays.stream() - .map(DeliverStructuralPackageOrderExtendVO::getId) - .distinct().map(id -> - new WmsStructuralPackageDeliverOrderMap() + + // 创建送货单与订单的关联关系 + structuralPackageDeliverOrderMapService.saveBatch( + orderIds.stream() + .map(orderId -> new WmsStructuralPackageDeliverOrderMap() .setDeliverId(deliverOrder.getId()) - .setOrderId(id)).toList()); - structuralPackageOrderTrayService.setStateByIds(ids, OrderState.InTransit); + .setOrderId(orderId)) + .toList() + ); + + // 将所有订单下已关联托盘项的托盘状态更新为运输中 + for (Long orderId : orderIds) { + // 获取该订单下所有已打包的托盘项,找出关联的托盘ID + List trayItems = structuralPackageOrderTrayItemService.getList(orderId); + Set packedTrayIds = trayItems.stream() + .map(WmsStructuralPackageOrderTrayItem::getTrayId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + if (CollectionUtil.isNotEmpty(packedTrayIds)) { + structuralPackageOrderTrayService.lambdaUpdate() + .set(WmsStructuralPackageOrderTray::getState, OrderState.InTransit.getState()) + .in(WmsStructuralPackageOrderTray::getId, packedTrayIds) + .eq(WmsStructuralPackageOrderTray::getState, OrderState.Packaged.getState()) + .update(); + } + } + return ApiResult.success(); } @@ -1335,7 +1560,7 @@ public class StructuralPackageOrderController extends BaseController { } } else { list.forEach(item -> { - item.setTray(generateTray(item.getPackageId(), item.getNum(), item.getTransportNum())); + item.setTray(generateTray(item.getPackageId(), item.getSupplierCode(), item.getNum(), item.getTransportNum())); item.setWeight(item.getTray().getItems().stream().map(TrayItemVO::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add)); }); return ApiResult.success(list); @@ -1359,4 +1584,453 @@ public class StructuralPackageOrderController extends BaseController { ); return ApiResult.success(); } + + /** + * 根据指定托盘数量重新生成订单托盘信息 + * + * @param request 请求参数 + */ + @Transactional + @PostMapping("updateTrayNum") + public ApiResult updateTrayNum(@Valid @RequestBody UpdatePackageTrayNumQO request) { + // 1. 验证并获取订单信息 + WmsStructuralPackageOrder order = structuralPackageOrderService.getById(request.getOrderId()); + VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在"); + + // 2. 检查是否有已打包的托盘 + VUtil.trueThrowBusinessError(structuralPackageOrderTrayService.lambdaQuery() + .eq(WmsStructuralPackageOrderTray::getOrderId, order.getId()) + .ne(WmsStructuralPackageOrderTray::getState, OrderState.Unpackaged.getState()) + .exists()) + .throwMessage("修改失败,该订单有托盘已打包或发货,无法修改托盘数量"); + + // 3. 验证托盘数量 + BigDecimal trayNumDecimal = request.getTrayNum(); + VUtil.trueThrowBusinessError(trayNumDecimal == null || trayNumDecimal.compareTo(BigDecimal.ZERO) <= 0) + .throwMessage("托盘数量必须大于0"); + Integer newTrayNum = trayNumDecimal.intValue(); + + // 4. 获取数据库中当前的托盘列表 + List existingTrays = structuralPackageOrderTrayService.getList(order.getId()); + int existingTrayCount = existingTrays.size(); + + // 5. 校验新传入的托盘数量必须比数据库中的大 + VUtil.trueThrowBusinessError(newTrayNum <= existingTrayCount) + .throwMessage("新托盘数量必须大于当前托盘数量(" + existingTrayCount + ")"); + + // 6. 计算需要新增的托盘数量 + int addTrayCount = newTrayNum - existingTrayCount; + + // 7. 获取钢构包信息 + PackageVO packageVO = structuralPackageService.getInfo(order.getPackageId()); + VUtil.trueThrowBusinessError(Objects.isNull(packageVO)).throwMessage("钢构包不存在"); + + // 8. 获取供应商代码 + UserSupplier supplier = userSupplierService.getById(order.getSupplierId()); + VUtil.trueThrowBusinessError(Objects.isNull(supplier)).throwMessage("供应商不存在"); + String supplierCode = supplier.getSupplierCode(); + + // 9. 生成日期部分:年后2位+月2位+日2位 + LocalDate now = LocalDate.now(); + String datePart = String.format("%02d%02d%02d", + now.getYear() % 100, + now.getMonthValue(), + now.getDayOfMonth()); + + // 10. 供应商代码后4位 + String supplierSuffix = ""; + if (StrUtil.isNotBlank(supplierCode)) { + supplierSuffix = supplierCode.length() >= 4 + ? supplierCode.substring(supplierCode.length() - 4) + : supplierCode; + } + + // 11. 构建托盘号前缀:S+供应商代码后4位+年后2位+月2位+日2位 + String trayPrefix = "S" + supplierSuffix + datePart; + + // 12. 查询数据库中该前缀的最新托盘号,获取当前最大流水号 + int startSeq = 1; + String lastTrayNo = structuralPackageOrderTrayService.getLast(trayPrefix); + if (StrUtil.isNotBlank(lastTrayNo)) { + // 从托盘号中提取流水号(格式:Sxxxxxx-序号) + int lastDashIndex = lastTrayNo.lastIndexOf('-'); + if (lastDashIndex > 0 && lastDashIndex < lastTrayNo.length() - 1) { + try { + String seqStr = lastTrayNo.substring(lastDashIndex + 1); + startSeq = Integer.parseInt(seqStr) + 1; + } catch (NumberFormatException e) { + // 如果解析失败,从1开始 + startSeq = 1; + } + } + } + + // 13. 保留原有托盘,只生成新增的托盘 + List traysToKeep = new ArrayList<>(existingTrays); + List traysToAdd = new ArrayList<>(); + + // 生成新增的托盘 + for (int i = 0; i < addTrayCount; i++) { + int currentSeq = startSeq + i; + String generatedTrayNo = trayPrefix + "-" + currentSeq; + + WmsStructuralPackageOrderTray newTray = new WmsStructuralPackageOrderTray() + .setId(IdUtil.getSnowflakeNextId()) + .setOrderId(order.getId()) + .setNo(generatedTrayNo) + .setWeight(BigDecimal.ZERO) + .setNum(BigDecimal.ZERO) + .setStation("") + .setTray(""); + traysToAdd.add(newTray); + } + + // 14. 合并所有托盘(原有 + 新增) + List allTrays = new ArrayList<>(); + allTrays.addAll(traysToKeep); + allTrays.addAll(traysToAdd); + + // 15. 保存所有托盘 + structuralPackageOrderTrayService.saveOrUpdateBatch(allTrays); + + return ApiResult.success(); + } + + /** + * 钢构件打包提交 PDA使用 + */ + @Transactional + @PostMapping("/packTraySubmit") + public ApiResult packTraySubmit(@Valid @RequestBody @NotNull PackTraySubmitQO request) { + // 1. 根据orderNo查询订单信息 + List orders = structuralPackageOrderService.getList(request.getOrderNo()); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(orders)).throwMessage("订单不存在"); + + DeliverStructuralPackageOrderVO order = orders.get(0); + Long orderId = order.getId(); + + // 2. 获取该订单下的所有托盘项(用于对比计划数量和实际数量) + List allTrayItems = structuralPackageOrderTrayItemService.getList(orderId); + + // 3. 计算每个物料的计划出货数量(按物料编号汇总) + Map plannedQtyMap = allTrayItems.stream() + .collect(Collectors.groupingBy( + WmsStructuralPackageOrderTrayItem::getMaterialNo, + Collectors.reducing(BigDecimal.ZERO, WmsStructuralPackageOrderTrayItem::getShipmentNum, BigDecimal::add) + )); + + // 4. 计算实际提交的数量(按物料编号汇总) + Map actualQtyMap = request.getMaterialSummary().stream() + .collect(Collectors.toMap( + MaterialSummaryQO::getMaterialNo, + MaterialSummaryQO::getTotalQty, + (v1, v2) -> v1 + )); + + // 5. 对比计划数量和实际数量,找出差异 + List diffList = new ArrayList<>(); + for (Map.Entry entry : plannedQtyMap.entrySet()) { + String materialNo = entry.getKey(); + BigDecimal plannedQty = entry.getValue(); + Integer actualQty = actualQtyMap.getOrDefault(materialNo, 0); + + if (plannedQty.compareTo(new BigDecimal(actualQty)) != 0) { + // 找到物料描述 + String materialDesc = allTrayItems.stream() + .filter(item -> StrUtil.equals(item.getMaterialNo(), materialNo)) + .map(WmsStructuralPackageOrderTrayItem::getMaterialDesc) + .findFirst() + .orElse(""); + + DiffItemVO diffItem = new DiffItemVO(); + diffItem.setMaterialNo(materialNo); + diffItem.setMaterialDesc(materialDesc); + diffItem.setShipmentNum(plannedQty.intValue()); + diffItem.setActualQty(actualQty); + diffItem.setDiffQty(plannedQty.intValue() - actualQty); + diffList.add(diffItem); + } + } + + // 6. 如果有差异,返回差异信息,不进行打包 + if (CollectionUtil.isNotEmpty(diffList)) { + PackTraySubmitResultVO result = new PackTraySubmitResultVO(); + result.setHasDiff(true); + result.setDiffList(diffList); + result.setMessage("存在数量差异,请使用packTraySubmitWithDiff接口提交差异原因"); + return ApiResult.success(result); + } + + // 7. 无差异,执行打包逻辑 + List trays = structuralPackageOrderTrayService.getList(orderId); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("该订单没有托盘数据"); + + // 8. 校验所有托盘状态是否为未打包 + for (TraySubmitQO trayQO : request.getTrays()) { + WmsStructuralPackageOrderTray tray = trays.stream() + .filter(t -> StrUtil.equals(t.getNo(), trayQO.getTrayNo())) + .findFirst() + .orElse(null); + VUtil.trueThrowBusinessError(Objects.isNull(tray)).throwMessage("托盘" + trayQO.getTrayNo() + "不存在"); + VUtil.trueThrowBusinessError(!Objects.equals(tray.getState(), OrderState.Unpackaged.getState())) + .throwMessage("托盘" + trayQO.getTrayNo() + "请勿重复打包"); + } + + // 9. 处理每个托盘的物料 + List allQrCodeDTOs = new ArrayList<>(); + + for (TraySubmitQO trayQO : request.getTrays()) { + WmsStructuralPackageOrderTray tray = trays.stream() + .filter(t -> StrUtil.equals(t.getNo(), trayQO.getTrayNo())) + .findFirst() + .orElse(null); + + // 获取托盘项 + List trayItems = structuralPackageOrderTrayItemService.getListByTrayId(tray.getId()); + + // 处理托盘中的每个物料 + for (TrayMaterialQO materialQO : trayQO.getItems()) { + WmsStructuralPackageOrderTrayItem trayItem = trayItems.stream() + .filter(item -> StrUtil.equals(item.getMaterialNo(), materialQO.getMaterialNo())) + .findFirst() + .orElse(null); + + VUtil.trueThrowBusinessError(Objects.isNull(trayItem)) + .throwMessage("托盘" + trayQO.getTrayNo() + "中物料" + materialQO.getMaterialNo() + "不存在"); + + // 更新托盘项的trayId + trayItem.setTrayId(tray.getId()); + + // 解析二维码 + if (CollectionUtil.isNotEmpty(materialQO.getQrCodes())) { + List dtos = materialQO.getQrCodes().stream() + .map(NoUtil::getStructuralPackageMaterialQRCodeContent) + .toList(); + + // 验证数量是否一致 + BigDecimal scannedQty = dtos.stream() + .map(StructuralPackageMaterialQRCodeContentDTO::getNum) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + if (trayItem.getShipmentNum().compareTo(scannedQty) != 0) { + throw new NflgException(STATE.BusinessError, "托盘" + trayQO.getTrayNo() + "中物料" + materialQO.getMaterialNo() + + "的数量不一致,应为:" + trayItem.getShipmentNum() + ",实际扫码:" + scannedQty); + } + + // 设置二维码相关信息 + dtos.forEach(dto -> { + dto.setPoNum(order.getExternalOrderNo()); + dto.setPackageNo(order.getPackageNo()); + dto.setTrayItemId(trayItem.getId()); + }); + + allQrCodeDTOs.addAll(dtos); + } + } + + // 批量更新托盘项的trayId + structuralPackageOrderTrayItemService.updateBatchById(trayItems); + + // 更新托盘状态为已打包 + VUtil.trueThrowBusinessError(!structuralPackageOrderTrayService.lambdaUpdate() + .set(WmsStructuralPackageOrderTray::getState, OrderState.Packaged.getState()) + .set(WmsStructuralPackageOrderTray::getPackBy, UserUtil.getUserName()) + .set(WmsStructuralPackageOrderTray::getPackTime, LocalDateTime.now()) + .eq(WmsStructuralPackageOrderTray::getState, OrderState.Unpackaged.getState()) + .eq(WmsStructuralPackageOrderTray::getId, tray.getId()) + .update()).throwMessage("托盘" + trayQO.getTrayNo() + "打包失败,请重试"); + } + + // 10. 保存二维码扫描记录 + saveMaterialQrCodeScanRecord(allQrCodeDTOs, 1); + + // 11. 构建返回结果 + PackTraySubmitResultVO result = new PackTraySubmitResultVO(); + result.setHasDiff(false); + result.setDiffList(new ArrayList<>()); + result.setMessage("打包成功"); + + return ApiResult.success(result); + } + + /** + * 钢构件打包提交(带差异原因)PDA使用 + */ + @Transactional + @PostMapping("/packTraySubmitWithDiff") + public ApiResult packTraySubmitWithDiff(@Valid @RequestBody @NotNull PackTraySubmitWithDiffQO request) { + // 1. 校验差异列表中的remark必填 + for (DiffItemQO diffItem : request.getDiffList()) { + VUtil.trueThrowBusinessError(StrUtil.isBlank(diffItem.getRemark())) + .throwMessage("物料" + diffItem.getMaterialNo() + "的差异原因不能为空"); + } + + // 2. 根据orderNo查询订单信息 + List orders = structuralPackageOrderService.getList(request.getOrderNo()); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(orders)).throwMessage("订单不存在"); + + DeliverStructuralPackageOrderVO order = orders.get(0); + Long orderId = order.getId(); + + // 3. 获取该订单下的所有托盘 + List trays = structuralPackageOrderTrayService.getList(orderId); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(trays)).throwMessage("该订单没有托盘数据"); + + // 4. 校验所有托盘状态是否为未打包 + for (TraySubmitQO trayQO : request.getTrays()) { + WmsStructuralPackageOrderTray tray = trays.stream() + .filter(t -> StrUtil.equals(t.getNo(), trayQO.getTrayNo())) + .findFirst() + .orElse(null); + VUtil.trueThrowBusinessError(Objects.isNull(tray)).throwMessage("托盘" + trayQO.getTrayNo() + "不存在"); + VUtil.trueThrowBusinessError(!Objects.equals(tray.getState(), OrderState.Unpackaged.getState())) + .throwMessage("托盘" + trayQO.getTrayNo() + "请勿重复打包"); + } + + // 5. 处理每个托盘的物料 + List allQrCodeDTOs = new ArrayList<>(); + + for (TraySubmitQO trayQO : request.getTrays()) { + WmsStructuralPackageOrderTray tray = trays.stream() + .filter(t -> StrUtil.equals(t.getNo(), trayQO.getTrayNo())) + .findFirst() + .orElse(null); + + // 获取托盘项 + List trayItems = structuralPackageOrderTrayItemService.getListByTrayId(tray.getId()); + + // 处理托盘中的每个物料 + for (TrayMaterialQO materialQO : trayQO.getItems()) { + WmsStructuralPackageOrderTrayItem trayItem = trayItems.stream() + .filter(item -> StrUtil.equals(item.getMaterialNo(), materialQO.getMaterialNo())) + .findFirst() + .orElse(null); + + VUtil.trueThrowBusinessError(Objects.isNull(trayItem)) + .throwMessage("托盘" + trayQO.getTrayNo() + "中物料" + materialQO.getMaterialNo() + "不存在"); + + // 判断该物料是否在差异列表中 + boolean hasDiff = request.getDiffList().stream() + .anyMatch(diff -> StrUtil.equals(diff.getMaterialNo(), materialQO.getMaterialNo())); + + // 更新托盘项的trayId + trayItem.setTrayId(tray.getId()); + + // 解析二维码 + if (CollectionUtil.isNotEmpty(materialQO.getQrCodes())) { + List dtos = materialQO.getQrCodes().stream() + .map(NoUtil::getStructuralPackageMaterialQRCodeContent) + .toList(); + + // 只有不在差异列表中的物料才需要校验数量一致性 + if (!hasDiff) { + // 验证数量是否一致 + BigDecimal scannedQty = dtos.stream() + .map(StructuralPackageMaterialQRCodeContentDTO::getNum) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + if (trayItem.getShipmentNum().compareTo(scannedQty) != 0) { + throw new NflgException(STATE.BusinessError, "托盘" + trayQO.getTrayNo() + "中物料" + materialQO.getMaterialNo() + + "的数量不一致,应为:" + trayItem.getShipmentNum() + ",实际扫码:" + scannedQty); + } + } + + // 设置二维码相关信息 + dtos.forEach(dto -> { + dto.setPoNum(order.getExternalOrderNo()); + dto.setPackageNo(order.getPackageNo()); + dto.setTrayItemId(trayItem.getId()); + }); + + allQrCodeDTOs.addAll(dtos); + } + } + + // 批量更新托盘项的trayId + structuralPackageOrderTrayItemService.updateBatchById(trayItems); + + // 更新托盘状态为已打包 + VUtil.trueThrowBusinessError(!structuralPackageOrderTrayService.lambdaUpdate() + .set(WmsStructuralPackageOrderTray::getState, OrderState.Packaged.getState()) + .set(WmsStructuralPackageOrderTray::getPackBy, UserUtil.getUserName()) + .set(WmsStructuralPackageOrderTray::getPackTime, LocalDateTime.now()) + .eq(WmsStructuralPackageOrderTray::getState, OrderState.Unpackaged.getState()) + .eq(WmsStructuralPackageOrderTray::getId, tray.getId()) + .update()).throwMessage("托盘" + trayQO.getTrayNo() + "打包失败,请重试"); + } + + // 6. 处理差异项,保存到托盘项的备注中 + List allTrayItems = structuralPackageOrderTrayItemService.getList(orderId); + for (DiffItemQO diffItem : request.getDiffList()) { + // 找到对应的托盘项 + WmsStructuralPackageOrderTrayItem trayItem = allTrayItems.stream() + .filter(item -> StrUtil.equals(item.getMaterialNo(), diffItem.getMaterialNo())) + .findFirst() + .orElse(null); + + if (Objects.nonNull(trayItem)) { + // 保存差异原因到托盘项的offlineRemark字段 + trayItem.setOfflineRemark(diffItem.getRemark()); + trayItem.setOfflineReceived(false); + } + } + + // 批量更新托盘项 + structuralPackageOrderTrayItemService.updateBatchById(allTrayItems.stream() + .filter(item -> StrUtil.isNotBlank(item.getOfflineRemark())) + .toList()); + + // 7. 如果有差异项,标记订单为缺料 + if (CollectionUtil.isNotEmpty(request.getDiffList())) { + structuralPackageOrderService.lambdaUpdate() + .set(WmsStructuralPackageOrder::getQuehuo, true) + .eq(WmsStructuralPackageOrder::getId, orderId) + .update(); + } + + // 8. 保存二维码扫描记录 + saveMaterialQrCodeScanRecord(allQrCodeDTOs, 1); + + // 9. 构建返回结果 + PackTraySubmitWithDiffVO result = new PackTraySubmitWithDiffVO(); + result.setOrderNo(request.getOrderNo()); + + // 转换托盘列表 + List trayVOs = new ArrayList<>(); + for (TraySubmitQO trayQO : request.getTrays()) { + TrayItemVO2 trayVO = new TrayItemVO2(); + trayVO.setTrayNo(trayQO.getTrayNo()); + trayVO.setOrderNo(trayQO.getOrderNo()); + + List materialVOs = new ArrayList<>(); + for (TrayMaterialQO materialQO : trayQO.getItems()) { + TrayMaterialVO materialVO = new TrayMaterialVO(); + materialVO.setMaterialNo(materialQO.getMaterialNo()); + materialVO.setMaterialDesc(materialQO.getMaterialDesc()); + materialVO.setQrCodes(materialQO.getQrCodes()); + materialVO.setTotalQty(materialQO.getTotalQty()); + materialVOs.add(materialVO); + } + + trayVO.setItems(materialVOs); + trayVOs.add(trayVO); + } + result.setTrays(trayVOs); + + // 转换差异列表 + List diffVOs = new ArrayList<>(); + for (DiffItemQO diffQO : request.getDiffList()) { + DiffItemVO diffVO = new DiffItemVO(); + diffVO.setMaterialNo(diffQO.getMaterialNo()); + diffVO.setMaterialDesc(diffQO.getMaterialDesc()); + diffVO.setShipmentNum(diffQO.getShipmentNum()); + diffVO.setActualQty(diffQO.getActualQty()); + diffVO.setDiffQty(diffQO.getDiffQty()); + diffVO.setRemark(diffQO.getRemark()); + diffVOs.add(diffVO); + } + result.setDiffList(diffVOs); + + return ApiResult.success(result); + } } \ No newline at end of file diff --git a/nflg-wms-admin/src/main/resources/template/钢构件老鼠图.html b/nflg-wms-admin/src/main/resources/template/钢构件老鼠图.html index bc03095a..70bcb0a0 100644 --- a/nflg-wms-admin/src/main/resources/template/钢构件老鼠图.html +++ b/nflg-wms-admin/src/main/resources/template/钢构件老鼠图.html @@ -109,7 +109,8 @@ 订单号:12255665451615 行号:1111 - 托盘号:1111 + + 供应商:1111 @@ -149,4 +150,4 @@ - \ No newline at end of file + diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/DiffItemQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/DiffItemQO.java new file mode 100644 index 00000000..d7e929a7 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/DiffItemQO.java @@ -0,0 +1,52 @@ +package com.nflg.wms.common.pojo.qo; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +/** + * 差异项QO + */ +@Data +public class DiffItemQO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 物料编号 + */ + @NotBlank(message = "物料编号不能为空") + private String materialNo; + + /** + * 物料描述 + */ + @NotBlank(message = "物料描述不能为空") + private String materialDesc; + + /** + * 出货数量 + */ + @NotNull(message = "出货数量不能为空") + private Integer shipmentNum; + + /** + * 已装数量 + */ + @NotNull(message = "已装数量不能为空") + private Integer actualQty; + + /** + * 差异数量 + */ + @NotNull(message = "差异数量不能为空") + private Integer diffQty; + + /** + * 差异原因描述(必填) + */ + @NotBlank(message = "差异原因不能为空") + private String remark; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/GenerateTrayQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/GenerateTrayQO.java index b69470c3..856cdda3 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/GenerateTrayQO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/GenerateTrayQO.java @@ -1,5 +1,6 @@ package com.nflg.wms.common.pojo.qo; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -14,6 +15,12 @@ public class GenerateTrayQO { @NotNull private Long packageId; + /** + * 供应商代码(6位数字) + */ + @NotBlank + private String supplierCode; + /** * 数量 */ diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/MaterialSummaryQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/MaterialSummaryQO.java new file mode 100644 index 00000000..a87d6b95 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/MaterialSummaryQO.java @@ -0,0 +1,34 @@ +package com.nflg.wms.common.pojo.qo; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; + +/** + * 物料汇总QO(按物料编号统计) + */ +@Data +public class MaterialSummaryQO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 物料编号 + */ + @NotBlank(message = "物料编号不能为空") + private String materialNo; + + /** + * 物料描述 + */ + @NotBlank(message = "物料描述不能为空") + private String materialDesc; + + /** + * 所有托盘该物料的总数量 + */ + @NotNull(message = "物料总数量不能为空") + private Integer totalQty; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/PackTraySubmitQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/PackTraySubmitQO.java new file mode 100644 index 00000000..00f7f1ee --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/PackTraySubmitQO.java @@ -0,0 +1,38 @@ +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.io.Serializable; +import java.util.List; + +/** + * 钢构件打包提交QO + */ +@Data +public class PackTraySubmitQO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 采购单号/钢构件订单号 + */ + @NotBlank(message = "订单号不能为空") + private String orderNo; + + /** + * 托盘列表 + */ + @NotEmpty(message = "托盘列表不能为空") + @Valid + private List trays; + + /** + * 物料汇总列表(按物料编号统计的总数量) + */ + @NotEmpty(message = "物料汇总列表不能为空") + @Valid + private List materialSummary; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/PackTraySubmitWithDiffQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/PackTraySubmitWithDiffQO.java new file mode 100644 index 00000000..a53bf7e1 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/PackTraySubmitWithDiffQO.java @@ -0,0 +1,38 @@ +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.io.Serializable; +import java.util.List; + +/** + * 钢构件打包提交带差异原因QO + */ +@Data +public class PackTraySubmitWithDiffQO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 采购单号/钢构件订单号 + */ + @NotBlank(message = "订单号不能为空") + private String orderNo; + + /** + * 托盘列表 + */ + @NotEmpty(message = "托盘列表不能为空") + @Valid + private List trays; + + /** + * 差异列表 + */ + @NotEmpty(message = "差异列表不能为空") + @Valid + private List diffList; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/TrayMaterialQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/TrayMaterialQO.java new file mode 100644 index 00000000..01873f04 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/TrayMaterialQO.java @@ -0,0 +1,40 @@ +package com.nflg.wms.common.pojo.qo; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 托盘物料QO + */ +@Data +public class TrayMaterialQO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 物料编号 + */ + @NotBlank(message = "物料编号不能为空") + private String materialNo; + + /** + * 物料描述 + */ + @NotBlank(message = "物料描述不能为空") + private String materialDesc; + + /** + * 二维码列表(该物料的所有条码) + */ + private List qrCodes; + + /** + * 该物料的总数量 + */ + @NotNull(message = "物料数量不能为空") + private Integer totalQty; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/TraySubmitQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/TraySubmitQO.java new file mode 100644 index 00000000..ace16cc4 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/TraySubmitQO.java @@ -0,0 +1,37 @@ +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.io.Serializable; +import java.util.List; + +/** + * 托盘提交QO + */ +@Data +public class TraySubmitQO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 托盘号 + */ + @NotBlank(message = "托盘号不能为空") + private String trayNo; + + /** + * 订单号 + */ + @NotBlank(message = "订单号不能为空") + private String orderNo; + + /** + * 托盘内物料明细 + */ + @NotEmpty(message = "物料明细不能为空") + @Valid + private List items; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/UpdatePackageTrayNumQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/UpdatePackageTrayNumQO.java new file mode 100644 index 00000000..eb773f73 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/UpdatePackageTrayNumQO.java @@ -0,0 +1,25 @@ +package com.nflg.wms.common.pojo.qo; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 修改钢构包订单托盘数量请求对象 + */ +@Data +public class UpdatePackageTrayNumQO { + + /** + * 钢构包订单ID + */ + @NotNull(message = "钢构包订单ID不能为空") + private Long orderId; + + /** + * 托盘数量 + */ + @NotNull(message = "托盘数量不能为空") + private BigDecimal trayNum; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DeliverStructuralPackageOrderExtendVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DeliverStructuralPackageOrderExtendVO.java index 6729c180..a73ba8a7 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DeliverStructuralPackageOrderExtendVO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DeliverStructuralPackageOrderExtendVO.java @@ -5,6 +5,7 @@ import lombok.Data; import lombok.experimental.Accessors; import org.ttzero.excel.annotation.ExcelColumn; +import java.math.BigDecimal; import java.util.Objects; @Data @@ -63,6 +64,11 @@ public class DeliverStructuralPackageOrderExtendVO extends DeliverStructuralPack */ private Short totalNum; + /** + * 托盘数量 + */ + private BigDecimal trayNum; + public String getStateDesc() { if (Objects.isNull(state)) { return ""; diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DeliverStructuralPackageOrderTrayVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DeliverStructuralPackageOrderTrayVO.java index a23da64e..d24edc49 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DeliverStructuralPackageOrderTrayVO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DeliverStructuralPackageOrderTrayVO.java @@ -8,6 +8,11 @@ import java.util.List; @Data public class DeliverStructuralPackageOrderTrayVO { + /** + * 订单ID + */ + private Long orderId; + /** * 供应商代码 */ diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DiffItemVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DiffItemVO.java new file mode 100644 index 00000000..0a3838c0 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/DiffItemVO.java @@ -0,0 +1,43 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; +import java.io.Serializable; + +/** + * 差异项VO + */ +@Data +public class DiffItemVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 物料编号 + */ + private String materialNo; + + /** + * 物料描述 + */ + private String materialDesc; + + /** + * 出货数量 + */ + private Integer shipmentNum; + + /** + * 已装数量 + */ + private Integer actualQty; + + /** + * 差异数量 + */ + private Integer diffQty; + + /** + * 差异原因描述(必填) + */ + private String remark; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackTraySubmitResultVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackTraySubmitResultVO.java new file mode 100644 index 00000000..fef685f0 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackTraySubmitResultVO.java @@ -0,0 +1,29 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.List; + +/** + * 打包提交返回结果VO + */ +@Data +public class PackTraySubmitResultVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 是否有差异 + */ + private Boolean hasDiff; + + /** + * 差异列表(如果有差异) + */ + private List diffList; + + /** + * 提示信息 + */ + private String message; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackTraySubmitWithDiffVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackTraySubmitWithDiffVO.java new file mode 100644 index 00000000..1ca03646 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackTraySubmitWithDiffVO.java @@ -0,0 +1,29 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.List; + +/** + * 钢构件打包提交带差异原因VO + */ +@Data +public class PackTraySubmitWithDiffVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 采购单号/钢构件订单号 + */ + private String orderNo; + + /** + * 托盘列表 + */ + private List trays; + + /** + * 差异列表 + */ + private List diffList; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackageVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackageVO.java index 3d490c4e..dd232464 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackageVO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/PackageVO.java @@ -58,6 +58,11 @@ public class PackageVO { */ private BigDecimal weight; + /** + * 托盘数量 + */ + private BigDecimal trayNum; + /** * 种类 */ diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/TrayItemVO2.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/TrayItemVO2.java new file mode 100644 index 00000000..a28a00ac --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/TrayItemVO2.java @@ -0,0 +1,30 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 托盘项VO + */ +@Data +public class TrayItemVO2 implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 托盘号 + */ + private String trayNo; + + /** + * 订单号 + */ + private String orderNo; + + /** + * 托盘内物料明细 + */ + private List items; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/TrayMaterialVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/TrayMaterialVO.java new file mode 100644 index 00000000..2dd960f3 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/TrayMaterialVO.java @@ -0,0 +1,34 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.List; + +/** + * 托盘物料VO + */ +@Data +public class TrayMaterialVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 物料编号 + */ + private String materialNo; + + /** + * 物料描述 + */ + private String materialDesc; + + /** + * 二维码列表(该物料的所有条码) + */ + private List qrCodes; + + /** + * 该物料的总数量 + */ + private Integer totalQty; +} diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsStructuralPackageOrderTrayItemMapper.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsStructuralPackageOrderTrayItemMapper.java index 50eb8ced..b5b969a2 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsStructuralPackageOrderTrayItemMapper.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/WmsStructuralPackageOrderTrayItemMapper.java @@ -20,4 +20,9 @@ public interface WmsStructuralPackageOrderTrayItemMapper extends BaseMapper getListByTrayId(Long id); List getSimpleListByTrayNo(String trayNo); + + /** + * 根据订单ID获取物料项列表(不依赖托盘关联) + */ + List getListByOrderId(Long orderId); } diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsStructuralPackageOrderTrayItemService.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsStructuralPackageOrderTrayItemService.java index 91ad93b8..c1fad08c 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsStructuralPackageOrderTrayItemService.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/IWmsStructuralPackageOrderTrayItemService.java @@ -31,4 +31,9 @@ public interface IWmsStructuralPackageOrderTrayItemService extends IService getSimpleListByTrayNo(@Valid @NotBlank String trayNo); List getListByTrayId(Long id); + + /** + * 根据订单ID获取物料项列表(不依赖托盘关联) + */ + List getListVOByOrderId(@Valid @NotNull Long orderId); } diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsStructuralPackageOrderTrayItemServiceImpl.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsStructuralPackageOrderTrayItemServiceImpl.java index 1dd764e2..279627e2 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsStructuralPackageOrderTrayItemServiceImpl.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/WmsStructuralPackageOrderTrayItemServiceImpl.java @@ -54,4 +54,9 @@ public class WmsStructuralPackageOrderTrayItemServiceImpl extends ServiceImpl getListByTrayId(Long id) { return lambdaQuery().eq(WmsStructuralPackageOrderTrayItem::getTrayId, id).list(); } + + @Override + public List getListVOByOrderId(Long orderId) { + return baseMapper.getListByOrderId(orderId); + } } diff --git a/nflg-wms-repository/src/main/resources/mapper/WmsStructuralPackageOrderTrayItemMapper.xml b/nflg-wms-repository/src/main/resources/mapper/WmsStructuralPackageOrderTrayItemMapper.xml index a387381b..394c4624 100644 --- a/nflg-wms-repository/src/main/resources/mapper/WmsStructuralPackageOrderTrayItemMapper.xml +++ b/nflg-wms-repository/src/main/resources/mapper/WmsStructuralPackageOrderTrayItemMapper.xml @@ -21,4 +21,16 @@ where ot.no=#{trayNo} order by oti.id + + diff --git a/nflg-wms-repository/src/main/resources/mapper/WmsStructuralPackageOrderTrayMapper.xml b/nflg-wms-repository/src/main/resources/mapper/WmsStructuralPackageOrderTrayMapper.xml index 30ae7b80..ba6f122e 100644 --- a/nflg-wms-repository/src/main/resources/mapper/WmsStructuralPackageOrderTrayMapper.xml +++ b/nflg-wms-repository/src/main/resources/mapper/WmsStructuralPackageOrderTrayMapper.xml @@ -3,17 +3,19 @@