| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 指定物料自动化定时任务:可配置物料编码后, |
| | | * 指定物料/空板自动化定时任务:可配置后 |
| | | * 1)有库存时自动生成全版出库单; |
| | | * 2)该物料出库单自动下发任务; |
| | | * 3)RCS 入库通知时(可选)自动组托,数量可配置。 |
| | | * 3)RCS 入库通知时(可选)自动组托,数量可配置; |
| | | * 4)空板(D)库位定时自动生成空板出库任务并下发 RCS(AUTO_EMPTY_OUT_ENABLED)。 |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | |
| | | } |
| | | |
| | | /** |
| | | * 定时任务:空板库存自动出库(每 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)); |