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.baomidou.mybatisplus.extension.plugins.pagination.Page; 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.*; import com.vincent.rsf.server.manager.service.*; import com.vincent.rsf.server.manager.service.impl.BasStationServiceImpl; import com.vincent.rsf.server.system.constant.SerialRuleCode; import com.vincent.rsf.server.system.service.ConfigService; import com.vincent.rsf.server.system.utils.SerialRuleUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; 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 list = locService.list(new LambdaQueryWrapper().eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type)); for (Loc loc : list) { List items = locItemService.list(new LambdaQueryWrapper().eq(LocItem::getLocId, loc.getId())); if (!items.isEmpty()) { continue; } List matnrs = matnrService.list(new LambdaQueryWrapper().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/35 * * * * ?") @Transactional(rollbackFor = Exception.class) public void autoCheckComplete() { // Boolean autoRunArea = configService.getVal("AUTO_RUN_CHECK_ORDERS", Boolean.class); // if (!autoRunArea) { // return; // } //获取任务列表中,为盘点出库的任务 List tasks = taskService.list(new LambdaQueryWrapper() .in(Task::getTaskType, Arrays.asList(TaskType.TASK_TYPE_CHECK_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() .eq(BasStation::getStationName, task.getTargSite()) .set(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_F.type))) { log.error("站点状态修改完成失败,当前任务状态:", task.getTaskStatus()); // throw new CoolException("站点状态修改失败!!"); } try { taskService.pickOrCheckTask(task.getId(), Constants.TASK_TYPE_OUT_CHECK); if (!stationService.update(new LambdaUpdateWrapper() .eq(BasStation::getStationName, task.getTargSite()) .set(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_R.type))) { log.error("站点状态修改完成失败,当前任务状态:", task.getTaskStatus()); // throw new CoolException("站点状态修改失败!!"); } } catch (Exception e) { log.error("error====>", e); } } } }); } } /** * @author Ryan * @date 2025/9/1 * @description: 自动生成任务 * @version 1.0 */ @Scheduled(cron = "0/25 * * * * ?") // @Scheduled(cron = "0 0/05 * * * ? ") public void genRun() { Boolean flagAuto = configService.getVal("AUTO_RUN_CHECK_ORDERS", Boolean.class); if (!flagAuto) { return; } //获取任务列表中,为盘点出库的任务 List tasks = taskService.list(new LambdaQueryWrapper() .in(Task::getTaskType, Arrays.asList(TaskType.TASK_TYPE_CHECK_OUT.type, TaskType.TASK_TYPE_CHECK_IN.type))); if (tasks.size() >= 6) { return; } String autoRunArea = configService.getVal("AUTO_RUN_AREA", String.class); if (Cools.isEmpty(autoRunArea)) { return; } for (char c : autoRunArea.toCharArray()) { switch (c) { case '1': this.autoRun(LocGroupConstant.FAR_RIGHT_LOC_ROW_LIST, StaGroupConstant.FAR_RIGHT_STA_ROW_LIST); break; case '2': this.autoRun(LocGroupConstant.RIGHT_LOC_ROW_LIST, StaGroupConstant.RIGHT_STA_ROW_LIST); break; case '3': this.autoRun(LocGroupConstant.MIDDLE_LOC_ROW_LIST, StaGroupConstant.MIDDLE_STA_ROW_LIST); break; case '4': this.autoRun(LocGroupConstant.LEFT_LOC_ROW_LIST, StaGroupConstant.LEFT_STA_ROW_LIST); break; case '5': this.autoRun(LocGroupConstant.FAR_LEFT_LOC_ROW_LIST, StaGroupConstant.FAR_LEFT_STA_ROW_LIST); break; default: break; } } } private void autoRun(List locGroupList, List staGroupList) { List staPreNos = getStaPrefixes(staGroupList); String staTaskMemo = "DEMO_STA_" + String.join("-", staPreNos); List list = taskService.list(new LambdaQueryWrapper().eq(Task::getMemo, staTaskMemo)); if (!Cools.isEmpty(list) && list.size() >= 1) { return; } List locs = getAreaLocs(locGroupList, staGroupList, staTaskMemo); for (Loc loc : locs) { List locItems = locItemService.list(new LambdaQueryWrapper().eq(LocItem::getLocId, loc.getId())); if (!locItems.isEmpty()) { locItems.forEach(locItem -> { locItem.setOutQty(locItem.getAnfme()); }); List stations = stationService.list(new LambdaQueryWrapper() .eq(BasStation::getStatus, 1) .eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)); List stationNames = stations.stream().map(BasStation::getStationName).collect(Collectors.toList()); if (Cools.isEmpty(stations)) { throw new CoolException("无可用站点!!"); } DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper() .in(DeviceSite::getSite, stationNames) .eq(DeviceSite::getType, TaskType.TASK_TYPE_CHECK_OUT.type), false); 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 tasks = taskService.list(new LambdaQueryWrapper().eq(Task::getTargSite, deviceSite.getSite())); if (!tasks.isEmpty()) { continue; } try { //生成盘点出库任务,站点预约 if (!stationService.update(new LambdaUpdateWrapper() .eq(BasStation::getStationName, deviceSite.getSite()) .set(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_S.type))) { throw new CoolException("站点状态更新失败!!"); } 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); // // 移库 // this.runLocToLoc(locGroupList, staTaskMemo); } private List getAreaLocs(List locGroupList, List staGroupList, String memo) { Integer startRow = Collections.min(locGroupList); Integer endRow = Collections.max(locGroupList); // STA IDLE // LambdaQueryWrapper idleWrapper = new LambdaQueryWrapper().eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type).in(BasStation::getStationName, staGroupList); // List idleList = stationService.list(idleWrapper); // if (Cools.isEmpty(idleList)) { // return new ArrayList<>(); // } // Collections.shuffle(idleList); // LOC STOCK LambdaQueryWrapper stockWrapper = new LambdaQueryWrapper().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 stockList = locService.list(stockWrapper); if (Cools.isEmpty(stockList)) { return new ArrayList<>(); } Collections.shuffle(stockList); return stockList; //生成入库工作档 // generateTask(idleList.get(0).getStationName(), stockList.get(0).getCode(), idleList.get(0).getBarcode()); } // 出库 private void runLocToSta(List locGroupList, List staGroupList, String memo) { Integer startRow = Collections.min(locGroupList); Integer endRow = Collections.max(locGroupList); // STA IDLE LambdaQueryWrapper idleWrapper = new LambdaQueryWrapper().eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type).in(BasStation::getStationName, staGroupList); List idleList = stationService.list(idleWrapper); if (Cools.isEmpty(idleList)) { return; } Collections.shuffle(idleList); // LOC STOCK LambdaQueryWrapper stockWrapper = new LambdaQueryWrapper().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 stockList = locService.list(stockWrapper); if (Cools.isEmpty(stockList)) { return; } Collections.shuffle(stockList); Loc loc = stockList.get(0); List list = locItemService.list(new LambdaQueryWrapper().eq(LocItem::getLocId, loc.getId())); LocToTaskParams param = new LocToTaskParams(); param.setType(Constants.TASK_TYPE_OUT_STOCK); param.setTarLoc(loc.getCode()); param.setItems(list); param.setSiteNo(idleList.get(0).getStationName()); param.setMemo(memo); //生成出库工作档 try { locItemService.generateTask(TaskResouceType.TASK_RESOUCE_STOCK_TYPE.val, param, getLoginUserId()); } catch (Exception e) { log.info("生成出库任务失败", e); } } // 移库 private void runLocToLoc(List locGroupList, String staTaskMemo) { Integer startRow = Collections.min(locGroupList); Integer endRow = Collections.max(locGroupList); String memo = "DEMO_LOC_" + startRow + "-" + endRow; // STOCK LambdaQueryWrapper stockWrapper = new LambdaQueryWrapper().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 stockList = locService.list(stockWrapper); if (Cools.isEmpty(stockList)) { return; } Collections.shuffle(stockList); // IDLE LambdaQueryWrapper idleWrapper = new LambdaQueryWrapper().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 idleList = locService.list(idleWrapper); if (Cools.isEmpty(idleList)) { return; } Collections.shuffle(idleList); //生成移库任务 Loc loc = stockList.get(0); List list = locItemService.list(new LambdaQueryWrapper().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); } } private void generateTask(String sourceStaNo, String locNo, String barcode) { String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_TASK_CODE, null); if (StringUtils.isBlank(ruleCode)) { throw new CoolException("编码错误:请确认编码「SYS_TASK_CODE」是否已生成!!"); } Task task = new Task(); task.setTaskCode(ruleCode) .setTaskStatus(TaskStsType.GENERATE_IN.id) .setTaskType(TaskType.TASK_TYPE_IN.type) .setResource(TaskResouceType.TASK_RESOUCE_PAKIN_TYPE.val) .setTargLoc(locNo) .setBarcode(barcode) .setOrgSite(sourceStaNo) .setCreateBy(6666L) .setUpdateBy(6666L); if (!taskService.save(task)) { throw new CoolException("任务保存失败!!"); } LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Matnr::getStatus, 1); wrapper.orderByAsc(Matnr::getUpdateTime); List list = matnrService.page(new Page<>(1, 100), wrapper).getRecords(); Collections.shuffle(list); List taskItems = new ArrayList<>(); int i = 0; for (Matnr item : list) { if (i > 5) { break; } TaskItem taskItem = new TaskItem(); BeanUtils.copyProperties(item, taskItem); taskItem.setTaskId(task.getId()) .setOrderType(OrderType.ORDER_IN.type) .setCreateBy(6666L) .setUpdateBy(6666L) .setExtendFields(item.getExtendFields()); taskItems.add(taskItem); item.setUpdateTime(new Date()); matnrService.updateById(item); i++; } taskItemService.saveBatch(taskItems); } public static List getStaPrefixes(List staGroupList) { Set rowSet = new HashSet<>(); for (String s : staGroupList) { rowSet.add(s.split("-")[0]); } List result = new ArrayList<>(rowSet); result.sort(Comparator.comparingInt(Integer::parseInt)); return result; } }