chen.lin
5 天以前 024504a3933e8f2f86e80383e61fa574524a0d28
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/MaterialAutoSchedules.java
@@ -3,14 +3,18 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.controller.params.LocToTaskParams;
import com.vincent.rsf.server.manager.controller.params.OutStockToTaskParams;
import com.vincent.rsf.server.manager.controller.params.PakinItem;
import com.vincent.rsf.server.manager.controller.params.WaitPakinParam;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.common.constant.Constants;
import com.vincent.rsf.server.manager.enums.AsnExceStatus;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.manager.enums.OrderType;
import com.vincent.rsf.server.manager.enums.OrderWorkType;
import com.vincent.rsf.server.manager.enums.TaskStsType;
import com.vincent.rsf.server.manager.enums.TaskType;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.system.constant.GlobalConfigCode;
@@ -19,6 +23,7 @@
import com.vincent.rsf.server.system.service.ConfigService;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@@ -29,10 +34,11 @@
import java.util.stream.Collectors;
/**
 * 指定物料自动化定时任务:可配置物料编码后,
 * 指定物料/空板自动化定时任务:可配置后
 * 1)有库存时自动生成全版出库单;
 * 2)该物料出库单自动下发任务;
 * 3)RCS 入库通知时(可选)自动组托,数量可配置。
 * 3)RCS 入库通知时(可选)自动组托,数量可配置;
 * 4)空板(D)库位定时自动生成空板出库任务并下发 RCS(AUTO_EMPTY_OUT_ENABLED)。
 */
@Slf4j
@Component
@@ -227,11 +233,94 @@
    }
    /**
     * 定时任务:空板库存自动出库(每 2 分钟)
     * 配置:AUTO_EMPTY_OUT_ENABLED=true 时,扫描空板(D)库位,生成空板出库任务并下发 RCS,流程与 AUTO_FULL_OUT 对应定时任务一致。
     */
    @Scheduled(cron = "0 0/2 * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void autoEmptyOutTask() {
        Config enabledConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_EMPTY_OUT_ENABLED));
        if (enabledConfig == null || !Boolean.parseBoolean(enabledConfig.getVal())) {
            return;
        }
        List<Loc> emptyLocs = locService.list(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type));
        if (emptyLocs.isEmpty()) {
            return;
        }
        List<Task> existingEmptyOut = taskService.list(new LambdaQueryWrapper<Task>()
                .eq(Task::getTaskType, TaskType.TASK_TYPE_EMPITY_OUT.type)
                .lt(Task::getTaskStatus, TaskStsType.COMPLETE_OUT.id));
        Set<String> locCodesInProgress = existingEmptyOut.stream()
                .map(Task::getOrgLoc).filter(Objects::nonNull).collect(Collectors.toSet());
        List<Task> created = new ArrayList<>();
        for (Loc loc : emptyLocs) {
            if (locCodesInProgress.contains(loc.getCode())) {
                continue;
            }
            try {
                LocToTaskParams params = new LocToTaskParams();
                params.setType(Constants.TASK_TYPE_OUT_STOCK_EMPTY)
                        .setOrgLoc(loc.getCode())
                        .setSiteNo(DEFAULT_SITE_NO);
                Task task = locItemService.generateTaskEmpty(params, SYSTEM_USER_ID);
                created.add(task);
                locCodesInProgress.add(loc.getCode());
            } catch (Exception e) {
                log.warn("[自动空板出库] 库位 {} 生成任务失败: {}", loc.getCode(), e.getMessage());
            }
        }
        if (!created.isEmpty()) {
            List<Task> toPublish = created.stream()
                    .filter(t -> TaskStsType.GENERATE_OUT.id.equals(t.getTaskStatus()))
                    .collect(Collectors.toList());
            if (!toPublish.isEmpty()) {
                try {
                    taskService.pubTaskToWcs(toPublish);
                    log.info("[自动空板出库] 已生成并下发 {} 个空板出库任务", toPublish.size());
                } catch (Exception e) {
                    log.error("[自动空板出库] 下发 RCS 失败", e);
                }
            }
        }
    }
    /**
     * 定时任务:配置物料出库任务在 RCS 回调为 199(待确认)后自动拣货完成,无需 PDA 快速拣货确认即可更新库存。
     * 配置:AUTO_FULL_OUT_MATNR_CODE(物料编码,配置了则对该物料生效)
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    public void autoConfirmPickOut() {
        Config matnrConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_FULL_OUT_MATNR_CODE));
        if (matnrConfig == null || StringUtils.isBlank(matnrConfig.getVal())) {
            return;
        }
        String matnrCode = matnrConfig.getVal().trim();
        List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
                .eq(Task::getTaskType, TaskType.TASK_TYPE_OUT.type)
                .eq(Task::getTaskStatus, TaskStsType.WAVE_SEED.id));
        for (Task task : tasks) {
            long cnt = taskItemService.count(new LambdaQueryWrapper<TaskItem>()
                    .eq(TaskItem::getTaskId, task.getId())
                    .eq(TaskItem::getMatnrCode, matnrCode));
            if (cnt == 0) {
                continue;
            }
            try {
                taskService.completeFullOutStock(task.getId(), SYSTEM_USER_ID);
                log.info("[自动拣货完成] 任务: {}, 料箱: {}, 物料: {} 已自动确认出库并更新库存", task.getTaskCode(), task.getBarcode(), matnrCode);
            } catch (Exception e) {
                log.warn("[自动拣货完成] 任务: {} 处理失败: {}", task.getTaskCode(), e.getMessage());
            }
        }
    }
    /**
     * 定时任务3:无订单组托 + 自动生成入库单(仅针对配置物料,)
     * 先按配置物料与数量做无订单组托,再生成入库单并关联组托明细,便于 RCS 入库闭环。
     * 配置:AUTO_PAKIN_ON_ASN_ENABLED(true)、AUTO_FULL_OUT_MATNR_CODE、AUTO_PAKIN_QTY(数量)
     */
    @Scheduled(cron = "0/35 * * * * ?")
//    @Scheduled(cron = "0/35 * * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void autoPakinOnInbound() {
        Config enabledConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_PAKIN_ON_ASN_ENABLED));