diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java index 465f0b87e..3c0c69df0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProduc import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockStatisticsRespVO; import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; @@ -93,6 +94,13 @@ public class ErpStockController { return success(stockService.getStockCount(productId)); } + @GetMapping("/statistics-cards") + @Operation(summary = "获得库存统计卡片") + @PreAuthorize("@ss.hasPermission('erp:stock:query')") + public CommonResult getStockStatistics() { + return success(stockService.getStockStatistics()); + } + @GetMapping("/page") @Operation(summary = "获得产品库存分页") @PreAuthorize("@ss.hasPermission('erp:stock:query')") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockStatisticsRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockStatisticsRespVO.java new file mode 100644 index 000000000..36be1bfc7 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockStatisticsRespVO.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +@Schema(description = "管理后台 - ERP 库存统计卡片 Response VO") +@Data +public class ErpStockStatisticsRespVO { + + @Schema(description = "产品品库存") + private ProductStockCard productStock; + + @Schema(description = "原材料库存") + private UnitGroupedStockCard materialStock; + + @Schema(description = "备件库存") + private UnitGroupedStockCard sparePartStock; + + @Schema(description = "今日入库") + private TodayInCard todayIn; + + @Schema(description = "今日出库") + private TodayOutCard todayOut; + + @Schema(description = "产品品库存卡片") + @Data + public static class ProductStockCard { + + @Schema(description = "SKU 数", example = "36") + private Long skuCount; + + @Schema(description = "库存摘要", example = "128托42包560个") + private String stockDisplay; + + @Schema(description = "今日完工入库", example = "12托8包") + private String todayFinishedInDisplay; + } + + @Schema(description = "按单位分组库存卡片") + @Data + public static class UnitGroupedStockCard { + + @Schema(description = "SKU/种类数", example = "24") + private Long skuCount; + + @Schema(description = "库存摘要", example = "18.6吨 / 1250L / 320包") + private String stockDisplay; + + @Schema(description = "按库存单位分组明细") + private List unitStocks; + } + + @Schema(description = "库存单位分组明细") + @Data + public static class UnitStock { + + @Schema(description = "库存单位编号", example = "3") + private Long unitId; + + @Schema(description = "库存单位名称", example = "kg") + private String unitName; + + @Schema(description = "库存数量", example = "820") + private BigDecimal count; + + @Schema(description = "库存展示", example = "820kg") + private String stockDisplay; + } + + @Schema(description = "今日入库卡片") + @Data + public static class TodayInCard { + + @Schema(description = "入库单数", example = "18") + private Long orderCount; + + @Schema(description = "明细行数", example = "46") + private Long itemCount; + + @Schema(description = "产品品入库") + private UnitGroupedStockCard productStock; + + @Schema(description = "原材料入库") + private UnitGroupedStockCard materialStock; + + @Schema(description = "备件入库") + private UnitGroupedStockCard sparePartStock; + } + + @Schema(description = "今日出库卡片") + @Data + public static class TodayOutCard { + + @Schema(description = "出库单数", example = "15") + private Long orderCount; + + @Schema(description = "明细行数", example = "38") + private Long itemCount; + + @Schema(description = "原材料领用") + private UnitGroupedStockCard materialStock; + + @Schema(description = "备件领用") + private UnitGroupedStockCard sparePartStock; + + @Schema(description = "产品品发货") + private UnitGroupedStockCard productStock; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java index 90c91f2b6..2e0bd87ac 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockStatisticsRespVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import java.math.BigDecimal; @@ -61,6 +62,8 @@ public interface ErpStockService { */ PageResult getStockPage(ErpStockPageReqVO pageReqVO); + ErpStockStatisticsRespVO getStockStatistics(); + /** * 增量更新产品库存数量 * 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 363838d90..d15042b41 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 @@ -4,17 +4,36 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockStatisticsRespVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutMapper; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.framework.bean.ProductTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_COUNT_NEGATIVE; @@ -42,6 +61,14 @@ public class ErpStockServiceImpl implements ErpStockService { @Resource private ErpStockMapper stockMapper; + @Resource + private ErpStockInMapper stockInMapper; + @Resource + private ErpStockInItemMapper stockInItemMapper; + @Resource + private ErpStockOutMapper stockOutMapper; + @Resource + private ErpStockOutItemMapper stockOutItemMapper; @Override public ErpStockDO getStock(Long id) { @@ -93,6 +120,21 @@ public class ErpStockServiceImpl implements ErpStockService { return stockMapper.selectPage(pageReqVO); } + @Override + public ErpStockStatisticsRespVO getStockStatistics() { + ErpStockStatisticsRespVO respVO = new ErpStockStatisticsRespVO(); + List stockList = stockMapper.selectList(new LambdaQueryWrapper()); + Map productMap = productService.getProductVOMap(stockList.stream() + .map(ErpStockDO::getProductId).collect(Collectors.toSet())); + fillStockCards(respVO, stockList, productMap); + + LocalDateTime beginTime = LocalDate.now().atStartOfDay(); + LocalDateTime endTime = beginTime.plusDays(1); + fillTodayInCard(respVO, beginTime, endTime, productMap); + fillTodayOutCard(respVO, beginTime, endTime, productMap); + return respVO; + } + @Override public BigDecimal updateStockCountIncrement(Long categoryId, Long productId, Long warehouseId, Long areaId, String areaName, BigDecimal count) { @@ -140,6 +182,266 @@ public class ErpStockServiceImpl implements ErpStockService { return stock.getCount().add(count); } + private void fillStockCards(ErpStockStatisticsRespVO respVO, List stockList, + Map productMap) { + ErpStockStatisticsRespVO.ProductStockCard productStockCard = new ErpStockStatisticsRespVO.ProductStockCard(); + + List productStockList = filterStockByCategory(stockList, productMap, ProductTypeEnum.ITEM.getTypeId()); + List materialStockList = filterStockByCategory(stockList, productMap, ProductTypeEnum.PRODUCT.getTypeId()); + List sparePartStockList = filterStockByCategory(stockList, productMap, ProductTypeEnum.BEIJIAN.getTypeId()); + + productStockCard.setSkuCount(countDistinctProduct(productStockList)); + productStockCard.setStockDisplay(formatProductStockDisplay(productStockList)); + productStockCard.setTodayFinishedInDisplay(formatProductStockDisplay(Collections.emptyList())); + respVO.setProductStock(productStockCard); + + respVO.setMaterialStock(buildUnitGroupedStockCard(materialStockList)); + respVO.setSparePartStock(buildUnitGroupedStockCard(sparePartStockList)); + } + + private void fillTodayInCard(ErpStockStatisticsRespVO respVO, LocalDateTime beginTime, LocalDateTime endTime, + Map stockProductMap) { + ErpStockStatisticsRespVO.TodayInCard todayInCard = new ErpStockStatisticsRespVO.TodayInCard(); + List stockInList = stockInMapper.selectList(new LambdaQueryWrapper() + .eq(ErpStockInDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .between(ErpStockInDO::getInTime, beginTime, endTime)); + List stockInIds = stockInList.stream().map(ErpStockInDO::getId).collect(Collectors.toList()); + List itemList = stockInIds.isEmpty() ? Collections.emptyList() + : stockInItemMapper.selectListByInIds(stockInIds); + Map productMap = buildProductMap(itemList.stream() + .map(ErpStockInItemDO::getProductId).collect(Collectors.toSet()), stockProductMap); + + todayInCard.setOrderCount((long) stockInIds.size()); + todayInCard.setItemCount((long) itemList.size()); + todayInCard.setProductStock(buildInItemUnitGroupedStockCard(filterInItemByCategory(itemList, productMap, ProductTypeEnum.ITEM.getTypeId()), productMap)); + todayInCard.setMaterialStock(buildInItemUnitGroupedStockCard(filterInItemByCategory(itemList, productMap, ProductTypeEnum.PRODUCT.getTypeId()), productMap)); + todayInCard.setSparePartStock(buildInItemUnitGroupedStockCard(filterInItemByCategory(itemList, productMap, ProductTypeEnum.BEIJIAN.getTypeId()), productMap)); + respVO.setTodayIn(todayInCard); + respVO.getProductStock().setTodayFinishedInDisplay(todayInCard.getProductStock().getStockDisplay()); + } + + private void fillTodayOutCard(ErpStockStatisticsRespVO respVO, LocalDateTime beginTime, LocalDateTime endTime, + Map stockProductMap) { + ErpStockStatisticsRespVO.TodayOutCard todayOutCard = new ErpStockStatisticsRespVO.TodayOutCard(); + List stockOutList = stockOutMapper.selectList(new LambdaQueryWrapper() + .eq(ErpStockOutDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .between(ErpStockOutDO::getOutTime, beginTime, endTime)); + List stockOutIds = stockOutList.stream().map(ErpStockOutDO::getId).collect(Collectors.toList()); + List itemList = stockOutIds.isEmpty() ? Collections.emptyList() + : stockOutItemMapper.selectListByOutIds(stockOutIds); + Map productMap = buildProductMap(itemList.stream() + .map(ErpStockOutItemDO::getProductId).collect(Collectors.toSet()), stockProductMap); + + todayOutCard.setOrderCount((long) stockOutIds.size()); + todayOutCard.setItemCount((long) itemList.size()); + todayOutCard.setProductStock(buildOutItemUnitGroupedStockCard(filterOutItemByCategory(itemList, productMap, ProductTypeEnum.ITEM.getTypeId()), productMap)); + todayOutCard.setMaterialStock(buildOutItemUnitGroupedStockCard(filterOutItemByCategory(itemList, productMap, ProductTypeEnum.PRODUCT.getTypeId()), productMap)); + todayOutCard.setSparePartStock(buildOutItemUnitGroupedStockCard(filterOutItemByCategory(itemList, productMap, ProductTypeEnum.BEIJIAN.getTypeId()), productMap)); + respVO.setTodayOut(todayOutCard); + } + + private Map buildProductMap(Set productIds, Map stockProductMap) { + Set missingProductIds = new HashSet<>(productIds); + missingProductIds.removeAll(stockProductMap.keySet()); + if (missingProductIds.isEmpty()) { + return stockProductMap; + } + Map resultMap = productService.getProductVOMap(productIds); + resultMap.putAll(stockProductMap); + return resultMap; + } + + private List filterStockByCategory(List stockList, Map productMap, + Integer categoryType) { + return stockList.stream() + .filter(stock -> categoryType.equals(resolveCategoryType(stock, productMap))) + .collect(Collectors.toList()); + } + + private List filterInItemByCategory(List itemList, + Map productMap, + Integer categoryType) { + return itemList.stream() + .filter(item -> categoryType.equals(resolveCategoryType(item.getProductId(), productMap))) + .collect(Collectors.toList()); + } + + private List filterOutItemByCategory(List itemList, + Map productMap, + Integer categoryType) { + return itemList.stream() + .filter(item -> categoryType.equals(resolveCategoryType(item.getProductId(), productMap))) + .collect(Collectors.toList()); + } + + private ErpStockStatisticsRespVO.UnitGroupedStockCard buildUnitGroupedStockCard(List stockList) { + ErpStockStatisticsRespVO.UnitGroupedStockCard card = new ErpStockStatisticsRespVO.UnitGroupedStockCard(); + card.setSkuCount(countDistinctProduct(stockList)); + List unitStocks = stockList.stream() + .collect(Collectors.groupingBy(stock -> buildUnitKey(stock.getUnitId(), stock.getUnitName()))) + .values().stream() + .map(this::buildUnitStock) + .collect(Collectors.toList()); + card.setUnitStocks(unitStocks); + card.setStockDisplay(unitStocks.stream() + .map(ErpStockStatisticsRespVO.UnitStock::getStockDisplay) + .collect(Collectors.joining(" / "))); + return card; + } + + private ErpStockStatisticsRespVO.UnitStock buildUnitStock(List stockList) { + ErpStockDO firstStock = stockList.get(0); + BigDecimal count = stockList.stream().map(stock -> defaultZero(stock.getCount())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + return buildUnitStock(firstStock.getUnitId(), firstStock.getUnitName(), count); + } + + private String buildUnitKey(Long unitId, String unitName) { + return String.valueOf(unitId) + "_" + String.valueOf(unitName); + } + + private ErpStockStatisticsRespVO.UnitGroupedStockCard buildInItemUnitGroupedStockCard(List itemList, + Map productMap) { + ErpStockStatisticsRespVO.UnitGroupedStockCard card = new ErpStockStatisticsRespVO.UnitGroupedStockCard(); + card.setSkuCount(itemList.stream().map(ErpStockInItemDO::getProductId).distinct().count()); + List unitStocks = itemList.stream() + .collect(Collectors.groupingBy(item -> buildProductUnitKey(item.getProductId(), productMap))) + .values().stream() + .map(items -> buildInItemUnitStock(items, productMap)) + .collect(Collectors.toList()); + card.setUnitStocks(unitStocks); + card.setStockDisplay(unitStocks.stream() + .map(ErpStockStatisticsRespVO.UnitStock::getStockDisplay) + .collect(Collectors.joining(" / "))); + return card; + } + + private ErpStockStatisticsRespVO.UnitGroupedStockCard buildOutItemUnitGroupedStockCard(List itemList, + Map productMap) { + ErpStockStatisticsRespVO.UnitGroupedStockCard card = new ErpStockStatisticsRespVO.UnitGroupedStockCard(); + card.setSkuCount(itemList.stream().map(ErpStockOutItemDO::getProductId).distinct().count()); + List unitStocks = itemList.stream() + .collect(Collectors.groupingBy(item -> buildProductUnitKey(item.getProductId(), productMap))) + .values().stream() + .map(items -> buildOutItemUnitStock(items, productMap)) + .collect(Collectors.toList()); + card.setUnitStocks(unitStocks); + card.setStockDisplay(unitStocks.stream() + .map(ErpStockStatisticsRespVO.UnitStock::getStockDisplay) + .collect(Collectors.joining(" / "))); + return card; + } + + private ErpStockStatisticsRespVO.UnitStock buildInItemUnitStock(List itemList, + Map productMap) { + ErpStockInItemDO firstItem = itemList.get(0); + ErpProductRespVO product = productMap.get(firstItem.getProductId()); + BigDecimal count = itemList.stream().map(item -> defaultZero(item.getCount())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + return buildUnitStock(product != null ? product.getUnitId() : null, + product != null ? product.getUnitName() : null, count); + } + + private ErpStockStatisticsRespVO.UnitStock buildOutItemUnitStock(List itemList, + Map productMap) { + ErpStockOutItemDO firstItem = itemList.get(0); + ErpProductRespVO product = productMap.get(firstItem.getProductId()); + BigDecimal count = itemList.stream().map(item -> defaultZero(item.getCount())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + return buildUnitStock(product != null ? product.getUnitId() : null, + product != null ? product.getUnitName() : null, count); + } + + private ErpStockStatisticsRespVO.UnitStock buildUnitStock(Long unitId, String unitName, BigDecimal count) { + ErpStockStatisticsRespVO.UnitStock unitStock = new ErpStockStatisticsRespVO.UnitStock(); + unitStock.setUnitId(unitId); + unitStock.setUnitName(unitName); + unitStock.setCount(count); + unitStock.setStockDisplay(formatNumber(count) + nullToEmpty(unitName)); + return unitStock; + } + + private String buildProductUnitKey(Long productId, Map productMap) { + ErpProductRespVO product = productMap.get(productId); + return product != null ? buildUnitKey(product.getUnitId(), product.getUnitName()) : buildUnitKey(null, null); + } + + private Integer resolveCategoryType(ErpStockDO stock, Map productMap) { + if (stock.getCategoryType() != null) { + return stock.getCategoryType(); + } + return resolveCategoryType(stock.getProductId(), productMap); + } + + private Integer resolveCategoryType(Long productId, Map productMap) { + ErpProductRespVO product = productMap.get(productId); + return product != null ? product.getCategoryType() : null; + } + + private Long countDistinctProduct(List stockList) { + return stockList.stream().map(ErpStockDO::getProductId).distinct().count(); + } + + private String formatProductStockDisplay(List stockList) { + BigDecimal palletCount = BigDecimal.ZERO; + BigDecimal packageCount = BigDecimal.ZERO; + BigDecimal pieceCount = BigDecimal.ZERO; + for (ErpStockDO stock : stockList) { + ProductQuantity quantity = calculateProductQuantity(stock.getCount(), stock.getPalletTotalQuantity(), stock.getPackageQuantity()); + palletCount = palletCount.add(quantity.getPalletCount()); + packageCount = packageCount.add(quantity.getPackageCount()); + pieceCount = pieceCount.add(quantity.getPieceCount()); + } + return formatProductQuantity(palletCount, packageCount, pieceCount); + } + + private ProductQuantity calculateProductQuantity(BigDecimal count, BigDecimal palletTotalQuantity, BigDecimal packageQuantity) { + BigDecimal safeCount = defaultZero(count); + BigDecimal palletCount = BigDecimal.ZERO; + BigDecimal packageCount = BigDecimal.ZERO; + BigDecimal pieceCount = safeCount; + if (palletTotalQuantity != null && palletTotalQuantity.compareTo(BigDecimal.ZERO) > 0) { + palletCount = safeCount.divideToIntegralValue(palletTotalQuantity); + pieceCount = safeCount.remainder(palletTotalQuantity); + } + if (packageQuantity != null && packageQuantity.compareTo(BigDecimal.ZERO) > 0) { + packageCount = pieceCount.divideToIntegralValue(packageQuantity); + pieceCount = pieceCount.remainder(packageQuantity); + } + return new ProductQuantity(palletCount, packageCount, pieceCount); + } + + private String formatProductQuantity(BigDecimal palletCount, BigDecimal packageCount, BigDecimal pieceCount) { + StringBuilder display = new StringBuilder(); + appendDisplay(display, palletCount, "托", false); + appendDisplay(display, packageCount, "包", false); + appendDisplay(display, pieceCount, "个", display.length() == 0); + return display.toString(); + } + + private void appendDisplay(StringBuilder display, BigDecimal quantity, String unitName, boolean keepZero) { + if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) { + if (!keepZero) { + return; + } + display.append("0").append(unitName); + return; + } + display.append(formatNumber(quantity)).append(unitName); + } + + private BigDecimal defaultZero(BigDecimal value) { + return value != null ? value : BigDecimal.ZERO; + } + + private String nullToEmpty(String value) { + return value != null ? value : ""; + } + + private String formatNumber(BigDecimal value) { + return value == null ? "0" : value.stripTrailingZeros().toPlainString(); + } + private void fillStockSnapshot(ErpStockDO stock, ErpProductRespVO product, ProductPackagingSchemeRespVO defaultPackagingScheme) { if (product == null) { @@ -196,4 +498,16 @@ public class ErpStockServiceImpl implements ErpStockService { .setPalletTotalQuantity(stock.getPalletTotalQuantity()); } + @lombok.Data + @lombok.AllArgsConstructor + private static class ProductQuantity { + + private BigDecimal palletCount; + + private BigDecimal packageCount; + + private BigDecimal pieceCount; + + } + } diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index dad9a7d0e..15f76c6ca 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -98,6 +98,7 @@ public interface ErrorCodeConstants { ErrorCode MOLD_GET_NOT_EXISTS = new ErrorCode(5_0087, "领模申请不存在"); ErrorCode MOLD_RETURN_NOT_EXISTS = new ErrorCode(5_0087, "模具入库不存在"); ErrorCode MOLD_OPERATE_NOT_EXISTS = new ErrorCode(5_0087, "模具上下模不存在"); + ErrorCode MOLD_OPERATE_DEVICE_HAS_MOLD = new ErrorCode(5_0089, "该设备已有上模模具组,请先下模后再上模"); ErrorCode MOLD_REPAIR_NOT_EXISTS = new ErrorCode(5_0087, "模具维修记录不存在"); ErrorCode MOLD_REPAIR_CODE_EXISTS = new ErrorCode(5_0087, "模具维修记录编码已存在"); diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldoperate/MoldOperateServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldoperate/MoldOperateServiceImpl.java index b3a6b19c1..2767c6567 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldoperate/MoldOperateServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldoperate/MoldOperateServiceImpl.java @@ -59,6 +59,7 @@ public class MoldOperateServiceImpl implements MoldOperateService { // 插入 MoldOperateDO moldOperate = BeanUtils.toBean(createReqVO, MoldOperateDO.class); DeviceLedgerDO deviceLedgerDO = deviceLedgerMapper.selectById(createReqVO.getDeviceId()); + validateDeviceMoldEmpty(createReqVO, deviceLedgerDO); fillDeviceAndLineInfo(moldOperate, deviceLedgerDO,createReqVO.getLineId()); MoldBrandDO moldDO = moldBrandMapper.selectById(createReqVO.getMoldId()); @@ -116,6 +117,13 @@ public class MoldOperateServiceImpl implements MoldOperateService { } } + private void validateDeviceMoldEmpty(MoldOperateSaveReqVO createReqVO, DeviceLedgerDO deviceLedgerDO) { + if (createReqVO.getOperateType() != null && createReqVO.getOperateType() == 1 + && deviceLedgerDO != null && StringUtil.isNotBlank(deviceLedgerDO.getMoldId())) { + throw exception(MOLD_OPERATE_DEVICE_HAS_MOLD); + } + } + @Override public MoldOperateDO getMoldOperate(Long id) { return moldOperateMapper.selectById(id);