chen.lin
2 天以前 9140aee230de0ef41de9682a9353fbd372e2bcaa
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/ReviseLogServiceImpl.java
@@ -4,25 +4,33 @@
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vincent.rsf.server.api.controller.erp.params.InventoryAdjustReportParam;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@Service("reviseLogService")
public class ReviseLogServiceImpl extends ServiceImpl<ReviseLogMapper, ReviseLog> implements ReviseLogService {
@@ -40,6 +48,21 @@
    @Autowired
    private ReviseLogItemService reviseLogItemService;
    @Autowired
    private OutStockService outStockService;
    @Autowired
    private OutStockItemService outStockItemService;
    @Autowired
    private WarehouseService warehouseService;
    @Autowired
    private CloudWmsNotifyLogService cloudWmsNotifyLogService;
    @Autowired
    private ObjectMapper objectMapper;
    /**
     * 库存调整单明细添加
@@ -130,6 +153,42 @@
                    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()) {
@@ -157,6 +216,7 @@
            // 删除原库位的库存明细(如果存在)
            locItemService.remove(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId()));
            final Loc sourceLoc = loc;
            Loc finalLoc = loc;
            reviseItems.forEach(logItem -> {
                LocItem locDetl = new LocItem();
@@ -166,14 +226,117 @@
                        .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("库存明细保存失败!!");
                }
                // 9.2 库存调整主动上报待办
                try {
                    String wareHouseId = null;
                    if (finalLoc.getWarehouseId() != null) {
                        Warehouse wh = warehouseService.getById(finalLoc.getWarehouseId());
                        if (wh != null) {
                            wareHouseId = wh.getCode();
                        }
                    }
                    if (wareHouseId != null && logItem.getMatnrCode() != null && sourceLoc != null) {
                        InventoryAdjustReportParam param = new InventoryAdjustReportParam()
                                .setChangeType(3) // 3 移库
                                .setWareHouseId(wareHouseId)
                                .setSourceLocId(sourceLoc.getCode())
                                .setTargetLocId(finalLoc.getCode())
                                .setMatNr(logItem.getMatnrCode())
                                .setQty(logItem.getReviseQty() != null ? String.valueOf(logItem.getReviseQty()) : "0");
                        String requestBody = objectMapper.writeValueAsString(param);
                        Date now = new Date();
                        CloudWmsNotifyLog notifyLog = new CloudWmsNotifyLog()
                                .setReportType(cloudWmsNotifyLogService.getReportTypeInventoryAdjust())
                                .setRequestBody(requestBody)
                                .setNotifyStatus(cloudWmsNotifyLogService.getNotifyStatusPending())
                                .setRetryCount(0)
                                .setBizRef("reviseId=" + revise.getId() + ",reviseLogItemId=" + logItem.getId())
                                .setCreateTime(now)
                                .setUpdateTime(now);
                        cloudWmsNotifyLogService.fillFromConfig(notifyLog);
                        cloudWmsNotifyLogService.save(notifyLog);
                    }
                } catch (Exception e) {
                    log.warn("库存调整上报待办落库失败(不影响库存保存),matNr={}:{}", logItem.getMatnrCode(), e.getMessage());
                }
                // 为库存调整产生的库存创建对应的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("调整单修改失败!!");