diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index a8f30708b..4b57e443f 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -139,6 +139,9 @@ public interface ErrorCodeConstants { ErrorCode STOCK_OUT_AUDIT_FAIL_STATUS = new ErrorCode(1_030_402_011, "审核失败,只有审核中的出库单才能审核"); ErrorCode STOCK_OUT_AUDIT_FAIL_USER = new ErrorCode(1_030_402_012, "审核失败,当前用户不是指定审核人"); ErrorCode STOCK_OUT_AUDIT_FAIL_RESULT = new ErrorCode(1_030_402_013, "审核失败,审核结果只支持通过或驳回"); + ErrorCode STOCK_OUT_PACKAGE_COUNT_EXCEED = new ErrorCode(1_030_402_014, "出库失败,产品({})在仓库({})的库存包数为{},小于出库包数{}"); + ErrorCode STOCK_OUT_PALLET_PACKAGE_COUNT_EXCEED = new ErrorCode(1_030_402_015, "出库失败,托盘({})的当前包数为{},小于出库包数{}"); + ErrorCode PALLET_ALREADY_HAS_DIFFERENT_PRODUCT = new ErrorCode(1_030_400_011, "入库失败,托盘({})已装载产品({}),不能混装其他产品"); // ========== ERP 库存调拨单 1-030-403-000 ========== ErrorCode STOCK_MOVE_NOT_EXISTS = new ErrorCode(1_030_402_000, "库存调拨单不存在"); diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java index e91e37195..bc88813fc 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -57,9 +57,15 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { SPARE_PARTS_OUT(100, "备件出库"), SPARE_PARTS_OUT_INVALIDATION(101, "备件出库(作废)"), + KEY_PART_OUT(100, "关键件出库"), + KEY_PART_OUT_INVALIDATION(101, "关键件出库(作废)"), PRODUCT_WAREHOUSING(110, "产品入库"), PRODUCT_WAREHOUSING_VOID(111, "产品入库(作废)"), + PRODUCT_OUT(112, "产品出库"), + PRODUCT_OUT_CANCEL(113, "产品出库(作废)"), + RAW_MATERIAL_OUT(27, "原料出库"), + RAW_MATERIAL_OUT_CANCEL(28, "原料出库(作废)"), ; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java index 3fc4d7966..1e9ab1c9c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java @@ -46,16 +46,17 @@ public class ErpPalletController { @PostMapping("/create") @Operation(summary = "创建托盘") @PreAuthorize("@ss.hasPermission('erp:pallet:create')") - public CommonResult createPallet(@Valid @RequestBody ErpPalletSaveReqVO createReqVO) { - return success(palletService.createPallet(createReqVO)); + public CommonResult createPallet(@Valid @RequestBody ErpPalletSaveReqVO createReqVO) { + Long id = palletService.createPallet(createReqVO); + return success(buildPalletRespVO(palletService.getPallet(id))); } @PutMapping("/update") @Operation(summary = "更新托盘") @PreAuthorize("@ss.hasPermission('erp:pallet:update')") - public CommonResult updatePallet(@Valid @RequestBody ErpPalletSaveReqVO updateReqVO) { + public CommonResult updatePallet(@Valid @RequestBody ErpPalletSaveReqVO updateReqVO) { palletService.updatePallet(updateReqVO); - return success(true); + return success(buildPalletRespVO(palletService.getPallet(updateReqVO.getId()))); } @DeleteMapping("/delete") @@ -123,6 +124,7 @@ public class ErpPalletController { return null; } ErpPalletRespVO respVO = BeanUtils.toBean(pallet, ErpPalletRespVO.class); + fillPackagingInfo(respVO); String qrcode = qrcodeService.selectQrcodeUrlByIdAndCode(QrcodeBizTypeEnum.PALLET.getCode(), pallet.getId(), pallet.getCode()); if (qrcode != null) { respVO.setQrcode(qrcode); @@ -132,10 +134,18 @@ public class ErpPalletController { private ErpPalletRespVO buildPalletRespVO(ErpPalletDO pallet, Map qrcodeMap) { ErpPalletRespVO respVO = BeanUtils.toBean(pallet, ErpPalletRespVO.class); + fillPackagingInfo(respVO); String qrcode = qrcodeMap.get(pallet.getId()); if (qrcode != null) { respVO.setQrcode(qrcode); } return respVO; } + + private void fillPackagingInfo(ErpPalletRespVO respVO) { + if (respVO == null) { + return; + } + respVO.setPackageCount(respVO.getProductCount()); + } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletPageReqVO.java index fa05fb24d..9b7ef3c3d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletPageReqVO.java @@ -33,6 +33,9 @@ public class ErpPalletPageReqVO extends PageParam { @InEnum(ErpPalletStatusEnum.class) private Integer status; + @Schema(description = "排除的托盘状态", example = "3") + private Integer excludeStatus; + @Schema(description = "仓库编号", example = "1") private Long warehouseId; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java index 0144a353b..aa9397d55 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java @@ -58,10 +58,17 @@ public class ErpPalletRespVO { @ExcelProperty("产品编号") private Long productId; + @Schema(description = "产品名称", example = "产品A") + @ExcelProperty("产品名称") + private String productName; + @Schema(description = "产品数量", example = "120") @ExcelProperty("产品数量") private BigDecimal productCount; + @Schema(description = "当前包数", example = "20") + private BigDecimal packageCount; + @Schema(description = "二维码", example = "https://xxx.com/qrcode/pallet/1") @ExcelProperty("二维码") private String qrcode; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletSaveReqVO.java index 09155b306..a0d81738a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletSaveReqVO.java @@ -54,6 +54,9 @@ public class ErpPalletSaveReqVO { @Schema(description = "产品编号", example = "1001") private Long productId; + @Schema(description = "产品名称", example = "产品A") + private String productName; + @Schema(description = "产品数量", example = "120") private BigDecimal productCount; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java index 02b9e4296..c96c3b11c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -58,6 +58,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -325,7 +326,7 @@ public class ErpStockInController { } else { Map productMap = pageProductMap != null ? pageProductMap : productService.getProductSimpleVOMap( convertSet(stockInItemList, ErpStockInItemDO::getProductId)); - stockInVO.setItems(BeanUtils.toBean(stockInItemList, ErpStockInRespVO.Item.class, item -> { + List items = BeanUtils.toBean(stockInItemList, ErpStockInRespVO.Item.class, item -> { ErpStockDO stock = pageStockMap != null ? pageStockMap.get(buildStockKey(item.getProductId(), item.getWarehouseId(), item.getAreaId())) : stockService.getStock(item.getProductId(), item.getWarehouseId(), item.getAreaId()); item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); @@ -349,7 +350,9 @@ public class ErpStockInController { .ifPresent(supplier -> item.setSupplierName(supplier.getSupplierName())); } }); - })); + }); + stockInVO.setItems(Objects.equals(stockIn.getInType(), StockInTypeEnum.产品入库.getValue()) + ? mergeProductStockInItems(items) : items); stockInVO.setProductNames(CollUtil.join(stockInVO.getItems(), ",", ErpStockInRespVO.Item::getProductName)); } @@ -375,6 +378,41 @@ public class ErpStockInController { Function.identity(), (left, right) -> left, HashMap::new)); } + private List mergeProductStockInItems(List items) { + if (CollUtil.isEmpty(items)) { + return Collections.emptyList(); + } + Map itemMap = new LinkedHashMap<>(); + for (ErpStockInRespVO.Item sourceItem : items) { + String key = buildProductItemMergeKey(sourceItem.getProductId(), sourceItem.getProductPrice(), + sourceItem.getPackagingSchemeId(), sourceItem.getInputUnitType(), sourceItem.getInputCount(), + sourceItem.getRelateTask(), sourceItem.getTaskId(), sourceItem.getRemark()); + ErpStockInRespVO.Item targetItem = itemMap.get(key); + if (targetItem == null) { + itemMap.put(key, copyMergedStockInItem(sourceItem)); + continue; + } + targetItem.setCount(defaultZero(targetItem.getCount()).add(defaultZero(sourceItem.getCount()))); + targetItem.setPackageCount(defaultZero(targetItem.getPackageCount()).add(defaultZero(sourceItem.getPackageCount()))); + targetItem.getPallets().addAll(sourceItem.getPallets()); + } + return new ArrayList<>(itemMap.values()); + } + + private ErpStockInRespVO.Item copyMergedStockInItem(ErpStockInRespVO.Item sourceItem) { + ErpStockInRespVO.Item targetItem = BeanUtils.toBean(sourceItem, ErpStockInRespVO.Item.class); + targetItem.setPallets(new ArrayList<>(sourceItem.getPallets() != null ? sourceItem.getPallets() : Collections.emptyList())); + return targetItem; + } + + private String buildProductItemMergeKey(Object... values) { + return java.util.Arrays.stream(values).map(String::valueOf).collect(Collectors.joining("_")); + } + + private BigDecimal defaultZero(BigDecimal value) { + return value != null ? value : BigDecimal.ZERO; + } + private String buildStockKey(Long productId, Long warehouseId, Long areaId) { return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId); } @@ -387,6 +425,9 @@ public class ErpStockInController { return convertList(itemPallets, itemPallet -> { ErpStockInRespVO.Item.PalletItem palletItem = new ErpStockInRespVO.Item.PalletItem(); palletItem.setPalletId(itemPallet.getPalletId()); + palletItem.setWarehouseId(itemPallet.getWarehouseId()); + palletItem.setAreaId(itemPallet.getAreaId()); + palletItem.setCount(itemPallet.getCount()); palletItem.setPackageCount(itemPallet.getPackageCount()); MapUtils.findAndThen(palletMap, itemPallet.getPalletId(), pallet -> palletItem.setPalletCode(pallet.getCode())); return palletItem; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java index 191df5a74..f9a1dd1d5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java @@ -60,6 +60,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -245,7 +246,7 @@ public class ErpStockOutController { convertSet(stockOuts, ErpStockOutDO::getId)).stream() .collect(Collectors.groupingBy(ErpStockOutItemDO::getOutId)); Map userMap = adminUserApi.getUserMap(convertListByFlatMap(stockOuts, - item -> Stream.of(NumberUtils.parseLong(item.getCreator()), item.getResponserId(), item.getAuditUserId()))); + item -> Stream.of(NumberUtils.parseLong(item.getCreator()), item.getStockUserId(), item.getAuditUserId()))); Map customerMap = customerService.getCustomerMap( convertSet(stockOuts, ErpStockOutDO::getCustomerId)); List allItems = convertListByFlatMap(itemMap.values(), Collection::stream); @@ -287,14 +288,14 @@ public class ErpStockOutController { stockOutVO.setStatusName(getStockOutStatusName(stockOut.getStatus())); Map userMap = pageUserMap != null ? pageUserMap : adminUserApi.getUserMap(convertListByFlatMap( Collections.singletonList(stockOut), item -> Stream.of(NumberUtils.parseLong(item.getCreator()), - item.getResponserId(), item.getAuditUserId()))); + item.getStockUserId(), item.getAuditUserId()))); Map> itemPalletMap = pageItemPalletMap != null ? pageItemPalletMap : stockOutService.getStockOutItemPalletListByOutId(stockOut.getId()).stream() .collect(Collectors.groupingBy(ErpStockOutItemPalletDO::getOutItemId)); Map palletMap = pagePalletMap != null ? pagePalletMap : palletService.getPalletMap( convertSet(convertListByFlatMap(itemPalletMap.values(), Collection::stream), ErpStockOutItemPalletDO::getPalletId)); MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockOut.getCreator()), user -> stockOutVO.setCreatorName(user.getNickname())); - MapUtils.findAndThen(userMap, stockOut.getResponserId(), user -> stockOutVO.setResponserName(user.getNickname())); + MapUtils.findAndThen(userMap, stockOut.getStockUserId(), user -> stockOutVO.setStockUserName(user.getNickname())); MapUtils.findAndThen(userMap, stockOut.getAuditUserId(), user -> stockOutVO.setAuditUserName(user.getNickname())); if (Objects.equals(stockOut.getOutType(), "模具出库")) { @@ -321,7 +322,7 @@ public class ErpStockOutController { } else { Map productMap = pageProductMap != null ? pageProductMap : productService.getProductSimpleVOMap( convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); - stockOutVO.setItems(BeanUtils.toBean(stockOutItemList, ErpStockOutRespVO.Item.class, item -> { + List items = BeanUtils.toBean(stockOutItemList, ErpStockOutRespVO.Item.class, item -> { ErpStockDO stock = pageStockMap != null ? pageStockMap.get(buildStockKey(item.getProductId(), item.getWarehouseId(), item.getAreaId())) : stockService.getStock(item.getProductId(), item.getWarehouseId(), item.getAreaId()); item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); @@ -339,7 +340,9 @@ public class ErpStockOutController { .ifPresent(supplier -> item.setSupplierName(supplier.getSupplierName())); } }); - })); + }); + stockOutVO.setItems(Objects.equals(stockOut.getOutType(), StockOutTypeEnum.产品出库.getValue()) + ? mergeProductStockOutItems(items) : items); stockOutVO.setProductNames(CollUtil.join(stockOutVO.getItems(), ",", ErpStockOutRespVO.Item::getProductName)); } if (CollUtil.isNotEmpty(stockOutVO.getItems())) { @@ -384,6 +387,42 @@ public class ErpStockOutController { Function.identity(), (left, right) -> left, HashMap::new)); } + private List mergeProductStockOutItems(List items) { + if (CollUtil.isEmpty(items)) { + return Collections.emptyList(); + } + Map itemMap = new LinkedHashMap<>(); + for (ErpStockOutRespVO.Item sourceItem : items) { + String key = buildProductItemMergeKey(sourceItem.getProductId(), sourceItem.getProductPrice(), + sourceItem.getPackagingSchemeId(), sourceItem.getInputUnitType(), sourceItem.getInputCount(), + sourceItem.getOutMode(), sourceItem.getOutUsageType(), sourceItem.getRepairId(), + sourceItem.getRepairDeviceId(), sourceItem.getMaintenanceId(), sourceItem.getRemark()); + ErpStockOutRespVO.Item targetItem = itemMap.get(key); + if (targetItem == null) { + itemMap.put(key, copyMergedStockOutItem(sourceItem)); + continue; + } + targetItem.setCount(defaultZero(targetItem.getCount()).add(defaultZero(sourceItem.getCount()))); + targetItem.setPackageCount(defaultZero(targetItem.getPackageCount()).add(defaultZero(sourceItem.getPackageCount()))); + targetItem.getPallets().addAll(sourceItem.getPallets()); + } + return new ArrayList<>(itemMap.values()); + } + + private ErpStockOutRespVO.Item copyMergedStockOutItem(ErpStockOutRespVO.Item sourceItem) { + ErpStockOutRespVO.Item targetItem = BeanUtils.toBean(sourceItem, ErpStockOutRespVO.Item.class); + targetItem.setPallets(new ArrayList<>(sourceItem.getPallets() != null ? sourceItem.getPallets() : Collections.emptyList())); + return targetItem; + } + + private String buildProductItemMergeKey(Object... values) { + return java.util.Arrays.stream(values).map(String::valueOf).collect(Collectors.joining("_")); + } + + private BigDecimal defaultZero(BigDecimal value) { + return value != null ? value : BigDecimal.ZERO; + } + private String buildStockKey(Long productId, Long warehouseId, Long areaId) { return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId); } @@ -396,6 +435,9 @@ public class ErpStockOutController { return convertList(itemPallets, itemPallet -> { ErpStockOutRespVO.Item.PalletItem palletItem = new ErpStockOutRespVO.Item.PalletItem(); palletItem.setPalletId(itemPallet.getPalletId()); + palletItem.setWarehouseId(itemPallet.getWarehouseId()); + palletItem.setAreaId(itemPallet.getAreaId()); + palletItem.setCount(itemPallet.getCount()); palletItem.setPackageCount(itemPallet.getPackageCount()); MapUtils.findAndThen(palletMap, itemPallet.getPalletId(), pallet -> palletItem.setPalletCode(pallet.getCode())); return palletItem; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java index 4f4578fd9..4fbc45266 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -219,6 +219,15 @@ public class ErpStockInRespVO { @Schema(description = "托盘编码", example = "TP20240601001") private String palletCode; + @Schema(description = "仓库编号", example = "3113") + private Long warehouseId; + + @Schema(description = "库区编号", example = "3113") + private Long areaId; + + @Schema(description = "产品数量", example = "100.00") + private BigDecimal count; + @Schema(description = "包数", example = "10") private BigDecimal packageCount; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java index 72b155291..5e7786384 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java @@ -39,7 +39,7 @@ public class ErpStockInSaveReqVO { @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") private String fileUrl; - @Schema(description = "入库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "入库项列表", implementation = Item.class) @NotEmpty(message = "入库项列表不能为空") @Valid private List items; @@ -69,8 +69,7 @@ public class ErpStockInSaveReqVO { @Schema(description = "产品单价", example = "100.00") private BigDecimal productPrice; - @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") - @NotNull(message = "产品数量不能为空") + @Schema(description = "产品数量", example = "100.00") private BigDecimal count; @Schema(description = "包装方案 ID", example = "1") @@ -109,7 +108,7 @@ public class ErpStockInSaveReqVO { @Schema(description = "任务单ID", example = "10001") private Long taskId; - @Schema(description = "托盘列表") + @Schema(description = "托盘列表", implementation = PalletItem.class) @Valid private List pallets; @@ -126,6 +125,15 @@ public class ErpStockInSaveReqVO { @NotNull(message = "托盘ID不能为空") private Long palletId; + @Schema(description = "仓库编号", example = "3113") + private Long warehouseId; + + @Schema(description = "库区编号", example = "3113") + private Long areaId; + + @Schema(description = "产品数量", example = "100.00") + private BigDecimal count; + @Schema(description = "包数", example = "10") private BigDecimal packageCount; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java index 6173ab455..4167af05f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java @@ -26,8 +26,8 @@ public class ErpStockOutPageReqVO extends PageParam { @Schema(description = "客户编号", example = "3113") private Long customerId; - @Schema(description = "负责人 id", example = "3113") - private Long responserId; + @Schema(description = "经办人编号", example = "3113") + private Long stockUserId; @Schema(description = "出库类型", example = "其他出库") private String outType; @@ -60,4 +60,8 @@ public class ErpStockOutPageReqVO extends PageParam { @Schema(description = "id 集合,导出时使用") private String ids; + + public void setResponserId(Long responserId) { + this.stockUserId = responserId; + } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java index 00d7ad76b..bc46f3eb6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -35,11 +35,11 @@ public class ErpStockOutRespVO { @ExcelProperty("客户名称") private String customerName; - @Schema(description = "负责人 id", example = "3113") - private Long responserId; + @Schema(description = "经办人编号", example = "3113") + private Long stockUserId; - @Schema(description = "负责人", example = "张三") - private String responserName; + @Schema(description = "经办人名称", example = "张三") + private String stockUserName; @Schema(description = "出库类型", example = "其他出库") private String outType; @@ -274,6 +274,15 @@ public class ErpStockOutRespVO { @Schema(description = "托盘编码", example = "TP20240601001") private String palletCode; + @Schema(description = "仓库编号", example = "3113") + private Long warehouseId; + + @Schema(description = "库区编号", example = "3113") + private Long areaId; + + @Schema(description = "产品数量", example = "100.00") + private BigDecimal count; + @Schema(description = "包数", example = "10") private BigDecimal packageCount; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java index 00be71acd..d80b79225 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java @@ -20,8 +20,8 @@ public class ErpStockOutSaveReqVO { @Schema(description = "客户编号", example = "3113") private Long customerId; - @Schema(description = "负责人 id", example = "3113") - private Long responserId; + @Schema(description = "经办人编号", example = "3113") + private Long stockUserId; @Schema(description = "出库类型", example = "其他出库") private String outType; @@ -46,4 +46,5 @@ public class ErpStockOutSaveReqVO { @Schema(description = "计划单 Code", example = "PLAN20240601") private String planCode; + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVOItem.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVOItem.java index 28f8122cc..a8577342c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVOItem.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVOItem.java @@ -99,6 +99,15 @@ public class ErpStockOutSaveReqVOItem { @NotNull(message = "托盘ID不能为空") private Long palletId; + @Schema(description = "仓库编号", example = "3113") + private Long warehouseId; + + @Schema(description = "库区编号", example = "3113") + private Long areaId; + + @Schema(description = "产品数量", example = "100.00") + private BigDecimal count; + @Schema(description = "包数", example = "10") private BigDecimal packageCount; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/pallet/ErpPalletDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/pallet/ErpPalletDO.java index 726c9bf19..80d801166 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/pallet/ErpPalletDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/pallet/ErpPalletDO.java @@ -36,6 +36,7 @@ public class ErpPalletDO extends BaseDO { private Long areaId; private String planCode; private Long productId; + private String productName; private BigDecimal productCount; private String qrcode; private LocalDate purchaseDate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemPalletDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemPalletDO.java index 9e5b07401..45a32c3ed 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemPalletDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemPalletDO.java @@ -28,5 +28,8 @@ public class ErpStockInItemPalletDO extends BaseDO { private Long inId; private Long inItemId; private Long palletId; + private Long warehouseId; + private Long areaId; + private BigDecimal count; private BigDecimal packageCount; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java index 51753f700..7a4d25759 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.stock; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; @@ -45,7 +46,8 @@ public class ErpStockOutDO extends BaseDO { * 领料人编号 * */ - private Long responserId; + @TableField("responser_id") + private Long stockUserId; //@Schema(description = "出库类型", example = "随便") private String outType; /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemPalletDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemPalletDO.java index 953de013d..6a9b1a095 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemPalletDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemPalletDO.java @@ -28,5 +28,8 @@ public class ErpStockOutItemPalletDO extends BaseDO { private Long outId; private Long outItemId; private Long palletId; + private Long warehouseId; + private Long areaId; + private BigDecimal count; private BigDecimal packageCount; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java index 86f8d573d..9eba7f8c6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java @@ -19,6 +19,7 @@ public interface ErpPalletMapper extends BaseMapperX { .likeIfPresent(ErpPalletDO::getCode, reqVO.getCode()) .eqIfPresent(ErpPalletDO::getPalletType, reqVO.getPalletType()) .eqIfPresent(ErpPalletDO::getStatus, reqVO.getStatus()) + .neIfPresent(ErpPalletDO::getStatus, reqVO.getExcludeStatus()) .eqIfPresent(ErpPalletDO::getWarehouseId, reqVO.getWarehouseId()) .eqIfPresent(ErpPalletDO::getAreaId, reqVO.getAreaId()) .likeIfPresent(ErpPalletDO::getPlanCode, reqVO.getPlanCode()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java index 0af2a9c85..a3672abf4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java @@ -21,7 +21,7 @@ public interface ErpStockOutMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX() .likeIfPresent(ErpStockOutDO::getNo, reqVO.getNo()) .eqIfPresent(ErpStockOutDO::getCustomerId, reqVO.getCustomerId()) - .eqIfPresent(ErpStockOutDO::getResponserId, reqVO.getResponserId()) + .eqIfPresent(ErpStockOutDO::getStockUserId, reqVO.getStockUserId()) .eqIfPresent(ErpStockOutDO::getOutType, reqVO.getOutType()) .inIfPresent(ErpStockOutDO::getOutType, reqVO.getOutTypeList()) .betweenIfPresent(ErpStockOutDO::getOutTime, reqVO.getOutTime()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java index 0137928b9..d60fa60f9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; import cn.iocoder.yudao.module.erp.dal.mysql.pallet.ErpPalletMapper; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; @@ -54,8 +55,9 @@ public class ErpPalletServiceImpl implements ErpPalletService { @Override public Long createPallet(ErpPalletSaveReqVO createReqVO) { validateWarehouseAreaMatch(createReqVO.getWarehouseId(), createReqVO.getAreaId()); - validateProductExists(createReqVO.getProductId()); + ErpProductDO product = validateProductExists(createReqVO.getProductId()); ErpPalletDO pallet = BeanUtils.toBean(createReqVO, ErpPalletDO.class); + fillProductName(pallet, product); if (StringUtils.isBlank(pallet.getCode())) { pallet.setCode(autoCodeUtil.genSerialCode("PALLET_CODE_GENERATE", null)); } else { @@ -73,8 +75,9 @@ public class ErpPalletServiceImpl implements ErpPalletService { public void updatePallet(ErpPalletSaveReqVO updateReqVO) { ErpPalletDO pallet = validatePalletExists(updateReqVO.getId()); validateWarehouseAreaMatch(updateReqVO.getWarehouseId(), updateReqVO.getAreaId()); - validateProductExists(updateReqVO.getProductId()); + ErpProductDO product = validateProductExists(updateReqVO.getProductId()); ErpPalletDO updateObj = BeanUtils.toBean(updateReqVO, ErpPalletDO.class); + fillProductName(updateObj, product); if (StringUtils.isBlank(updateObj.getCode())) { updateObj.setCode(pallet.getCode()); } else { @@ -176,13 +179,19 @@ public class ErpPalletServiceImpl implements ErpPalletService { } } - private void validateProductExists(Long productId) { + private ErpProductDO validateProductExists(Long productId) { if (productId == null) { - return; + return null; } - if (productService.validProductList(Collections.singleton(productId)).isEmpty()) { + List products = productService.validProductList(Collections.singleton(productId)); + if (products.isEmpty()) { throw exception(PRODUCT_NOT_EXISTS); } + return products.get(0); + } + + private void fillProductName(ErpPalletDO pallet, ErpProductDO product) { + pallet.setProductName(product != null ? product.getName() : null); } private void generatePalletQrcode(Long id, String code) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 34f8feb6c..7e645a746 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInAuditR import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSubmitReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.StockInTypeEnum; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; @@ -49,8 +50,10 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -63,24 +66,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_ALERADY_IN; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_APPROVE_FAIL; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_AUDIT_FAIL_RESULT; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_AUDIT_FAIL_STATUS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_AUDIT_FAIL_USER; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_DELETE_FAIL_APPROVE; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_DELETE_FAIL_PROCESS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_NOT_EXISTS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_NO_EXISTS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_PROCESS_FAIL; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_SUBMIT_FAIL_AUDIT_USER_EMPTY; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_SUBMIT_FAIL_STATUS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_SUBMIT_FAIL_USER; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_UPDATE_FAIL_APPROVE; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_UPDATE_FAIL_PROCESS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PALLET_NOT_EXISTS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_AREA_NOT_EXISTS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_LOCATION_WAREHOUSE_AREA_NOT_MATCH; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; @Service @Validated @@ -124,6 +110,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { @Override @Transactional(rollbackFor = Exception.class) public Long createStockIn(ErpStockInSaveReqVO createReqVO) { + normalizeProductStockInItems(createReqVO); List stockInItems = validateStockInItems(createReqVO.getItems(), createReqVO.getInType()); if (createReqVO.getStockUserId() != null) { adminUserApi.validateUser(createReqVO.getStockUserId()); @@ -166,6 +153,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { @Override @Transactional(rollbackFor = Exception.class) public void updateStockIn(ErpStockInSaveReqVO updateReqVO) { + normalizeProductStockInItems(updateReqVO); ErpStockInDO stockIn = validateStockInExists(updateReqVO.getId()); if (ErpAuditStatus.APPROVE.getStatus().equals(stockIn.getStatus())) { throw exception(STOCK_IN_UPDATE_FAIL_APPROVE, stockIn.getNo()); @@ -186,7 +174,8 @@ public class ErpStockInServiceImpl implements ErpStockInService { .setTotalCount(getSumValue(stockInItems, ErpStockInItemDO::getCount, BigDecimal::add)) .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); stockInMapper.updateById(updateObj); - updateStockInItemList(updateReqVO.getId(), stockInItems); + updateStockInItemList(updateReqVO.getId(), stockInItems, + Objects.equals(updateReqVO.getInType(), StockInTypeEnum.产品入库.getValue())); saveStockInItemPallets(updateReqVO.getId(), stockInItems, updateReqVO.getItems()); } @@ -379,6 +368,80 @@ public class ErpStockInServiceImpl implements ErpStockInService { stockInMapper.updateById(stockIn); } + private void normalizeProductStockInItems(ErpStockInSaveReqVO reqVO) { + if (reqVO == null || !Objects.equals(reqVO.getInType(), StockInTypeEnum.产品入库.getValue()) + || CollUtil.isEmpty(reqVO.getItems())) { + return; + } + List normalizedItems = new ArrayList<>(); + for (ErpStockInSaveReqVO.Item sourceItem : reqVO.getItems()) { + if (CollUtil.isEmpty(sourceItem.getPallets())) { + normalizedItems.add(sourceItem); + continue; + } + Map itemMap = new LinkedHashMap<>(); + Map> palletMap = new LinkedHashMap<>(); + for (ErpStockInSaveReqVO.Item.PalletItem pallet : sourceItem.getPallets()) { + Long warehouseId = pallet.getWarehouseId() != null ? pallet.getWarehouseId() : sourceItem.getWarehouseId(); + Long areaId = pallet.getAreaId() != null ? pallet.getAreaId() : sourceItem.getAreaId(); + StockInPalletGroupKey key = new StockInPalletGroupKey(warehouseId, areaId); + ErpStockInSaveReqVO.Item targetItem = itemMap.computeIfAbsent(key, + item -> copyStockInItem(sourceItem, warehouseId, areaId)); + targetItem.setCount(defaultZero(targetItem.getCount()).add(resolvePalletCount(pallet))); + targetItem.setPackageCount(defaultZero(targetItem.getPackageCount()).add(defaultZero(pallet.getPackageCount()))); + palletMap.computeIfAbsent(key, item -> new ArrayList<>()).add(pallet); + } + itemMap.forEach((key, item) -> { + item.setPallets(palletMap.getOrDefault(key, Collections.emptyList())); + normalizedItems.add(item); + }); + } + reqVO.setItems(normalizedItems); + } + + private ErpStockInSaveReqVO.Item copyStockInItem(ErpStockInSaveReqVO.Item sourceItem, Long warehouseId, Long areaId) { + ErpStockInSaveReqVO.Item targetItem = BeanUtils.toBean(sourceItem, ErpStockInSaveReqVO.Item.class); + targetItem.setId(null); + targetItem.setWarehouseId(warehouseId); + targetItem.setAreaId(areaId); + targetItem.setCount(BigDecimal.ZERO); + targetItem.setPackageCount(BigDecimal.ZERO); + targetItem.setPallets(new ArrayList<>()); + return targetItem; + } + + private BigDecimal resolvePalletCount(ErpStockInSaveReqVO.Item.PalletItem pallet) { + return defaultZero(pallet.getCount()); + } + + private static class StockInPalletGroupKey { + + private final Long warehouseId; + private final Long areaId; + + private StockInPalletGroupKey(Long warehouseId, Long areaId) { + this.warehouseId = warehouseId; + this.areaId = areaId; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof StockInPalletGroupKey)) { + return false; + } + StockInPalletGroupKey that = (StockInPalletGroupKey) obj; + return Objects.equals(warehouseId, that.warehouseId) && Objects.equals(areaId, that.areaId); + } + + @Override + public int hashCode() { + return Objects.hash(warehouseId, areaId); + } + } + private void applyStockInEffect(ErpStockInDO stockIn, List stockInItems, Integer bizType) { operateStockInEffect(stockIn, stockInItems, true, bizType); } @@ -531,10 +594,11 @@ public class ErpStockInServiceImpl implements ErpStockInService { }); } - private void updateStockInItemList(Long id, List newList) { + private void updateStockInItemList(Long id, List newList, boolean recreateItems) { boolean moldStockIn = CollUtil.isNotEmpty(newList) && newList.stream().anyMatch(item -> item.getMoldSetId() != null); - if (moldStockIn) { + if (moldStockIn || recreateItems) { + stockInItemPalletMapper.deleteByInId(id); stockInItemMapper.deleteByInId(id); newList.forEach(item -> { item.setId(null); @@ -576,7 +640,10 @@ public class ErpStockInServiceImpl implements ErpStockInService { .inId(inId) .inItemId(stockInItem.getId()) .palletId(pallet.getPalletId()) - .packageCount(defaultPackageCount(pallet.getPackageCount(), stockInItem.getCount())) + .warehouseId(pallet.getWarehouseId() != null ? pallet.getWarehouseId() : stockInItem.getWarehouseId()) + .areaId(pallet.getAreaId() != null ? pallet.getAreaId() : stockInItem.getAreaId()) + .count(resolvePalletCount(pallet)) + .packageCount(defaultZero(pallet.getPackageCount())) .build())); } if (CollUtil.isNotEmpty(palletRelations)) { @@ -590,6 +657,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { return; } Map itemMap = convertMap(stockInItems, ErpStockInItemDO::getId); + Map productMap = productService.getProductMap(convertSet(stockInItems, ErpStockInItemDO::getProductId)); Map palletMap = convertMap(palletMapper.selectBatchIds( convertSet(palletRelations, ErpStockInItemPalletDO::getPalletId)), ErpPalletDO::getId); palletRelations.forEach(relation -> { @@ -598,10 +666,15 @@ public class ErpStockInServiceImpl implements ErpStockInService { if (item == null || pallet == null) { return; } - BigDecimal packageCount = defaultZero(relation.getPackageCount()); - if (approve) { + BigDecimal packageCount = defaultZero(relation.getPackageCount()); + if (approve) { + if (pallet.getProductId() != null && !pallet.getProductId().equals(item.getProductId())) { + throw exception(PALLET_ALREADY_HAS_DIFFERENT_PRODUCT, pallet.getCode(), pallet.getProductId()); + } pallet.setStatus(ErpPalletStatusEnum.OCCUPIED.getStatus()); pallet.setProductId(item.getProductId()); + ErpProductDO product = productMap.get(item.getProductId()); + pallet.setProductName(product != null ? product.getName() : null); pallet.setProductCount(defaultZero(pallet.getProductCount()).add(packageCount)); pallet.setWarehouseId(item.getWarehouseId()); pallet.setAreaId(item.getAreaId()); @@ -610,7 +683,10 @@ public class ErpStockInServiceImpl implements ErpStockInService { if (remainCount.compareTo(BigDecimal.ZERO) <= 0) { pallet.setStatus(ErpPalletStatusEnum.IDLE.getStatus()); pallet.setProductId(null); + pallet.setProductName(null); pallet.setProductCount(BigDecimal.ZERO); + pallet.setWarehouseId(null); + pallet.setAreaId(null); } else { pallet.setProductCount(remainCount); } @@ -619,10 +695,6 @@ public class ErpStockInServiceImpl implements ErpStockInService { }); } - private BigDecimal defaultPackageCount(BigDecimal packageCount, BigDecimal itemCount) { - return packageCount != null ? packageCount : defaultZero(itemCount); - } - private BigDecimal defaultZero(BigDecimal value) { return value != null ? value : BigDecimal.ZERO; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java index 2b097c11d..0e0a17891 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldBrandMapper; import cn.iocoder.yudao.module.common.enums.MoldBrandStatusEnum; import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletStatusEnum; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutAuditReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; @@ -21,6 +22,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; @@ -55,8 +57,10 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -105,6 +109,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { @Resource private ErpStockRecordService stockRecordService; @Resource + private ErpStockService stockService; + @Resource private WarehouseAreaService warehouseAreaService; @Resource private AdminUserApi adminUserApi; @@ -120,12 +126,14 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { @Override @Transactional(rollbackFor = Exception.class) public Long createStockOut(ErpStockOutSaveReqVO createReqVO) { + BigDecimal totalCount = getOriginalProductStockOutTotalCount(createReqVO); + normalizeProductStockOutItems(createReqVO); List stockOutItems = validateStockOutItems(createReqVO.getItems(), createReqVO.getOutType()); if (createReqVO.getCustomerId() != null) { customerService.validateCustomer(createReqVO.getCustomerId()); } - if (createReqVO.getResponserId() != null) { - adminUserApi.validateUser(createReqVO.getResponserId()); + if (createReqVO.getStockUserId() != null) { + adminUserApi.validateUser(createReqVO.getStockUserId()); } if (createReqVO.getAuditUserId() != null) { adminUserApi.validateUser(createReqVO.getAuditUserId()); @@ -141,7 +149,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { .setNo(no) .setNeedAudit(needAudit) .setStatus(status) - .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) + .setTotalCount(totalCount != null ? totalCount + : getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); fillUsageSnapshot(stockOutItems, createReqVO.getItems()); stockOutMapper.insert(stockOut); @@ -165,6 +174,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { @Override @Transactional(rollbackFor = Exception.class) public void updateStockOut(ErpStockOutSaveReqVO updateReqVO) { + BigDecimal totalCount = getOriginalProductStockOutTotalCount(updateReqVO); + normalizeProductStockOutItems(updateReqVO); ErpStockOutDO stockOut = validateStockOutExists(updateReqVO.getId()); if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockOut.getNo()); @@ -175,8 +186,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { if (updateReqVO.getCustomerId() != null) { customerService.validateCustomer(updateReqVO.getCustomerId()); } - if (updateReqVO.getResponserId() != null) { - adminUserApi.validateUser(updateReqVO.getResponserId()); + if (updateReqVO.getStockUserId() != null) { + adminUserApi.validateUser(updateReqVO.getStockUserId()); } if (updateReqVO.getAuditUserId() != null) { adminUserApi.validateUser(updateReqVO.getAuditUserId()); @@ -185,11 +196,13 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { boolean needAudit = needAudit(); ErpStockOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockOutDO.class, out -> out .setNeedAudit(needAudit) - .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) + .setTotalCount(totalCount != null ? totalCount + : getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); fillUsageSnapshot(stockOutItems, updateReqVO.getItems()); stockOutMapper.updateById(updateObj); - updateStockOutItemList(updateReqVO.getId(), stockOutItems); + updateStockOutItemList(updateReqVO.getId(), stockOutItems, + Objects.equals(updateReqVO.getOutType(), "产品出库")); saveStockOutItemPallets(updateReqVO.getId(), stockOutItems, updateReqVO.getItems()); } @@ -375,6 +388,88 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { return stockOutMapper.selectByOutType(outTypes); } + private BigDecimal getOriginalProductStockOutTotalCount(ErpStockOutSaveReqVO reqVO) { + if (reqVO == null || !Objects.equals(reqVO.getOutType(), "产品出库") + || CollUtil.isEmpty(reqVO.getItems())) { + return null; + } + return getSumValue(reqVO.getItems(), ErpStockOutSaveReqVOItem::getCount, BigDecimal::add, BigDecimal.ZERO); + } + + private void normalizeProductStockOutItems(ErpStockOutSaveReqVO reqVO) { + if (reqVO == null || !Objects.equals(reqVO.getOutType(), "产品出库") + || CollUtil.isEmpty(reqVO.getItems())) { + return; + } + List normalizedItems = new ArrayList<>(); + for (ErpStockOutSaveReqVOItem sourceItem : reqVO.getItems()) { + if (CollUtil.isEmpty(sourceItem.getPallets())) { + normalizedItems.add(sourceItem); + continue; + } + Map itemMap = new LinkedHashMap<>(); + Map> palletMap = new LinkedHashMap<>(); + for (ErpStockOutSaveReqVOItem.PalletItem pallet : sourceItem.getPallets()) { + Long warehouseId = pallet.getWarehouseId() != null ? pallet.getWarehouseId() : sourceItem.getWarehouseId(); + Long areaId = pallet.getAreaId() != null ? pallet.getAreaId() : sourceItem.getAreaId(); + StockOutPalletGroupKey key = new StockOutPalletGroupKey(warehouseId, areaId); + ErpStockOutSaveReqVOItem targetItem = itemMap.computeIfAbsent(key, + item -> copyStockOutItem(sourceItem, warehouseId, areaId)); + targetItem.setCount(defaultZero(targetItem.getCount()).add(resolvePalletCount(pallet))); + targetItem.setPackageCount(defaultZero(targetItem.getPackageCount()).add(defaultZero(pallet.getPackageCount()))); + palletMap.computeIfAbsent(key, item -> new ArrayList<>()).add(pallet); + } + itemMap.forEach((key, item) -> { + item.setPallets(palletMap.getOrDefault(key, Collections.emptyList())); + normalizedItems.add(item); + }); + } + reqVO.setItems(normalizedItems); + } + + private ErpStockOutSaveReqVOItem copyStockOutItem(ErpStockOutSaveReqVOItem sourceItem, Long warehouseId, Long areaId) { + ErpStockOutSaveReqVOItem targetItem = BeanUtils.toBean(sourceItem, ErpStockOutSaveReqVOItem.class); + targetItem.setId(null); + targetItem.setWarehouseId(warehouseId); + targetItem.setAreaId(areaId); + targetItem.setCount(BigDecimal.ZERO); + targetItem.setPackageCount(BigDecimal.ZERO); + targetItem.setPallets(new ArrayList<>()); + return targetItem; + } + + private BigDecimal resolvePalletCount(ErpStockOutSaveReqVOItem.PalletItem pallet) { + return defaultZero(pallet.getCount()); + } + + private static class StockOutPalletGroupKey { + + private final Long warehouseId; + private final Long areaId; + + private StockOutPalletGroupKey(Long warehouseId, Long areaId) { + this.warehouseId = warehouseId; + this.areaId = areaId; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof StockOutPalletGroupKey)) { + return false; + } + StockOutPalletGroupKey that = (StockOutPalletGroupKey) obj; + return Objects.equals(warehouseId, that.warehouseId) && Objects.equals(areaId, that.areaId); + } + + @Override + public int hashCode() { + return Objects.hash(warehouseId, areaId); + } + } + @Override public void updateMoldStatus(Long id, Integer status) { ErpStockOutDO stockOut = validateStockOutExists(id); @@ -568,10 +663,11 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { }); } - private void updateStockOutItemList(Long id, List newList) { + private void updateStockOutItemList(Long id, List newList, boolean recreateItems) { boolean moldStockOut = CollUtil.isNotEmpty(newList) && newList.stream().anyMatch(item -> item.getMoldSetId() != null); - if (moldStockOut) { + if (moldStockOut || recreateItems) { + stockOutItemPalletMapper.deleteByOutId(id); stockOutItemMapper.deleteByOutId(id); newList.forEach(item -> { item.setId(null); @@ -612,7 +708,10 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { .outId(outId) .outItemId(stockOutItem.getId()) .palletId(pallet.getPalletId()) - .packageCount(defaultPackageCount(pallet.getPackageCount(), stockOutItem.getCount())) + .warehouseId(pallet.getWarehouseId() != null ? pallet.getWarehouseId() : stockOutItem.getWarehouseId()) + .areaId(pallet.getAreaId() != null ? pallet.getAreaId() : stockOutItem.getAreaId()) + .count(resolvePalletCount(pallet)) + .packageCount(defaultZero(pallet.getPackageCount())) .build())); } if (CollUtil.isNotEmpty(palletRelations)) { @@ -626,6 +725,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { return; } Map itemMap = convertMap(stockOutItems, ErpStockOutItemDO::getId); + Map productMap = productService.getProductMap(convertSet(stockOutItems, ErpStockOutItemDO::getProductId)); Map palletMap = convertMap(palletMapper.selectBatchIds( convertSet(palletRelations, ErpStockOutItemPalletDO::getPalletId)), ErpPalletDO::getId); palletRelations.forEach(relation -> { @@ -640,13 +740,18 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { if (remainCount.compareTo(BigDecimal.ZERO) <= 0) { pallet.setStatus(ErpPalletStatusEnum.IDLE.getStatus()); pallet.setProductId(null); + pallet.setProductName(null); pallet.setProductCount(BigDecimal.ZERO); + pallet.setWarehouseId(null); + pallet.setAreaId(null); } else { pallet.setProductCount(remainCount); } } else { pallet.setStatus(ErpPalletStatusEnum.OCCUPIED.getStatus()); pallet.setProductId(item.getProductId()); + ErpProductDO product = productMap.get(item.getProductId()); + pallet.setProductName(product != null ? product.getName() : null); pallet.setProductCount(defaultZero(pallet.getProductCount()).add(packageCount)); pallet.setWarehouseId(item.getWarehouseId()); pallet.setAreaId(item.getAreaId()); @@ -655,10 +760,6 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { }); } - private BigDecimal defaultPackageCount(BigDecimal packageCount, BigDecimal itemCount) { - return packageCount != null ? packageCount : defaultZero(itemCount); - } - private BigDecimal defaultZero(BigDecimal value) { return value != null ? value : BigDecimal.ZERO; }