| | |
| | | import com.vincent.rsf.framework.exception.CoolException; |
| | | import com.vincent.rsf.server.manager.controller.params.ReviseLogParams; |
| | | import com.vincent.rsf.server.manager.entity.*; |
| | | import com.vincent.rsf.server.manager.enums.AsnExceStatus; |
| | | import com.vincent.rsf.server.manager.enums.CommonExceStatus; |
| | | import com.vincent.rsf.server.manager.enums.OrderType; |
| | | import com.vincent.rsf.server.manager.enums.OrderWorkType; |
| | | import com.vincent.rsf.server.manager.mapper.ReviseLogMapper; |
| | | import com.vincent.rsf.server.manager.service.*; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | |
| | | |
| | | @Autowired |
| | | private ReviseLogItemService reviseLogItemService; |
| | | |
| | | @Autowired |
| | | private OutStockService outStockService; |
| | | |
| | | @Autowired |
| | | private OutStockItemService outStockItemService; |
| | | |
| | | /** |
| | | * 库存调整单明细添加 |
| | |
| | | |
| | | Double sum = locItems.stream().mapToDouble(LocItem::getAnfme).sum(); |
| | | |
| | | locRevise.setAnfme(Math.round((sum + locRevise.getAnfme()) * 10000) / 10000.0); |
| | | locRevise.setAnfme(Math.round((sum + locRevise.getAnfme()) * 1000000) / 1000000.0); |
| | | }); |
| | | |
| | | locRevise.setExceStatus(CommonExceStatus.COMMON_EXCE_STATUS_UN_EXCE.val); |
| | |
| | | if (logItems.isEmpty()) { |
| | | throw new CoolException("调整明细为空!!"); |
| | | } |
| | | Map<Long, List<ReviseLogItem>> listMap = logItems.stream().collect(Collectors.groupingBy(ReviseLogItem::getLocId)); |
| | | listMap.keySet().forEach(items -> { |
| | | Loc loc = locService.getById(items); |
| | | // 按库位ID分组,如果locId为null则按locCode分组 |
| | | Map<String, List<ReviseLogItem>> listMap = logItems.stream() |
| | | .filter(item -> item.getLocCode() != null && !item.getLocCode().isEmpty()) |
| | | .collect(Collectors.groupingBy(item -> { |
| | | // 优先使用locId,如果为null则使用locCode作为key |
| | | return item.getLocId() != null ? String.valueOf(item.getLocId()) : item.getLocCode(); |
| | | })); |
| | | |
| | | // 优化:在循环外查询所有未完成的出库单和明细,避免重复查询 |
| | | // 查询所有未完成的出库单状态:初始化、待处理、生成波次、生成工作档、作业中 |
| | | List<WkOrder> outOrders = outStockService.list(new LambdaQueryWrapper<WkOrder>() |
| | | .eq(WkOrder::getType, OrderType.ORDER_OUT.type) |
| | | .in(WkOrder::getExceStatus, |
| | | AsnExceStatus.OUT_STOCK_STATUS_TASK_INIT.val, |
| | | AsnExceStatus.OUT_STOCK_STATUS_TASK_EXCE.val, |
| | | AsnExceStatus.OUT_STOCK_STATUS_TASK_WAVE.val, |
| | | AsnExceStatus.OUT_STOCK_STATUS_TASK_CREATE.val, |
| | | AsnExceStatus.OUT_STOCK_STATUS_TASK_WORKING.val)); |
| | | |
| | | // 预先查询所有出库单的明细,建立索引以提高查询效率 |
| | | Map<Long, List<WkOrderItem>> orderItemsMap = new HashMap<>(); |
| | | Map<Long, Boolean> orderHasItemsMap = new HashMap<>(); |
| | | if (!outOrders.isEmpty()) { |
| | | Set<Long> orderIds = outOrders.stream().map(WkOrder::getId).collect(Collectors.toSet()); |
| | | List<WkOrderItem> allOrderItems = outStockItemService.list( |
| | | new LambdaQueryWrapper<WkOrderItem>().in(WkOrderItem::getOrderId, orderIds)); |
| | | |
| | | // 按orderId分组建立索引 |
| | | orderItemsMap = allOrderItems.stream() |
| | | .collect(Collectors.groupingBy(WkOrderItem::getOrderId)); |
| | | |
| | | // 记录每个出库单是否有明细 |
| | | for (Long orderId : orderIds) { |
| | | orderHasItemsMap.put(orderId, orderItemsMap.containsKey(orderId) && !orderItemsMap.get(orderId).isEmpty()); |
| | | } |
| | | } |
| | | |
| | | // 使用final变量以便在lambda中使用 |
| | | final Map<Long, List<WkOrderItem>> finalOrderItemsMap = orderItemsMap; |
| | | final Map<Long, Boolean> finalOrderHasItemsMap = orderHasItemsMap; |
| | | |
| | | // 批量收集需要创建的WkOrderItem |
| | | List<WkOrderItem> newOrderItems = new ArrayList<>(); |
| | | |
| | | listMap.keySet().forEach(key -> { |
| | | List<ReviseLogItem> reviseItems = listMap.get(key); |
| | | if (Objects.isNull(reviseItems) || reviseItems.isEmpty()) { |
| | | throw new CoolException("调整明细为空!!"); |
| | | } |
| | | |
| | | // 获取第一个明细的库位信息 |
| | | ReviseLogItem firstItem = reviseItems.get(0); |
| | | String locCode = firstItem.getLocCode(); |
| | | Long locId = firstItem.getLocId(); |
| | | |
| | | // 查询库位:优先使用locId,如果为null则使用locCode |
| | | Loc loc = null; |
| | | if (locId != null) { |
| | | loc = locService.getById(locId); |
| | | } |
| | | if (loc == null && locCode != null && !locCode.isEmpty()) { |
| | | loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, locCode).eq(Loc::getDeleted, 0)); |
| | | } |
| | | |
| | | if (Objects.isNull(loc)) { |
| | | throw new CoolException("库位不存在!!"); |
| | | throw new CoolException("库位不存在!库位编码:" + locCode + ", 库位ID:" + locId); |
| | | } |
| | | List<LocItem> list = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId())); |
| | | if (!list.isEmpty()) { |
| | | throw new CoolException("库位:" + loc.getCode() + ", 调整信息为空!!"); |
| | | } |
| | | |
| | | // 删除原库位的库存明细(如果存在) |
| | | locItemService.remove(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId())); |
| | | listMap.get(items).forEach(logItem -> { |
| | | |
| | | Loc finalLoc = loc; |
| | | reviseItems.forEach(logItem -> { |
| | | LocItem locDetl = new LocItem(); |
| | | BeanUtils.copyProperties(logItem, locDetl); |
| | | locDetl.setLocId(loc.getId()) |
| | | locDetl.setLocId(finalLoc.getId()) |
| | | .setType(OrderType.ORDER_REVISE.type) |
| | | .setLocCode(loc.getCode()) |
| | | .setWkType(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_REVISE.type)) |
| | | .setLocCode(finalLoc.getCode()) |
| | | .setAnfme(logItem.getReviseQty()) |
| | | // 如果batch不为空,同时设置splrBatch,以便查询时能匹配 |
| | | .setSplrBatch(StringUtils.isNotBlank(logItem.getBatch()) ? logItem.getBatch() : null) |
| | | .setUpdateBy(loginUserId) |
| | | .setId(null) |
| | | .setCreateBy(loginUserId); |
| | | if (!locItemService.save(locDetl)) { |
| | | throw new CoolException("库存明细保存失败!!"); |
| | | } |
| | | |
| | | // 为库存调整产生的库存创建对应的WkOrderItem |
| | | // 遍历所有未完成的出库单,检查是否需要这些物料 |
| | | for (WkOrder outOrder : outOrders) { |
| | | // 从预加载的索引中查找该出库单的明细 |
| | | List<WkOrderItem> orderItems = finalOrderItemsMap.getOrDefault(outOrder.getId(), new ArrayList<>()); |
| | | |
| | | // 检查该出库单是否已有匹配的明细 |
| | | boolean hasMatchingItem = orderItems.stream().anyMatch(item -> { |
| | | // 物料ID必须匹配 |
| | | if (!Objects.equals(item.getMatnrId(), logItem.getMatnrId())) { |
| | | return false; |
| | | } |
| | | |
| | | // 如果有批次信息,需要匹配批次 |
| | | if (StringUtils.isNotBlank(logItem.getBatch())) { |
| | | boolean batchMatch = Objects.equals(item.getBatch(), logItem.getBatch()) || |
| | | Objects.equals(item.getSplrBatch(), logItem.getBatch()); |
| | | if (!batchMatch) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // 如果有字段索引,需要匹配 |
| | | if (StringUtils.isNotBlank(logItem.getFieldsIndex())) { |
| | | if (!Objects.equals(item.getFieldsIndex(), logItem.getFieldsIndex())) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | }); |
| | | |
| | | // 如果该出库单需要这个物料但没有对应的明细,则创建 |
| | | if (!hasMatchingItem) { |
| | | // 为所有未完成的出库单创建WkOrderItem,即使出库单没有其他明细 |
| | | // 因为库存调整的物料可能需要出库 |
| | | WkOrderItem newOrderItem = new WkOrderItem(); |
| | | newOrderItem.setOrderId(outOrder.getId()) |
| | | .setOrderCode(outOrder.getCode()) |
| | | .setMatnrId(logItem.getMatnrId()) |
| | | .setMatnrCode(logItem.getMatnrCode()) |
| | | .setMaktx(logItem.getMaktx()) |
| | | .setBatch(logItem.getBatch()) |
| | | // 如果batch不为空,同时设置splrBatch,以便查询时能匹配 |
| | | .setSplrBatch(StringUtils.isNotBlank(logItem.getBatch()) ? logItem.getBatch() : null) |
| | | .setFieldsIndex(logItem.getFieldsIndex()) |
| | | .setAnfme(logItem.getReviseQty()) |
| | | .setWorkQty(0.0) |
| | | .setStockUnit(logItem.getUnit()) |
| | | .setPurUnit(logItem.getUnit()) |
| | | .setSpec(logItem.getSpec()) |
| | | .setModel(logItem.getModel()) |
| | | .setCreateBy(loginUserId) |
| | | .setUpdateBy(loginUserId) |
| | | .setCreateTime(new Date()) |
| | | .setUpdateTime(new Date()); |
| | | |
| | | newOrderItems.add(newOrderItem); |
| | | } |
| | | } |
| | | }); |
| | | }); |
| | | |
| | | |
| | | // 批量保存WkOrderItem,减少数据库操作次数 |
| | | if (!newOrderItems.isEmpty()) { |
| | | if (!outStockItemService.saveBatch(newOrderItems)) { |
| | | throw new CoolException("库存调整单据明细创建失败!!"); |
| | | } |
| | | } |
| | | revise.setExceStatus(CommonExceStatus.COMMON_EXCE_STATUS_TASK_DONE.val); |
| | | if (!locReviseService.updateById(revise)) { |
| | | throw new CoolException("调整单修改失败!!"); |