From 4a602adf27f804c8b8a3d9ab02e1166d4d707bf6 Mon Sep 17 00:00:00 2001 From: ldj_willow Date: Wed, 19 Oct 2022 16:34:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nl/wms/sch/tasks/CallEmpVehicleTask.java | 23 +- .../wms/sch/tasks/GjxCallEmpVehicleTask.java | 284 +++++++++++++++++ .../wms/sch/tasks/YqxCallEmpVehicleTask.java | 301 ++++++++++++++++++ .../src/main/java/org/nl/wms/wms.xls | Bin 229376 -> 229376 bytes 4 files changed, 602 insertions(+), 6 deletions(-) create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/GjxCallEmpVehicleTask.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/YqxCallEmpVehicleTask.java diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/CallEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/CallEmpVehicleTask.java index 286b449..b7238ef 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/CallEmpVehicleTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/CallEmpVehicleTask.java @@ -121,19 +121,25 @@ public class CallEmpVehicleTask extends AbstractAcsTask { * 1. 点对点: 起点和终点都确定,直接创建任务 * 2. 终点确定: 需要找到对应起点,在创建任务 具体找起点货位的规则在findBeginPoint()中 */ - // 终点确定:找起点 + //起点不确定 if (ObjectUtil.isEmpty(point_code1)) { + JSONObject param = new JSONObject(); - param.put("point_code2", point_code2); - param.put("vehicle_qty", qty); - JSONObject json = this.findNextPoint(param); - point_code1 = json.getString("point_code1"); + param.put("point_code2",point_code2); + param.put("vehicle_qty",qty); + + + JSONObject json = this.findBeginPoint(param); + point_code1 = json.getString("start_point_code"); vehicle_type = json.getString("vehicle_type"); } else { // 判断终点是否是空位 JSONObject jsonPoint = pointTab.query("point_code = '" + point_code1 + "' and lock_type = '00' and point_status <> '02' and is_delete = '0' and is_used = '1'").uniqueResult(0); if (ObjectUtil.isEmpty(jsonPoint)) throw new BadRequestException("起点点位不可用或不存在"); } + + + // 创建任务 JSONObject jsonTask = new JSONObject(); String task_id = IdUtil.getSnowflake(1, 1).nextId() + ""; @@ -189,6 +195,7 @@ public class CallEmpVehicleTask extends AbstractAcsTask { WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); WQLObject regionTab = WQLObject.getWQLObject("SCH_BASE_Region"); WQLObject orderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 根据终点区域判断优先的起点区域 JSONObject jsonPointEnd = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); if (ObjectUtil.isEmpty(jsonPointEnd)) throw new BadRequestException("终点点位不存在"); @@ -213,7 +220,11 @@ public class CallEmpVehicleTask extends AbstractAcsTask { String point_code1 = ""; JSONObject map = new JSONObject(); if (StrUtil.equals(jsonRegionEnd.getString("region_code"), RegionTypeEnum.GJQY.getCode())) { - //1、判断是否有到该叠盘位的堆叠任务。 + //1、判断是否有拆托盘任务。 + taskTab.query("task_type= 'gjxsqkp' "); + + //2、判断是否有到该叠盘位的堆叠任务。 + //1、判断叠盘架B是否有对应类型的空载具 diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/GjxCallEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/GjxCallEmpVehicleTask.java new file mode 100644 index 0000000..c946b2a --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/GjxCallEmpVehicleTask.java @@ -0,0 +1,284 @@ +package org.nl.wms.sch.tasks; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.common.utils.SecurityUtils; +import org.nl.modules.system.util.CodeUtil; +import org.nl.modules.wql.WQL; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.modules.wql.util.SpringContextHolder; +import org.nl.wms.pdm.service.DeviceService; +import org.nl.wms.pdm.service.dto.DeviceDto; +import org.nl.wms.sch.manage.AbstractAcsTask; +import org.nl.wms.sch.manage.TaskStatusEnum; +import org.nl.wms.sch.service.PointService; +import org.nl.wms.sch.service.dto.PointDto; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; + +@Service +@RequiredArgsConstructor +@Slf4j +/** + * 共挤线申请空盘 + */ +public class GjxCallEmpVehicleTask extends AbstractAcsTask { + private final String THIS_CLASS = GjxCallEmpVehicleTask.class.getName(); + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTaskStatus(JSONObject taskObj, String status) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + + String task_id = taskObj.getString("task_id"); + JSONObject jsonTask = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); + + if (StrUtil.equals(status, "0")) { + // 取消删除任务 + taskTab.delete("task_id = '" + task_id + "'"); + } + + if (TaskStatusEnum.EXECUTING.getCode().equals(status)) { + // 更新任务状态为执行中 + jsonTask.put("task_status", TaskStatusEnum.EXECUTING.getCode()); + jsonTask.put("update_time", DateUtil.now()); + jsonTask.put("car_no", taskObj.getString("car_no")); + taskTab.update(jsonTask); + } + + if (StrUtil.equals(status, TaskStatusEnum.FINISHED.getCode())) { + // 更改任务状态为完成 + jsonTask.put("task_status", TaskStatusEnum.FINISHED.getCode()); + jsonTask.put("update_optid", SecurityUtils.getCurrentUserId()); + jsonTask.put("update_optname", SecurityUtils.getCurrentUsername()); + jsonTask.put("update_time", DateUtil.now()); + taskTab.update(jsonTask); + + PointService point = SpringContextHolder.getBean(PointService.class); + // 校验起点是否存在 + PointDto point_code1 = point.findByCode(jsonTask.getString("point_code1")); + if (ObjectUtil.isEmpty(point_code1)) throw new BadRequestException("未找到可用点位:" + point_code1); + // 校验终点是否存在 + PointDto point_code2 = point.findByCode(jsonTask.getString("point_code2")); + if (ObjectUtil.isEmpty(point_code1)) throw new BadRequestException("未找到可用点位:" + point_code2); + + // 1.更新点位数量 2.解锁点位 + int vehicle_qty = JSONObject.parseObject(JSON.toJSONString(point_code1)).getIntValue("vehicle_qty"); + BigDecimal vehicle_qty_point = NumberUtil.sub(String.valueOf(vehicle_qty), String.valueOf(1)); + + point_code1.setVehicle_qty(vehicle_qty_point); + if (StrUtil.equals(vehicle_qty_point.toString(), "0")) { + point_code1.setPoint_status("00"); + point_code1.setVehicle_type(""); + } + point_code1.setLock_type("00"); + pointTab.update(JSONObject.parseObject(JSON.toJSONString(point_code1))); + } + } + + @Override + public JSONObject findStartPoint(JSONObject param) { + return null; + } + + @Override + public JSONObject findNextPoint(JSONObject param) { + return null; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String createTask(JSONObject form) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + + String start_point_code = form.getString("point_code1"); + String end_point_code = form.getString("point_code2"); + String qty = form.getString("qty"); + String vehicle_type = form.getString("vehicle_type"); + + // 终点不能为空 + if (ObjectUtil.isEmpty(end_point_code)) { + throw new BadRequestException("终点不能为空"); + } else { + // 判断终点是否有正在执行的任务 + JSONObject beforTaskObj = taskTab.query("is_delete='0' and point_code2='" + end_point_code + "' and task_status <>'" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(beforTaskObj)) + throw new BadRequestException("存在任务号为'" + beforTaskObj.getString("task_code") + "' 未完成!"); + } + // 创建任务 + JSONObject jsonTask = new JSONObject(); + Long task_id = IdUtil.getSnowflake(1, 1).nextId(); + jsonTask.put("task_id", task_id); + jsonTask.put("task_code", CodeUtil.getNewCode("TASK_CODE")); + jsonTask.put("handle_class", THIS_CLASS); + jsonTask.put("vehicle_type", vehicle_type); + + jsonTask.put("point_code2", end_point_code); + jsonTask.put("create_name", SecurityUtils.getCurrentUsername()); + jsonTask.put("create_id", SecurityUtils.getCurrentUserId()); + jsonTask.put("create_time", DateUtil.now()); + + //见基础分类表的任务分类 + jsonTask.put("task_type", "gjxsqkp"); + + //判断叠盘位是否有任务 + JSONObject taskObj = taskTab.query("is_delete='0' and point_code1='" + start_point_code + "' and task_status <>'" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + + if (ObjectUtil.isNotEmpty(taskObj)){ + jsonTask.put("task_status", TaskStatusEnum.SURE_END); + jsonTask.put("point_code1", ""); + }else { + // 锁定起点点位 + JSONObject jsonPoint = pointTab.query("point_code = '" + start_point_code + "'").uniqueResult(0); + jsonPoint.put("lock_type", "02"); + pointTab.update(jsonPoint); + } + + taskTab.insert(jsonTask); + + return String.valueOf(task_id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void forceFinish(String task_id) { + JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0); + this.updateTaskStatus(taskObj, TaskStatusEnum.FINISHED.getCode()); + } + + @Override + public void pullBack(String task_id) { + + } + + @Override + public void cancel(String task_id) { + + } + + @Transactional(rollbackFor = Exception.class) + public JSONObject findBeginPoint(JSONObject json) { + String point_code2 = json.getString("point_code2"); + String vehicle_qty = json.getString("vehicle_qty"); + if (ObjectUtil.isEmpty(point_code2)) throw new BadRequestException("终点不能为空"); + if (ObjectUtil.isEmpty(vehicle_qty)) throw new BadRequestException("载具数量不能为空"); + + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + WQLObject regionTab = WQLObject.getWQLObject("SCH_BASE_Region"); + WQLObject orderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + // 根据终点区域判断优先的起点区域 + JSONObject jsonPointEnd = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonPointEnd)) throw new BadRequestException("终点点位不存在"); + JSONObject jsonRegionEnd = regionTab.query("region_id ='" + jsonPointEnd.getString("region_id") + "'").uniqueResult(0); + + // 根据起点找到对应设备,根据设备查询工单表中 - 正在运行的工单中的载具类型 + String device_code = point_code2.substring(0, point_code2.indexOf("_")); + + DeviceService deviceBean = SpringContextHolder.getBean(DeviceService.class); + DeviceDto deviceDto = deviceBean.findByCode(device_code); + if (ObjectUtil.isEmpty(deviceDto)) throw new BadRequestException("此设备不存在"); + JSONObject jsonOrder = orderTab.query("device_id = '" + deviceDto.getDevice_id() + "' and order_status = '02' and is_delete = '0'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonOrder)) throw new BadRequestException("此设备未在生产中或不存在"); + + //当前设备所需要的载具类型 + String vehicle_type = jsonOrder.getString("vehicle_type"); + /* + * 空托盘出库任务: + * 1.叠盘架B区、养生A区 --> 共挤线 (优先级:1叠盘架B区 2养生A区) + * 2.叠盘架A区、养生A区 --> 油漆线 (优先级:1叠盘架A区 2养生A区) + */ + String point_code1 = ""; + JSONObject map = new JSONObject(); + if (StrUtil.equals(jsonRegionEnd.getString("region_code"), RegionTypeEnum.GJQY.getCode())) { + //1、判断是否有拆托盘任务。 + taskTab.query("task_type= 'gjxsqkp' "); + + //2、判断是否有到该叠盘位的堆叠任务。 + + + + //1、判断叠盘架B是否有对应类型的空载具 + JSONObject jsonDpjB = pointTab.query("point_status ='2' and lock_type='00' and can_vehicle_type = '" + vehicle_type + "'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonDpjB)) {//没有则去空托盘缓存区B和养生A区找 + + } + + + // 共挤线呼叫空托盘业务:查找叠盘架B区是否有满足条件的点位 + map.put("flag", "1"); + map.put("vehicle_qty", vehicle_qty); + map.put("vehicle_type", jsonOrder.getString("vehicle_type")); + map.put("region_code", RegionTypeEnum.DPJQB.getCode()); + JSONObject jsonStartPointDPB = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isNotEmpty(jsonStartPointDPB)) { + point_code1 = jsonStartPointDPB.getString("point_code"); + } else { + // 为空说明叠盘架B区没有,则去养生A区找 : 只能找数量为1的空托盘 + map.put("flag", "3"); + map.put("region_code", RegionTypeEnum.YSQA.getCode()); + JSONObject jsonStartPointYSA = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + + if (ObjectUtil.isNotEmpty(jsonStartPointYSA)) { + point_code1 = jsonStartPointYSA.getString("point_code"); + } else { + throw new BadRequestException("没有满足需求数量的点位"); + /* // 如果没有则需要从养生区A区里找到 > 1的货位 出库到叠盘架B中 + map.put("flag", "1"); + map.put("region_code", RegionTypeEnum.YSQA.getCode()); + // 起点 + JSONObject jsonStart = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isEmpty(jsonStart)) throw new BadRequestException("没有满足需求数量的点位"); + // 终点 + JSONObject jsonEnd = pointTab.query("region_id = '" + RegionTypeEnum.DPJQB.getId() + "' and point_status = '00' and lock_type = '00' and is_used = '1' and is_delete = '0'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonEnd)) throw new BadRequestException("叠盘架B货位不足"); + + JSONObject parem = new JSONObject(); + parem.put("point_code1",jsonStart.getString("point_code")); + parem.put("point_code2",jsonEnd.getString("point_code")); + parem.put("qty",jsonStart.getString("vehicle_qty")); + parem.put("vehicle_type",jsonStart.getString("vehicle_qty")); + String task_id = this.createTask(parem); + + // 生成 叠盘架 -> 共挤线的任务 返回叠盘架B的点位code + point_code1 = jsonEnd.getString("point_code");*/ + } + + } + + } else if (StrUtil.equals(jsonRegionEnd.getString("region_code"), RegionTypeEnum.YQQY.getCode())) { + // 油漆线呼叫空托盘业务:查找叠盘架A区是否有满足条件的点位 + map.put("flag", "1"); + map.put("vehicle_qty", vehicle_qty); + map.put("vehicle_type", jsonOrder.getString("vehicle_type")); + map.put("region_code", RegionTypeEnum.DPJQA.getCode()); + JSONObject jsonStartPointDPA = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isNotEmpty(jsonStartPointDPA)) { + point_code1 = jsonStartPointDPA.getString("point_code"); + } else { + // 为空说明叠盘架A区没有,则去养生A区找 + map.put("flag", "3"); + map.put("region_code", RegionTypeEnum.YSQA.getCode()); + JSONObject jsonStartPointYSA = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isEmpty(jsonStartPointYSA)) throw new BadRequestException("没有满足需求数量的点位"); + point_code1 = jsonStartPointYSA.getString("point_code"); + } + } + JSONObject resuft = new JSONObject(); + resuft.put("point_code1", point_code1); + resuft.put("vehicle_type", jsonOrder.getString("vehicle_type")); + return resuft; + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/YqxCallEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/YqxCallEmpVehicleTask.java new file mode 100644 index 0000000..9a498b7 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/YqxCallEmpVehicleTask.java @@ -0,0 +1,301 @@ +package org.nl.wms.sch.tasks; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.common.utils.SecurityUtils; +import org.nl.modules.system.util.CodeUtil; +import org.nl.modules.wql.WQL; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.modules.wql.util.SpringContextHolder; +import org.nl.wms.pdm.service.DeviceService; +import org.nl.wms.pdm.service.dto.DeviceDto; +import org.nl.wms.sch.manage.AbstractAcsTask; +import org.nl.wms.sch.manage.TaskStatusEnum; +import org.nl.wms.sch.service.PointService; +import org.nl.wms.sch.service.dto.PointDto; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; + +@Service +@RequiredArgsConstructor +@Slf4j +public class YqxCallEmpVehicleTask extends AbstractAcsTask { + private final String THIS_CLASS = YqxCallEmpVehicleTask.class.getName(); + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTaskStatus(JSONObject taskObj, String status) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + + String task_id = taskObj.getString("task_id"); + JSONObject jsonTask = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); + + if (StrUtil.equals(status, "0")) { + // 取消删除任务 + taskTab.delete("task_id = '" + task_id + "'"); + } + + if (TaskStatusEnum.EXECUTING.getCode().equals(status)) { + // 更新任务状态为执行中 + jsonTask.put("task_status", TaskStatusEnum.EXECUTING.getCode()); + jsonTask.put("update_time", DateUtil.now()); + jsonTask.put("car_no", taskObj.getString("car_no")); + taskTab.update(jsonTask); + } + + if (StrUtil.equals(status, TaskStatusEnum.FINISHED.getCode())) { + // 更改任务状态为完成 + jsonTask.put("task_status", TaskStatusEnum.FINISHED.getCode()); + jsonTask.put("update_optid", SecurityUtils.getCurrentUserId()); + jsonTask.put("update_optname", SecurityUtils.getCurrentUsername()); + jsonTask.put("update_time", DateUtil.now()); + taskTab.update(jsonTask); + + PointService point = SpringContextHolder.getBean(PointService.class); + // 校验起点是否存在 + PointDto point_code1 = point.findByCode(jsonTask.getString("point_code1")); + if (ObjectUtil.isEmpty(point_code1)) throw new BadRequestException("未找到可用点位:" + point_code1); + // 校验终点是否存在 + PointDto point_code2 = point.findByCode(jsonTask.getString("point_code2")); + if (ObjectUtil.isEmpty(point_code1)) throw new BadRequestException("未找到可用点位:" + point_code2); + + // 1.更新点位数量 2.解锁点位 + int vehicle_qty = JSONObject.parseObject(JSON.toJSONString(point_code1)).getIntValue("vehicle_qty"); + BigDecimal vehicle_qty_point = NumberUtil.sub(String.valueOf(vehicle_qty), String.valueOf(1)); + + point_code1.setVehicle_qty(vehicle_qty_point); + if (StrUtil.equals(vehicle_qty_point.toString(), "0")) { + point_code1.setPoint_status("00"); + point_code1.setVehicle_type(""); + } + point_code1.setLock_type("00"); + pointTab.update(JSONObject.parseObject(JSON.toJSONString(point_code1))); + } + } + + @Override + public JSONObject findStartPoint(JSONObject param) { + return null; + } + + @Override + public JSONObject findNextPoint(JSONObject param) { + return null; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String createTask(JSONObject form) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + + String point_code1 = form.getString("point_code1"); + String point_code2 = form.getString("point_code2"); + String qty = form.getString("qty"); + String vehicle_type = form.getString("vehicle_type"); + + // 出库终点不能为空 + if (ObjectUtil.isEmpty(point_code2)) { + throw new BadRequestException("终点不能为空"); + } else { + // 判断终点是否有正在执行的任务 + JSONObject beforTaskObj = taskTab.query("is_delete='0' and point_code2='" + point_code2 + "' and task_status <>'" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(beforTaskObj)) + throw new BadRequestException("存在任务号为'" + beforTaskObj.getString("task_code") + "' 未完成!"); + } + // 载具数量不能为空 + if (ObjectUtil.isEmpty(qty)) throw new BadRequestException("载具数量不能为空"); + + /* + * 1. 点对点: 起点和终点都确定,直接创建任务 + * 2. 终点确定: 需要找到对应起点,在创建任务 具体找起点货位的规则在findBeginPoint()中 + */ + //起点不确定 + if (ObjectUtil.isEmpty(point_code1)) { + + JSONObject param = new JSONObject(); + param.put("point_code2",point_code2); + param.put("vehicle_qty",qty); + + + JSONObject json = this.findBeginPoint(param); + point_code1 = json.getString("start_point_code"); + vehicle_type = json.getString("vehicle_type"); + } else { + // 判断终点是否是空位 + JSONObject jsonPoint = pointTab.query("point_code = '" + point_code1 + "' and lock_type = '00' and point_status <> '02' and is_delete = '0' and is_used = '1'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonPoint)) throw new BadRequestException("起点点位不可用或不存在"); + } + + + + // 创建任务 + JSONObject jsonTask = new JSONObject(); + String task_id = IdUtil.getSnowflake(1, 1).nextId() + ""; + + jsonTask.put("task_id", task_id); + jsonTask.put("taskdtl_id", task_id); + jsonTask.put("task_code", CodeUtil.getNewCode("TASK_CODE")); + jsonTask.put("task_type", "04"); + jsonTask.put("taskdtl_type", "04"); + jsonTask.put("task_status", "01"); + jsonTask.put("point_code1", point_code1); + jsonTask.put("point_code2", point_code2); + jsonTask.put("handle_class", THIS_CLASS); + jsonTask.put("vehicle_type", vehicle_type); + jsonTask.put("create_name", SecurityUtils.getCurrentUsername()); + jsonTask.put("create_id", SecurityUtils.getCurrentUserId()); + jsonTask.put("create_time", DateUtil.now()); + jsonTask.put("acs_task_type", "1"); + taskTab.insert(jsonTask); + + // 锁定起点点位 + JSONObject jsonPoint = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + jsonPoint.put("lock_type", "02"); + pointTab.update(jsonPoint); + + return task_id; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void forceFinish(String task_id) { + JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0); + this.updateTaskStatus(taskObj, TaskStatusEnum.FINISHED.getCode()); + } + + @Override + public void pullBack(String task_id) { + + } + + @Override + public void cancel(String task_id) { + + } + + @Transactional(rollbackFor = Exception.class) + public JSONObject findBeginPoint(JSONObject json) { + String point_code2 = json.getString("point_code2"); + String vehicle_qty = json.getString("vehicle_qty"); + if (ObjectUtil.isEmpty(point_code2)) throw new BadRequestException("终点不能为空"); + if (ObjectUtil.isEmpty(vehicle_qty)) throw new BadRequestException("载具数量不能为空"); + + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + WQLObject regionTab = WQLObject.getWQLObject("SCH_BASE_Region"); + WQLObject orderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + // 根据终点区域判断优先的起点区域 + JSONObject jsonPointEnd = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonPointEnd)) throw new BadRequestException("终点点位不存在"); + JSONObject jsonRegionEnd = regionTab.query("region_id ='" + jsonPointEnd.getString("region_id") + "'").uniqueResult(0); + + // 根据起点找到对应设备,根据设备查询工单表中 - 正在运行的工单中的载具类型 + String device_code = point_code2.substring(0, point_code2.indexOf("_")); + + DeviceService deviceBean = SpringContextHolder.getBean(DeviceService.class); + DeviceDto deviceDto = deviceBean.findByCode(device_code); + if (ObjectUtil.isEmpty(deviceDto)) throw new BadRequestException("此设备不存在"); + JSONObject jsonOrder = orderTab.query("device_id = '" + deviceDto.getDevice_id() + "' and order_status = '02' and is_delete = '0'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonOrder)) throw new BadRequestException("此设备未在生产中或不存在"); + + //当前设备所需要的载具类型 + String vehicle_type = jsonOrder.getString("vehicle_type"); + /* + * 空托盘出库任务: + * 1.叠盘架B区、养生A区 --> 共挤线 (优先级:1叠盘架B区 2养生A区) + * 2.叠盘架A区、养生A区 --> 油漆线 (优先级:1叠盘架A区 2养生A区) + */ + String point_code1 = ""; + JSONObject map = new JSONObject(); + if (StrUtil.equals(jsonRegionEnd.getString("region_code"), RegionTypeEnum.GJQY.getCode())) { + //1、判断是否有拆托盘任务。 + taskTab.query("task_type= 'gjxsqkp' "); + + //2、判断是否有到该叠盘位的堆叠任务。 + + + + //1、判断叠盘架B是否有对应类型的空载具 + JSONObject jsonDpjB = pointTab.query("point_status ='2' and lock_type='00' and can_vehicle_type = '" + vehicle_type + "'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonDpjB)) {//没有则去空托盘缓存区B和养生A区找 + + } + + + // 共挤线呼叫空托盘业务:查找叠盘架B区是否有满足条件的点位 + map.put("flag", "1"); + map.put("vehicle_qty", vehicle_qty); + map.put("vehicle_type", jsonOrder.getString("vehicle_type")); + map.put("region_code", RegionTypeEnum.DPJQB.getCode()); + JSONObject jsonStartPointDPB = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isNotEmpty(jsonStartPointDPB)) { + point_code1 = jsonStartPointDPB.getString("point_code"); + } else { + // 为空说明叠盘架B区没有,则去养生A区找 : 只能找数量为1的空托盘 + map.put("flag", "3"); + map.put("region_code", RegionTypeEnum.YSQA.getCode()); + JSONObject jsonStartPointYSA = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + + if (ObjectUtil.isNotEmpty(jsonStartPointYSA)) { + point_code1 = jsonStartPointYSA.getString("point_code"); + } else { + throw new BadRequestException("没有满足需求数量的点位"); + /* // 如果没有则需要从养生区A区里找到 > 1的货位 出库到叠盘架B中 + map.put("flag", "1"); + map.put("region_code", RegionTypeEnum.YSQA.getCode()); + // 起点 + JSONObject jsonStart = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isEmpty(jsonStart)) throw new BadRequestException("没有满足需求数量的点位"); + // 终点 + JSONObject jsonEnd = pointTab.query("region_id = '" + RegionTypeEnum.DPJQB.getId() + "' and point_status = '00' and lock_type = '00' and is_used = '1' and is_delete = '0'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonEnd)) throw new BadRequestException("叠盘架B货位不足"); + + JSONObject parem = new JSONObject(); + parem.put("point_code1",jsonStart.getString("point_code")); + parem.put("point_code2",jsonEnd.getString("point_code")); + parem.put("qty",jsonStart.getString("vehicle_qty")); + parem.put("vehicle_type",jsonStart.getString("vehicle_qty")); + String task_id = this.createTask(parem); + + // 生成 叠盘架 -> 共挤线的任务 返回叠盘架B的点位code + point_code1 = jsonEnd.getString("point_code");*/ + } + + } + + } else if (StrUtil.equals(jsonRegionEnd.getString("region_code"), RegionTypeEnum.YQQY.getCode())) { + // 油漆线呼叫空托盘业务:查找叠盘架A区是否有满足条件的点位 + map.put("flag", "1"); + map.put("vehicle_qty", vehicle_qty); + map.put("vehicle_type", jsonOrder.getString("vehicle_type")); + map.put("region_code", RegionTypeEnum.DPJQA.getCode()); + JSONObject jsonStartPointDPA = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isNotEmpty(jsonStartPointDPA)) { + point_code1 = jsonStartPointDPA.getString("point_code"); + } else { + // 为空说明叠盘架A区没有,则去养生A区找 + map.put("flag", "3"); + map.put("region_code", RegionTypeEnum.YSQA.getCode()); + JSONObject jsonStartPointYSA = WQL.getWO("ST_VEHICLE_OUT_02").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isEmpty(jsonStartPointYSA)) throw new BadRequestException("没有满足需求数量的点位"); + point_code1 = jsonStartPointYSA.getString("point_code"); + } + } + JSONObject resuft = new JSONObject(); + resuft.put("point_code1", point_code1); + resuft.put("vehicle_type", jsonOrder.getString("vehicle_type")); + return resuft; + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/wms.xls b/lms/nladmin-system/src/main/java/org/nl/wms/wms.xls index 7e21f29e6cf51aaeb9450cb485f4347f2c58843c..94552dafcd2185928aebcc3e7fe9ee4bc7b235e1 100644 GIT binary patch delta 15200 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 KFilfn_WuBNDlY8+