| | |
| | | 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.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 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.*; |
| | | |
| | |
| | | |
| | | @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/35 * * * * ?") |
| | | public void autoCheckComplete() { |
| | | Boolean autoRunArea = configService.getVal("AUTO_RUN_CHECK_ORDERS", Boolean.class); |
| | | if (!autoRunArea) { |
| | | return; |
| | | } |
| | | //获取任务列表中,为盘点出库的任务 |
| | | 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() >= 5) { |
| | | return; |
| | | } |
| | | if (!tasks.isEmpty()) { |
| | | tasks.forEach(task -> { |
| | | if (task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) { |
| | | if (task.getTaskStatus().equals(TaskStsType.COMPLETE_IN.id)) { |
| | | if (!stationService.update(new LambdaUpdateWrapper<BasStation>() |
| | | .eq(BasStation::getStationName, task.getOrgSite()) |
| | | .set(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type))) { |
| | | throw new CoolException("站点状态修改失败!!"); |
| | | } |
| | | } |
| | | } else { |
| | | //创建出库任务状态 |
| | | // if (task.getTaskStatus().equals(TaskStsType.WCS_EXECUTE_OUT.id)) { |
| | | // task.setTaskStatus(TaskStsType.COMPLETE_OUT.id); |
| | | // if (!taskService.updateById(task)) { |
| | | // throw new CoolException("盘点出库任务完成失败!!"); |
| | | // } |
| | | // //出库已完成,等待盘点中 |
| | | // } else |
| | | |
| | | if (task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)) { |
| | | if (!stationService.update(new LambdaUpdateWrapper<BasStation>() |
| | | .eq(BasStation::getStationName, task.getOrgSite()) |
| | | .set(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_F.type))) { |
| | | throw new CoolException("站点状态修改失败!!"); |
| | | } |
| | | try { |
| | | taskService.pickOrCheckTask(task.getId(), Constants.TASK_TYPE_OUT_CHECK); |
| | | |
| | | if (!stationService.update(new LambdaUpdateWrapper<BasStation>() |
| | | .eq(BasStation::getStationName, task.getOrgSite()) |
| | | .set(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_R.type))) { |
| | | throw new CoolException("站点状态修改失败!!"); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new CoolException(e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @date 2025/9/1 |
| | | * @description: 自动完成盘点功能 |
| | | * @version 1.0 |
| | | */ |
| | | @Scheduled(cron = "0/25 * * * * ?") |
| | | public void genRun() { |
| | | Boolean flagAuto = configService.getVal("AUTO_RUN_CHECK_ORDERS", Boolean.class); |
| | | if (!flagAuto) { |
| | | return; |
| | | } |
| | | //获取任务列表中,为盘点出库的任务 |
| | | 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() >= 6) { |
| | | return; |
| | | } |
| | | String autoRunArea = configService.getVal("AUTO_RUN_AREA", String.class); |
| | | if (Cools.isEmpty(autoRunArea)) { |
| | | return; |
| | |
| | | break; |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | 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() > 30) { |
| | | if (!Cools.isEmpty(list) && list.size() >= 1) { |
| | | return; |
| | | } |
| | | // 入库 应该根据工作档回去 |
| | | this.runStaToLoc(locGroupList, staGroupList, staTaskMemo); |
| | | // 出库,需要校验工作档是否存在,存在就说明站点处于忙碌状态 |
| | | this.runLocToSta(locGroupList, staGroupList, staTaskMemo); |
| | | |
| | | // 移库 |
| | | this.runLocToLoc(locGroupList, staTaskMemo); |
| | | 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::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)); |
| | | if (Cools.isEmpty(stations)) { |
| | | throw new CoolException("无可用站点!!"); |
| | | } |
| | | DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>() |
| | | .in(DeviceSite::getSite, stations) |
| | | .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<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTargSite, deviceSite.getSite())); |
| | | if (!tasks.isEmpty()) { |
| | | continue; |
| | | } |
| | | try { |
| | | //生成盘点出库任务,站点预约 |
| | | if (!stationService.update(new LambdaUpdateWrapper<BasStation>() |
| | | .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 void runStaToLoc(List<Integer> locGroupList, List<String> staGroupList, String memo) { |
| | | private List<Loc> getAreaLocs(List<Integer> locGroupList, List<String> staGroupList, String memo) { |
| | | Integer startRow = Collections.min(locGroupList); |
| | | Integer endRow = Collections.max(locGroupList); |
| | | |
| | | |
| | | // STA IDLE |
| | | LambdaQueryWrapper<BasStation> idleWrapper = new LambdaQueryWrapper<BasStation>().eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_F.type).in(BasStation::getStationName, staGroupList); |
| | | List<BasStation> idleList = stationService.list(idleWrapper); |
| | | if (Cools.isEmpty(idleList)) { |
| | | return; |
| | | } |
| | | Collections.shuffle(idleList); |
| | | // LambdaQueryWrapper<BasStation> idleWrapper = new LambdaQueryWrapper<BasStation>().eq(BasStation::getUseStatus, LocStsType.LOC_STS_TYPE_O.type).in(BasStation::getStationName, staGroupList); |
| | | // List<BasStation> idleList = stationService.list(idleWrapper); |
| | | // if (Cools.isEmpty(idleList)) { |
| | | // return new ArrayList<>(); |
| | | // } |
| | | // Collections.shuffle(idleList); |
| | | |
| | | // LOC STOCK |
| | | LambdaQueryWrapper<Loc> stockWrapper = new LambdaQueryWrapper<Loc>().eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type); |
| | | LambdaQueryWrapper<Loc> stockWrapper = new LambdaQueryWrapper<Loc>().eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type); |
| | | if (null != startRow) { |
| | | stockWrapper.ge(Loc::getRow, startRow); |
| | | } |
| | |
| | | } |
| | | List<Loc> stockList = locService.list(stockWrapper); |
| | | if (Cools.isEmpty(stockList)) { |
| | | return; |
| | | return new ArrayList<>(); |
| | | } |
| | | Collections.shuffle(stockList); |
| | | |
| | | return stockList; |
| | | //生成入库工作档 |
| | | generateTask(idleList.get(0).getStationName(), stockList.get(0).getCode(), idleList.get(0).getBarcode()); |
| | | // generateTask(idleList.get(0).getStationName(), stockList.get(0).getCode(), idleList.get(0).getBarcode()); |
| | | } |
| | | |
| | | |