cl
6 天以前 50393719d85fc30438456b0d0f065573a404fba5
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -27,6 +27,7 @@
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.utils.LocUtils;
import com.vincent.rsf.server.manager.constant.CloudWmsInoutReportMode;
import com.vincent.rsf.server.manager.controller.params.GenerateTaskParams;
import com.vincent.rsf.server.manager.entity.CloudWmsNotifyLog;
import com.vincent.rsf.server.manager.entity.*;
@@ -55,6 +56,8 @@
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
@@ -211,6 +214,7 @@
                    throw new CoolException("组托明细修执行数量修改失败!!");
                }
            });
            syncAsnOrderItemBarcodeByPakin(waitPakinItems, pakin.getBarcode(), loginUserId);
        });
        if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>()
@@ -301,6 +305,7 @@
                    throw new CoolException("组托明细修执行数量修改失败!!");
                }
            });
            syncAsnOrderItemBarcodeByPakin(waitPakinItems, pakin.getBarcode(), loginUserId);
        });
        if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>()
@@ -453,6 +458,7 @@
                    throw new CoolException("组托明细修执行数量修改失败!!");
                }
            });
            syncAsnOrderItemBarcodeByPakin(waitPakinItems, pakin.getBarcode(), loginUserId);
        });
        if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>()
@@ -463,6 +469,27 @@
            throw new CoolException("组拖状态修改失败!!");
        }
        return R.ok("任务生成完毕!");
    }
    /** 组托后将通知单明细条码回写为料箱码 */
    private void syncAsnOrderItemBarcodeByPakin(List<WaitPakinItem> waitPakinItems, String pakinBarcode, Long loginUserId) {
        if (waitPakinItems == null || waitPakinItems.isEmpty() || StringUtils.isBlank(pakinBarcode)) {
            return;
        }
        Set<Long> asnItemIds = waitPakinItems.stream()
                .map(WaitPakinItem::getAsnItemId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        if (asnItemIds.isEmpty()) {
            return;
        }
        if (!asnOrderItemService.update(new LambdaUpdateWrapper<WkOrderItem>()
                .in(WkOrderItem::getId, asnItemIds)
                .set(WkOrderItem::getBarcode, pakinBarcode)
                .set(WkOrderItem::getUpdateBy, loginUserId)
                .set(WkOrderItem::getUpdateTime, new Date()))) {
            throw new CoolException("通知单明细条码回写失败!!");
        }
    }
    /**
@@ -597,7 +624,36 @@
        if (StringUtils.isNotBlank(task.getTaskCode())) {
            rcsBusTaskNoticeService.notifyTaskStatus(task.getTaskCode(), task.getTaskStatus());
        }
        final Long taskIdForFinish = task.getId();
        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    taskService.runStockFinishAfterManualComplete(taskIdForFinish);
                }
            });
        }
        return task;
    }
    @Override
    public void runStockFinishAfterManualComplete(Long taskId) {
        if (taskId == null) {
            return;
        }
        try {
            Task t = taskService.getById(taskId);
            if (t == null) {
                return;
            }
            if (Objects.equals(t.getTaskStatus(), TaskStsType.COMPLETE_IN.id)) {
                taskService.complateInTask(Collections.singletonList(t));
            } else if (Objects.equals(t.getTaskStatus(), TaskStsType.COMPLETE_OUT.id)) {
                taskService.completeTask(Collections.singletonList(t));
            }
        } catch (Exception e) {
            log.warn("手动完结后立即库存收尾失败,将由定时任务重试,taskId={}:{}", taskId, e.getMessage());
        }
    }
    /**
@@ -2566,6 +2622,10 @@
            WkOrder o = asnOrderService.getById(e.getKey());
            if (o != null) {
                Double newQty = QuantityUtils.roundToScale(QuantityUtils.add(o.getQty() != null ? o.getQty() : 0.0, e.getValue()));
                Double planQty = QuantityUtils.roundToScale(o.getAnfme() != null ? o.getAnfme() : 0.0);
                if (QuantityUtils.compare(newQty, planQty) > 0) {
                    newQty = planQty;
                }
                o.setQty(newQty);
                if (!asnOrderService.updateById(o)) {
                    throw new CoolException("入库单完成数量更新失败!!");
@@ -2576,6 +2636,10 @@
            WkOrderItem oi = asnOrderItemService.getById(e.getKey());
            if (oi != null) {
                Double newQty = QuantityUtils.roundToScale(QuantityUtils.add(oi.getQty() != null ? oi.getQty() : 0.0, e.getValue()));
                Double planQty = QuantityUtils.roundToScale(oi.getAnfme() != null ? oi.getAnfme() : 0.0);
                if (QuantityUtils.compare(newQty, planQty) > 0) {
                    newQty = planQty;
                }
                oi.setQty(newQty);
                if (!asnOrderItemService.updateById(oi)) {
                    throw new CoolException("入库单明细完成数量更新失败!!");
@@ -2817,19 +2881,61 @@
                    }
                }
            }
            // 出库仅云仓来源单据参与上报
            if (!isInbound) {
                boolean hasCloudSource = taskItems.stream().anyMatch(this::hasCloudOrderRef);
                if (!hasCloudSource) {
//                    log.info("入/出库结果上报待办跳过:无云仓来源单据,taskId={}", task.getId());
                    log.info("入/出库结果上报待办跳过:手动创建出库单据不通知云仓,taskId={}", task.getId());
                    return;
            // 入库组托场景允许按 WaitPakinItem.asnCode 兜底识别云仓来源,避免 plat* 为空时误跳过
            boolean hasCloudSource = taskItems.stream().anyMatch(this::hasCloudOrderRef)
                    || (isInbound && !sourceToOrderNo.isEmpty());
            if (!hasCloudSource) {
                log.info("入/出库结果上报待办跳过:无云仓来源单据,taskId={}", task.getId());
                return;
            }
            Set<Long> orderIdSet = taskItems.stream()
                    .filter(Objects::nonNull)
                    .map(TaskItem::getOrderId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            Map<Long, WkOrder> orderById = new HashMap<>();
            if (!orderIdSet.isEmpty()) {
                for (WkOrder o : asnOrderService.listByIds(orderIdSet)) {
                    if (o != null && o.getId() != null) {
                        orderById.put(o.getId(), o);
                    }
                }
            }
            Set<String> orderCodeSet = new HashSet<>();
            for (TaskItem ti : taskItems) {
                if (ti == null) {
                    continue;
                }
                String on = isInbound && ti.getSource() != null
                        ? sourceToOrderNo.get(ti.getSource())
                        : (ti.getPlatOrderCode() != null ? ti.getPlatOrderCode() : ti.getPlatWorkCode());
                if (on == null && isInbound) {
                    on = ti.getPlatOrderCode() != null ? ti.getPlatOrderCode() : ti.getPlatWorkCode();
                }
                if (StringUtils.isNotBlank(on)) {
                    orderCodeSet.add(on);
                }
            }
            Map<String, WkOrder> orderByCode = new HashMap<>();
            if (!orderCodeSet.isEmpty()) {
                for (WkOrder o : asnOrderService.list(new LambdaQueryWrapper<WkOrder>().in(WkOrder::getCode, orderCodeSet))) {
                    if (o != null && StringUtils.isNotBlank(o.getCode())) {
                        orderByCode.put(o.getCode(), o);
                    }
                }
            }
            ObjectMapper om = new ObjectMapper();
            Date now = new Date();
            Map<String, List<InOutResultReportParam>> byOrder = new LinkedHashMap<>();
            for (TaskItem item : taskItems) {
                if (!isInbound && !hasCloudOrderRef(item)) {
                if (item == null) {
                    continue;
                }
                boolean hasTaskItemCloudRef = hasCloudOrderRef(item);
                boolean hasInboundAsnFallbackRef = isInbound
                        && item.getSource() != null
                        && StringUtils.isNotBlank(sourceToOrderNo.get(item.getSource()));
                if (!hasTaskItemCloudRef && !hasInboundAsnFallbackRef) {
                    continue;
                }
                String orderNo = isInbound ? sourceToOrderNo.get(item.getSource()) : (item.getPlatOrderCode() != null ? item.getPlatOrderCode() : item.getPlatWorkCode());
@@ -2839,31 +2945,56 @@
                if (orderNo == null || item.getMatnrCode() == null) {
                    continue;
                }
                WkOrder asnOrder = null;
                if (item.getOrderId() != null) {
                    asnOrder = orderById.get(item.getOrderId());
                }
                if (asnOrder == null) {
                    asnOrder = orderByCode.get(orderNo);
                }
                InOutResultReportParam param = new InOutResultReportParam()
                        .setOrderNo(orderNo)
                        .setPlanNo(item.getPlatWorkCode())
                        .setWkType(item.getWkType())
                        .setUnitNo(item.getUnit())
                        .setLineId(item.getPlatItemId())
                        .setWareHouseId(wareHouseId)
                        .setDocWarehouseNo(asnOrder != null ? asnOrder.getDocTaskWarehouseNo() : null)
                        .setOrgNo(asnOrder != null ? asnOrder.getDocOrgNo() : null)
                        .setInWarehouseNo(isInbound && asnOrder != null ? asnOrder.getDocInWarehouseNo() : null)
                        .setOutWarehouseNo(!isInbound && asnOrder != null ? asnOrder.getDocOutWarehouseNo() : null)
                        .setLocId(locId)
                        .setMatNr(item.getMatnrCode())
                        .setQty(item.getAnfme() != null ? String.valueOf(item.getAnfme()) : "0")
                        .setBatch(item.getBatch())
                        .setInbound(isInbound)
                        .setBarcode(task.getBarcode());
                try {
                    String requestBody = om.writeValueAsString(param);
                    CloudWmsNotifyLog notifyLog = new CloudWmsNotifyLog()
                            .setReportType(cloudWmsNotifyLogService.getReportTypeInOutResult())
                            .setRequestBody(requestBody)
                            .setNotifyStatus(cloudWmsNotifyLogService.getNotifyStatusPending())
                            .setRetryCount(0)
                            .setBizRef("taskId=" + task.getId() + ",orderNo=" + orderNo)
                            .setCreateTime(now)
                            .setUpdateTime(now);
                    cloudWmsNotifyLogService.fillFromConfig(notifyLog);
                    cloudWmsNotifyLogService.save(notifyLog);
                } catch (JsonProcessingException e) {
                    log.warn("入/出库结果上报待办落库失败(不影响主流程),taskId={},orderNo={}:{}", task.getId(), orderNo, e.getMessage());
                byOrder.computeIfAbsent(orderNo, k -> new ArrayList<>()).add(param);
            }
            String mode = resolveCloudWmsInoutReportMode();
            boolean sendHold = CloudWmsInoutReportMode.MANUAL.equals(mode) || CloudWmsInoutReportMode.WAIT_ORDER.equals(mode);
            for (Map.Entry<String, List<InOutResultReportParam>> e : byOrder.entrySet()) {
                String orderNo = e.getKey();
                for (InOutResultReportParam param : e.getValue()) {
                    try {
                        String requestBody = om.writeValueAsString(param);
                        CloudWmsNotifyLog notifyLog = new CloudWmsNotifyLog()
                                .setReportType(cloudWmsNotifyLogService.getReportTypeInOutResult())
                                .setRequestBody(requestBody)
                                .setRetryCount(0)
                                .setBizRef("taskId=" + task.getId() + ",orderNo=" + orderNo)
                                .setCreateTime(now)
                                .setUpdateTime(now)
                                .setSourceOrderNo(orderNo)
                                .setInboundFlag(isInbound ? 1 : 0)
                                .setWareHouseCode(wareHouseId)
                                .setSendHold(sendHold ? 1 : 0)
                                .setSending(0);
                        cloudWmsNotifyLogService.fillFromConfig(notifyLog);
                        cloudWmsNotifyLogService.save(notifyLog);
                    } catch (JsonProcessingException ex) {
                        log.warn("入/出库结果上报待办落库失败(不影响主流程),taskId={},orderNo={}:{}", task.getId(), orderNo, ex.getMessage());
                    }
                }
            }
        } catch (Exception e) {
@@ -2878,4 +3009,16 @@
        return StringUtils.isNotBlank(item.getPlatOrderCode())
                || StringUtils.isNotBlank(item.getPlatWorkCode());
    }
    /** sys_config CLOUD_WMS_INOUT_REPORT_MODE:immediate / wait_order / manual / single */
    private String resolveCloudWmsInoutReportMode() {
        try {
            Config cfg = configService.getCachedOrLoad(GlobalConfigCode.CLOUD_WMS_INOUT_REPORT_MODE);
            if (cfg != null && StringUtils.isNotBlank(cfg.getVal())) {
                return cfg.getVal().trim().toLowerCase();
            }
        } catch (Exception ignored) {
        }
        return CloudWmsInoutReportMode.IMMEDIATE;
    }
}