fix:修改盘点执行相关接口及添加库存总览接口

main
HuangHuiKang 1 day ago
parent 48e624ace6
commit e3d1dac817

@ -160,6 +160,7 @@ public interface ErrorCodeConstants {
ErrorCode STOCK_CHECK_AUDIT_FAIL_STATUS = new ErrorCode(1_030_403_011, "审核失败,只有审核中的盘点单才能审核");
ErrorCode STOCK_CHECK_AUDIT_FAIL_USER = new ErrorCode(1_030_403_012, "审核失败,当前用户不是指定审核人");
ErrorCode STOCK_CHECK_AUDIT_FAIL_RESULT = new ErrorCode(1_030_403_013, "审核失败,审核结果只支持通过或驳回");
ErrorCode STOCK_CHECK_SOURCE_TYPE_NOT_EXISTS = new ErrorCode(1_030_403_014, "盘点单生成来源类型不存在");
// ========== ERP 产品库存 1-030-404-000 ==========
ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_404_000, "操作失败,产品({})所在仓库({})的库存:{},小于变更数量:{}");

@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.erp.enums.stock;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
@RequiredArgsConstructor
@Getter
public enum ErpStockCheckSourceTypeEnum implements IntArrayValuable {
BY_LOCATION(1, "按库存"),
BY_PRODUCT(2, "按产品");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockCheckSourceTypeEnum::getType).toArray();
private final Integer type;
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

@ -5,13 +5,17 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.erp.controller.admin.stock.enums.ErpWarehouseCategoryEnum;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSummaryRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO;
import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService;
import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseSummaryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
@ -38,6 +42,8 @@ public class ErpWarehouseController {
@Resource
private ErpWarehouseService warehouseService;
@Resource
private ErpWarehouseSummaryService warehouseSummaryService;
@PostMapping("/create")
@Operation(summary = "创建仓库")
@ -93,13 +99,23 @@ public class ErpWarehouseController {
@GetMapping("/simple-list")
@Operation(summary = "获得仓库精简列表", description = "只包含被开启的仓库,主要用于前端的下拉选项")
public CommonResult<List<ErpWarehouseRespVO>> getWarehouseSimpleList() {
List<ErpWarehouseDO> list = warehouseService.getWarehouseListByStatus(CommonStatusEnum.ENABLE.getStatus());
@Parameter(name = "categoryType", description = "仓库分类", example = "1")
public CommonResult<List<ErpWarehouseRespVO>> getWarehouseSimpleList(
@RequestParam(value = "categoryType", required = false) Integer categoryType) {
List<ErpWarehouseDO> list = warehouseService.getWarehouseListByStatus(CommonStatusEnum.ENABLE.getStatus(), categoryType);
return success(convertList(list, warehouse -> new ErpWarehouseRespVO().setId(warehouse.getId())
.setName(warehouse.getName()).setCategoryType(warehouse.getCategoryType())
.setDefaultStatus(warehouse.getDefaultStatus())));
}
@GetMapping("/summary")
@Operation(summary = "获得仓库总览")
@Parameter(name = "warehouseId", description = "仓库编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('erp:warehouse:query')")
public CommonResult<ErpWarehouseSummaryRespVO> getWarehouseSummary(@RequestParam("warehouseId") Long warehouseId) {
return success(warehouseSummaryService.getWarehouseSummary(warehouseId));
}
@GetMapping("/export-excel")
@Operation(summary = "导出仓库 Excel")
@PreAuthorize("@ss.hasPermission('erp:warehouse:export')")

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Schema(description = "管理后台 - ERP 库存盘点按仓库/库区生成盘点项 Request VO")
@ -16,8 +15,8 @@ public class ErpStockCheckGenerateByLocationReqVO {
@Schema(description = "库区编号列表", example = "[11,12]")
private List<Long> areaIds;
@Schema(description = "是否允许为空,默认 false", example = "false")
private Boolean allowEmpty;
@Schema(description = "是否允许为空库存,默认 true", example = "true")
private Boolean allowEmpty = Boolean.TRUE;
public boolean validSelection() {
return (warehouseIds != null && !warehouseIds.isEmpty()) || (areaIds != null && !areaIds.isEmpty());

@ -14,4 +14,7 @@ public class ErpStockCheckGenerateByProductReqVO {
@NotEmpty(message = "产品编号列表不能为空")
private List<Long> productIds;
@Schema(description = "是否允许为空库存,默认 true", example = "true")
private Boolean allowEmpty = Boolean.TRUE;
}

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.PRODUCT_CATEGORY_TYPE;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
@ -31,6 +32,11 @@ public class ErpStockCheckRespVO {
@ExcelProperty("盘点时间")
private LocalDateTime checkTime;
@Schema(description = "生成来源类型1-按库存2-按产品", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "生成来源类型", converter = DictConvert.class)
@DictFormat("erp_stock_check_source_type")
private Integer sourceType;
@Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663")
@ExcelProperty("合计数量")
private BigDecimal totalCount;

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockCheckSourceTypeEnum;
import lombok.Data;
import javax.validation.Valid;
@ -21,13 +23,18 @@ public class ErpStockCheckSaveReqVO {
@NotNull(message = "盘点时间不能为空")
private LocalDateTime checkTime;
@Schema(description = "生成来源类型1-按库存2-按产品", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "生成来源类型不能为空")
@InEnum(ErpStockCheckSourceTypeEnum.class)
private Integer sourceType;
@Schema(description = "备注", example = "随便")
private String remark;
@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<Item> items;

@ -0,0 +1,66 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - ERP 仓库总览 Response VO")
@Data
public class ErpWarehouseSummaryRespVO {
@Schema(description = "仓库编号", example = "1")
private Long warehouseId;
@Schema(description = "仓库名称", example = "A仓")
private String warehouseName;
@Schema(description = "产品库存量", example = "1000")
private BigDecimal productStockCount;
@Schema(description = "产品库存展示", example = "2托3包4个")
private String productStockDisplay;
@Schema(description = "物料库存量", example = "1000")
private BigDecimal materialStockCount;
@Schema(description = "物料库存展示", example = "10采购单位20库存单位")
private String materialStockDisplay;
@Schema(description = "备件库存量", example = "1000")
private BigDecimal sparePartStockCount;
@Schema(description = "备件库存展示", example = "10采购单位20库存单位")
private String sparePartStockDisplay;
@Schema(description = "今日入库单数量", example = "5")
private Long todayStockInOrderCount;
@Schema(description = "今日入库明细行数量", example = "18")
private Long todayStockInItemCount;
@Schema(description = "今日入库产成品展示", example = "2托3包4个")
private String todayProductStockInDisplay;
@Schema(description = "今日入库物料展示", example = "100个")
private String todayMaterialStockInDisplay;
@Schema(description = "今日入库备件展示", example = "100个")
private String todaySparePartStockInDisplay;
@Schema(description = "今日出库单数量", example = "3")
private Long todayStockOutOrderCount;
@Schema(description = "今日出库明细行数量", example = "10")
private Long todayStockOutItemCount;
@Schema(description = "今日出库产成品展示", example = "2托3包4个")
private String todayProductStockOutDisplay;
@Schema(description = "今日出库物料展示", example = "100个")
private String todayMaterialStockOutDisplay;
@Schema(description = "今日出库备件展示", example = "100个")
private String todaySparePartStockOutDisplay;
}

@ -37,6 +37,10 @@ public class ErpStockCheckDO extends BaseDO {
*
*/
private LocalDateTime checkTime;
/**
* 1-2-
*/
private Integer sourceType;
/**
*
*/

@ -44,8 +44,11 @@ public interface ErpWarehouseMapper extends BaseMapperX<ErpWarehouseDO> {
return selectOne(ErpWarehouseDO::getDefaultStatus, true);
}
default List<ErpWarehouseDO> selectListByStatus(Integer status) {
return selectList(ErpWarehouseDO::getStatus, status);
default List<ErpWarehouseDO> selectListByStatus(Integer status, Integer categoryType) {
return selectList(new LambdaQueryWrapperX<ErpWarehouseDO>()
.eqIfPresent(ErpWarehouseDO::getStatus, status)
.eqIfPresent(ErpWarehouseDO::getCategoryType, categoryType)
.orderByDesc(ErpWarehouseDO::getId));
}
}

@ -29,6 +29,7 @@ import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper;
import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockCheckApproveActionEnum;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockCheckSourceTypeEnum;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO;
@ -63,6 +64,7 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_D
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_DELETE_FAIL_PROCESS;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_NOT_EXISTS;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_NO_EXISTS;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_SOURCE_TYPE_NOT_EXISTS;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_PROCESS_FAIL;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_SUBMIT_FAIL_AUDIT_USER_EMPTY;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_SUBMIT_FAIL_STATUS;
@ -102,6 +104,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
@Override
@Transactional(rollbackFor = Exception.class)
public Long createStockCheck(ErpStockCheckSaveReqVO createReqVO) {
validateSourceType(createReqVO.getSourceType());
List<ErpStockCheckItemDO> stockCheckItems = validateStockCheckItems(createReqVO.getItems());
String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_CHECK_NO_PREFIX);
if (stockCheckMapper.selectByNo(no) != null) {
@ -130,6 +133,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
throw exception(STOCK_CHECK_UPDATE_FAIL_PROCESS, stockCheck.getNo());
}
validateSourceType(updateReqVO.getSourceType());
List<ErpStockCheckItemDO> stockCheckItems = validateStockCheckItems(updateReqVO.getItems());
ErpStockCheckDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockCheckDO.class, in -> in
.setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add, BigDecimal.ZERO))
@ -289,7 +293,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
return Collections.emptyList();
}
List<ErpStockDO> stockList = stockMapper.selectListByWarehouseIdsAndAreaIds(reqVO.getWarehouseIds(), reqVO.getAreaIds());
if (!Boolean.TRUE.equals(reqVO.getAllowEmpty())) {
if (Boolean.FALSE.equals(reqVO.getAllowEmpty())) {
stockList = filterNonZeroStocks(stockList);
}
return buildPreviewItems(stockList);
@ -300,7 +304,11 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
if (reqVO == null || CollUtil.isEmpty(reqVO.getProductIds())) {
return Collections.emptyList();
}
return buildPreviewItems(filterNonZeroStocks(stockMapper.selectListByProductIds(reqVO.getProductIds())));
List<ErpStockDO> stockList = stockMapper.selectListByProductIds(reqVO.getProductIds());
if (Boolean.FALSE.equals(reqVO.getAllowEmpty())) {
stockList = filterNonZeroStocks(stockList);
}
return buildPreviewItems(stockList);
}
private List<ErpStockDO> filterNonZeroStocks(List<ErpStockDO> stockList) {
@ -484,4 +492,11 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
return stockCheck;
}
private void validateSourceType(Integer sourceType) {
if (!ErpStockCheckSourceTypeEnum.BY_LOCATION.getType().equals(sourceType)
&& !ErpStockCheckSourceTypeEnum.BY_PRODUCT.getType().equals(sourceType)) {
throw exception(STOCK_CHECK_SOURCE_TYPE_NOT_EXISTS);
}
}
}

@ -75,7 +75,7 @@ public interface ErpWarehouseService {
* @param status
* @return
*/
List<ErpWarehouseDO> getWarehouseListByStatus(Integer status);
List<ErpWarehouseDO> getWarehouseListByStatus(Integer status, Integer categoryType);
/**
*

@ -128,8 +128,8 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService {
}
@Override
public List<ErpWarehouseDO> getWarehouseListByStatus(Integer status) {
return warehouseMapper.selectListByStatus(status);
public List<ErpWarehouseDO> getWarehouseListByStatus(Integer status, Integer categoryType) {
return warehouseMapper.selectListByStatus(status, categoryType);
}
@Override

@ -0,0 +1,9 @@
package cn.iocoder.yudao.module.erp.service.stock;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSummaryRespVO;
public interface ErpWarehouseSummaryService {
ErpWarehouseSummaryRespVO getWarehouseSummary(Long warehouseId);
}

@ -0,0 +1,261 @@
package cn.iocoder.yudao.module.erp.service.stock;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSummaryRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
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.dataobject.stock.ErpWarehouseDO;
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.service.product.ErpProductService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Validated
public class ErpWarehouseSummaryServiceImpl implements ErpWarehouseSummaryService {
@Resource
private ErpWarehouseService warehouseService;
@Resource
private ErpStockMapper stockMapper;
@Resource
private ErpStockInMapper stockInMapper;
@Resource
private ErpStockInItemMapper stockInItemMapper;
@Resource
private ErpStockOutMapper stockOutMapper;
@Resource
private ErpStockOutItemMapper stockOutItemMapper;
@Resource
private ErpProductService productService;
@Override
public ErpWarehouseSummaryRespVO getWarehouseSummary(Long warehouseId) {
ErpWarehouseDO warehouse = warehouseService.getWarehouse(warehouseId);
ErpWarehouseSummaryRespVO respVO = new ErpWarehouseSummaryRespVO();
respVO.setWarehouseId(warehouseId);
respVO.setWarehouseName(warehouse != null ? warehouse.getName() : null);
List<ErpStockDO> stockList = stockMapper.selectListByWarehouseIdsAndAreaIds(Collections.singletonList(warehouseId), null);
fillStockSummary(respVO, stockList);
LocalDateTime beginTime = LocalDate.now().atStartOfDay();
LocalDateTime endTime = beginTime.plusDays(1);
fillTodayInSummary(respVO, warehouseId, beginTime, endTime);
fillTodayOutSummary(respVO, warehouseId, beginTime, endTime);
return respVO;
}
private void fillStockSummary(ErpWarehouseSummaryRespVO respVO, List<ErpStockDO> stockList) {
if (CollUtil.isEmpty(stockList)) {
respVO.setProductStockCount(BigDecimal.ZERO);
respVO.setMaterialStockCount(BigDecimal.ZERO);
respVO.setSparePartStockCount(BigDecimal.ZERO);
respVO.setProductStockDisplay(formatProductDisplay(BigDecimal.ZERO, null, null, null));
respVO.setMaterialStockDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null));
respVO.setSparePartStockDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null));
return;
}
Map<Integer, List<ErpStockDO>> categoryMap = stockList.stream().collect(Collectors.groupingBy(this::resolveCategoryType));
BigDecimal productCount = sumCount(categoryMap.get(1));
BigDecimal materialCount = sumCount(categoryMap.get(2));
BigDecimal sparePartCount = sumCount(categoryMap.get(3));
respVO.setProductStockCount(productCount);
respVO.setMaterialStockCount(materialCount);
respVO.setSparePartStockCount(sparePartCount);
ErpStockDO productStock = firstStock(categoryMap.get(1));
ErpStockDO materialStock = firstStock(categoryMap.get(2));
ErpStockDO sparePartStock = firstStock(categoryMap.get(3));
respVO.setProductStockDisplay(formatProductDisplay(productCount,
productStock != null ? productStock.getPalletTotalQuantity() : null,
productStock != null ? productStock.getPalletPackageQuantity() : null,
productStock != null ? productStock.getPackageQuantity() : null));
respVO.setMaterialStockDisplay(formatUnitDisplay(materialCount,
materialStock != null ? materialStock.getPurchaseUnitConvertQuantity() : null,
materialStock != null ? materialStock.getPurchaseUnitName() : null,
materialStock != null ? materialStock.getUnitName() : null));
respVO.setSparePartStockDisplay(formatUnitDisplay(sparePartCount,
sparePartStock != null ? sparePartStock.getPurchaseUnitConvertQuantity() : null,
sparePartStock != null ? sparePartStock.getPurchaseUnitName() : null,
sparePartStock != null ? sparePartStock.getUnitName() : null));
}
private void fillTodayInSummary(ErpWarehouseSummaryRespVO respVO, Long warehouseId, LocalDateTime beginTime, LocalDateTime endTime) {
List<ErpStockInDO> stockInList = stockInMapper.selectList(new LambdaQueryWrapper<ErpStockInDO>()
.eq(ErpStockInDO::getStatus, 20)
.between(ErpStockInDO::getInTime, beginTime, endTime));
List<Long> inIds = stockInList.stream()
.filter(stockIn -> hasWarehouseIn(stockIn.getId(), warehouseId))
.map(ErpStockInDO::getId)
.collect(Collectors.toList());
respVO.setTodayStockInOrderCount((long) inIds.size());
List<ErpStockInItemDO> itemList = stockInItemMapper.selectListByInIds(inIds);
respVO.setTodayStockInItemCount((long) itemList.size());
fillInOutDisplay(respVO, true, itemList);
}
private void fillTodayOutSummary(ErpWarehouseSummaryRespVO respVO, Long warehouseId, LocalDateTime beginTime, LocalDateTime endTime) {
List<ErpStockOutDO> stockOutList = stockOutMapper.selectList(new LambdaQueryWrapper<ErpStockOutDO>()
.eq(ErpStockOutDO::getStatus, 20)
.between(ErpStockOutDO::getOutTime, beginTime, endTime));
List<Long> outIds = stockOutList.stream()
.filter(stockOut -> hasWarehouseOut(stockOut.getId(), warehouseId))
.map(ErpStockOutDO::getId)
.collect(Collectors.toList());
respVO.setTodayStockOutOrderCount((long) outIds.size());
List<ErpStockOutItemDO> itemList = stockOutItemMapper.selectListByOutIds(outIds);
respVO.setTodayStockOutItemCount((long) itemList.size());
fillInOutDisplay(respVO, false, itemList);
}
private void fillInOutDisplay(ErpWarehouseSummaryRespVO respVO, boolean inbound, List<?> itemList) {
if (CollUtil.isEmpty(itemList)) {
if (inbound) {
respVO.setTodayProductStockInDisplay(formatProductDisplay(BigDecimal.ZERO, null, null, null));
respVO.setTodayMaterialStockInDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null));
respVO.setTodaySparePartStockInDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null));
} else {
respVO.setTodayProductStockOutDisplay(formatProductDisplay(BigDecimal.ZERO, null, null, null));
respVO.setTodayMaterialStockOutDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null));
respVO.setTodaySparePartStockOutDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null));
}
return;
}
Set<Long> productIds = itemList.stream()
.map(item -> item instanceof ErpStockInItemDO ? ((ErpStockInItemDO) item).getProductId() : ((ErpStockOutItemDO) item).getProductId())
.collect(Collectors.toSet());
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(productIds);
BigDecimal productCount = BigDecimal.ZERO;
BigDecimal materialCount = BigDecimal.ZERO;
BigDecimal sparePartCount = BigDecimal.ZERO;
for (Object item : itemList) {
Long productId = item instanceof ErpStockInItemDO ? ((ErpStockInItemDO) item).getProductId() : ((ErpStockOutItemDO) item).getProductId();
BigDecimal count = item instanceof ErpStockInItemDO ? ((ErpStockInItemDO) item).getCount() : ((ErpStockOutItemDO) item).getCount();
ErpProductRespVO product = productMap.get(productId);
Integer categoryType = product != null ? product.getCategoryType() : null;
if (Integer.valueOf(1).equals(categoryType)) {
productCount = productCount.add(safeCount(count));
} else if (Integer.valueOf(2).equals(categoryType)) {
materialCount = materialCount.add(safeCount(count));
} else if (Integer.valueOf(3).equals(categoryType)) {
sparePartCount = sparePartCount.add(safeCount(count));
}
}
if (inbound) {
respVO.setTodayProductStockInDisplay(formatProductDisplay(productCount, null, null, null));
respVO.setTodayMaterialStockInDisplay(formatUnitDisplay(materialCount, null, null, null));
respVO.setTodaySparePartStockInDisplay(formatUnitDisplay(sparePartCount, null, null, null));
} else {
respVO.setTodayProductStockOutDisplay(formatProductDisplay(productCount, null, null, null));
respVO.setTodayMaterialStockOutDisplay(formatUnitDisplay(materialCount, null, null, null));
respVO.setTodaySparePartStockOutDisplay(formatUnitDisplay(sparePartCount, null, null, null));
}
}
private boolean hasWarehouseIn(Long inId, Long warehouseId) {
return stockInItemMapper.selectListByInId(inId).stream().anyMatch(item -> warehouseId.equals(item.getWarehouseId()));
}
private boolean hasWarehouseOut(Long outId, Long warehouseId) {
return stockOutItemMapper.selectListByOutId(outId).stream().anyMatch(item -> warehouseId.equals(item.getWarehouseId()));
}
private Integer resolveCategoryType(ErpStockDO stock) {
if (stock.getCategoryType() != null) {
return stock.getCategoryType();
}
ErpProductRespVO product = productService.getProductVOMap(Collections.singleton(stock.getProductId())).get(stock.getProductId());
return product != null ? product.getCategoryType() : null;
}
private ErpStockDO firstStock(List<ErpStockDO> list) {
return CollUtil.isEmpty(list) ? null : list.get(0);
}
private BigDecimal sumCount(List<ErpStockDO> list) {
if (CollUtil.isEmpty(list)) {
return BigDecimal.ZERO;
}
BigDecimal total = BigDecimal.ZERO;
for (ErpStockDO stock : list) {
total = total.add(safeCount(stock.getCount()));
}
return total;
}
private BigDecimal safeCount(BigDecimal count) {
return count == null ? BigDecimal.ZERO : count;
}
private String formatProductDisplay(BigDecimal count, BigDecimal palletTotalQuantity, BigDecimal palletPackageQuantity,
BigDecimal packageQuantity) {
BigDecimal safeCount = safeCount(count);
if (palletTotalQuantity == null || palletTotalQuantity.compareTo(BigDecimal.ZERO) <= 0) {
return formatNumber(safeCount) + "个";
}
BigDecimal palletCount = safeCount.divideToIntegralValue(palletTotalQuantity);
BigDecimal remainAfterPallet = safeCount.remainder(palletTotalQuantity);
if (palletPackageQuantity == null || palletPackageQuantity.compareTo(BigDecimal.ZERO) <= 0) {
return formatNumber(palletCount) + "托" + formatNumber(remainAfterPallet) + "个";
}
BigDecimal packageCount = remainAfterPallet.divideToIntegralValue(palletPackageQuantity);
BigDecimal remainAfterPackage = remainAfterPallet.remainder(palletPackageQuantity);
if (packageQuantity == null || packageQuantity.compareTo(BigDecimal.ZERO) <= 0) {
return formatNumber(palletCount) + "托" + formatNumber(packageCount) + "包" + formatNumber(remainAfterPackage) + "个";
}
BigDecimal unitCount = remainAfterPackage.divideToIntegralValue(packageQuantity);
return formatNumber(palletCount) + "托" + formatNumber(packageCount) + "包" + formatNumber(unitCount) + "个";
}
private String formatUnitDisplay(BigDecimal count, BigDecimal purchaseUnitConvertQuantity, String purchaseUnitName, String unitName) {
BigDecimal safeCount = safeCount(count);
if (purchaseUnitConvertQuantity == null || purchaseUnitConvertQuantity.compareTo(BigDecimal.ZERO) <= 0
|| purchaseUnitName == null || unitName == null) {
return formatNumber(safeCount) + (unitName != null ? unitName : "个");
}
BigDecimal purchaseCount = safeCount.divideToIntegralValue(purchaseUnitConvertQuantity);
BigDecimal unitCount = safeCount.remainder(purchaseUnitConvertQuantity);
StringBuilder display = new StringBuilder();
if (purchaseCount.compareTo(BigDecimal.ZERO) > 0) {
display.append(formatNumber(purchaseCount)).append(purchaseUnitName);
}
if (unitCount.compareTo(BigDecimal.ZERO) > 0 || display.length() == 0) {
display.append(formatNumber(unitCount)).append(unitName);
}
return display.toString();
}
private String formatNumber(BigDecimal value) {
return value == null ? "0" : value.stripTrailingZeros().toPlainString();
}
}
Loading…
Cancel
Save