package cn.iocoder.yudao.module.mes.service.wm.sorting; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.sorting.vo.MesWmSortPendingNoticeRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.sorting.vo.MesWmSortProductionRequestRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.sorting.vo.MesWmSortTaskPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.sorting.vo.MesWmSortTaskRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.sorting.vo.MesWmSortTaskScanReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sorting.MesWmSortTaskDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sorting.MesWmSortTaskLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesMapper; import cn.iocoder.yudao.module.mes.dal.mysql.wm.sorting.MesWmSortTaskLineMapper; import cn.iocoder.yudao.module.mes.dal.mysql.wm.sorting.MesWmSortTaskMapper; import cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmSortTaskStatusEnum; import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; import cn.iocoder.yudao.module.mes.service.pro.mps.MesProMpsService; import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeLineService; import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService; import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 分拣任务 Service 实现类 */ @Service @Validated @Slf4j public class MesWmSortTaskServiceImpl implements MesWmSortTaskService { private static final DateTimeFormatter CODE_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd"); @Resource private MesWmSortTaskMapper sortTaskMapper; @Resource private MesWmSortTaskLineMapper sortTaskLineMapper; @Resource private MesWmSalesNoticeService salesNoticeService; @Resource private MesWmSalesNoticeLineService salesNoticeLineService; @Resource private MesWmMaterialStockService materialStockService; @Resource private MesWmProductSalesMapper productSalesMapper; @Resource private MesMdmItemService mdmItemService; @Resource private MesWmWarehouseService warehouseService; @Resource private MesWmWarehouseAreaService areaService; @Resource private MesWmWarehouseLocationService locationService; @Resource private AdminUserApi adminUserApi; @Resource private MesProMpsService mpsService; @Override @Transactional(rollbackFor = Exception.class) public Long createSortTaskFromNotice(Long noticeId) { // 1. 校验发货通知单:必须存在且为「待出库」 MesWmSalesNoticeDO notice = salesNoticeService.validateSalesNoticeExists(noticeId); if (!MesWmSalesNoticeStatusEnum.APPROVED.getStatus().equals(notice.getStatus())) { throw new ServiceException(WM_SORT_TASK_NOT_PENDING.getCode(), "发货通知单[" + notice.getCode() + "]当前状态为[" + MesWmSalesNoticeStatusEnum.valueOf(notice.getStatus()).getName() + "],只有「待出库」的发货通知单才能生成分拣任务,请先提交该发货通知单。"); } // 2. 防止重复生成 MesWmSortTaskDO exists = sortTaskMapper.selectByNoticeId(noticeId); if (exists != null) { throw new ServiceException(WM_SORT_TASK_NOTICE_EXISTS.getCode(), "发货通知单[" + notice.getCode() + "]已存在分拣任务[" + exists.getCode() + "],请直接在该任务上执行分拣,或先取消原任务。"); } // 3. 发货明细 + 分配货位 List noticeLines = salesNoticeLineService.getSalesNoticeLineListByNoticeId(noticeId); if (CollUtil.isEmpty(noticeLines)) { throw new ServiceException(WM_SORT_TASK_NO_STOCK.getCode(), "发货通知单[" + notice.getCode() + "]没有发货明细,无法分拣,请先补全发货明细。"); } List lines = allocateStock(notice, noticeLines); // 4. 插入任务 MesWmSortTaskDO task = MesWmSortTaskDO.builder() .code(generateCode()) .noticeId(notice.getId()).noticeCode(notice.getCode()) .saleOrderId(notice.getSaleOrderId()).saleOrderCode(notice.getSaleOrderCode()) .clientId(notice.getClientId()) .recipientName(notice.getRecipientName()).recipientTelephone(notice.getRecipientTelephone()) .recipientAddress(notice.getRecipientAddress()) .status(MesWmSortTaskStatusEnum.PENDING.getStatus()) .printCount(0) .build(); sortTaskMapper.insert(task); lines.forEach(line -> line.setTaskId(task.getId())); lines.forEach(sortTaskLineMapper::insert); return task.getId(); } /** * 按发货明细分配合格库存:同物料优先按入库时间 FIFO,可跨库位拆分 */ private List allocateStock(MesWmSalesNoticeDO notice, List noticeLines) { List result = new ArrayList<>(); for (MesWmSalesNoticeLineDO noticeLine : noticeLines) { BigDecimal remaining = noticeLine.getQuantity() != null ? noticeLine.getQuantity() : BigDecimal.ZERO; if (remaining.compareTo(BigDecimal.ZERO) <= 0) { continue; } // 查询该物料可用库存(按批次过滤,若有) MesWmMaterialStockListReqVO stockQuery = new MesWmMaterialStockListReqVO(); stockQuery.setItemId(noticeLine.getItemId()); stockQuery.setBatchId(noticeLine.getBatchId()); List stocks = materialStockService.getMaterialStockList(stockQuery); stocks = stocks.stream() .filter(stock -> stock.getQuantity() != null && stock.getQuantity().compareTo(BigDecimal.ZERO) > 0 && !Boolean.TRUE.equals(stock.getFrozen())) .sorted(Comparator.comparing(MesWmMaterialStockDO::getReceiptTime, Comparator.nullsLast(Comparator.naturalOrder()))) .collect(Collectors.toList()); BigDecimal available = stocks.stream() .map(stock -> stock.getQuantity() != null ? stock.getQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); MesMdmItemDO item = mdmItemService.getItemMap(Collections.singletonList(noticeLine.getItemId())) .get(noticeLine.getItemId()); String itemName = item != null ? item.getName() : "ID=" + noticeLine.getItemId(); if (available.compareTo(remaining) < 0) { throw new ServiceException(WM_SORT_TASK_NO_STOCK.getCode(), "物料[" + itemName + "]在库位上的可用库存为[" + available.stripTrailingZeros().toPlainString() + "],发货通知单需要[" + remaining.stripTrailingZeros().toPlainString() + "],库存不足,请先补货入库或调整发货数量后再生成分拣任务。"); } for (MesWmMaterialStockDO stock : stocks) { if (remaining.compareTo(BigDecimal.ZERO) <= 0) { break; } BigDecimal stockQuantity = stock.getQuantity() != null ? stock.getQuantity() : BigDecimal.ZERO; BigDecimal allocate = stockQuantity.min(remaining); result.add(MesWmSortTaskLineDO.builder() .noticeLineId(noticeLine.getId()) .itemId(noticeLine.getItemId()) .batchId(stock.getBatchId()).batchCode(stock.getBatchCode()) .materialStockId(stock.getId()) .warehouseId(stock.getWarehouseId()).areaId(stock.getAreaId()).locationId(stock.getLocationId()) .planQuantity(allocate).sortedQuantity(BigDecimal.ZERO) .scanned(false) .build()); remaining = remaining.subtract(allocate); } } return result; } @Override @Transactional(rollbackFor = Exception.class) public void scanLine(MesWmSortTaskScanReqVO scanReqVO) { MesWmSortTaskDO task = validateTaskExists(scanReqVO.getTaskId()); validateTaskPending(task); MesWmSortTaskLineDO line = sortTaskLineMapper.selectById(scanReqVO.getLineId()); if (line == null || !ObjUtil.equal(line.getTaskId(), task.getId())) { throw exception(WM_SORT_TASK_LINE_NOT_EXISTS); } if (MesWmSortTaskStatusEnum.FINISHED.getStatus().equals(task.getStatus())) { throw new ServiceException(WM_SORT_TASK_LINE_ALREADY_SORTED.getCode(), "分拣任务[" + task.getCode() + "]已完成,不能再扫码分拣。"); } // 扫码校验:物料条码 或 批次号 匹配即可 MesMdmItemDO item = mdmItemService.getItemMap(Collections.singletonList(line.getItemId())) .get(line.getItemId()); String barcode = StrUtil.trim(scanReqVO.getBarcode()); boolean matched = (item != null && StrUtil.equalsIgnoreCase(barcode, StrUtil.trim(item.getBarCode()))) || StrUtil.equalsIgnoreCase(barcode, StrUtil.trim(line.getBatchCode())); if (!matched) { throw new ServiceException(WM_SORT_TASK_SCAN_MISMATCH.getCode(), "扫码内容[" + barcode + "]与分拣明细[" + (item != null ? item.getName() : "ID=" + line.getItemId()) + "]不匹配:明细要求的物料条码为[" + (item != null && StrUtil.isNotBlank(item.getBarCode()) ? item.getBarCode() : "未维护") + "],批次号为[" + StrUtil.blankToDefault(line.getBatchCode(), "无批次") + "]。" + "请核对货品后重新扫码。"); } BigDecimal quantity = scanReqVO.getQuantity() != null ? scanReqVO.getQuantity() : line.getPlanQuantity(); if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) { quantity = line.getPlanQuantity(); } // 更新明细:累加分拣数量,但不超过计划数量 BigDecimal sorted = line.getSortedQuantity() != null ? line.getSortedQuantity() : BigDecimal.ZERO; BigDecimal newSorted = sorted.add(quantity).min(Objects.requireNonNullElse(line.getPlanQuantity(), quantity)); sortTaskLineMapper.updateById(MesWmSortTaskLineDO.builder() .id(line.getId()).sortedQuantity(newSorted).scanned(true).build()); // 任务进入分拣中 if (MesWmSortTaskStatusEnum.PENDING.getStatus().equals(task.getStatus())) { sortTaskMapper.updateById(MesWmSortTaskDO.builder() .id(task.getId()).status(MesWmSortTaskStatusEnum.SORTING.getStatus()) .sortUserId(getCurrentUserId()).build()); } } @Override @Transactional(rollbackFor = Exception.class) public void finishSortTask(Long id, String carrier, String shippingNumber, String remark) { MesWmSortTaskDO task = validateTaskExists(id); validateTaskPending(task); // 1. 校验所有明细已扫码且分拣数量完整 List lines = sortTaskLineMapper.selectListByTaskId(id); if (CollUtil.isEmpty(lines)) { throw new ServiceException(WM_SORT_TASK_NO_STOCK.getCode(), "分拣任务[" + task.getCode() + "]没有分拣明细,无法完成分拣。"); } List unscanned = new ArrayList<>(); Map itemMap = mdmItemService.getItemMap(convertSet(lines, MesWmSortTaskLineDO::getItemId)); for (MesWmSortTaskLineDO line : lines) { BigDecimal sorted = line.getSortedQuantity() != null ? line.getSortedQuantity() : BigDecimal.ZERO; BigDecimal plan = line.getPlanQuantity() != null ? line.getPlanQuantity() : BigDecimal.ZERO; if (!Boolean.TRUE.equals(line.getScanned()) || sorted.compareTo(plan) < 0) { MesMdmItemDO item = itemMap.get(line.getItemId()); unscanned.add((item != null ? item.getName() : "ID=" + line.getItemId()) + "(计划 " + plan.stripTrailingZeros().toPlainString() + ",已分拣 " + sorted.stripTrailingZeros().toPlainString() + ")"); } } if (!unscanned.isEmpty()) { throw new ServiceException(WM_SORT_TASK_NOT_PENDING.getCode(), "分拣任务[" + task.getCode() + "]还有未完成扫码的明细:" + String.join(";", unscanned) + "。请对上述明细逐条扫码至计划数量后再完成分拣。"); } // 2. 触发配送:发货通知单尚未生成销售出库单时自动生成 if (productSalesMapper.selectByNoticeId(task.getNoticeId()) == null) { salesNoticeService.generateProductSalesFromNotice(task.getNoticeId()); } // 3. 更新任务为已完成并记录承运信息 sortTaskMapper.updateById(MesWmSortTaskDO.builder() .id(id).status(MesWmSortTaskStatusEnum.FINISHED.getStatus()) .carrier(carrier).shippingNumber(shippingNumber) .sortUserId(getCurrentUserId()).sortTime(LocalDateTime.now()) .remark(StrUtil.isBlank(remark) ? null : remark).build()); } @Override @Transactional(rollbackFor = Exception.class) public void cancelSortTask(Long id) { MesWmSortTaskDO task = validateTaskExists(id); if (MesWmSortTaskStatusEnum.FINISHED.getStatus().equals(task.getStatus())) { throw new ServiceException(WM_SORT_TASK_NOT_PENDING.getCode(), "分拣任务[" + task.getCode() + "]已完成,不能取消。"); } sortTaskMapper.updateById(MesWmSortTaskDO.builder() .id(id).status(MesWmSortTaskStatusEnum.CANCELED.getStatus()).build()); } @Override @Transactional(rollbackFor = Exception.class) public void deleteSortTask(Long id) { MesWmSortTaskDO task = validateTaskExists(id); if (!MesWmSortTaskStatusEnum.PENDING.getStatus().equals(task.getStatus()) && !MesWmSortTaskStatusEnum.CANCELED.getStatus().equals(task.getStatus())) { throw new ServiceException(WM_SORT_TASK_NOT_PENDING.getCode(), "只有「待分拣」或「已取消」的分拣任务才能删除,任务[" + task.getCode() + "]当前为[" + MesWmSortTaskStatusEnum.valueOf(task.getStatus()).getName() + "],请先取消任务。"); } sortTaskMapper.deleteById(id); sortTaskLineMapper.deleteByTaskId(id); } @Override public void updatePrintCount(Long id) { MesWmSortTaskDO task = validateTaskExists(id); sortTaskMapper.updateById(MesWmSortTaskDO.builder() .id(id).printCount((task.getPrintCount() != null ? task.getPrintCount() : 0) + 1).build()); } @Override @Transactional(rollbackFor = Exception.class) public MesWmSortProductionRequestRespVO submitProductionRequest(Long id) { MesWmSortTaskDO task = validateTaskExists(id); MesWmSalesNoticeDO notice = salesNoticeService.validateSalesNoticeExists(task.getNoticeId()); List noticeLines = salesNoticeLineService.getSalesNoticeLineListByNoticeId(task.getNoticeId()); MesWmSortProductionRequestRespVO result = new MesWmSortProductionRequestRespVO(); if (CollUtil.isEmpty(noticeLines)) { result.getFailures().add("分拣任务[" + task.getCode() + "]对应的发货通知单没有明细,无法提交生产申请"); return result; } Map itemMap = mdmItemService.getItemMap( convertSet(noticeLines, MesWmSalesNoticeLineDO::getItemId)); String requestDate = notice.getSalesDate() != null ? notice.getSalesDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) : null; for (MesWmSalesNoticeLineDO noticeLine : noticeLines) { MesMdmItemDO item = itemMap.get(noticeLine.getItemId()); String itemName = item != null ? item.getName() : "ID=" + noticeLine.getItemId(); if (noticeLine.getSaleOrderItemId() == null) { result.getFailures().add(itemName + ":发货明细未关联销售订单明细,无法提交生产申请"); continue; } // 已存在生产申请(MPS)时跳过,避免重复提交 if (mpsService.getMpsBySaleOrderItemId(noticeLine.getSaleOrderItemId()) != null) { result.setSkippedCount(result.getSkippedCount() + 1); continue; } try { mpsService.createMps(notice.getSaleOrderId(), notice.getSaleOrderCode(), noticeLine.getSaleOrderItemId(), noticeLine.getItemId(), itemName, noticeLine.getQuantity(), notice.getClientId(), requestDate, "由分拣任务[" + task.getCode() + "]提交生产申请"); result.setCreatedCount(result.getCreatedCount() + 1); } catch (ServiceException ex) { result.getFailures().add(itemName + ":" + ex.getMessage()); } } return result; } @Override public MesWmSortTaskRespVO getSortTask(Long id) { MesWmSortTaskDO task = validateTaskExists(id); return buildRespList(Collections.singletonList(task)).get(0); } @Override public PageResult getSortTaskPage(MesWmSortTaskPageReqVO pageReqVO) { PageResult pageResult = sortTaskMapper.selectPage(pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return PageResult.empty(pageResult.getTotal()); } return new PageResult<>(buildRespList(pageResult.getList()), pageResult.getTotal()); } @Override public List getPendingNoticeList(String noticeCode) { // 1. 查询待出库的发货通知单 MesWmSalesNoticePageReqVO pageReqVO = new MesWmSalesNoticePageReqVO(); pageReqVO.setCode(noticeCode); pageReqVO.setStatus(MesWmSalesNoticeStatusEnum.APPROVED.getStatus()); pageReqVO.setPageSize(cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE); List notices = salesNoticeService.getSalesNoticePage(pageReqVO).getList(); if (CollUtil.isEmpty(notices)) { return Collections.emptyList(); } // 2. 剔除已存在未完成分拣任务的通知单 Set taskNoticeIds = sortTaskMapper.selectList(new LambdaQueryWrapperX() .in(MesWmSortTaskDO::getNoticeId, convertSet(notices, MesWmSalesNoticeDO::getId)) .ne(MesWmSortTaskDO::getStatus, MesWmSortTaskStatusEnum.CANCELED.getStatus())) .stream().map(MesWmSortTaskDO::getNoticeId).collect(Collectors.toSet()); return notices.stream().filter(notice -> !taskNoticeIds.contains(notice.getId())) .map(notice -> new MesWmSortPendingNoticeRespVO() .setNoticeId(notice.getId()).setNoticeCode(notice.getCode()) .setSaleOrderCode(notice.getSaleOrderCode()) .setRecipientName(notice.getRecipientName()) .setRecipientTelephone(notice.getRecipientTelephone()) .setRecipientAddress(notice.getRecipientAddress()) .setDeliveryDate(notice.getSalesDate()) .setOutStatus(notice.getOutStatus())) .collect(Collectors.toList()); } // ==================== 私有方法 ==================== private String generateCode() { String prefix = "SORT" + LocalDateTime.now().format(CODE_DATE_FORMAT); long count = sortTaskMapper.selectCount(new LambdaQueryWrapperX() .likeRight(MesWmSortTaskDO::getCode, prefix)) + 1; String code = prefix + String.format("%03d", count); while (sortTaskMapper.selectByCode(code) != null) { count++; code = prefix + String.format("%03d", count); } return code; } private MesWmSortTaskDO validateTaskExists(Long id) { MesWmSortTaskDO task = id != null ? sortTaskMapper.selectById(id) : null; if (task == null) { throw exception(WM_SORT_TASK_NOT_EXISTS); } return task; } private void validateTaskPending(MesWmSortTaskDO task) { if (!MesWmSortTaskStatusEnum.PENDING.getStatus().equals(task.getStatus()) && !MesWmSortTaskStatusEnum.SORTING.getStatus().equals(task.getStatus())) { String statusName = MesWmSortTaskStatusEnum.valueOf(task.getStatus()) != null ? MesWmSortTaskStatusEnum.valueOf(task.getStatus()).getName() : String.valueOf(task.getStatus()); throw new ServiceException(WM_SORT_TASK_NOT_PENDING.getCode(), "分拣任务[" + task.getCode() + "]当前状态为[" + statusName + "],只有「待分拣」或「分拣中」的任务才能扫码/完成分拣。"); } } private List buildRespList(List list) { List allLines = sortTaskLineMapper.selectListByTaskIds( convertSet(list, MesWmSortTaskDO::getId)); Map> lineMap = allLines.stream() .collect(Collectors.groupingBy(MesWmSortTaskLineDO::getTaskId)); // 关联名称 Map itemMap = mdmItemService.getItemMap(convertSet(allLines, MesWmSortTaskLineDO::getItemId)); Map warehouseMap = warehouseService.getWarehouseMap( convertSet(allLines, MesWmSortTaskLineDO::getWarehouseId)); Map areaMap = areaService.getWarehouseAreaMap( convertSet(allLines, MesWmSortTaskLineDO::getAreaId)); Map locationMap = locationService.getWarehouseLocationMap( convertSet(allLines, MesWmSortTaskLineDO::getLocationId)); Map userMap = adminUserApi.getUserMap( convertSet(list, MesWmSortTaskDO::getSortUserId)); List result = new ArrayList<>(list.size()); for (MesWmSortTaskDO task : list) { MesWmSortTaskRespVO vo = new MesWmSortTaskRespVO(); vo.setId(task.getId()).setCode(task.getCode()) .setNoticeId(task.getNoticeId()).setNoticeCode(task.getNoticeCode()) .setSaleOrderId(task.getSaleOrderId()).setSaleOrderCode(task.getSaleOrderCode()) .setClientId(task.getClientId()) .setRecipientName(task.getRecipientName()) .setRecipientTelephone(task.getRecipientTelephone()) .setRecipientAddress(task.getRecipientAddress()) .setCarrier(task.getCarrier()).setShippingNumber(task.getShippingNumber()) .setStatus(task.getStatus()).setSortUserId(task.getSortUserId()) .setSortTime(task.getSortTime()).setPrintCount(task.getPrintCount()) .setRemark(task.getRemark()).setCreateTime(task.getCreateTime()); AdminUserRespDTO user = userMap.get(task.getSortUserId()); if (user != null) { vo.setSortUserName(user.getNickname()); } List lines = lineMap.getOrDefault(task.getId(), Collections.emptyList()); BigDecimal totalPlan = BigDecimal.ZERO; BigDecimal totalSorted = BigDecimal.ZERO; List lineVOs = new ArrayList<>(lines.size()); for (MesWmSortTaskLineDO line : lines) { MesWmSortTaskRespVO.Line lineVO = new MesWmSortTaskRespVO.Line(); lineVO.setId(line.getId()).setNoticeLineId(line.getNoticeLineId()) .setItemId(line.getItemId()).setBatchCode(line.getBatchCode()) .setMaterialStockId(line.getMaterialStockId()) .setWarehouseId(line.getWarehouseId()).setAreaId(line.getAreaId()) .setLocationId(line.getLocationId()) .setPlanQuantity(line.getPlanQuantity()).setSortedQuantity(line.getSortedQuantity()) .setScanned(line.getScanned()).setRemark(line.getRemark()); MesMdmItemDO item = itemMap.get(line.getItemId()); if (item != null) { lineVO.setItemCode(item.getCode()).setItemName(item.getName()).setItemBarCode(item.getBarCode()); } MesWmWarehouseDO warehouse = warehouseMap.get(line.getWarehouseId()); if (warehouse != null) { lineVO.setWarehouseName(warehouse.getName()); } MesWmWarehouseAreaDO area = areaMap.get(line.getAreaId()); if (area != null) { lineVO.setAreaName(area.getName()); } MesWmWarehouseLocationDO location = locationMap.get(line.getLocationId()); if (location != null) { lineVO.setLocationName(location.getName()); } totalPlan = totalPlan.add(line.getPlanQuantity() != null ? line.getPlanQuantity() : BigDecimal.ZERO); totalSorted = totalSorted.add(line.getSortedQuantity() != null ? line.getSortedQuantity() : BigDecimal.ZERO); lineVOs.add(lineVO); } vo.setLines(lineVOs).setTotalPlanQuantity(totalPlan).setTotalSortedQuantity(totalSorted); result.add(vo); } return result; } private Long getCurrentUserId() { try { return cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId(); } catch (Exception ex) { return null; } } }