gaoluyang
昨天 8c65f898ed6e5b0c7a94c792c4562f6ec831dccd
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java
@@ -26,6 +26,11 @@
import java.math.BigDecimal;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@@ -137,7 +142,7 @@
        // 3. 根据冻结标识,对物资进行冻结
        if (Boolean.TRUE.equals(task.getFrozen())) {
            updateMaterialStockFrozen(lines, true);
            updateMaterialStockFrozen(id, lines, true);
        }
    }
@@ -146,6 +151,7 @@
    public void finishStockTakingTask(Long id) {
        // 1. 校验任务存在且为审批中状态
        MesWmStockTakingTaskDO task = validateStockTakingTaskExistsAndApproving(id);
        validateAllLinesCounted(id);
        // 2. 更新任务状态为已完成
        stockTakingTaskMapper.updateById(new MesWmStockTakingTaskDO().setId(id)
@@ -154,7 +160,41 @@
        // 3. 解冻库存
        if (Boolean.TRUE.equals(task.getFrozen())) {
            List<MesWmStockTakingTaskLineDO> lines = stockTakingTaskLineService.getStockTakingTaskLineListByTaskId(id);
            updateMaterialStockFrozen(lines, false);
            updateMaterialStockFrozen(id, lines, false);
        }
        // 与完成状态、解冻共用事务;差异入账失败时整单回滚。
        processStockTakingDifference(id);
    }
    private void validateAllLinesCounted(Long taskId) {
        List<MesWmStockTakingTaskLineDO> lines = stockTakingTaskLineService.getStockTakingTaskLineListByTaskId(taskId);
        if (CollUtil.isEmpty(lines)) {
            throw exception(WM_STOCK_TAKING_TASK_NO_LINE);
        }
        List<MesWmStockTakingTaskResultDO> results = stockTakingTaskResultService.getStockTakingTaskResultListByTaskId(taskId);
        Map<Long, MesWmStockTakingTaskLineDO> lineMap = new HashMap<>();
        lines.forEach(line -> lineMap.put(line.getId(), line));
        Set<Long> counted = new HashSet<>();
        for (MesWmStockTakingTaskResultDO result : results) {
            MesWmStockTakingTaskLineDO line = lineMap.get(result.getLineId());
            if (line == null || !ObjUtil.equal(result.getTaskId(), taskId)
                    || !ObjUtil.equal(result.getMaterialStockId(), line.getMaterialStockId())
                    || !ObjUtil.equal(result.getItemId(), line.getItemId())
                    || !ObjUtil.equal(result.getBatchId(), line.getBatchId())
                    || !ObjUtil.equal(result.getWarehouseId(), line.getWarehouseId())
                    || !ObjUtil.equal(result.getLocationId(), line.getLocationId())
                    || !ObjUtil.equal(result.getAreaId(), line.getAreaId())
                    || !ObjUtil.equal(result.getQuantity(), line.getQuantity())
                    || result.getTakingQuantity() == null || result.getTakingQuantity().signum() < 0
                    || !counted.add(result.getLineId())) {
                throw exception(WM_STOCK_TAKING_TASK_RESULT_LINE_INVALID);
            }
        }
        List<Long> missing = new ArrayList<>();
        lines.stream().map(MesWmStockTakingTaskLineDO::getId)
                .filter(lineId -> !counted.contains(lineId)).forEach(missing::add);
        if (!missing.isEmpty()) {
            throw exception(WM_STOCK_TAKING_TASK_INCOMPLETE, missing);
        }
    }
@@ -169,7 +209,7 @@
        task.setStatus(MesWmStockTakingTaskStatusEnum.CANCELED.getStatus());
        stockTakingTaskMapper.updateById(task);
        if (Boolean.TRUE.equals(task.getFrozen())) {
            updateMaterialStockFrozen(stockTakingTaskLineService.getStockTakingTaskLineListByTaskId(id), false);
            updateMaterialStockFrozen(id, stockTakingTaskLineService.getStockTakingTaskLineListByTaskId(id), false);
        }
    }
@@ -210,13 +250,13 @@
        return stockTakingTaskMapper.selectPage(pageReqVO);
    }
    private void updateMaterialStockFrozen(List<MesWmStockTakingTaskLineDO> lines, boolean frozen) {
    private void updateMaterialStockFrozen(Long taskId, List<MesWmStockTakingTaskLineDO> lines, boolean frozen) {
        if (CollUtil.isEmpty(lines)) {
            return;
        }
        List<Long> materialStockIds = convertList(lines,
                MesWmStockTakingTaskLineDO::getMaterialStockId, line -> line.getMaterialStockId() != null);
        materialStockService.updateMaterialStockFrozen(materialStockIds, frozen);
        materialStockService.setMaterialStockFreeze(materialStockIds, "STOCK_TAKING", taskId, frozen);
    }
    private void validateStockTakingTaskCodeUnique(Long id, String code) {
@@ -236,6 +276,10 @@
        MesWmStockTakingTaskDO task = validateStockTakingTaskExists(id);
        if (!MesWmStockTakingTaskStatusEnum.FINISHED.getStatus().equals(task.getStatus())) {
            throw exception(WM_STOCK_TAKING_TASK_NOT_FINISHED);
        }
        // 原子认领;重复调用不会重复生成盘盈/盘亏流水。
        if (stockTakingTaskMapper.claimDifferenceProcessing(id) == 0) {
            return;
        }
        // 2. 获取盘点结果列表
@@ -268,6 +312,7 @@
                    .setWarehouseId(result.getWarehouseId())
                    .setLocationId(result.getLocationId())
                    .setAreaId(result.getAreaId())
                    .setMaterialStockId(result.getMaterialStockId())
                    .setBizId(task.getId())
                    .setBizCode(task.getCode())
                    .setBizLineId(result.getLineId());
@@ -280,7 +325,7 @@
            } else {
                // 盘亏:库存减少
                transaction.setType(MesWmTransactionTypeEnum.OUT.getType())
                        .setQuantity(difference.negate()) // 出库数量传正数,但内部会转为负数
                        .setQuantity(difference) // 盘亏为负数,符合出库事务方向
                        .setBizType(MesBizTypeConstants.WM_STOCK_TAKING);
            }