From bff1ffa31b7f9756f532224a34356599cebb427f Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Tue, 23 Jun 2026 17:33:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=BB=93=E5=BA=93?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 3 ++ .../admin/stock/ErpStockInController.java | 1 - .../admin/stock/ErpStockOutController.java | 1 - .../dataobject/stock/ErpStockInItemDO.java | 4 +++ .../dataobject/stock/ErpStockOutItemDO.java | 4 +++ .../dal/mysql/product/ErpProductMapper.java | 25 +++++++++++++-- .../erp/dal/mysql/stock/ErpStockInMapper.java | 18 +++++++++-- .../service/stock/ErpStockInServiceImpl.java | 1 + .../service/stock/ErpStockOutServiceImpl.java | 31 ++++++++++++++++--- .../service/stock/ErpStockServiceImpl.java | 3 ++ 10 files changed, 80 insertions(+), 11 deletions(-) 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 4b57e443f..fece8bd8f 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 @@ -141,6 +141,9 @@ public interface ErrorCodeConstants { 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 STOCK_OUT_PRODUCT_PALLET_COUNT_EMPTY = new ErrorCode(1_030_402_016, "产品出库失败,托盘({})的出库数量不能为空或小于等于0"); + ErrorCode STOCK_OUT_PRODUCT_COUNT_EMPTY = new ErrorCode(1_030_402_017, "产品出库失败,出库数量不能为空或小于等于0"); + ErrorCode STOCK_OUT_PRODUCT_COUNT_NOT_MATCH = new ErrorCode(1_030_402_018, "产品出库失败,明细出库数量({})与托盘出库数量合计({})不一致"); ErrorCode PALLET_ALREADY_HAS_DIFFERENT_PRODUCT = new ErrorCode(1_030_400_011, "入库失败,托盘({})已装载产品({}),不能混装其他产品"); // ========== ERP 库存调拨单 1-030-403-000 ========== 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 c96c3b11c..78be661fc 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 @@ -338,7 +338,6 @@ public class ErpStockInController { } item.setPallets(buildStockInPalletRespList(itemPalletMap.get(item.getId()), palletMap)); MapUtils.findAndThen(productMap, item.getProductId(), product -> { - item.setProductName(product.getName()); item.setProductBarCode(product.getBarCode()); item.setProductUnitName(product.getUnitName()); item.setCategoryType(product.getCategoryType()); 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 f9a1dd1d5..e51995f0b 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 @@ -328,7 +328,6 @@ public class ErpStockOutController { item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); item.setPallets(buildStockOutPalletRespList(itemPalletMap.get(item.getId()), palletMap)); MapUtils.findAndThen(productMap, item.getProductId(), product -> { - item.setProductName(product.getName()); item.setProductBarCode(product.getBarCode()); item.setProductUnitName(product.getUnitName()); item.setCategoryType(product.getCategoryType()); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java index 54bacfa42..c068a7e7b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java @@ -52,6 +52,10 @@ public class ErpStockInItemDO extends BaseDO { * 关联 {@link ErpProductDO#getId()} */ private Long productId; + /** + * 产品名称快照 + */ + private String productName; /** * 产品单位编号 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java index 6cadaf609..e207772c3 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java @@ -91,6 +91,10 @@ public class ErpStockOutItemDO extends BaseDO { * 关联 {@link ErpProductDO#getId()} */ private Long productId; + /** + * 产品名称快照 + */ + private String productName; /** * 产品单位编号 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java index 0edda1a7c..f984ecd16 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductListReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductRelationRespVO; @@ -13,6 +14,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; +import org.apache.poi.util.StringUtil; import org.springframework.util.StringUtils; import java.util.ArrayList; @@ -38,14 +40,31 @@ public interface ErpProductMapper extends BaseMapperX { if (reqVO.getCategoryType() != null && CollUtil.isEmpty(categoryIds)) { return PageResult.empty(); } - - return selectPage(reqVO, new LambdaQueryWrapperX() + LambdaQueryWrapperX queryWrapper = new LambdaQueryWrapperX<>(); + if(StringUtil.isNotBlank(reqVO.getCode())&& StringUtil.isNotBlank(reqVO.getName())&&reqVO.getCode().equals(reqVO.getName())){ + if(reqVO.getCode().contains("PRODUCTMATERIAL-")){ + queryWrapper.eq(ErpProductDO::getId, reqVO.getCode().replace("PRODUCTMATERIAL-","")); + }else{ + queryWrapper.and(w -> w + .like(ErpProductDO::getBarCode, reqVO.getCode()) + .or() + .like(ErpProductDO::getName, reqVO.getName()) + ); + } + }else{ + queryWrapper.likeIfPresent(ErpProductDO::getBarCode, reqVO.getCode()) + .likeIfPresent(ErpProductDO::getName, reqVO.getName()); + } + queryWrapper .likeIfPresent(ErpProductDO::getName, reqVO.getName()) .likeIfPresent(ErpProductDO::getBarCode, resolveCode(reqVO)) .eqIfPresent(ErpProductDO::getCategoryId, reqVO.getCategoryId()) .inIfPresent(ErpProductDO::getCategoryId, categoryIds) .betweenIfPresent(ErpProductDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ErpProductDO::getId)); + .orderByDesc(ErpProductDO::getId); + + + return selectPage(reqVO,queryWrapper); } default List selectCategoryIdsByType(Integer categoryType) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java index 9020a9274..41cf7b406 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java @@ -2,12 +2,15 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import com.alibaba.excel.util.StringUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.poi.util.StringUtil; import java.util.Arrays; import java.util.List; @@ -17,8 +20,19 @@ import java.util.stream.Collectors; public interface ErpStockInMapper extends BaseMapperX { default PageResult selectPage(ErpStockInPageReqVO reqVO) { - MPJLambdaWrapperX query = new MPJLambdaWrapperX() - .likeIfPresent(ErpStockInDO::getNo, reqVO.getNo()) + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + + if(StringUtil.isNotBlank(reqVO.getNo())){ + if(reqVO.getNo().contains("PRODUCTMATERIAL-")){ + query.eq(ErpProductDO::getId, reqVO.getNo().replace("PRODUCTMATERIAL-","")); + }else{ + query.likeIfPresent(ErpStockInDO::getNo, reqVO.getNo()); + + } + } + + query +// .likeIfPresent(ErpStockInDO::getNo, reqVO.getNo()) .eqIfPresent(ErpStockInDO::getSupplierId, reqVO.getSupplierId()) .betweenIfPresent(ErpStockInDO::getInTime, reqVO.getInTime()) .inIfPresent(ErpStockInDO::getStatus, reqVO.getStatusList()) 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 7e645a746..f70c64c58 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 @@ -558,6 +558,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { return convertList(list, item -> BeanUtils.toBean(item, ErpStockInItemDO.class, target -> target .setWarehouseName(warehouseMap.containsKey(target.getWarehouseId()) ? warehouseMap.get(target.getWarehouseId()).getName() : null) .setAreaName(areaMap.containsKey(target.getAreaId()) ? areaMap.get(target.getAreaId()).getAreaName() : null) + .setProductName(productMap.get(target.getProductId()).getName()) .setProductUnitId(productMap.get(target.getProductId()).getUnitId()) .setTotalPrice(MoneyUtils.priceMultiply(target.getProductPrice(), target.getCount())))); } 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 0e0a17891..729d19e55 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 @@ -407,18 +407,30 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { normalizedItems.add(sourceItem); continue; } + if (defaultZero(sourceItem.getCount()).compareTo(BigDecimal.ZERO) <= 0) { + throw exception(STOCK_OUT_PRODUCT_COUNT_EMPTY); + } Map itemMap = new LinkedHashMap<>(); Map> palletMap = new LinkedHashMap<>(); + BigDecimal palletTotalCount = BigDecimal.ZERO; 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))); + BigDecimal palletCount = resolvePalletCount(pallet, sourceItem); + if (palletCount.compareTo(BigDecimal.ZERO) <= 0) { + throw exception(STOCK_OUT_PRODUCT_PALLET_COUNT_EMPTY, pallet.getPalletId()); + } + palletTotalCount = palletTotalCount.add(palletCount); + targetItem.setCount(defaultZero(targetItem.getCount()).add(palletCount)); targetItem.setPackageCount(defaultZero(targetItem.getPackageCount()).add(defaultZero(pallet.getPackageCount()))); palletMap.computeIfAbsent(key, item -> new ArrayList<>()).add(pallet); } + if (defaultZero(sourceItem.getCount()).compareTo(palletTotalCount) != 0) { + throw exception(STOCK_OUT_PRODUCT_COUNT_NOT_MATCH, sourceItem.getCount(), palletTotalCount); + } itemMap.forEach((key, item) -> { item.setPallets(palletMap.getOrDefault(key, Collections.emptyList())); normalizedItems.add(item); @@ -438,8 +450,18 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { return targetItem; } - private BigDecimal resolvePalletCount(ErpStockOutSaveReqVOItem.PalletItem pallet) { - return defaultZero(pallet.getCount()); + private BigDecimal resolvePalletCount(ErpStockOutSaveReqVOItem.PalletItem pallet, + ErpStockOutSaveReqVOItem item) { + if (pallet.getCount() != null && pallet.getCount().compareTo(BigDecimal.ZERO) > 0) { + return pallet.getCount(); + } + if (pallet.getPackageCount() != null && item.getPackageQuantity() != null) { + return pallet.getPackageCount().multiply(item.getPackageQuantity()); + } + if (CollUtil.size(item.getPallets()) == 1) { + return defaultZero(item.getCount()); + } + return BigDecimal.ZERO; } private static class StockOutPalletGroupKey { @@ -616,6 +638,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { convertSet(list, ErpStockOutSaveReqVOItem::getAreaId)); return convertList(list, item -> BeanUtils.toBean(item, ErpStockOutItemDO.class, target -> target .setAreaName(areaMap.containsKey(target.getAreaId()) ? areaMap.get(target.getAreaId()).getAreaName() : null) + .setProductName(productMap.get(target.getProductId()).getName()) .setProductUnitId(productMap.get(target.getProductId()).getUnitId()) .setTotalPrice(MoneyUtils.priceMultiply(target.getProductPrice(), target.getCount())) .setOutUsageType(item.getOutUsageType()) @@ -710,7 +733,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { .palletId(pallet.getPalletId()) .warehouseId(pallet.getWarehouseId() != null ? pallet.getWarehouseId() : stockOutItem.getWarehouseId()) .areaId(pallet.getAreaId() != null ? pallet.getAreaId() : stockOutItem.getAreaId()) - .count(resolvePalletCount(pallet)) + .count(resolvePalletCount(pallet, reqItem)) .packageCount(defaultZero(pallet.getPackageCount())) .build())); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java index 370fca223..363838d90 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -119,6 +119,9 @@ public class ErpStockServiceImpl implements ErpStockService { fillStockSnapshot(stock, product, defaultPackagingScheme); stockMapper.updateById(buildStockSnapshotUpdate(stock)); } + if (count == null || count.compareTo(BigDecimal.ZERO) == 0) { + return stock.getCount(); + } // 1.2 校验库存是否充足 if (!NEGATIVE_STOCK_COUNT_ENABLE && stock.getCount().add(count).compareTo(BigDecimal.ZERO) < 0) { throw exception(STOCK_COUNT_NEGATIVE, productService.getProduct(productId).getName(),