| package com.vincent.rsf.server.manager.schedules; | 
|   | 
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
| import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 
| import com.vincent.rsf.framework.common.Cools; | 
| import com.vincent.rsf.framework.exception.CoolException; | 
| import com.vincent.rsf.server.common.constant.Constants; | 
| import com.vincent.rsf.server.manager.constant.LocGroupConstant; | 
| import com.vincent.rsf.server.manager.constant.StaGroupConstant; | 
| import com.vincent.rsf.server.manager.controller.params.LocToTaskParams; | 
| import com.vincent.rsf.server.manager.entity.*; | 
| import com.vincent.rsf.server.manager.enums.LocStsType; | 
| import com.vincent.rsf.server.manager.enums.TaskResouceType; | 
| 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.system.constant.GlobalConfigCode; | 
| import com.vincent.rsf.server.system.entity.Config; | 
| import com.vincent.rsf.server.system.service.ConfigService; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.beans.BeanUtils; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.scheduling.annotation.Scheduled; | 
| import org.springframework.stereotype.Component; | 
| import org.springframework.transaction.annotation.Transactional; | 
|   | 
| import java.util.*; | 
| import java.util.stream.Collectors; | 
|   | 
| import static com.vincent.rsf.server.system.utils.SystemAuthUtils.getLoginUserId; | 
|   | 
| /** | 
|  * 自动跑库程序 | 
|  */ | 
| @Slf4j | 
| @Component | 
| public class AutoRunSchedules { | 
|   | 
|     @Autowired | 
|     private LocService locService; | 
|     @Autowired | 
|     private ConfigService configService; | 
|     @Autowired | 
|     private BasStationService stationService; | 
|     @Autowired | 
|     private TaskService taskService; | 
|     @Autowired | 
|     private TaskItemService taskItemService; | 
|     @Autowired | 
|     private MatnrService matnrService; | 
|     @Autowired | 
|     private LocItemService locItemService; | 
|     @Autowired | 
|     private DeviceSiteService deviceSiteService; | 
|   | 
|   | 
|     /** | 
|      * 自动生成库位明细 | 
|      */ | 
|     @Transactional(rollbackFor = Exception.class) | 
| //    @Scheduled(cron = "0/25 * * * * ?") | 
|     public void insertRandomMats() { | 
|         List<Loc> list = locService.list(new LambdaQueryWrapper<Loc>().eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type)); | 
|         for (Loc loc : list) { | 
|             List<LocItem> items = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId())); | 
|             if (!items.isEmpty()) { | 
|                 continue; | 
|             } | 
|             List<Matnr> matnrs = matnrService.list(new LambdaQueryWrapper<Matnr>().orderByAsc(Matnr::getBarcode).last("limit 100")); | 
|             Collections.shuffle(matnrs); | 
|             Matnr matnr = matnrs.stream().findFirst().get(); | 
|             LocItem locItem = new LocItem(); | 
|             BeanUtils.copyProperties(matnr, locItem); | 
|             locItem.setBarcode(loc.getBarcode()) | 
|                     .setLocId(loc.getId()) | 
|                     .setMatnrCode(matnr.getCode()) | 
|                     .setMaktx(matnr.getName()) | 
|                     .setMatnrId(matnr.getId()) | 
|                     .setId(null) | 
|                     .setAnfme(45.0) | 
|                     .setLocCode(loc.getCode()); | 
|             locItemService.save(locItem); | 
|         } | 
|     } | 
|   | 
| //    /** | 
| //     * @author Ryan | 
| //     * @date 2025/9/1 | 
| //     * @description: 自动生成盘点跑库单 | 
| //     * @version 1.0 | 
| //     */ | 
| //    @Scheduled(cron = "0/25 * * * * ?") | 
| //    public void autoCheckOrders() { | 
| // | 
| // | 
| //    } | 
|   | 
|     /** | 
|      * @author Ryan | 
|      * @date 2025/9/1 | 
|      * @description: 自动完成盘点功能 | 
|      * @version 1.0 | 
|      */ | 
|     @Scheduled(cron = "0/25 * * * * ?") | 
|     @Transactional(rollbackFor = Exception.class) | 
|     public void autoCheckComplete() { | 
|         //获取任务列表中,为盘点出库的任务 | 
|         List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>() | 
|                 .in(Task::getTaskType, Arrays.asList(TaskType.TASK_TYPE_CHECK_OUT.type, | 
|                         TaskType.TASK_TYPE_PICK_IN.type, | 
|                         TaskType.TASK_TYPE_PICK_AGAIN_OUT.type, | 
|                         TaskType.TASK_TYPE_CHECK_IN.type))); | 
|   | 
|         if (!tasks.isEmpty()) { | 
|             tasks.forEach(task -> { | 
|                 if (task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) { | 
|                     if (task.getTaskStatus().equals(TaskStsType.COMPLETE_IN.id)) { | 
|   | 
|                     } | 
|                 } else { | 
|                     if (task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)) { | 
|                         if (!stationService.update(new LambdaUpdateWrapper<BasStation>() | 
|                                 .eq(BasStation::getStationName, task.getTargSite()) | 
|                                 .set(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_R.type))) { | 
|                             log.error("站点状态修改完成失败,当前任务状态:", task.getTaskStatus()); | 
| //                                throw new CoolException("站点状态修改失败!!"); | 
|                         } | 
|                         try { | 
|                             taskService.pickOrCheckTask(task.getId(), task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_OUT.type) ? Constants.TASK_TYPE_OUT_CHECK : ""); | 
|   | 
|                         } catch (Exception e) { | 
|                             log.error("error====>", e); | 
|                         } | 
|                     } | 
|                 } | 
|             }); | 
|         } | 
|     } | 
|   | 
|   | 
|     /** | 
|      * @author Ryan | 
|      * @date 2025/9/1 | 
|      * @description: 自动生成任务 | 
|      * @version 1.0 | 
|      */ | 
|     @Scheduled(cron = "0/15 * * * * ?") | 
|     public void genRun() { | 
|         Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_RUN_CHECK_ORDERS)); | 
|         if (!Boolean.parseBoolean(config.getVal())) { | 
|             return; | 
|         } | 
|   | 
|         Integer maxThread = 30; | 
|         Config confNum = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_RUN_MOVE_THEAD_MAX)); | 
|         if (!Objects.isNull(confNum)) { | 
|             maxThread = Integer.valueOf(confNum.getVal()); | 
|         } | 
|   | 
|   | 
|         //获取任务列表中,为盘点出库的任务 | 
|         List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>() | 
|                 .in(Task::getTaskType, Arrays.asList(TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_CHECK_IN.type))); | 
|         if (tasks.size() >= maxThread) { | 
|             return; | 
|         } | 
|         String autoRunArea = configService.getVal("AUTO_RUN_AREA", String.class); | 
|         if (Cools.isEmpty(autoRunArea)) { | 
|             return; | 
|         } | 
|         List<Integer> array = new ArrayList<>(); | 
|         List<String> list = new ArrayList<>(); | 
|         for (char c : autoRunArea.toCharArray()) { | 
|             switch (c) { | 
|                 case '1': | 
|                     array.addAll(LocGroupConstant.FAR_RIGHT_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.FAR_RIGHT_STA_ROW_LIST); | 
|                     break; | 
|                 case '2': | 
|                     array.addAll(LocGroupConstant.RIGHT_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.RIGHT_STA_ROW_LIST); | 
|                     break; | 
|                 case '3': | 
|                     array.addAll(LocGroupConstant.MIDDLE_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.MIDDLE_STA_ROW_LIST); | 
|                     break; | 
|                 case '4': | 
|                     array.addAll(LocGroupConstant.LEFT_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.LEFT_STA_ROW_LIST); | 
|                     break; | 
|                 case '5': | 
|                     array.addAll(LocGroupConstant.FAR_LEFT_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.FAR_LEFT_STA_ROW_LIST); | 
|                     break; | 
|                 default: | 
|                     break; | 
|             } | 
|         } | 
|         this.autoRun(array, list); | 
|     } | 
|   | 
|     private void autoRun(List<Integer> locGroupList, List<String> staGroupList) { | 
|         List<String> staPreNos = getStaPrefixes(staGroupList); | 
|         String staTaskMemo = "DEMO_STA_" + String.join("-", staPreNos); | 
|         List<Task> list = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getMemo, staTaskMemo)); | 
|         if (!Cools.isEmpty(list) && list.size() >= 1) { | 
|             return; | 
|         } | 
|   | 
|         List<Loc> locs = getAreaLocs(locGroupList, staGroupList, staTaskMemo); | 
|   | 
|         for (Loc loc : locs) { | 
|             List<LocItem> locItems = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId())); | 
|             if (!locItems.isEmpty()) { | 
|                 locItems.forEach(locItem -> { | 
|                     locItem.setOutQty(locItem.getAnfme()); | 
|                 }); | 
|                 List<BasStation> stations = stationService.list(new LambdaQueryWrapper<BasStation>() | 
|                         .eq(BasStation::getStatus, 1) | 
|                         .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)); | 
|                 List<String> stationNames = stations.stream().map(BasStation::getStationName).collect(Collectors.toList()); | 
|                 if (Cools.isEmpty(stations)) { | 
|                     throw new CoolException("无可用站点!!"); | 
|                 } | 
|                 DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>() | 
|                         .in(DeviceSite::getSite, stationNames) | 
|                         .eq(DeviceSite::getType, TaskType.TASK_TYPE_CHECK_OUT.type).last("limit 1")); | 
|                 if (Cools.isEmpty(deviceSite)) { | 
|                     throw new CoolException("无可用路径!!"); | 
|                 } | 
|                 //生成盘点任务参数 | 
|                 LocToTaskParams locToTaskParams = new LocToTaskParams(); | 
|                 locToTaskParams.setType(Constants.TASK_TYPE_OUT_CHECK) | 
|                         .setItems(locItems) | 
|                         .setSiteNo(deviceSite.getSite()) | 
|                         .setOrgLoc(loc.getCode()); | 
|   | 
|                 List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTargSite, deviceSite.getSite())); | 
|                 if (!tasks.isEmpty()) { | 
|                     continue; | 
|                 } | 
|                 try { | 
|                     locItemService.generateTask(TaskResouceType.TASK_RESOUCE_CHECK_TYPE.val, locToTaskParams, getLoginUserId()); | 
|                 } catch (Exception e) { | 
|                     throw new CoolException(e.getMessage()); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         // 入库 应该根据工作档回去 | 
| //        this.runStaToLoc(locGroupList, staGroupList, staTaskMemo); | 
|   | 
| //        // 出库,需要校验工作档是否存在,存在就说明站点处于忙碌状态 | 
| //        this.runLocToSta(locGroupList, staGroupList, staTaskMemo); | 
| //        // 移库locGroupList | 
| //        this.runLocToLoc(locGroupList, staTaskMemo); | 
|     } | 
|   | 
|   | 
|     private List<Loc> getAreaLocs(List<Integer> locGroupList, List<String> staGroupList, String memo) { | 
|         Integer startRow = Collections.min(locGroupList); | 
|         Integer endRow = Collections.max(locGroupList); | 
|   | 
|         // LOC STOCK | 
|         LambdaQueryWrapper<Loc> stockWrapper = new LambdaQueryWrapper<Loc>().eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type); | 
|         if (null != startRow) { | 
|             stockWrapper.ge(Loc::getRow, startRow); | 
|         } | 
|         if (null != endRow) { | 
|             stockWrapper.le(Loc::getRow, endRow); | 
|         } | 
|         List<Loc> stockList = locService.list(stockWrapper); | 
|         if (Cools.isEmpty(stockList)) { | 
|             return new ArrayList<>(); | 
|         } | 
|         Collections.shuffle(stockList); | 
|   | 
|         return stockList; | 
|   | 
|     } | 
|   | 
|     /** | 
|      * 生成移库任务 | 
|      * | 
|      * @param | 
|      * @param | 
|      */ | 
|     // 移库 | 
|     @Scheduled(cron = "0/23 * * * * ?") | 
|     @Transactional(rollbackFor = Exception.class) | 
|     public void runLocToLoc() { | 
|         Config config = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_RUN_CHECK_ORDERS)); | 
|         if (!Boolean.parseBoolean(config.getVal())) { | 
|             return; | 
|         } | 
|   | 
|         String autoRunArea = configService.getVal("AUTO_RUN_AREA", String.class); | 
|         if (Cools.isEmpty(autoRunArea)) { | 
|             return; | 
|         } | 
|         List<Integer> array = new ArrayList<>(); | 
|         List<String> list = new ArrayList<>(); | 
|         for (char c : autoRunArea.toCharArray()) { | 
|             switch (c) { | 
|                 case '1': | 
|                     array.addAll(LocGroupConstant.FAR_RIGHT_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.FAR_RIGHT_STA_ROW_LIST); | 
|                     break; | 
|                 case '2': | 
|                     array.addAll(LocGroupConstant.RIGHT_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.RIGHT_STA_ROW_LIST); | 
|                     break; | 
|                 case '3': | 
|                     array.addAll(LocGroupConstant.MIDDLE_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.MIDDLE_STA_ROW_LIST); | 
|                     break; | 
|                 case '4': | 
|                     array.addAll(LocGroupConstant.LEFT_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.LEFT_STA_ROW_LIST); | 
|                     break; | 
|                 case '5': | 
|                     array.addAll(LocGroupConstant.FAR_LEFT_LOC_ROW_LIST); | 
|                     list.addAll(StaGroupConstant.FAR_LEFT_STA_ROW_LIST); | 
|                     break; | 
|                 default: | 
|                     break; | 
|             } | 
|         } | 
|         xx(array); | 
|   | 
|     } | 
|   | 
|     private void xx(List<Integer> locGroupList) { | 
|         Integer startRow = Collections.min(locGroupList); | 
|         Integer endRow = Collections.max(locGroupList); | 
|   | 
|         String memo = "DEMO_LOC_" + startRow + "-" + endRow; | 
|   | 
|         Integer maxThread = 30; | 
|         Config confNum = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_RUN_MOVE_THEAD_MAX)); | 
|         if (!Objects.isNull(confNum)) { | 
|             maxThread = Integer.valueOf(confNum.getVal()); | 
|         } | 
|   | 
|         List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>() | 
|                 .eq(Task::getMemo,memo)); | 
|         if (!tasks.isEmpty() && tasks.size() >= maxThread) { | 
|             return; | 
|         } | 
|   | 
|         // STOCK | 
|         LambdaQueryWrapper<Loc> stockWrapper = new LambdaQueryWrapper<Loc>().eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type); | 
|         if (null != startRow) { | 
|             stockWrapper.ge(Loc::getRow, startRow); | 
|         } | 
|         if (null != endRow) { | 
|             stockWrapper.le(Loc::getRow, endRow); | 
|         } | 
|         List<Loc> stockList = locService.list(stockWrapper); | 
|         if (Cools.isEmpty(stockList)) { | 
|             return; | 
|         } | 
|         Collections.shuffle(stockList); | 
|   | 
|         // IDLE | 
|         LambdaQueryWrapper<Loc> idleWrapper = new LambdaQueryWrapper<Loc>().eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type); | 
|         if (null != startRow) { | 
|             idleWrapper.ge(Loc::getRow, startRow); | 
|         } | 
|         if (null != endRow) { | 
|             idleWrapper.le(Loc::getRow, endRow); | 
|         } | 
|         List<Loc> idleList = locService.list(idleWrapper); | 
|         if (Cools.isEmpty(idleList)) { | 
|             return; | 
|         } | 
|         Collections.shuffle(idleList); | 
|         //生成移库任务 | 
|         Loc loc = stockList.get(0); | 
|         List<LocItem> list = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocId, loc.getId())); | 
|         LocToTaskParams param = new LocToTaskParams(); | 
|         param.setType(Constants.TASK_TYPE_OUT_CHECK); | 
|         param.setTarLoc(idleList.get(0).getCode()); | 
|         param.setItems(list); | 
|         param.setOrgLoc(stockList.get(0).getCode()); | 
|         param.setMemo(memo); | 
|         //生成移库工作档 | 
|         try { | 
|             locItemService.genMoveTask(param, 6666L); | 
|         } catch (Exception e) { | 
|             log.info("生成出库任务失败", e); | 
|         } | 
|     } | 
|   | 
|     public static List<String> getStaPrefixes(List<String> staGroupList) { | 
|         Set<String> rowSet = new HashSet<>(); | 
|         for (String s : staGroupList) { | 
|             rowSet.add(s.split("-")[0]); | 
|         } | 
|         List<String> result = new ArrayList<>(rowSet); | 
|         result.sort(Comparator.comparingInt(Integer::parseInt)); | 
|         return result; | 
|     } | 
| } |