| | |
| | | |
| | | 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; |
| | |
| | | |
| | | // 3. 根据冻结标识,对物资进行冻结 |
| | | if (Boolean.TRUE.equals(task.getFrozen())) { |
| | | updateMaterialStockFrozen(lines, true); |
| | | updateMaterialStockFrozen(id, lines, true); |
| | | } |
| | | } |
| | | |
| | |
| | | public void finishStockTakingTask(Long id) { |
| | | // 1. 校验任务存在且为审批中状态 |
| | | MesWmStockTakingTaskDO task = validateStockTakingTaskExistsAndApproving(id); |
| | | validateAllLinesCounted(id); |
| | | |
| | | // 2. 更新任务状态为已完成 |
| | | stockTakingTaskMapper.updateById(new MesWmStockTakingTaskDO().setId(id) |
| | |
| | | // 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); |
| | | } |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | |
| | | 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) { |
| | |
| | | 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. 获取盘点结果列表 |
| | |
| | | .setWarehouseId(result.getWarehouseId()) |
| | | .setLocationId(result.getLocationId()) |
| | | .setAreaId(result.getAreaId()) |
| | | .setMaterialStockId(result.getMaterialStockId()) |
| | | .setBizId(task.getId()) |
| | | .setBizCode(task.getCode()) |
| | | .setBizLineId(result.getLineId()); |
| | |
| | | } else { |
| | | // 盘亏:库存减少 |
| | | transaction.setType(MesWmTransactionTypeEnum.OUT.getType()) |
| | | .setQuantity(difference.negate()) // 出库数量传正数,但内部会转为负数 |
| | | .setQuantity(difference) // 盘亏为负数,符合出库事务方向 |
| | | .setBizType(MesBizTypeConstants.WM_STOCK_TAKING); |
| | | } |
| | | |