chen.lin
16 小时以前 82065a03737fa1370eb9f4f01ab5332933baf08a
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
@@ -28,7 +28,12 @@
import com.vincent.rsf.server.api.utils.SlaveProperties;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.controller.params.PakinItem;
import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
import com.vincent.rsf.server.manager.service.impl.LocServiceImpl;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
import com.vincent.rsf.server.system.entity.Config;
import com.vincent.rsf.server.system.service.ConfigService;
import com.vincent.rsf.server.system.utils.SystemAuthUtils;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.manager.enums.LocStsType;
@@ -88,6 +93,16 @@
    private RestTemplate restTemplate;
    @Autowired
    private RemotesInfoProperties.RcsApi rcsApi;
    @Autowired
    private ConfigService configService;
    @Autowired
    private MatnrService matnrService;
    @Autowired
    private AsnOrderService asnOrderService;
    @Autowired
    private AsnOrderItemService asnOrderItemService;
    @Autowired
    private com.vincent.rsf.server.api.service.MobileService mobileService;
    @Override
@@ -307,6 +322,16 @@
        // 2. 若未命中拣料/盘点入库,再校验组托并继续其他入库逻辑
        if (pickInTask == null && checkInTask == null) {
            waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                    .eq(WaitPakin::getBarcode, param.getBarcode())
                    .in(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
            // 空托盘无组托时:若配置启用则按 AUTO_FULL_OUT_MATNR_CODE 自动组托并生成入库单,再继续入库任务逻辑
            if (waitPakin == null) {
                tryAutoPakinForBarcode(param.getBarcode());
                waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
                        .eq(WaitPakin::getBarcode, param.getBarcode())
                        .in(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
            }
            waitPakin = validateWaitPakin(param.getBarcode());
            waitPakinItems = waitPakinItemService.list(
                    new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId()));
@@ -376,6 +401,9 @@
            throw new RuntimeException(e);
        }
        if (waitPakin == null) {
            throw new CoolException("请检查组拖状态是否完成!!");
        }
        // 创建并保存任务
        Task task = createTask(ruleCode, locNo.getLocNo(), waitPakin.getBarcode(),
                deviceSite.getDeviceSite(), param.getSourceStaNo().toString(), param.getUser());
@@ -398,6 +426,93 @@
        return locNo;
    }
    /**
     * RCS 入库申请时若 barcode 无组托且配置启用:按 AUTO_FULL_OUT_MATNR_CODE 无订单组托并生成入库单,便于后续生成入库任务。
     */
    private void tryAutoPakinForBarcode(String barcode) {
        Config enabledConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_PAKIN_ON_ASN_ENABLED));
        if (enabledConfig == null || !Boolean.parseBoolean(enabledConfig.getVal())) {
            return;
        }
        Config matnrConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_FULL_OUT_MATNR_CODE));
        if (matnrConfig == null || StringUtils.isBlank(matnrConfig.getVal())) {
            return;
        }
        Config qtyConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_PAKIN_QTY));
        double autoQty = 1.0;
        if (qtyConfig != null && StringUtils.isNotBlank(qtyConfig.getVal())) {
            try {
                autoQty = Double.parseDouble(qtyConfig.getVal().trim());
                if (autoQty <= 0) autoQty = 1.0;
            } catch (NumberFormatException e) {
                // ignore
            }
        }
        String matnrCode = matnrConfig.getVal().trim();
        Matnr matnr = matnrService.getOne(new LambdaQueryWrapper<Matnr>().eq(Matnr::getCode, matnrCode));
        if (matnr == null) {
            log.warn("[RCS入库申请-自动组托] 物料不存在: {}", matnrCode);
            return;
        }
        List<PakinItem> pakinItems = new ArrayList<>();
        PakinItem pi = new PakinItem();
        pi.setMatnrId(matnr.getId());
        pi.setReceiptQty(autoQty);
        pi.setAsnCode(null);
        pi.setId(null);
        pakinItems.add(pi);
        WaitPakinParam param = new WaitPakinParam();
        param.setBarcode(barcode);
        param.setItems(pakinItems);
        WaitPakin waitPakin;
        try {
            waitPakin = mobileService.mergeItems(param, 1L);
        } catch (Exception e) {
            log.warn("[RCS入库申请-自动组托] 组托失败, barcode={}: {}", barcode, e.getMessage());
            return;
        }
        String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_ASN_ORDER, null);
        if (StringUtils.isBlank(ruleCode)) {
            log.warn("[RCS入库申请-自动组托] 入库单编码规则未配置");
            return;
        }
        WkOrder order = new WkOrder();
        order.setCode(ruleCode)
                .setType(OrderType.ORDER_IN.type)
                .setExceStatus(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val)
                .setAnfme(autoQty)
                .setWorkQty(0.0)
                .setQty(0.0)
                .setCreateBy(1L)
                .setUpdateBy(1L);
        if (!asnOrderService.save(order)) {
            throw new CoolException("入库主单保存失败");
        }
        WkOrderItem orderItem = new WkOrderItem();
        orderItem.setOrderId(order.getId())
                .setOrderCode(order.getCode())
                .setMatnrId(matnr.getId())
                .setMatnrCode(matnr.getCode())
                .setMaktx(matnr.getName())
                .setAnfme(autoQty)
                .setWorkQty(0.0)
                .setQty(0.0)
                .setStockUnit(matnr.getStockUnit() != null ? matnr.getStockUnit() : "个")
                .setPurUnit(matnr.getPurUnit() != null ? matnr.getPurUnit() : "个")
                .setFieldsIndex(matnr.getFieldsIndex())
                .setCreateBy(1L)
                .setUpdateBy(1L);
        if (!asnOrderItemService.save(orderItem)) {
            throw new CoolException("入库明细保存失败");
        }
        waitPakinItemService.update(new LambdaUpdateWrapper<WaitPakinItem>()
                .eq(WaitPakinItem::getPakinId, waitPakin.getId())
                .set(WaitPakinItem::getAsnId, order.getId())
                .set(WaitPakinItem::getAsnCode, order.getCode())
                .set(WaitPakinItem::getAsnItemId, orderItem.getId()));
        log.info("[RCS入库申请-自动组托] 已组托并生成入库单: {}, barcode: {}, 物料: {}, 数量: {}", order.getCode(), barcode, matnrCode, autoQty);
    }
    /**
     * 验证设备站点
@@ -878,6 +993,7 @@
                        throw new CoolException("任务状态修改失败!!当前任务状态:" + task.getTaskStatus() + ",目标状态:" + TaskStsType.COMPLETE_IN.id);
                    }
                    log.info("入库任务状态更新成功 - 任务编码:{}", task.getTaskCode());
                    // 入库完整闭环由定时任务完成:TaskSchedules.completeInStock 扫描 COMPLETE_IN,执行库位/组托/上报云仓
                }
            } else if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)
                    || task.getTaskType().equals(TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
@@ -920,33 +1036,7 @@
                        throw new CoolException("任务状态修改失败!!当前任务状态:" + task.getTaskStatus() + ",目标状态:" + TaskStsType.COMPLETE_OUT.id);
                    }
                    log.info("出库任务状态更新成功 - 任务编码:{}", task.getTaskCode());
                    // 全版出库在RCS回调后处理库存并设置为199,等待PDA快速拣货确认后更新为200
                    if (task.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) {
                        log.info("全版出库任务,开始处理库存并更新状态为199 - 任务编码:{}", task.getTaskCode());
                        try {
                            // 重新查询任务以获取最新状态(198)
                            task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getTaskCode, task.getTaskCode()));
                            // 调用completeTask处理库存(会设置为199)
                            List<Task> taskList = new ArrayList<>();
                            taskList.add(task);
                            taskService.completeTask(taskList);
                            // 重新查询任务以获取最新状态(199)
                            task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getTaskCode, task.getTaskCode()));
                            if (task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)) {
                                log.info("全版出库任务状态已更新为199(等待PDA快速拣货确认后更新为200) - 任务编码:{}", task.getTaskCode());
                            } else {
                                log.warn("全版出库任务状态更新为199失败 - 任务编码:{},当前状态:{}",
                                        task.getTaskCode(), task.getTaskStatus());
                            }
                        } catch (Exception e) {
                            log.error("全版出库任务处理失败 - 任务编码:{},错误:{}", task.getTaskCode(), e.getMessage(), e);
                            // 不抛出异常,避免影响RCS回调的正常返回
                        }
                    }
                    // 出库完整闭环(库存、出库单、9.1 上报云仓)由定时任务 TaskSchedules.complateOutStock 统一执行
                }
            }
        } else {