From f89e0ae81951c744ff65b4c1eae9a4fce53e7c61 Mon Sep 17 00:00:00 2001 From: ldj_willow Date: Fri, 28 Oct 2022 11:13:14 +0800 Subject: [PATCH] init project --- .../wms/ext/acs/rest/AcsToWmsController.java | 4 +- .../acs/service/impl/AcsToWmsServiceImpl.java | 154 ++--- .../service/impl/CallMaterialServiceImpl.java | 10 +- .../callmaterial/wql/PDA_CALLMATERIAL_01.wql | 8 +- .../service/impl/CallVehicleServiceImpl.java | 15 +- .../callvehicle/wql/PDA_CALLVEHICLE_01.wql | 8 +- .../rest/EmptyAndQtyController.java | 32 -- .../service/EmptyAndQtyService.java | 13 - .../service/impl/EmptyAndQtyServiceImpl.java | 51 -- .../service/impl/SendMaterialServiceImpl.java | 15 +- .../sendmaterial/wql/PDA_SENDMATERIAL_01.wql | 8 +- .../sendvehicle/wql/PDA_SENDVEHICLE_01.wql | 11 +- .../nl/wms/pdm/service/dto/WorkorderDto.java | 3 + .../service/impl/WorkorderServiceImpl.java | 7 +- .../org/nl/wms/pdm/wql/MPS_PRODUCEDURE001.wql | 4 - .../java/org/nl/wms/sch/PointFindUtil.java | 93 --- .../main/java/org/nl/wms/sch/SchTaskDto.java | 71 ++- .../nl/wms/sch/manage/AbstractAcsTask.java | 4 +- .../org/nl/wms/sch/rest/PointController.java | 8 + .../org/nl/wms/sch/rest/TaskController.java | 15 - .../org/nl/wms/sch/service/PointService.java | 6 + .../org/nl/wms/sch/service/TaskService.java | 27 +- .../org/nl/wms/sch/service/dto/PointDto.java | 5 +- .../sch/service/impl/PointServiceImpl.java | 26 + .../wms/sch/service/impl/TaskServiceImpl.java | 41 +- .../org/nl/wms/sch/tasks/TaskTypeEnum.java | 33 -- .../tasks/callEmpty/CallEmpVehicleTask.java | 301 ---------- .../callEmpty/GjxCallEmpVehicleTask.java | 442 +++++++++++---- .../callEmpty/YqxCallEmpVehicleTask.java | 536 +++++++++++------- .../wql/QSCH_GjxCallEmpVehicleTask.wql | 60 ++ .../wql/QSCH_YqxCallEmpVehicleTask.wql | 60 ++ .../tasks/callMaterial/CallMaterialTask.java | 277 --------- .../callMaterial/YqxCallMaterialTask.java | 258 +++++++++ .../wql/QSCH_yqxCallMAterial_01.wql | 71 +++ .../org/nl/wms/sch/tasks/cpOut/CpOutTask.java | 235 ++++++++ .../wms/sch/tasks/cpOut/wql/QSCH_cpOut_01.wql | 59 ++ .../tasks/sendEmpty/HtSendEmpVehicleTask.java | 34 +- .../tasks/sendEmpty/SendEmpVehicleTask.java | 279 --------- .../sendEmpty/YqxSendEmpVehicleTask.java | 354 +++++++++--- .../sendMaterial/GjxSendMaterialTask.java | 384 +++++++++++++ ...Material.java => HkxSendMaterialTask.java} | 168 +++--- .../sendMaterial/YqxSendMaterialTask.java | 252 ++++---- .../wql/QSCH_gjxSendMaterial_01.wql | 34 +- .../wql/QSCH_hkxSendMaterial_01.wql | 69 +++ .../wql/QSCH_yqxSendMaterial_01.wql | 62 ++ .../org/nl/wms/sch/wql/ST_VEHICLE_OUT_01.wql | 113 ---- .../src/main/java/org/nl/wms/sch/wql/sch.xls | Bin 0 -> 179712 bytes .../wms/st/bill/rest/RegionIoController.java | 10 + .../wms/st/bill/service/RegionIoService.java | 5 + .../service/impl/RegionIoServiceImpl.java | 27 + .../nl/wms/st/bill/wql/ST_IVT_REGIONIO.wql | 2 +- .../structivt/rest/StructivtController.java | 9 + .../structivt/service/StructivtService.java | 7 + .../service/impl/StructivtServiceImpl.java | 49 +- .../wms/st/structivt/wql/ST_IVT_STRUCTIVT.wql | 41 +- .../src/main/java/org/nl/wms/wms.xls | Bin 285184 -> 291328 bytes .../main/resources/config/application-dev.yml | 4 +- .../src/main/resources/logback-spring.xml | 89 ++- lms/nladmin-ui/src/api/wms/sch/point.js | 10 +- .../src/views/wms/pdm/workerorder/index.vue | 50 +- .../src/views/wms/sch/point/index.vue | 103 +++- .../src/views/wms/sch/task/index.vue | 46 +- .../src/views/wms/st/cppoint/cppInRegion.vue | 8 +- .../src/views/wms/st/cppoint/cppInventory.vue | 71 +-- .../src/views/wms/st/cppoint/cppOutRegion.vue | 34 +- lms/nladmin-ui/src/views/wms/st/regionio.js | 10 +- lms/nladmin-ui/src/views/wms/st/structivt.js | 10 +- .../src/views/wms/st/ysa/inventory.vue | 38 +- .../src/views/wms/st/ysa/ysqInRegion.vue | 8 +- 69 files changed, 3011 insertions(+), 2340 deletions(-) delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/rest/EmptyAndQtyController.java delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/service/EmptyAndQtyService.java delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/service/impl/EmptyAndQtyServiceImpl.java delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/PointFindUtil.java delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/TaskTypeEnum.java delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/CallEmpVehicleTask.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/wql/QSCH_GjxCallEmpVehicleTask.wql create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/wql/QSCH_YqxCallEmpVehicleTask.wql delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/CallMaterialTask.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/YqxCallMaterialTask.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/wql/QSCH_yqxCallMAterial_01.wql create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/cpOut/CpOutTask.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/cpOut/wql/QSCH_cpOut_01.wql delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/SendEmpVehicleTask.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/GjxSendMaterialTask.java rename lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/{GjxSendMaterial.java => HkxSendMaterialTask.java} (62%) create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_hkxSendMaterial_01.wql create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_yqxSendMaterial_01.wql delete mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/wql/ST_VEHICLE_OUT_01.wql create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/sch/wql/sch.xls diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/ext/acs/rest/AcsToWmsController.java b/lms/nladmin-system/src/main/java/org/nl/wms/ext/acs/rest/AcsToWmsController.java index 301c847..0fe289f 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/ext/acs/rest/AcsToWmsController.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/ext/acs/rest/AcsToWmsController.java @@ -17,8 +17,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.Map; - /** * @author ludj * @date 2021-07-21 @@ -57,7 +55,7 @@ public class AcsToWmsController { @Log("二次申请任务") @ApiOperation("二次申请任务") @SaCheckPermission("menu:list") - public ResponseEntity towApply(@RequestBody String task_id) { + public ResponseEntity againApply(@RequestBody String task_id) { return new ResponseEntity<>(acsToWmsService.againApply(task_id), HttpStatus.OK); } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/ext/acs/service/impl/AcsToWmsServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/ext/acs/service/impl/AcsToWmsServiceImpl.java index cfb62b7..cfff4c4 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/ext/acs/service/impl/AcsToWmsServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/ext/acs/service/impl/AcsToWmsServiceImpl.java @@ -1,7 +1,6 @@ package org.nl.wms.ext.acs.service.impl; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; @@ -9,26 +8,20 @@ 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.core.bean.WQLObject; import org.nl.modules.wql.util.SpringContextHolder; import org.nl.wms.ext.acs.service.AcsToWmsService; import org.nl.wms.log.LokiLog; import org.nl.wms.log.LokiLogType; -import org.nl.wms.pdm.service.DeviceService; -import org.nl.wms.pdm.service.dto.DeviceDto; import org.nl.wms.sch.manage.TaskStatusEnum; -import org.nl.wms.sch.service.PointService; import org.nl.wms.sch.service.TaskService; -import org.nl.wms.sch.service.dto.TaskDto; -import org.nl.wms.sch.tasks.PointToPointTask; -import org.nl.wms.sch.tasks.callEmpty.CallEmpVehicleTask; import org.nl.wms.sch.tasks.callEmpty.GjxCallEmpVehicleTask; -import org.nl.wms.sch.tasks.callMaterial.CallMaterialTask; +import org.nl.wms.sch.tasks.callEmpty.YqxCallEmpVehicleTask; +import org.nl.wms.sch.tasks.callMaterial.YqxCallMaterialTask; import org.nl.wms.sch.tasks.sendEmpty.HtSendEmpVehicleTask; import org.nl.wms.sch.tasks.sendEmpty.YqxSendEmpVehicleTask; -import org.nl.wms.sch.tasks.sendMaterial.GjxSendMaterial; +import org.nl.wms.sch.tasks.sendMaterial.GjxSendMaterialTask; +import org.nl.wms.sch.tasks.sendMaterial.HkxSendMaterialTask; import org.nl.wms.sch.tasks.sendMaterial.YqxSendMaterialTask; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; @@ -61,8 +54,9 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { for (int i = 0; i < array.size(); i++) { JSONObject row = array.getJSONObject(i); String task_id = row.getString("task_id"); - TaskDto taskDto = taskService.findById(task_id); - String processing_class = taskDto.getHandle_class(); + JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0); + // 任务处理类 + String processing_class = taskObj.getString("handle_class"); //1:执行中,2:完成 ,3:acs取消 String acs_task_status = row.getString("task_status"); String message = ""; @@ -107,7 +101,6 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { json.put("task_id", task_id); json.put("message", message); errArr.add(json); - } } @@ -122,20 +115,24 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { @LokiLog(type = LokiLogType.ACS_TO_LMS) @Override public String againApply(String task_id) { - log.info("输入参数:"+task_id); + log.info("输入参数:" + task_id); WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); - JSONObject jsonTask = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); + JSONObject jsonTask = taskTab.query("task_id = '" + task_id + "' and task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonTask)) throw new BadRequestException("任务已删除或已完成!"); String point_code = ""; + String message = ""; try { Class clz = Class.forName(jsonTask.getString("handle_class")); Object obj = clz.newInstance(); - Method m = obj.getClass().getDeclaredMethod("againApply",String.class); - point_code = (String) m.invoke(obj,task_id); + Method m = obj.getClass().getDeclaredMethod("againApply", String.class); + point_code = (String) m.invoke(obj, task_id); } catch (Exception e) { - + e.printStackTrace(); + message = e.getMessage(); + log.info("二次申请失败:{}", message); } - log.info("输出参数:"+point_code); + log.info("输出参数:" + point_code); return point_code; } @@ -174,20 +171,16 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { public JSONObject apply(JSONObject whereJson) { String type = whereJson.getString("type"); String point_code = whereJson.getString("point_code"); - String vehicle_num = whereJson.getString("vehicle_num"); String vehicle_type = whereJson.getString("vehicle_type"); String vehicle_code = whereJson.getString("vehicle_code"); - String qty = whereJson.getString("qty"); + //载具数量 + String vehicle_num = whereJson.getString("vehicle_num"); + //物料数量 + String material_num = whereJson.getString("material_num"); if (ObjectUtil.isEmpty(type)) throw new BadRequestException("类型不能为空"); if (ObjectUtil.isEmpty(point_code)) throw new BadRequestException("点位不能为空"); - WQLObject taskTab = WQLObject.getWQLObject("sch_base_task");// 任务表 - WQLObject regionTab = WQLObject.getWQLObject("ST_IVT_regionIO"); // 区域出入库表 - WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); // 点位表 -// WQLObject veQtyTab = WQLObject.getWQLObject("PDM_BI_vehicleQty"); // 托盘对应数量表 - - /* * 根据type判断是什么业务类型: * 1.共挤线申请空盘 @@ -196,7 +189,7 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { * 4.油漆线申请物料 * 5.油漆线空盘入库 * 6.一楼空盘入库 (有载具号) - * 7.油漆线->输送线 + * 7.油漆线->输送线(油漆线满料) * 8.豪凯自动线下料入库 */ if (StrUtil.equals(type, "1")) { @@ -206,21 +199,23 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { JSONObject param = new JSONObject(); param.put("point_code2", point_code); param.put("vehicle_type", vehicle_type); - param.put("qty", vehicle_num); + param.put("qty", material_num); // 创建任务 GjxCallEmpVehicleTask taskBean = SpringContextHolder.getBean(GjxCallEmpVehicleTask.class); - taskBean.createTask(param); + taskBean.createTask(param); } else if (StrUtil.equals(type, "2")) { // 2.共挤线满托入库: 调用物料入库处理类创建任务 - if (ObjectUtil.isEmpty(qty) || (StrUtil.equals(qty, "0"))) + if (ObjectUtil.isEmpty(material_num) || (StrUtil.equals(material_num, "0"))) throw new BadRequestException("物料数量不能为空或者为0"); JSONObject param = new JSONObject(); param.put("point_code1", point_code); // 满料位 - param.put("qty", qty); // 满料位 + param.put("qty", material_num); // 满料位 + param.put("vehicle_type", vehicle_type); + param.put("vehicle_code", vehicle_code); - GjxSendMaterial taskBean = SpringContextHolder.getBean(GjxSendMaterial.class); + GjxSendMaterialTask taskBean = SpringContextHolder.getBean(GjxSendMaterialTask.class); String task_id = taskBean.createTask(param); // 创建任务 } else if (StrUtil.equals(type, "3")) { // 3.油漆线申请空盘: 调用空托盘出库处理类创建任务 @@ -230,45 +225,33 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { param.put("point_code2", point_code); param.put("qty", vehicle_num); // 创建任务 - CallEmpVehicleTask taskBean = SpringContextHolder.getBean(CallEmpVehicleTask.class); + YqxCallEmpVehicleTask taskBean = SpringContextHolder.getBean(YqxCallEmpVehicleTask.class); String task_id = taskBean.createTask(param); } else if (StrUtil.equals(type, "4")) { // 4.油漆线申请物料: 调用物料出库库处理类创建任务 JSONObject param = new JSONObject(); - param.put("point_code2", point_code); - param.put("io_type", "1"); - // 插入区域出库单 - JSONObject json = this.outCreateRegion(param); - - param.put("vehicle_type", json.getString("vehicle_type")); - param.put("material_id", json.getString("material_id")); - param.put("create_mode", json.getString("create_mode")); - param.put("iostorinv_id", json.getString("iostorinv_id")); + param.put("point_code2", point_code); // 叫料点 + param.put("io_type", "2"); + param.put("vehicle_type", vehicle_type); + param.put("vehicle_code", vehicle_code); + param.put("material_num", material_num); // 创建任务 - CallMaterialTask taskBean = SpringContextHolder.getBean(CallMaterialTask.class); + YqxCallMaterialTask taskBean = SpringContextHolder.getBean(YqxCallMaterialTask.class); String task_id = taskBean.createTask(param); - JSONObject jsonTask = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); - // 回显出库单:起始点位、起始区域、任务id - JSONObject jsonRegion = regionTab.query("iostorinv_id = '" + json.getString("iostorinv_id") + "'").uniqueResult(0); - jsonRegion.put("point_code1", jsonTask.getString("point_code1")); - Long start_region_id = SpringContextHolder.getBean(PointService.class).findByCode(jsonTask.getString("point_code1")).getRegion_id(); - jsonRegion.put("start_region_id", String.valueOf(start_region_id)); - jsonRegion.put("task_id", Long.valueOf(task_id)); - regionTab.update(jsonRegion); - } else if (StrUtil.equals(type, "5")) { // 5.油漆线空盘入库: 调用空托盘入库处理类创建任务 + if (ObjectUtil.isEmpty(point_code)) throw new BadRequestException("点位不能为空"); if (ObjectUtil.isEmpty(vehicle_num)) throw new BadRequestException("数量不能为空"); if (ObjectUtil.isEmpty(vehicle_type)) throw new BadRequestException("载具类型不能为空"); JSONObject param = new JSONObject(); param.put("point_code1", point_code); - param.put("vehicle_num", vehicle_num); + param.put("qty", vehicle_num); param.put("vehicle_type", vehicle_type); // 创建任务 YqxSendEmpVehicleTask taskBean = SpringContextHolder.getBean(YqxSendEmpVehicleTask.class); - taskBean.createTask(param); + taskBean.createTask(param); } else if (StrUtil.equals(type, "6")) { @@ -278,10 +261,10 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { // 查询载具号对应的数量 JSONObject jsonVeQty = new JSONObject(); - if (ObjectUtil.isEmpty(qty)) { + if (ObjectUtil.isEmpty(vehicle_num)) { if (ObjectUtil.isEmpty(jsonVeQty)) throw new BadRequestException("请先手持扫码"); } else { - jsonVeQty.put("qty", qty); + jsonVeQty.put("qty", vehicle_num); } param.put("qty", jsonVeQty.getString("qty")); @@ -295,63 +278,20 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { } else if (StrUtil.equals(type, "7")) { JSONObject param = new JSONObject(); param.put("point_code1", point_code); + param.put("qty", material_num); // 1.生成起点确定的任务 - SpringContextHolder.getBean(PointToPointTask.class).createTask(param); + SpringContextHolder.getBean(YqxSendMaterialTask.class).createTask(param); } else if (StrUtil.equals(type, "8")) { // 8.豪凯自动线下料入库 JSONObject param = new JSONObject(); param.put("point_code1", point_code); - YqxSendMaterialTask taskBean = SpringContextHolder.getBean(YqxSendMaterialTask.class); + param.put("vehicle_code", vehicle_code); + param.put("vehicle_type", vehicle_type); + param.put("qty", material_num); + HkxSendMaterialTask taskBean = SpringContextHolder.getBean(HkxSendMaterialTask.class); String task_id = taskBean.createTask(param); } return null; } - - @Transactional(rollbackFor = Exception.class) - public JSONObject outCreateRegion(JSONObject json) { - String point_code2 = json.getString("point_code2"); - String io_type = json.getString("io_type"); - - WQLObject regionTab = WQLObject.getWQLObject("ST_IVT_regionIO"); - WQLObject orderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); - WQLObject materTab = WQLObject.getWQLObject("md_me_materialbase"); - - JSONObject jsonRegion = new JSONObject(); - jsonRegion.put("iostorinv_id", IdUtil.getSnowflake(1, 1).nextId()); - jsonRegion.put("bill_code", CodeUtil.getNewCode("OUT_STORE_CODE")); - jsonRegion.put("io_type", io_type); - jsonRegion.put("bill_status", "20"); - // 根据起点点位找到起点设备,根据设备找到对应工单, 根据工单找到对应物料及托盘类型 - 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("此设备未在生产中或不存在"); - - jsonRegion.put("material_id", jsonOrder.getString("material_id")); - jsonRegion.put("qty", "100"); // 暂时先按照100 - JSONObject jsonMater = materTab.query("material_id ='" + jsonOrder.getString("material_id") + "'").uniqueResult(0); - jsonRegion.put("qty_unit_id", jsonMater.getString("base_unit_id")); - - jsonRegion.put("end_point_code", point_code2); - Long end_region_id = SpringContextHolder.getBean(PointService.class).findByCode(point_code2).getRegion_id(); - jsonRegion.put("end_region_id", String.valueOf(end_region_id)); - - jsonRegion.put("create_mode", "02"); - jsonRegion.put("create_id", SecurityUtils.getCurrentUserId()); - jsonRegion.put("create_name", SecurityUtils.getCurrentNickName()); - jsonRegion.put("create_time", DateUtil.now()); - regionTab.insert(jsonRegion); - - // 需回显起始点位、起始区域、任务id - JSONObject resuft = new JSONObject(); - resuft.put("iostorinv_id", jsonRegion.getString("iostorinv_id")); - resuft.put("vehicle_type", jsonOrder.getString("vehicle_type")); - resuft.put("create_mode", jsonRegion.getString("create_mode")); - resuft.put("material_id", jsonOrder.getString("material_id")); - return resuft; - } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/callmaterial/service/impl/CallMaterialServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/pda/callmaterial/service/impl/CallMaterialServiceImpl.java index 7b76de5..7c1ac15 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/callmaterial/service/impl/CallMaterialServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pda/callmaterial/service/impl/CallMaterialServiceImpl.java @@ -1,5 +1,6 @@ package org.nl.wms.pda.callmaterial.service.impl; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -8,7 +9,6 @@ import lombok.extern.slf4j.Slf4j; import org.nl.modules.wql.WQL; import org.nl.wms.ext.acs.service.AcsToWmsService; import org.nl.wms.pda.callmaterial.service.CallMaterialService; - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -43,18 +43,18 @@ public class CallMaterialServiceImpl implements CallMaterialService { JSONObject result = new JSONObject(); // 1、准备参数:point_code、type = 4 JSONObject param = new JSONObject(); - param.put("type","4"); - param.put("point_code",whereJson.getString("point_code")); + param.put("type", "4"); + param.put("point_code", whereJson.getString("point_code")); // 2、调用接口 JSONObject json = acsToWmsService.apply(param); - if (StrUtil.equals(json.getString("status"), "200")) { + if (ObjectUtil.isEmpty(json) || StrUtil.equals(json.getString("status"), "200")) { result.put("result", ""); result.put("code", "1"); result.put("desc", "操作成功"); } else { result.put("result", ""); result.put("code", "0"); - result.put("desc", "操作失败:"+json.getString("message")); + result.put("desc", "操作失败:" + json.getString("message")); } return result; } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/callmaterial/wql/PDA_CALLMATERIAL_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/pda/callmaterial/wql/PDA_CALLMATERIAL_01.wql index 3c39c5e..41b449f 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/callmaterial/wql/PDA_CALLMATERIAL_01.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pda/callmaterial/wql/PDA_CALLMATERIAL_01.wql @@ -47,8 +47,7 @@ FROM sch_base_region WHERE - is_used = '1' - AND region_code = 'YQQY01' + region_code = 'YQQY01' ENDSELECT ENDQUERY @@ -65,8 +64,7 @@ WHERE is_used = '1' AND is_delete = '0' - AND is_host = '0' - AND device_point_type = '3' + AND point_type = '3' OPTION 输入.region_id <> "" region_id = 输入.region_id @@ -74,4 +72,4 @@ ENDSELECT ENDQUERY - ENDIF \ No newline at end of file + ENDIF diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/callvehicle/service/impl/CallVehicleServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/pda/callvehicle/service/impl/CallVehicleServiceImpl.java index 95a2ad8..1f193db 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/callvehicle/service/impl/CallVehicleServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pda/callvehicle/service/impl/CallVehicleServiceImpl.java @@ -1,5 +1,6 @@ package org.nl.wms.pda.callvehicle.service.impl; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -9,8 +10,6 @@ import org.nl.modules.wql.WQL; import org.nl.modules.wql.core.bean.WQLObject; import org.nl.wms.ext.acs.service.AcsToWmsService; import org.nl.wms.pda.callvehicle.service.CallVehicleService; - - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -50,21 +49,21 @@ public class CallVehicleServiceImpl implements CallVehicleService { String region_id = whereJson.getString("region_id"); JSONObject jsonObject = WQLObject.getWQLObject("sch_base_region").query("region_id ='" + region_id + "'").uniqueResult(0); String region_code = jsonObject.getString("region_code"); - if (StrUtil.equals(region_code, "GJQY01")) param.put("type","1"); - if (StrUtil.equals(region_code, "YQQY01")) param.put("type","3"); + if (StrUtil.equals(region_code, "GJQY01")) param.put("type", "1"); + if (StrUtil.equals(region_code, "YQQY01")) param.put("type", "3"); - param.put("point_code",whereJson.getString("point_code")); - param.put("vehicle_num",whereJson.getString("qty")); + param.put("point_code", whereJson.getString("point_code")); + param.put("vehicle_num", whereJson.getString("qty")); // 2、调用接口 JSONObject json = acsToWmsService.apply(param); - if (StrUtil.equals(json.getString("status"), "200")) { + if (ObjectUtil.isEmpty(json) || StrUtil.equals(json.getString("status"), "200")) { result.put("result", ""); result.put("code", "1"); result.put("desc", "操作成功"); } else { result.put("result", ""); result.put("code", "0"); - result.put("desc", "操作失败:"+json.getString("message")); + result.put("desc", "操作失败:" + json.getString("message")); } return result; } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/callvehicle/wql/PDA_CALLVEHICLE_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/pda/callvehicle/wql/PDA_CALLVEHICLE_01.wql index 339dd16..65bdadd 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/callvehicle/wql/PDA_CALLVEHICLE_01.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pda/callvehicle/wql/PDA_CALLVEHICLE_01.wql @@ -47,8 +47,7 @@ FROM sch_base_region WHERE - is_used = '1' - AND region_code in ('YQQY01','GJQY01') + region_code in ('YQQY01','GJQY01') ENDSELECT ENDQUERY @@ -65,8 +64,7 @@ WHERE is_used = '1' AND is_delete = '0' - AND is_host = '0' - AND device_point_type = '1' + AND point_type = '1' OPTION 输入.region_id <> "" region_id = 输入.region_id @@ -74,4 +72,4 @@ ENDSELECT ENDQUERY - ENDIF \ No newline at end of file + ENDIF diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/rest/EmptyAndQtyController.java b/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/rest/EmptyAndQtyController.java deleted file mode 100644 index 371d7c9..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/rest/EmptyAndQtyController.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.nl.wms.pda.emptyandqty.rest; - -import com.alibaba.fastjson.JSONObject; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.nl.modules.logging.annotation.Log; -import org.nl.wms.pda.emptyandqty.service.EmptyAndQtyService; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@Api(tags = "手持空托盘与数量绑定") -@RequestMapping("api/pda/emptyAndQty") -@Slf4j -public class EmptyAndQtyController { - - private final EmptyAndQtyService emptyAndQtyService; - - @PostMapping("/confirm") - @Log("绑定") - @ApiOperation("绑定") - public ResponseEntity confirm(@RequestBody JSONObject whereJson) { - return new ResponseEntity<>(emptyAndQtyService.confirm(whereJson), HttpStatus.OK); - } -} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/service/EmptyAndQtyService.java b/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/service/EmptyAndQtyService.java deleted file mode 100644 index 70a1bd8..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/service/EmptyAndQtyService.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.nl.wms.pda.emptyandqty.service; - -import com.alibaba.fastjson.JSONObject; - -public interface EmptyAndQtyService { - - /** - * 绑定 - * @param whereJson / - * @return JSONObject - */ - JSONObject confirm(JSONObject whereJson); -} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/service/impl/EmptyAndQtyServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/service/impl/EmptyAndQtyServiceImpl.java deleted file mode 100644 index 4c0ce22..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/emptyandqty/service/impl/EmptyAndQtyServiceImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.nl.wms.pda.emptyandqty.service.impl; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.IdUtil; -import com.alibaba.fastjson.JSONObject; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import org.nl.modules.common.utils.SecurityUtils; -import org.nl.modules.wql.core.bean.WQLObject; - -import org.nl.modules.wql.util.SpringContextHolder; -import org.nl.wms.basedata.service.VehicleService; -import org.nl.wms.basedata.service.dto.VehicleDto; -import org.nl.wms.pda.emptyandqty.service.EmptyAndQtyService; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Slf4j -public class EmptyAndQtyServiceImpl implements EmptyAndQtyService { - - @Override - @Transactional(rollbackFor = Exception.class) - public JSONObject confirm(JSONObject whereJson) { - String vehicle_code = whereJson.getString("vehicle_code"); - String qty = whereJson.getString("qty"); - - WQLObject vqTab = WQLObject.getWQLObject("PDM_BI_vehicleQty"); - VehicleDto byCode = SpringContextHolder.getBean(VehicleService.class).findByCode(vehicle_code); - - // 插入记录 - JSONObject json = new JSONObject(); - json.put("vehicleqty_id", IdUtil.getSnowflake(1, 1).nextId()); - json.put("vehicle_id", byCode.getVehicle_id()); - json.put("vehicle_code", vehicle_code); - json.put("qty", qty); - json.put("create_id", SecurityUtils.getCurrentUserId()); - json.put("create_name", SecurityUtils.getCurrentNickName()); - json.put("create_time", DateUtil.now()); - vqTab.insert(json); - // 返回成功 - JSONObject result = new JSONObject(); - result.put("srb", ""); - result.put("code", "1"); - result.put("desc", "操作成功"); - return result; - } -} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/service/impl/SendMaterialServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/service/impl/SendMaterialServiceImpl.java index 4a8ac9b..3253249 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/service/impl/SendMaterialServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/service/impl/SendMaterialServiceImpl.java @@ -1,5 +1,6 @@ package org.nl.wms.pda.sendmaterial.service.impl; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -9,8 +10,6 @@ import org.nl.modules.wql.WQL; import org.nl.modules.wql.core.bean.WQLObject; import org.nl.wms.ext.acs.service.AcsToWmsService; import org.nl.wms.pda.sendmaterial.service.SendMaterialService; - - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -50,21 +49,21 @@ public class SendMaterialServiceImpl implements SendMaterialService { String region_id = whereJson.getString("region_id"); JSONObject jsonObject = WQLObject.getWQLObject("sch_base_region").query("region_id ='" + region_id + "'").uniqueResult(0); String region_code = jsonObject.getString("region_code"); - if (StrUtil.equals(region_code, "GJQY01")) param.put("type","2"); - if (StrUtil.equals(region_code, "HKQY01")) param.put("type","8"); + if (StrUtil.equals(region_code, "GJQY01")) param.put("type", "2"); + if (StrUtil.equals(region_code, "HKQY01")) param.put("type", "8"); - param.put("point_code",whereJson.getString("point_code")); - param.put("qty",whereJson.getString("qty")); + param.put("point_code", whereJson.getString("point_code")); + param.put("material_num", whereJson.getString("qty")); // 2、调用接口 JSONObject json = acsToWmsService.apply(param); - if (StrUtil.equals(json.getString("status"), "200")) { + if (ObjectUtil.isEmpty(json) || StrUtil.equals(json.getString("status"), "200")) { result.put("result", ""); result.put("code", "1"); result.put("desc", "操作成功"); } else { result.put("result", ""); result.put("code", "0"); - result.put("desc", "操作失败:"+json.getString("message")); + result.put("desc", "操作失败:" + json.getString("message")); } return result; } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/wql/PDA_SENDMATERIAL_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/wql/PDA_SENDMATERIAL_01.wql index 5c5c7ce..4632d02 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/wql/PDA_SENDMATERIAL_01.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/wql/PDA_SENDMATERIAL_01.wql @@ -47,8 +47,7 @@ FROM sch_base_region WHERE - is_used = '1' - AND region_code in ('HKQY01','GJQY01') + region_code in ('HKQY01','GJQY01') ENDSELECT ENDQUERY @@ -65,8 +64,7 @@ WHERE is_used = '1' AND is_delete = '0' - AND is_host = '0' - AND device_point_type = '2' + AND point_type = '3' OPTION 输入.region_id <> "" region_id = 输入.region_id @@ -74,4 +72,4 @@ ENDSELECT ENDQUERY - ENDIF \ No newline at end of file + ENDIF diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendvehicle/wql/PDA_SENDVEHICLE_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendvehicle/wql/PDA_SENDVEHICLE_01.wql index 4c7fdef..b8bb4a3 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendvehicle/wql/PDA_SENDVEHICLE_01.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pda/sendvehicle/wql/PDA_SENDVEHICLE_01.wql @@ -47,8 +47,7 @@ FROM sch_base_region WHERE - is_used = '1' - AND region_code in ('SSX01','YQQY01') + region_code in ('SSX01','YQQY01') ENDSELECT ENDQUERY @@ -65,8 +64,7 @@ WHERE is_used = '1' AND is_delete = '0' - AND is_host = '0' - AND device_point_type = '6' + AND point_type = '6' OPTION 输入.region_id <> "" region_id = 输入.region_id @@ -87,8 +85,7 @@ WHERE is_used = '1' AND is_delete = '0' - AND is_host = '0' - AND device_point_type = '4' + AND point_type = '4' OPTION 输入.region_id <> "" region_id = 输入.region_id @@ -96,4 +93,4 @@ ENDSELECT ENDQUERY - ENDIF \ No newline at end of file + ENDIF diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pdm/service/dto/WorkorderDto.java b/lms/nladmin-system/src/main/java/org/nl/wms/pdm/service/dto/WorkorderDto.java index d607f5a..b4c2586 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pdm/service/dto/WorkorderDto.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pdm/service/dto/WorkorderDto.java @@ -61,6 +61,9 @@ public class WorkorderDto implements Serializable { /** 回传MES状态 */ private String passback_status; + /** 设备编码 */ + private String device_code; + /** 外部标识 */ private String ext_id; diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pdm/service/impl/WorkorderServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/pdm/service/impl/WorkorderServiceImpl.java index 2efb31c..8addcce 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pdm/service/impl/WorkorderServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pdm/service/impl/WorkorderServiceImpl.java @@ -113,6 +113,12 @@ public class WorkorderServiceImpl implements WorkordeService { @Override @Transactional(rollbackFor = Exception.class) public void create(WorkorderDto dto) { + Long device_id = dto.getDevice_id(); + if (ObjectUtil.isNotEmpty(device_id)) { + WQLObject deviceTab = WQLObject.getWQLObject("PDM_BI_Device"); + JSONObject object = deviceTab.query("device_id = '" + device_id + "'").uniqueResult(0); + dto.setDevice_code(object.getString("device_code")); + } Long currentUserId = SecurityUtils.getCurrentUserId(); String nickName = SecurityUtils.getCurrentNickName(); String now = DateUtil.now(); @@ -121,7 +127,6 @@ public class WorkorderServiceImpl implements WorkordeService { String newCode = CodeUtil.getNewCode("PDM_SHIFTORDER"); dto.setWorkorder_id(IdUtil.getSnowflake(1, 1).nextId()); dto.setWorkorder_code(newCode); - dto.setOrder_status("1"); dto.setCreate_id(currentUserId); dto.setCreate_time(now); dto.setCreate_name(nickName); diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pdm/wql/MPS_PRODUCEDURE001.wql b/lms/nladmin-system/src/main/java/org/nl/wms/pdm/wql/MPS_PRODUCEDURE001.wql index adeff47..634533b 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pdm/wql/MPS_PRODUCEDURE001.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pdm/wql/MPS_PRODUCEDURE001.wql @@ -17,7 +17,6 @@ 输入.jockey_id TYPEAS s_string 输入.workorder_id TYPEAS s_string 输入.workprocedure_id TYPEAS s_string - 输入.order_type_scode TYPEAS s_string 输入.order_status TYPEAS s_string 输入.workorder_procedure TYPEAS s_string 输入.shift_type_scode TYPEAS s_string @@ -70,9 +69,6 @@ LEFT JOIN md_pb_classstandard classstandard ON classstandard.class_id = material.product_series WHERE ShiftOrder.is_delete = '0' - OPTION 输入.order_type_scode <> "" - ShiftOrder.order_type_scode = 输入.order_type_scode - ENDOPTION OPTION 输入.unFinish <> "" ShiftOrder.order_status <> '5' ENDOPTION diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/PointFindUtil.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/PointFindUtil.java deleted file mode 100644 index 43f7200..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/PointFindUtil.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.nl.wms.sch; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.alibaba.fastjson.JSONObject; - -import org.nl.modules.common.exception.BadRequestException; -import org.nl.modules.wql.WQL; -import org.nl.modules.wql.core.bean.WQLObject; - - -public class PointFindUtil { - public static JSONObject getInStruct(JSONObject jsonObject) { - String material_id = jsonObject.getString("material_id"); - String area_type = jsonObject.getString("area_type"); - String vehicle_code = jsonObject.getString("vehicle_code"); - if (StrUtil.isEmpty(vehicle_code)) { - throw new BadRequestException("托盘不能为空!"); - } - //根据托盘找托盘类型, - JSONObject vehicleObj = WQLObject.getWQLObject("md_pb_vehicle").query("vehicle_code='" + vehicle_code + "'").uniqueResult(0); - if (ObjectUtil.isEmpty(vehicleObj)) { - throw new BadRequestException("未找到托盘号为'" + vehicle_code + "' 托盘信息!"); - } - if (StrUtil.isEmpty(material_id)) { - throw new BadRequestException("物料不能为空!"); - } - if (StrUtil.isEmpty(area_type)) { - throw new BadRequestException("区域不能为空!"); - } - String vehice_type = vehicleObj.getString("vehicle_type"); - JSONObject result = WQL.getWO("QSTRUCT_RULE").addParam("flag", "2") - .addParam("material_id", material_id).addParam("area_type", area_type).addParam("vehice_type", vehice_type).process().uniqueResult(0); - return result; - } - - public static JSONObject getOutStruct(JSONObject jsonObject) { - String material_id = jsonObject.getString("material_id"); - String area_type = jsonObject.getString("area_type"); - String is_full = jsonObject.getString("is_full"); - String workprocedure_id = jsonObject.getString("workprocedure_id"); - - if (StrUtil.isEmpty(material_id)) { - throw new BadRequestException("物料不能为空!"); - } - if (StrUtil.isEmpty(area_type)) { - throw new BadRequestException("区域不能为空!"); - } - if (StrUtil.isEmpty(is_full)) { - throw new BadRequestException("是否满托不能为空!"); - } - if (StrUtil.isEmpty(workprocedure_id)) { - throw new BadRequestException("工序不能为空!"); - } - JSONObject result = WQL.getWO("QSTRUCT_RULE").addParam("flag", "3") - .addParam("material_id", material_id).addParam("area_type", area_type) - .addParam("is_full", is_full).addParam("workprocedure_id", workprocedure_id) - .process().uniqueResult(0); - return result; - } - - public static JSONObject getEmptyVehicleInStruct(JSONObject jsonObject) { - String area_type = jsonObject.getString("area_type"); - String vehicle_code = jsonObject.getString("vehicle_code"); - if (StrUtil.isEmpty(vehicle_code)) { - throw new BadRequestException("托盘不能为空!"); - } - //根据托盘找托盘类型, - JSONObject vehicleObj = WQLObject.getWQLObject("md_pb_vehicle").query("vehicle_code='" + vehicle_code + "'").uniqueResult(0); - if (ObjectUtil.isEmpty(vehicleObj)) { - throw new BadRequestException("未找到托盘号为'" + vehicle_code + "' 托盘信息!"); - } - if (StrUtil.isEmpty(area_type)) { - throw new BadRequestException("区域不能为空!"); - } - String vehice_type = vehicleObj.getString("vehicle_type"); - JSONObject result = WQL.getWO("QSTRUCT_RULE").addParam("flag", "4") - .addParam("area_type", area_type).addParam("vehice_type", vehice_type).process().uniqueResult(0); - return result; - } - - public static JSONObject getEmptyVehicleOutStruct(JSONObject jsonObject) { - String area_type = jsonObject.getString("area_type"); - String vehicle_type = jsonObject.getString("vehicle_type"); - if (StrUtil.isEmpty(area_type)) { - throw new BadRequestException("区域不能为空!"); - } - JSONObject result = WQL.getWO("QSTRUCT_RULE").addParam("flag", "5") - .addParam("area_type", area_type).addParam("vehicle_type", vehicle_type).process().uniqueResult(0); - return result; - } - -} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/SchTaskDto.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/SchTaskDto.java index 38de98a..313d52d 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/SchTaskDto.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/SchTaskDto.java @@ -27,6 +27,10 @@ public class SchTaskDto implements Serializable { * 任务编码 */ private String task_code; + /** + * 任务名称 + */ + private String task_name; /** * 任务类型 @@ -103,7 +107,7 @@ public class SchTaskDto implements Serializable { */ private Integer sort_seq; //物料数量 - private Integer material_qty; + private String material_qty; /** * 任务完成类型 @@ -135,31 +139,6 @@ public class SchTaskDto implements Serializable { */ private String remark; - /** - * 备注1 - */ - private String remark2; - - /** - * 备注2 - */ - private String remark3; - - /** - * 是否删除 - */ - private String is_delete; - - /** - * 创建时间 - */ - private String create_time; - - /** - * 修改时间 - */ - private String update_time; - /** * 车号 */ @@ -179,4 +158,44 @@ public class SchTaskDto implements Serializable { * 下发任务的请求参数 */ private String response_param; + + + /** + * 是否删除 + */ + private String is_delete; + + /** + * 创建人 + */ + private Long create_id; + + /** + * 创建人 + */ + private String create_name; + /** + * 创建方式 + */ + private String create_mode; + + /** + * 创建时间 + */ + private String create_time; + + /** + * 修改人 + */ + private Long update_optid; + + /** + * 修改人 + */ + private String update_optname; + + /** + * 修改时间 + */ + private String update_time; } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/manage/AbstractAcsTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/manage/AbstractAcsTask.java index d30f72f..1473a84 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/manage/AbstractAcsTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/manage/AbstractAcsTask.java @@ -1,6 +1,7 @@ package org.nl.wms.sch.manage; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.nl.wms.sch.AcsUtil; @@ -109,7 +110,8 @@ public abstract class AbstractAcsTask { public JSONObject immediateNotifyAcs() { List taskList = this.schedule(); if (ObjectUtil.isNotEmpty(taskList)) { - JSONArray arr = JSONArray.parseArray(taskList.toString()); + + JSONArray arr = JSONArray.parseArray(JSON.toJSONString(taskList)); return AcsUtil.notifyAcs("api/wms/task", arr); } return null; diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/rest/PointController.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/rest/PointController.java index 631da66..7310c4e 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/rest/PointController.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/rest/PointController.java @@ -104,4 +104,12 @@ public class PointController { pointService.changeUsed(jsonObject); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } + + @Log("锁定与解锁") + @PostMapping("/changeLock") + @ApiOperation("锁定与解锁") + public ResponseEntity changeLock(@RequestBody JSONObject jsonObject) { + pointService.changeLock(jsonObject); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/rest/TaskController.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/rest/TaskController.java index 037a66a..cafc411 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/rest/TaskController.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/rest/TaskController.java @@ -12,7 +12,6 @@ import org.nl.modules.logging.annotation.Log; import org.nl.wms.sch.manage.FinishTypeEnum; import org.nl.wms.sch.manage.TaskStatusEnum; import org.nl.wms.sch.service.TaskService; -import org.nl.wms.sch.tasks.TaskTypeEnum; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -61,20 +60,6 @@ public class TaskController { return new ResponseEntity<>(arr, HttpStatus.OK); } - @GetMapping("/taskType") - @Log("获取任务类型列表") - @ApiOperation("获取任务类型列表") - public ResponseEntity getTaskType() { - TaskTypeEnum[] values = TaskTypeEnum.values(); - JSONArray arr = new JSONArray(); - for (TaskTypeEnum value : values) { - JSONObject json = new JSONObject(); - json.put("code", value.getCode()); - json.put("name", value.getName()); - arr.add(json); - } - return new ResponseEntity<>(arr, HttpStatus.OK); - } @GetMapping("/finishType") @Log("获取任务类型列表") diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/PointService.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/PointService.java index 79aedfa..d4eec70 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/PointService.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/PointService.java @@ -90,4 +90,10 @@ public interface PointService { * @param jsonObject */ void changeUsed(JSONObject jsonObject); + + /** + * 改变锁定类型 + * @param jsonObject + */ + void changeLock(JSONObject jsonObject); } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/TaskService.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/TaskService.java index e8f4398..222cbc7 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/TaskService.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/TaskService.java @@ -1,10 +1,8 @@ package org.nl.wms.sch.service; -import org.nl.wms.sch.service.dto.TaskDto; import org.springframework.data.domain.Pageable; -import java.util.List; import java.util.Map; /** @@ -23,34 +21,11 @@ public interface TaskService { */ Map queryAll(Map whereJson, Pageable page); - /** - * 查询所有数据不分页 - * - * @param whereJson 条件参数 - * @return List - */ - List queryAll(Map whereJson); - - /** - * 根据ID查询 - * - * @param task_id - * @return Task - */ - TaskDto findById(String task_id); - - /** - * 根据编码查询 - * - * @param code code - * @return Task - */ - TaskDto findByCode(String code); - /** * 任务操作 * * @param param */ void operation(Map param); + } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/dto/PointDto.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/dto/PointDto.java index 805300d..9b36397 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/dto/PointDto.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/dto/PointDto.java @@ -49,6 +49,9 @@ public class PointDto implements Serializable { /** MES设备编码 */ private String mes_device_code; + /** 物料标识 */ + private Long material_id; + /** 允许的载具类型 */ private String can_vehicle_type; @@ -108,4 +111,4 @@ public class PointDto implements Serializable { /** 修改时间 */ private String update_time; -} +} \ No newline at end of file diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/impl/PointServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/impl/PointServiceImpl.java index 1c5c664..fe130b5 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/impl/PointServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/impl/PointServiceImpl.java @@ -153,6 +153,14 @@ public class PointServiceImpl implements PointService { throw new BadRequestException("被删除或无权限,操作失败!"); } + String pointStatus = dto.getPoint_status(); + if (ObjectUtil.isNotEmpty(pointStatus) && pointStatus.equals("1")) { + entity.setMaterial_id(null); + entity.setVehicle_type(null); + entity.setVehicle_code(null); + entity.setVehicle_qty(null); + } + Long currentUserId = SecurityUtils.getCurrentUserId(); String nickName = SecurityUtils.getCurrentNickName(); @@ -275,6 +283,24 @@ public class PointServiceImpl implements PointService { } } + /** + * 改变锁定类型 + * + * @param jsonObject + */ + @Override + public void changeLock(JSONObject jsonObject) { + WQLObject wo = WQLObject.getWQLObject("sch_base_Point"); + JSONArray data = jsonObject.getJSONArray("data"); + String lock = jsonObject.getString("lock_type"); + for ( int i = 0; i < data.size(); i++ ) { + JSONObject object = data.getJSONObject(i); + if (lock.equals("1")) object.put("lock_type", 1); + else object.put("lock_type", 2); + wo.update(object); + } + } + //根据重量返回最大的 级数 public String getLoadSeriesByqty(Double qty) { JSONArray dictArr = WQLObject.getWQLObject("sys_dict_detail").query("dict_id ='108'", "label").getResultJSONArray(0); diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/impl/TaskServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/impl/TaskServiceImpl.java index 612099e..5283eaa 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/impl/TaskServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/service/impl/TaskServiceImpl.java @@ -19,14 +19,12 @@ import org.nl.wms.basedata.service.dto.ClassstandardDto; import org.nl.wms.sch.service.PointService; import org.nl.wms.sch.service.RegionService; import org.nl.wms.sch.service.TaskService; -import org.nl.wms.sch.service.dto.TaskDto; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -92,56 +90,37 @@ public class TaskServiceImpl implements TaskService { //点位基础表【SCH_BASE_Point】 WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); - for ( int i = 0; i < content.size(); i++) { + for (int i = 0; i < content.size(); i++) { JSONObject taskObj = content.getJSONObject(i); String point_code1 = taskObj.getString("point_code1"); - if (ObjectUtil.isNotEmpty(point_code1)){ + if (ObjectUtil.isNotEmpty(point_code1)) { JSONObject point1 = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); taskObj.put("point1_region_name", point1.getString("region_name")); } String point_code2 = taskObj.getString("point_code2"); - if (ObjectUtil.isNotEmpty(point_code2)){ + if (ObjectUtil.isNotEmpty(point_code2)) { JSONObject point2 = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); taskObj.put("point2_region_name", point2.getString("region_name")); } + String point_code3 = taskObj.getString("point_code3"); + if (ObjectUtil.isNotEmpty(point_code3)) { + JSONObject point3 = pointTab.query("point_code = '" + point_code3 + "'").uniqueResult(0); + taskObj.put("point3_region_name", point3.getString("region_name")); + } res.add(taskObj); } json.put("content", res); return json; } - @Override - public List queryAll(Map whereJson) { - WQLObject wo = WQLObject.getWQLObject("sch_base_task"); - JSONArray arr = wo.query().getResultJSONArray(0); - List list = arr.toJavaList(TaskDto.class); - return list; - } - - @Override - public TaskDto findById(String task_id) { - WQLObject wo = WQLObject.getWQLObject("sch_base_task"); - JSONObject json = wo.query("task_id = '" + task_id + "'").uniqueResult(0); - final TaskDto obj = json.toJavaObject(TaskDto.class); - return obj; - } - - @Override - public TaskDto findByCode(String code) { - WQLObject wo = WQLObject.getWQLObject("sch_base_task"); - JSONObject json = wo.query("task_code ='" + code + "'").uniqueResult(0); - final TaskDto obj = json.toJavaObject(TaskDto.class); - return obj; - } - @Override public void operation(Map map) { String task_id = MapUtil.getStr(map, "task_id"); String method_name = MapUtil.getStr(map, "method_name"); - TaskDto dto = this.findById(task_id); + JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0); // 任务处理类 - String processing_class = dto.getHandle_class(); + String processing_class = taskObj.getString("handle_class"); String message = ""; // 根据任务类型获取对应的任务操作类 try { diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/TaskTypeEnum.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/TaskTypeEnum.java deleted file mode 100644 index 9b0e82d..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/TaskTypeEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.nl.wms.sch.tasks; - -/** - * 任务状态枚举 - */ -public enum TaskTypeEnum { - IN_TASK(1, "01", "入库"), - Out_TASK(2, "02", "出库"), - IN_EMPTY_VEHICLE_TASK(3, "03", "入空载具"), - OUT_EMPTY_VEHICLE_TASK(4, "04", "出空载具"), - DUMPINV_TASK(5, "05", "转储"), - QUALITY_TASK(6, "06", "质检"), - MATERIAL_BACK_TASK(7, "07", "余料回库"); - - private int index; - private String code; - private String name; - - public String getCode() { - return code; - } - - public String getName() { - return name; - } - - TaskTypeEnum(int index, String code, String name) { - this.index = index; - this.code = code; - this.name = name; - } - -} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/CallEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/CallEmpVehicleTask.java deleted file mode 100644 index 012f8db..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/CallEmpVehicleTask.java +++ /dev/null @@ -1,301 +0,0 @@ -package org.nl.wms.sch.tasks.callEmpty; - -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.nl.wms.sch.tasks.AcsTaskDto; -import org.nl.wms.sch.tasks.RegionTypeEnum; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.math.BigDecimal; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Slf4j -public class CallEmpVehicleTask extends AbstractAcsTask { - private final String THIS_CLASS = CallEmpVehicleTask.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 - @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("task_code", CodeUtil.getNewCode("TASK_CODE")); - jsonTask.put("task_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 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; - } - - @Override - public List addTask() { - return null; - } - -} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/GjxCallEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/GjxCallEmpVehicleTask.java index 38cfed1..1e73ff8 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/GjxCallEmpVehicleTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/GjxCallEmpVehicleTask.java @@ -1,9 +1,10 @@ package org.nl.wms.sch.tasks.callEmpty; 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.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; @@ -13,12 +14,16 @@ 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.wms.sch.SchTaskDto; import org.nl.wms.sch.manage.AbstractAcsTask; import org.nl.wms.sch.manage.TaskStatusEnum; import org.nl.wms.sch.tasks.AcsTaskDto; +import org.nl.wms.sch.tasks.RegionTypeEnum; +import org.nl.wms.util.IdUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; @Service @@ -41,7 +46,47 @@ public class GjxCallEmpVehicleTask extends AbstractAcsTask { JSONObject jsonTask = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); if (StrUtil.equals(status, "0")) { - // 取消删除任务 + /* + * 取消删除 + * 1.终点为叠盘架更新起点点位、等待点点位、叠盘架点位 + * 2.终点为供给线更新叠盘架点位 + */ + if (StrUtil.equals(jsonTask.getString("task_status"), TaskStatusEnum.FINISHED.getCode())) { + throw new BadRequestException("已完成不能取消!"); + } + + String point_code1 = jsonTask.getString("point_code1"); + String point_code2 = jsonTask.getString("point_code2"); + + JSONObject jsonEnd = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + // 终点在叠盘架 + if (StrUtil.equals(jsonEnd.getString("region_id"), RegionTypeEnum.DPJQB.getId())) { + JSONObject jsonStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + // 判断此起点是否是等待点 + if (!StrUtil.equals(jsonStart.getString("row_num"), "9")) { + // 如果不是等待点更新等待点状态 + JSONObject jsonEmpWait = pointTab.query("region_id = '" + jsonStart.getString("region_id") + + "' and block_num = '" + jsonStart.getString("block_num") + + "' and col_num = '" + jsonStart.getString("col_num") + + "' and row_num = '9'").uniqueResult(0); + + jsonEmpWait.put("lock_type", "1"); + pointTab.update(jsonEmpWait); + } + jsonStart.put("lock_type", "1"); + pointTab.update(jsonStart); + + // 更新终点(叠盘架状态) + jsonEnd.put("lock_type", "1"); + pointTab.update(jsonEnd); + + } else { + // 终点在供给线 + JSONObject jsonStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + jsonStart.put("lock_type", "1"); + pointTab.update(jsonStart); + } + taskTab.delete("task_id = '" + task_id + "'"); } @@ -54,56 +99,79 @@ public class GjxCallEmpVehicleTask extends AbstractAcsTask { } if (StrUtil.equals(status, TaskStatusEnum.FINISHED.getCode())) { - // 更改任务状态为完成 + /* + * 更改任务状态为完成 + * 1.终点为叠盘架更新叠盘架数量、起点点位状态、等待位状态,更新任务组状态 + * 2.终点为供给线,更新起点载数量 + */ 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); - String end_point_code = jsonTask.getString("point_code2"); - String start_point_code = jsonTask.getString("point_code1"); - JSONObject endPoint = pointTab.query("point_code = '" + end_point_code + "'").uniqueResult(0); - //从空托盘缓存B区或养生A区搬运到叠盘架 - if (StrUtil.equals("DPJQB01", endPoint.getString("region_code"))) { - //解锁起点 - JSONObject startPoint = new JSONObject(); - startPoint.put("lock_type", "1"); - startPoint.put("point_status", "1"); - startPoint.put("update_time", DateUtil.now()); - pointTab.update(startPoint, "point_code = '" + start_point_code + "'"); - //更新终点点位状态 - endPoint.put("point_status", "2"); - endPoint.put("lock_type", "00"); - endPoint.put("vehicle_qty", jsonTask.getString("vehicle_qty")); - endPoint.put("vehicle_type", jsonTask.getString("vehicle_type")); - endPoint.put("update_time", DateUtil.now()); - pointTab.update(endPoint); - } else { - JSONObject startPoint = pointTab.query("point_code = '" + start_point_code + "'").uniqueResult(0); - Integer vehicle_qty = startPoint.getInteger("vehicle_qty"); - int after_qty = vehicle_qty - 1; - startPoint.put("lock_type", "1"); - startPoint.put("vehicle_qty", after_qty); - if (after_qty > 0) { - startPoint.put("point_status", "2"); - } else { - startPoint.put("point_status", "1"); + // 判断终点在哪里 + String point_code1 = jsonTask.getString("point_code1"); + String point_code2 = jsonTask.getString("point_code2"); + + JSONObject jsonEnd = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + // 终点在叠盘架 + if (StrUtil.equals(jsonEnd.getString("region_id"), RegionTypeEnum.DPJQB.getId())) { + // 更新起点点位状态 + JSONObject jsonStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + // 判断起点是不是养生A区空载具 + if (StrUtil.equals(jsonStart.getString("region_id"), RegionTypeEnum.YSAQKTPQ01.getId())) { + // 判断此起点是否是等待点 + if (!StrUtil.equals(jsonStart.getString("row_num"), "9")) { + // 如果不是等待点更新等待点状态 + JSONObject jsonEmpWait = pointTab.query("region_id = '" + jsonStart.getString("region_id") + + "' and block_num = '" + jsonStart.getString("block_num") + + "' and col_num = '" + jsonStart.getString("col_num") + + "' and row_num = '9'").uniqueResult(0); + + jsonEmpWait.put("lock_type", "1"); + pointTab.update(jsonEmpWait); + } } - startPoint.put("update_time", DateUtil.now()); - pointTab.update(startPoint, "point_code = '" + start_point_code + "'"); + + jsonStart.put("point_status", "1"); + jsonStart.put("lock_type", "1"); + jsonStart.put("vehicle_type", ""); + jsonStart.put("vehicle_code", ""); + jsonStart.put("vehicle_qty", 0); + pointTab.update(jsonStart); + + // 更新终点(叠盘架状态) + jsonEnd.put("vehicle_qty", NumberUtil.add(jsonEnd.getString("vehicle_qty"), jsonTask.getString("vehicle_qty"))); + jsonEnd.put("lock_type", "1"); + jsonEnd.put("point_status", "2"); + jsonEnd.put("vehicle_type", jsonTask.getString("vehicle_type")); + pointTab.update(jsonEnd); + + // 更新任务组状态 + JSONObject jsonTask2 = taskTab.query("task_group_id = '" + jsonTask.getString("task_group_id") + "' and task_id <> '" + jsonTask.getString("task_id") + "'").uniqueResult(0); + jsonTask2.put("point_code1", jsonEnd.getString("point_code")); + jsonTask2.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + taskTab.update(jsonTask2); + } else { + // 终点在供给线线: 更新起点(叠盘架)数量 + JSONObject jsonStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + jsonStart.put("vehicle_qty", NumberUtil.sub(jsonStart.getString("vehicle_qty"), "1")); + jsonStart.put("lock_type", "1"); + if (StrUtil.equals(jsonStart.getString("vehicle_qty"), "0")) { + jsonStart.put("point_status", "1"); + jsonStart.put("vehicle_type", ""); + } + pointTab.update(jsonStart); } } } - @Override - public List addTask() { - return null; - } @Override + @Transactional(rollbackFor = Exception.class) public void findStartPoint() { - WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); - WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); // 点位表 JSONArray taskArr = taskTab.query("is_delete = '0' and handle_class = '" + this.THIS_CLASS + "' and task_status = '" + TaskStatusEnum.SURE_END.getCode() + "'").getResultJSONArray(0); for (int i = 0; i < taskArr.size(); i++) { @@ -111,74 +179,128 @@ public class GjxCallEmpVehicleTask extends AbstractAcsTask { JSONObject jsonTask = taskArr.getJSONObject(i); String vehicle_type = jsonTask.getString("vehicle_type"); - //判断叠盘位是否有另外任务 - JSONObject taskObj = taskTab.query("is_delete='0' and handle_class='" + this.THIS_CLASS + "' and task_status <>'" + TaskStatusEnum.FINISHED.getCode() + "' and task_id <> " + jsonTask.getLong("task_id")).uniqueResult(0); - if (ObjectUtil.isNotEmpty(taskObj)) continue; + // 找叠盘架是否与对应的载具类型 + JSONObject jsonDpjStart = pointTab.query("region_id = '" + RegionTypeEnum.DPJQB.getId() + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and vehicle_qty <> '0'").uniqueResult(0); - //判断叠盘架是否有载具 - JSONObject dpjPoint = pointTab.query("is_used ='1' and lock_type='00' and is_delete='0' and region_code='DPJQB01' and vehicle_qty >0 and can_vehicle_type like '%" + vehicle_type + "%'").uniqueResult(0); - if (ObjectUtil.isNotEmpty(dpjPoint)) { + if (ObjectUtil.isNotEmpty(jsonDpjStart)) { + // 判断叠盘架是否有任务 有就下一个任务 + boolean is_point = this.isTask(jsonDpjStart.getString("point_code")); + if (!is_point) continue; + + // 更新任务起点 + jsonTask.put("point_code1", jsonDpjStart.getString("point_code")); jsonTask.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); - jsonTask.put("point_code1", dpjPoint.getString("point_code")); - jsonTask.put("update_time", DateUtil.now()); taskTab.update(jsonTask); - //锁住点位 - dpjPoint.put("lock_type", "2"); - pointTab.update(dpjPoint); } else { - //查找叠盘架编码 - JSONObject dpjPoint1 = pointTab.query("is_delete='0' and region_code='DPJQB01' and can_vehicle_type like '%" + vehicle_type + "%'").uniqueResult(0); + // 判断叠盘架载具数量是否是0 + JSONObject jsonDpjStart2 = pointTab.query("region_id = '" + RegionTypeEnum.DPJQB.getId() + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and vehicle_qty = '0'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonDpjStart2)) continue; - //叠盘架无载具:1-判断是否有在执行中的堆叠任务,有则等堆叠任务完成以后再去,否则去去缓存位和养生A区找 - JSONObject ddTask = taskTab.query("is_delete='0' and point_code2 = '" + dpjPoint1.getString("point_code") + "'" + " and task_status <> '7' ").uniqueResult(0); - if (ObjectUtil.isNotEmpty(ddTask)) continue; + // 判断叠盘架是否有任务 + boolean is_point = this.isTask(jsonDpjStart2.getString("point_code")); + if (!is_point) continue; - //去缓存位和养生A区找,生成到叠盘架的任务 - JSONObject whereParam = new JSONObject(); - whereParam.put("flag", "1"); - whereParam.put("vehicle_type", '%' + jsonTask.getString("vehicle_type") + "%"); - JSONObject outJsonObj = WQL.getWO("ST_VEHICLE_OUT_01").addParamMap(whereParam).process().uniqueResult(0); + // 找叠盘架暂存位是否有空托盘 + JSONObject map = new JSONObject(); + map.put("flag", "1"); + map.put("vehicle_type", vehicle_type); - // 空托盘缓存货架或者养生A区------>叠盘架B区 - JSONObject param = new JSONObject(); - Long task_id = IdUtil.getSnowflake(1, 1).nextId(); - Long task_group_id = IdUtil.getSnowflake(1, 1).nextId(); - param.put("task_id", task_id); - param.put("task_code", CodeUtil.getNewCode("TASK_CODE")); - param.put("vehicle_type", vehicle_type); - param.put("priority", 100); - param.put("handle_class", THIS_CLASS); - param.put("task_type", "kzj"); - param.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); - param.put("task_group_id", task_group_id); - param.put("sort_seq", 1); - param.put("point_code1", outJsonObj.getString("point_code")); - param.put("point_code2", dpjPoint1.getString("point_code")); - param.put("create_name", SecurityUtils.getCurrentUsername()); - param.put("create_id", SecurityUtils.getCurrentUserId()); - param.put("create_time", DateUtil.now()); - taskTab.insert(param); + JSONObject jsonZcKtp = WQL.getWO("QSCH_GjxCallEmpVehicleTask").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isNotEmpty(jsonZcKtp)) { + // 创建任务:空载具暂存位 --> 叠盘架 + SchTaskDto dto = SchTaskDto.builder() + .task_id(org.nl.wms.util.IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .acs_task_type("2") + .task_name("暂存位->叠盘架空载具") + .task_status(TaskStatusEnum.START_AND_POINT.getCode()) + .point_code1(jsonZcKtp.getString("point_code")) + .point_code2(jsonDpjStart2.getString("point_code")) + .vehicle_code(jsonZcKtp.getString("vehicle_code")) + .vehicle_type(jsonZcKtp.getString("vehicle_type")) + .vehicle_qty(jsonZcKtp.getIntValue("vehicle_qty")) + .task_group_id(jsonTask.getLong("task_group_id")) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + // 锁定起点 + jsonZcKtp.put("lock_type", "2"); + pointTab.update(jsonZcKtp); + } else { + // 空托盘暂存区没有就到养生A区找: 先找到出库等待点 + JSONObject jsonEmpWait = pointTab.query("region_id = '" + RegionTypeEnum.YSAQKTPQ01.getId() + + "' and row_num = '9' and can_vehicle_type = '" + vehicle_type + + "' and is_used = '1' and is_delete = '0'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonEmpWait)) continue; - //锁住起点 - outJsonObj.put("lock_type", "2"); - pointTab.update(outJsonObj); - this.notifyAcs(String.valueOf(task_id)); + JSONObject jsonStartPoint = pointTab.query("region_id = '" + jsonEmpWait.getString("region_id") + + "' and block_num = '" + jsonEmpWait.getString("block_num") + + "' and col_num = '" + jsonEmpWait.getString("col_num") + + "' and point_status = '2' and lock_type = '1' order by out_empty_seq DESC").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonStartPoint)) continue; - - jsonTask.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); - jsonTask.put("point_code1", outJsonObj.getString("point_code")); - jsonTask.put("sort_seq", 2); - jsonTask.put("task_group_id", task_group_id); - jsonTask.put("remark", "叠盘架无载具!"); - taskTab.update(jsonTask); - - //锁住点位 - dpjPoint1.put("lock_type", "2"); - pointTab.update(outJsonObj); + // 判断找到的空载具点位是否是等待点 + if (StrUtil.equals(jsonEmpWait.getString("point_code"), jsonStartPoint.getString("point_code"))) { + // 创建 养生A区空载具等待点 --> 叠盘架 + SchTaskDto dto = SchTaskDto.builder() + .task_id(IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .acs_task_type("2") + .task_name("养生A区-> 叠盘架空载具") + .task_status(TaskStatusEnum.START_AND_POINT.getCode()) + .point_code1(jsonStartPoint.getString("point_code")) + .point_code2(jsonDpjStart2.getString("point_code")) + .vehicle_code(jsonStartPoint.getString("vehicle_code")) + .vehicle_type(jsonStartPoint.getString("vehicle_type")) + .vehicle_qty(jsonStartPoint.getIntValue("vehicle_qty")) + .task_group_id(jsonTask.getLong("task_group_id")) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + // 锁起点 + jsonStartPoint.put("lock_type", "2"); + pointTab.update(jsonStartPoint); + } else { + // 判断等待点是否是 未锁定、为空载具 + if (StrUtil.equals(jsonEmpWait.getString("lock_type"), "1")) { + // 创建 养生A区空载具 --> 叠盘架 + SchTaskDto dto = SchTaskDto.builder() + .task_id(org.nl.wms.util.IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .acs_task_type("2") + .task_name("养生A区>叠盘架空载具") + .task_status(TaskStatusEnum.START_AND_POINT.getCode()) + .point_code1(jsonStartPoint.getString("point_code")) + .point_code2(jsonDpjStart2.getString("point_code")) + .vehicle_code(jsonStartPoint.getString("vehicle_code")) + .vehicle_type(jsonStartPoint.getString("vehicle_type")) + .vehicle_qty(jsonStartPoint.getIntValue("vehicle_qty")) + .task_group_id(jsonTask.getLong("task_group_id")) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + // 锁起点 + jsonStartPoint.put("lock_type", "2"); + pointTab.update(jsonStartPoint); + // 锁等待点 + jsonEmpWait.put("lock_type", "2"); + pointTab.update(jsonEmpWait); + } else { + continue; + } + } + } } - - } } @@ -186,42 +308,52 @@ public class GjxCallEmpVehicleTask extends AbstractAcsTask { @Override @Transactional(rollbackFor = Exception.class) +// 虽然是养生A区,应该有二次申请,但是通过判断叠盘架是否有任务来判断做限制 public String createTask(JSONObject form) { - WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + /* + * 1.先生成确定终点的任务 + * 2.通过findStartPoint()找起点 + * 3.下发给ACS + */ + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 + WQLObject workOrderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); // 生产工单表 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); //点位基础表 - String end_point_code = form.getString("point_code2"); - String vehicle_type = form.getString("vehicle_type"); + //任务表【SCH_BASE_Task】 + //判断当前点是否有未完成的任务 + JSONObject taskObj = taskTab.query("is_delete='0' and point_code2 = '" + form.getString("point_code2") + "' and task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) throw new BadRequestException("当前点位" + form.getString("point_code2") + "存在未完成的任务"); - // 终点不能为空 - 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"); - jsonTask.put("task_status", TaskStatusEnum.SURE_END.getCode()); - jsonTask.put("point_code1", ""); - taskTab.insert(jsonTask); - this.findStartPoint(); - return String.valueOf(task_id); + String point_code2 = form.getString("point_code2"); + String sub_device_code = point_code2.substring(0, point_code2.indexOf("_")); + + String device_code = pointTab.query("point_code = '" + sub_device_code + "'").uniqueResult(0).getString("device_code"); + + JSONObject workOrderObj = workOrderTab.query("device_code = '" + device_code + "' and order_status = '3' and is_delete ='0'").uniqueResult(0); + if (ObjectUtil.isEmpty(workOrderObj)) throw new BadRequestException("该设备当前未生产或者已删除"); + + SchTaskDto dto = SchTaskDto.builder().task_id(org.nl.wms.util.IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .task_name("共挤线叫空载具") + .task_status(TaskStatusEnum.SURE_END.getCode()) + .point_code2(point_code2) + .acs_task_type("2") + .vehicle_code(form.getString("vehicle_code")) + .vehicle_type(workOrderObj.getString("vehicle_type")) + .vehicle_qty(form.getIntValue("qty")) + .task_group_id(IdUtil.getLongId()) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + + this.immediateNotifyAcs(); + return String.valueOf(dto.getTask_id()); } @Override @@ -236,4 +368,62 @@ public class GjxCallEmpVehicleTask extends AbstractAcsTask { } + @Override + public List addTask() { + /* + * 下发给ACS时需要特殊处理 + */ + JSONArray arr = WQLObject.getWQLObject("SCH_BASE_Task").query("handle_class = '" + THIS_CLASS + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and is_delete ='0'").getResultJSONArray(0); + + ArrayList resultList = new ArrayList<>(); + for (int i = 0; i < arr.size(); i++) { + JSONObject json = arr.getJSONObject(i); + + String point_code1 = json.getString("point_code1"); + //判断起点是否属于养生A区 + if (point_code1.startsWith("2")) { + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + point_code1 = point_code1.substring(0, 4) + "1" + point_code1.substring(4, 9); + } + + AcsTaskDto dto = AcsTaskDto.builder() + .task_id(json.getString("task_id")) + .task_code(json.getString("task_code")) + .task_type(json.getString("acs_task_type")) + .start_device_code(point_code1) + .next_device_code(json.getString("point_code3")) + .vehicle_code(json.getString("vehicle_code")) + .vehicle_type(json.getString("vehicle_type")) + .priority(json.getString("priority")) + .remark(json.getString("remark")) + .build(); + resultList.add(dto); + } + return resultList; + } + + @Transactional(rollbackFor = Exception.class) + public boolean isTask(String point_code) { + /* + * 判断点位是否有任务存在 + */ + WQLObject tab = WQLObject.getWQLObject("SCH_BASE_Task"); + + boolean result; + + JSONObject jsonPointCode1 = tab.query("point_code1 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode2 = tab.query("point_code2 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode3 = tab.query("point_code3 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode4 = tab.query("point_code4 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + + if (ObjectUtil.isEmpty(jsonPointCode1) && ObjectUtil.isEmpty(jsonPointCode2) && ObjectUtil.isEmpty(jsonPointCode3) && ObjectUtil.isEmpty(jsonPointCode4)) { + result = true; + } else { + result = false; + } + + return result; + } + + } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/YqxCallEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/YqxCallEmpVehicleTask.java index 98c5697..6c70069 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/YqxCallEmpVehicleTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/YqxCallEmpVehicleTask.java @@ -1,11 +1,11 @@ package org.nl.wms.sch.tasks.callEmpty; 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.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -14,19 +14,15 @@ 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.SchTaskDto; 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.nl.wms.sch.tasks.AcsTaskDto; import org.nl.wms.sch.tasks.RegionTypeEnum; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.math.BigDecimal; +import java.util.ArrayList; import java.util.List; @Service @@ -36,7 +32,6 @@ 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) { @@ -47,7 +42,47 @@ public class YqxCallEmpVehicleTask extends AbstractAcsTask { JSONObject jsonTask = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); if (StrUtil.equals(status, "0")) { - // 取消删除任务 + /* + * 取消删除 + * 1.终点为叠盘架更新起点点位、等待点点位、叠盘架点位 + * 2.终点为油漆线更新叠盘架点位 + */ + if (StrUtil.equals(jsonTask.getString("task_status"), TaskStatusEnum.FINISHED.getCode())) { + throw new BadRequestException("已完成不能取消!"); + } + + String point_code1 = jsonTask.getString("point_code1"); + String point_code2 = jsonTask.getString("point_code2"); + + JSONObject jsonEnd = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + // 终点在叠盘架 + if (StrUtil.equals(jsonEnd.getString("region_id"), RegionTypeEnum.DPJQB.getId())) { + JSONObject jsonStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + // 判断此起点是否是等待点 + if (!StrUtil.equals(jsonStart.getString("row_num"), "9")) { + // 如果不是等待点更新等待点状态 + JSONObject jsonEmpWait = pointTab.query("region_id = '" + jsonStart.getString("region_id") + + "' and block_num = '" + jsonStart.getString("block_num") + + "' and col_num = '" + jsonStart.getString("col_num") + + "' and row_num = '9'").uniqueResult(0); + + jsonEmpWait.put("lock_type", "1"); + pointTab.update(jsonEmpWait); + } + jsonStart.put("lock_type", "1"); + pointTab.update(jsonStart); + + // 更新终点(叠盘架状态) + jsonEnd.put("lock_type", "1"); + pointTab.update(jsonEnd); + + } else { + // 终点在油漆线 + JSONObject jsonStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + jsonStart.put("lock_type", "1"); + pointTab.update(jsonStart); + } + taskTab.delete("task_id = '" + task_id + "'"); } @@ -60,107 +95,272 @@ public class YqxCallEmpVehicleTask extends AbstractAcsTask { } if (StrUtil.equals(status, TaskStatusEnum.FINISHED.getCode())) { - // 更改任务状态为完成 + /* + * 更改任务状态为完成 + * 1.终点为叠盘架更新叠盘架数量、起点点位状态、等待位状态,更新任务组状态 + * 2.终点为油漆线,更新起点载具数量 + */ 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); + // 判断终点在哪里 + String point_code1 = jsonTask.getString("point_code1"); + String point_code2 = jsonTask.getString("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)); + JSONObject jsonEnd = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + // 终点在叠盘架 + if (StrUtil.equals(jsonEnd.getString("region_id"), RegionTypeEnum.DPJQA.getId())) { + // 更新起点点位状态 + JSONObject jsonStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + // 判断起点是不是养生A区空载具 + if (StrUtil.equals(jsonStart.getString("region_id"), RegionTypeEnum.YSAQKTPQ01.getId())) { + // 判断此起点是否是等待点 + if (!StrUtil.equals(jsonStart.getString("row_num"), "9")) { + // 如果不是等待点更新等待点状态 + JSONObject jsonEmpWait = pointTab.query("region_id = '" + jsonStart.getString("region_id") + + "' and block_num = '" + jsonStart.getString("block_num") + + "' and col_num = '" + jsonStart.getString("col_num") + + "' and row_num = '9'").uniqueResult(0); - point_code1.setVehicle_qty(vehicle_qty_point); - if (StrUtil.equals(vehicle_qty_point.toString(), "0")) { - point_code1.setPoint_status("00"); - point_code1.setVehicle_type(""); + jsonEmpWait.put("lock_type", "1"); + pointTab.update(jsonEmpWait); + } + } + + jsonStart.put("point_status", "1"); + jsonStart.put("lock_type", "1"); + jsonStart.put("vehicle_type", ""); + jsonStart.put("vehicle_code", ""); + jsonStart.put("vehicle_qty", 0); + pointTab.update(jsonStart); + + // 更新终点(叠盘架状态) + jsonEnd.put("vehicle_qty", NumberUtil.add(jsonEnd.getString("vehicle_qty"),jsonTask.getString("vehicle_qty"))); + jsonEnd.put("lock_type", "1"); + jsonEnd.put("point_status", "2"); + jsonEnd.put("vehicle_type", jsonTask.getString("vehicle_type")); + pointTab.update(jsonEnd); + + // 更新任务组状态 + JSONObject jsonTask2 = taskTab.query("task_group_id = '" + jsonTask.getString("task_group_id") + "' and task_id <> '" + jsonTask.getString("task_id") + "'").uniqueResult(0); + // 判断叠盘架数量是否 < 需求数量 (暂时只能<需求数量) + if (jsonEnd.getIntValue("vehicle_qty") < jsonTask2.getIntValue("vehicle_qty")) { + jsonTask2.put("vehicle_qty", jsonEnd.getIntValue("vehicle_qty")); + } + jsonTask2.put("point_code1", jsonEnd.getString("point_code")); + jsonTask2.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + taskTab.update(jsonTask2); + } else { + // 终点在油漆线: 更新起点(叠盘架)数量 + JSONObject jsonStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); + jsonStart.put("vehicle_qty",NumberUtil.sub(jsonStart.getString("vehicle_qty"),jsonTask.getString("vehicle_qty"))); + jsonStart.put("lock_type", "1"); + if (StrUtil.equals(jsonStart.getString("vehicle_qty"),"0")) { + jsonStart.put("point_status", "1"); + jsonStart.put("vehicle_type", ""); + } + pointTab.update(jsonStart); } - point_code1.setLock_type("00"); - pointTab.update(JSONObject.parseObject(JSON.toJSONString(point_code1))); } } + /** + * 虽然是养生A区,应该有二次申请,但是通过判断叠盘架是否有任务来判断做限制 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void findStartPoint() { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); // 点位表 + + JSONArray taskArr = taskTab.query("is_delete = '0' and handle_class = '" + this.THIS_CLASS + "' and task_status = '" + TaskStatusEnum.SURE_END.getCode() + "'").getResultJSONArray(0); + for (int i = 0; i < taskArr.size(); i++) { + // 创建任务 + JSONObject jsonTask = taskArr.getJSONObject(i); + String vehicle_type = jsonTask.getString("vehicle_type"); + + // 找叠盘架是否与对应的载具类型 + JSONObject jsonDpjStart = pointTab.query("region_id = '" + RegionTypeEnum.DPJQA.getId() + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and vehicle_qty <> '0'").uniqueResult(0); + + if (ObjectUtil.isNotEmpty(jsonDpjStart)) { + // 判断叠盘架是否有任务 有就下一个任务 + boolean is_point = this.isTask(jsonDpjStart.getString("point_code")); + if (!is_point) continue; + + // 判断叠盘架数量是否 < 需求数量 (暂时只能<需求数量) + if (jsonDpjStart.getIntValue("vehicle_qty") < jsonTask.getIntValue("vehicle_qty")) { + jsonTask.put("vehicle_qty", jsonDpjStart.getIntValue("vehicle_qty")); + } + + // 更新任务起点 + jsonTask.put("point_code1", jsonDpjStart.getString("point_code")); + jsonTask.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + taskTab.update(jsonTask); + + } else { + // 判断叠盘架载具数量是否是0 + JSONObject jsonDpjStart2 = pointTab.query("region_id = '" + RegionTypeEnum.DPJQA.getId() + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and vehicle_qty = '0'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonDpjStart2)) continue; + + // 判断叠盘架是否有任务 + boolean is_point = this.isTask(jsonDpjStart2.getString("point_code")); + if (!is_point) continue; + + // 找叠盘架暂存位是否有空托盘 + JSONObject map = new JSONObject(); + map.put("flag", "1"); + map.put("vehicle_type", vehicle_type); + + JSONObject jsonZcKtp = WQL.getWO("QSCH_YqxCallEmpVehicleTask").addParamMap(map).process().uniqueResult(0); + if (ObjectUtil.isNotEmpty(jsonZcKtp)) { + // 创建任务:空载具暂存位 --> 叠盘架 + SchTaskDto dto = SchTaskDto.builder() + .task_id(org.nl.wms.util.IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .acs_task_type("2") + .task_name("暂存位>叠盘架空载具") + .task_status(TaskStatusEnum.START_AND_POINT.getCode()) + .point_code1(jsonZcKtp.getString("point_code")) + .point_code2(jsonDpjStart2.getString("point_code")) + .vehicle_code(jsonZcKtp.getString("vehicle_code")) + .vehicle_type(jsonZcKtp.getString("vehicle_type")) + .vehicle_qty(jsonZcKtp.getIntValue("vehicle_qty")) + .task_group_id(jsonTask.getLong("task_group_id")) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + // 锁定起点 + jsonZcKtp.put("lock_type", "2"); + pointTab.update(jsonZcKtp); + } else { + // 空托盘暂存区没有就到养生A区找: 先找到出库等待点 + JSONObject jsonEmpWait = pointTab.query("region_id = '" + RegionTypeEnum.YSAQKTPQ01.getId() + + "' and row_num = '9' and can_vehicle_type = '" + vehicle_type + + "' and is_used = '1' and is_delete = '0'").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonEmpWait)) continue; + + JSONObject jsonStartPoint = pointTab.query("region_id = '" + jsonEmpWait.getString("region_id") + + "' and block_num = '" + jsonEmpWait.getString("block_num") + + "' and col_num = '" + jsonEmpWait.getString("col_num") + + "' and point_status = '2' and lock_type = '1' order by out_empty_seq DESC").uniqueResult(0); + if (ObjectUtil.isEmpty(jsonStartPoint)) continue; + + // 判断找到的空载具点位是否是等待点 + if (StrUtil.equals(jsonEmpWait.getString("point_code"), jsonStartPoint.getString("point_code"))) { + // 创建 养生A区空载具等待点 --> 叠盘架 + SchTaskDto dto = SchTaskDto.builder() + .task_id(org.nl.wms.util.IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .acs_task_type("2") + .task_name("养生A区>叠盘架空载具") + .task_status(TaskStatusEnum.START_AND_POINT.getCode()) + .point_code1(jsonStartPoint.getString("point_code")) + .point_code2(jsonDpjStart2.getString("point_code")) + .vehicle_code(jsonStartPoint.getString("vehicle_code")) + .vehicle_type(jsonStartPoint.getString("vehicle_type")) + .vehicle_qty(jsonStartPoint.getIntValue("vehicle_qty")) + .task_group_id(jsonTask.getLong("task_group_id")) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + // 锁起点 + jsonStartPoint.put("lock_type", "2"); + pointTab.update(jsonStartPoint); + } else { + // 判断等待点是否是 未锁定 + if (StrUtil.equals(jsonEmpWait.getString("lock_type"), "1")) { + // 创建 养生A区空载具 --> 叠盘架 + SchTaskDto dto = SchTaskDto.builder() + .task_id(org.nl.wms.util.IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .acs_task_type("2") + .task_name("养生A区>叠盘架空载具") + .task_status(TaskStatusEnum.START_AND_POINT.getCode()) + .point_code1(jsonStartPoint.getString("point_code")) + .point_code2(jsonDpjStart2.getString("point_code")) + .vehicle_code(jsonStartPoint.getString("vehicle_code")) + .vehicle_type(jsonStartPoint.getString("vehicle_type")) + .vehicle_qty(jsonStartPoint.getIntValue("vehicle_qty")) + .task_group_id(jsonTask.getLong("task_group_id")) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + // 锁起点 + jsonStartPoint.put("lock_type", "2"); + pointTab.update(jsonStartPoint); + // 锁等待点 + jsonEmpWait.put("lock_type", "2"); + pointTab.update(jsonEmpWait); + } else { + continue; + + } + } + } + } + } + + } @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()中 + * 1.先生成确定终点的任务 + * 2.通过findStartPoint()找起点 + * 3.下发给ACS */ - //起点不确定 - if (ObjectUtil.isEmpty(point_code1)) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 + WQLObject workOrderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); // 生产工单表 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); //点位基础表 - 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("起点点位不可用或不存在"); - } + //任务表【SCH_BASE_Task】 + //判断当前点是否有未完成的任务 + JSONObject taskObj = taskTab.query("is_delete='0' and point_code2 = '" + form.getString("point_code2") + "' and task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) throw new BadRequestException("当前点位" + form.getString("point_code2") + "存在未完成的任务"); - // 创建任务 - JSONObject jsonTask = new JSONObject(); - String task_id = IdUtil.getSnowflake(1, 1).nextId() + ""; - jsonTask.put("task_id", task_id); + String point_code2 = form.getString("point_code2"); + String sub_device_code = point_code2.substring(0, point_code2.indexOf("_")); - jsonTask.put("task_code", CodeUtil.getNewCode("TASK_CODE")); - jsonTask.put("task_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); + String device_code = pointTab.query("point_code = '" + sub_device_code + "'").uniqueResult(0).getString("device_code"); - // 锁定起点点位 - JSONObject jsonPoint = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); - jsonPoint.put("lock_type", "02"); - pointTab.update(jsonPoint); + JSONObject workOrderObj = workOrderTab.query("device_code = '" + device_code + "' and order_status = '3' and is_delete ='0'").uniqueResult(0); + if (ObjectUtil.isEmpty(workOrderObj)) throw new BadRequestException("该设备当前未生产或者已删除"); - return task_id; + SchTaskDto dto = SchTaskDto.builder().task_id(org.nl.wms.util.IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .task_name("油漆线叫空载具") + .task_status(TaskStatusEnum.SURE_END.getCode()) + .point_code2(point_code2) + .acs_task_type("2") + .vehicle_code(form.getString("vehicle_code")) + .vehicle_type(workOrderObj.getString("vehicle_type")) + .vehicle_qty(form.getIntValue("qty")) + .task_group_id(org.nl.wms.util.IdUtil.getLongId()) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + + this.immediateNotifyAcs(); + return String.valueOf(dto.getTask_id()); } @Override @@ -171,128 +371,64 @@ public class YqxCallEmpVehicleTask extends AbstractAcsTask { } - @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; - } - @Override public List addTask() { - return null; + /* + * 下发给ACS时需要特殊处理 + */ + JSONArray arr = WQLObject.getWQLObject("SCH_BASE_Task").query("handle_class = '"+THIS_CLASS+"' and task_status = '"+TaskStatusEnum.START_AND_POINT.getCode()+"' and is_delete ='0'").getResultJSONArray(0); + + ArrayList resultList = new ArrayList<>(); + for (int i = 0; i < arr.size(); i++) { + JSONObject json = arr.getJSONObject(i); + String point_code1 = json.getString("point_code1"); + //判断起点是否属于养生A区 + if (point_code1.startsWith("2")) { + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + point_code1 = point_code1.substring(0, 4) + "1" + point_code1.substring(4, 9); + } + + AcsTaskDto dto = AcsTaskDto.builder() + .task_id(json.getString("task_id")) + .task_code(json.getString("task_code")) + .task_type(json.getString("acs_task_type")) + .start_device_code(point_code1) + .next_device_code(json.getString("point_code3")) + .vehicle_code(json.getString("vehicle_code")) + .vehicle_type(json.getString("vehicle_type")) + .priority(json.getString("priority")) + .remark(json.getString("remark")) + .build(); + resultList.add(dto); + } + return resultList; + } + + @Transactional(rollbackFor = Exception.class) + public boolean isTask(String point_code) { + /* + * 判断点位是否有任务存在 + */ + WQLObject tab = WQLObject.getWQLObject("SCH_BASE_Task"); + + boolean result; + + JSONObject jsonPointCode1 = tab.query("point_code1 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode2 = tab.query("point_code2 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode3 = tab.query("point_code3 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode4 = tab.query("point_code4 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + + if (ObjectUtil.isEmpty(jsonPointCode1) && ObjectUtil.isEmpty(jsonPointCode2) && ObjectUtil.isEmpty(jsonPointCode3) && ObjectUtil.isEmpty(jsonPointCode4)) { + result = true; + } else { + result = false; + } + + return result; } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/wql/QSCH_GjxCallEmpVehicleTask.wql b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/wql/QSCH_GjxCallEmpVehicleTask.wql new file mode 100644 index 0000000..b76c2fb --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/wql/QSCH_GjxCallEmpVehicleTask.wql @@ -0,0 +1,60 @@ +[交易说明] + 交易名: 共挤线申请空盘 + 所属模块: + 功能简述: + 版权所有: + 表引用: + 版本经历: + +[数据库] + --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 + +[IO定义] + ################################################# + ## 表字段对应输入参数 + ################################################# + 输入.flag TYPEAS s_string + 输入.vehicle_type TYPEAS s_string + +[临时表] + --这边列出来的临时表就会在运行期动态创建 + +[临时变量] + --所有中间过程变量均可在此处定义 + +[业务过程] + + ########################################## + # 1、输入输出检查 # + ########################################## + + + ########################################## + # 2、主过程前处理 # + ########################################## + + + ########################################## + # 3、业务主过程 # + ########################################## + + IF 输入.flag = "1" + QUERY + SELECT + * + FROM + SCH_BASE_Point + WHERE + is_used = '1' + AND is_delete = '0' + AND lock_type = '1' + AND point_status = '2' + AND region_code = 'KTPHCQB01' + + OPTION 输入.vehicle_type <> "" + can_vehicle_type = 输入.vehicle_type + ENDOPTION + + ENDSELECT + ENDQUERY + ENDIF \ No newline at end of file diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/wql/QSCH_YqxCallEmpVehicleTask.wql b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/wql/QSCH_YqxCallEmpVehicleTask.wql new file mode 100644 index 0000000..8163667 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callEmpty/wql/QSCH_YqxCallEmpVehicleTask.wql @@ -0,0 +1,60 @@ +[交易说明] + 交易名: 油漆线申请空盘 + 所属模块: + 功能简述: + 版权所有: + 表引用: + 版本经历: + +[数据库] + --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 + +[IO定义] + ################################################# + ## 表字段对应输入参数 + ################################################# + 输入.flag TYPEAS s_string + 输入.vehicle_type TYPEAS s_string + +[临时表] + --这边列出来的临时表就会在运行期动态创建 + +[临时变量] + --所有中间过程变量均可在此处定义 + +[业务过程] + + ########################################## + # 1、输入输出检查 # + ########################################## + + + ########################################## + # 2、主过程前处理 # + ########################################## + + + ########################################## + # 3、业务主过程 # + ########################################## + + IF 输入.flag = "1" + QUERY + SELECT + * + FROM + SCH_BASE_Point + WHERE + is_used = '1' + AND is_delete = '0' + AND lock_type = '1' + AND point_status = '2' + AND region_code = 'KTPHCQA01' + + OPTION 输入.vehicle_type <> "" + can_vehicle_type = 输入.vehicle_type + ENDOPTION + + ENDSELECT + ENDQUERY + ENDIF \ No newline at end of file diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/CallMaterialTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/CallMaterialTask.java deleted file mode 100644 index c1c5623..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/CallMaterialTask.java +++ /dev/null @@ -1,277 +0,0 @@ -package org.nl.wms.sch.tasks.callMaterial; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -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.sch.PointFindUtil; -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.nl.wms.sch.service.impl.PointServiceImpl; -import org.nl.wms.sch.tasks.AcsTaskDto; -import org.nl.wms.sch.tasks.RegionTypeEnum; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -@Service -public class CallMaterialTask extends AbstractAcsTask { - private final String THIS_CLASS = CallMaterialTask.class.getName(); - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateTaskStatus(JSONObject taskObj, String status) { - /** - *改变任务状态 - **/ - String task_id = taskObj.getString("task_id"); - WQLObject taskTab = WQLObject.getWQLObject("sch_base_task"); - 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); - HashMap map = new HashMap(); - map.put("bill_status", "40"); - map.put("update_optid", SecurityUtils.getCurrentUserId()); - map.put("update_optname", SecurityUtils.getCurrentNickName()); - map.put("update_time", DateUtil.now()); - WQLObject.getWQLObject("ST_IVT_regionIO").update(map, "task_id='" + jsonTask.getString("task_id") + "'"); - - } - - if (TaskStatusEnum.FINISHED.getCode().equals(status)) { - // 更新任务状态为完成 - jsonTask.put("task_status", TaskStatusEnum.FINISHED.getCode()); - jsonTask.put("taskfinish_mode", taskObj.getString("taskfinish_mode")); - jsonTask.put("update_time", DateUtil.now()); - jsonTask.put("remark", "任务执行完成"); - ///审核单据 增加库存 改变出入库表的状态 - WQLObject mstTab = WQLObject.getWQLObject("ST_IVT_regionIO"); - JSONObject mstObj = mstTab.query("task_id='" + task_id + "' and is_delete='0'").uniqueResult(0); - - //解锁仓位,托盘信息,回写到点位上去 - WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); - - JSONObject startPointObj = pointTab.query("point_code='" + jsonTask.getString("point_code1") + "'").uniqueResult(0); - startPointObj.put("lock_type", "1"); - startPointObj.put("point_status", "00"); - startPointObj.put("vehicle_code", ""); - startPointObj.put("vehicle_type", ""); - pointTab.update(startPointObj); - taskTab.update(jsonTask); - } - - } - - @Override - public void findStartPoint() { - String task_status = TaskStatusEnum.SURE_START.getCode(); - WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); - JSONArray taskArry = taskTab.query("task_status='" + task_status + "' AND handle_class='" + THIS_CLASS + "' AND is_delete='0' ").getResultJSONArray(0); - for (int i = 0; i < taskArry.size(); i++) { - JSONObject taskObj = taskArry.getJSONObject(i); - String task_id = taskObj.getString("task_id"); - //1 将任务修改为分配 2将终点写入,完成分配,3 加锁点位 - //找一个合适的仓位 - WQLObject ProcedureIOStable = WQLObject.getWQLObject("ST_IVT_regionIO"); - JSONObject IosObj = ProcedureIOStable.query("task_id='" + task_id + "' and is_delete ='0'").uniqueResult(0); - if (ObjectUtil.isEmpty(IosObj)) { - throw new BadRequestException("未找到任务号为'" + taskObj.getString("task_code") + "'的入库单据!"); - } - JSONObject param = new JSONObject(); - param.put("material_id", IosObj.getString("material_id")); - param.put("area_type", IosObj.getString("start_area")); - JSONObject inStructObj = PointFindUtil.getOutStruct(param); - if (ObjectUtil.isEmpty(inStructObj)) { - throw new BadRequestException("未找到合适的出库仓位!"); - } - //修改单据状态,将终点填入 - IosObj.put("bill_status", "20"); - IosObj.put("point_code1", inStructObj.getString("struct_code")); - ProcedureIOStable.update(IosObj); - //终点加锁 - HashMap lock_map = new HashMap(); - lock_map.put("lock_type", "2"); - WQLObject.getWQLObject("sch_base_point").update(lock_map, "point_code = '" + inStructObj.getString("struct_code") + "'"); - //修改任务状态 - taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); - taskObj.put("update_optid", SecurityUtils.getCurrentUserId()); - taskObj.put("update_optname", SecurityUtils.getCurrentNickName()); - taskObj.put("update_time", DateUtil.now()); - taskTab.update(taskObj); - } - - } - - - @Override - @Transactional(rollbackFor = Exception.class) - public String createTask(JSONObject form) { - //请求参数 载具、起点、终点 - String vehicle_code = form.getString("vehicle_code"); - String point_code1 = form.getString("point_code1"); - String point_code2 = form.getString("point_code2"); - String vehicle_type = form.getString("vehicle_type"); - - String task_status = TaskStatusEnum.START_AND_POINT.getCode(); - String material_id = form.getString("material_id"); - String create_mode = form.getString("create_mode"); - String iostorinv_id = form.getString("iostorinv_id"); - - WQLObject taskTable = WQLObject.getWQLObject("SCH_BASE_Task"); - WQLObject regionTable = WQLObject.getWQLObject("ST_IVT_regionIO"); - - if (StrUtil.isEmpty(point_code2)) { - throw new BadRequestException("终点不能为空!"); - } - if (StrUtil.isEmpty(material_id)) { - throw new BadRequestException("物料标识不能为空!"); - } - if (StrUtil.isEmpty(create_mode)) { - throw new BadRequestException("创建方式不能为空!"); - } - //判断终点有没有未完成的指令 - JSONObject beforTaskObj = taskTable. - 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") + "' 未完成!"); - } - PointServiceImpl pointService = SpringContextHolder.getBean(PointServiceImpl.class); - String task_id = IdUtil.getSnowflake(1, 1).nextId() + ""; - String start_area = ""; - String qty = ""; - String qty_unit_id = ""; - - if (StrUtil.isEmpty(point_code1)) { - // 起点为空找到对应的起点 - JSONObject param = new JSONObject(); - param.put("point_code2", point_code2); - param.put("vehicle_type", vehicle_type); - param.put("material_id", material_id); - JSONObject ivtObj = this.findBeginPoint(param); - - qty = ivtObj.getString("canuse_qty"); - qty_unit_id = ivtObj.getString("qty_unit_id"); - point_code1 = ivtObj.getString("struct_code"); - } else { - // 不能空则为点对点,查找对应出入库单据 - if (ObjectUtil.isEmpty(iostorinv_id)) throw new BadRequestException("出库单id不能为空"); - JSONObject jsonRegion = regionTable.query("iostorinv_id = '" + iostorinv_id + "'").uniqueResult(0); - qty = jsonRegion.getString("qty"); - qty_unit_id = jsonRegion.getString("qty_unit_id"); - } - - PointDto startPoint = pointService.findByCode(point_code1); - //起点点加锁 - WQLObject pointTable = WQLObject.getWQLObject("sch_base_point"); - JSONObject startPointObj = pointTable.query("point_code='" + point_code1 + "'").uniqueResult(0); - startPointObj.put("lock_type", "2"); - pointTable.update(startPointObj); - - JSONObject taskObj = new JSONObject(); - taskObj.put("task_id", task_id); - taskObj.put("task_code", CodeUtil.getNewCode("TASK_CODE")); - taskObj.put("task_type", "02"); - taskObj.put("task_status", task_status); - taskObj.put("point_code1", point_code1); - taskObj.put("start_area", start_area); - taskObj.put("request_param", form.toJSONString()); - taskObj.put("point_code2", point_code2); - taskObj.put("vehicle_code", vehicle_code); - taskObj.put("handle_class", THIS_CLASS); - taskObj.put("is_auto_issue", "1"); - taskObj.put("create_name", SecurityUtils.getCurrentUsername()); - taskObj.put("create_id", SecurityUtils.getCurrentUserId()); - taskObj.put("create_time", DateUtil.now()); - taskObj.put("is_delete", "0"); - taskTable.insert(taskObj); - return task_id; - } - - @Override - public List addTask() { - //任务基础表【sch_base_task】 - WQLObject taskTab = WQLObject.getWQLObject("sch_base_task"); - JSONArray tasks = taskTab.query("handle_class = '" + this.getClass().getName() + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and is_delete ='0'").getResultJSONArray(0); - List arr = new ArrayList<>(); - for (int i = 0, j = tasks.size(); i < j; i++) { - /*JSONObject json = tasks.getJSONObject(i); - AcsTaskDto taskDto = new AcsTaskDto(); - taskDto.setTask_id(json.getString("task_id")); - taskDto.setTask_code(json.getString("task_code")); - taskDto.setTask_type("1"); - taskDto.setRoute_plan_code("normal"); - taskDto.setStart_device_code(json.getString("point_code1")); - taskDto.setNext_device_code(json.getString("point_code2")); - taskDto.setVehicle_code(json.getString("vehicle_code")); - arr.add(taskDto);*/ - } - return arr; - } - - @Override - 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 cancel(String task_id) { - - } - - @Transactional(rollbackFor = Exception.class) - public JSONObject findBeginPoint(JSONObject json) { - String point_code2 = json.getString("point_code2"); - String vehicle_type = json.getString("vehicle_type"); - String material_id = json.getString("material_id"); - - WQLObject regionTab = WQLObject.getWQLObject("SCH_BASE_Region"); - - // 根据起点判断是什么区域 然后要入到什么区 - PointDto endDto = SpringContextHolder.getBean(PointService.class).findByCode(point_code2); - if (ObjectUtil.isEmpty(endDto)) throw new BadRequestException("终点点位不存在"); - JSONObject jsonEndRegion = regionTab.query("region_id = '" + endDto.getRegion_id() + "'").uniqueResult(0); - - /* - * 物料出库业务:目前只有1个业务,如果区域不正确则报错 - * 1.养生A区 --> 油漆线 - */ - JSONObject resuft = new JSONObject(); - if (StrUtil.equals(jsonEndRegion.getString("region_code"), RegionTypeEnum.YQQY.getCode())) { - JSONObject map = new JSONObject(); - map.put("flag", "3"); - map.put("vehicle_type", vehicle_type); - map.put("material_id", material_id); - map.put("region_code", RegionTypeEnum.YSQA.getCode()); - resuft = WQL.getWO("ST_REGION_OUT_01").addParamMap(map).process().uniqueResult(0); - if (ObjectUtil.isEmpty(resuft)) throw new BadRequestException("库存不足"); - } else { - throw new BadRequestException("业务类型错误"); - } - return resuft; - } -} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/YqxCallMaterialTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/YqxCallMaterialTask.java new file mode 100644 index 0000000..be830eb --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/YqxCallMaterialTask.java @@ -0,0 +1,258 @@ +package org.nl.wms.sch.tasks.callMaterial; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +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.wms.sch.SchTaskDto; +import org.nl.wms.sch.manage.AbstractAcsTask; +import org.nl.wms.sch.manage.TaskStatusEnum; +import org.nl.wms.sch.tasks.AcsTaskDto; +import org.nl.wms.util.IdUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + + +/** + *油漆线叫料 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class YqxCallMaterialTask extends AbstractAcsTask { + private final String THIS_CLASS = YqxCallMaterialTask.class.getName(); + + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTaskStatus(JSONObject task, String status) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + + String task_id = task.getString("task_id"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); + // 物料点 + JSONObject material_point = pointTab.query("point_code = '" + taskObj.getString("point_code1") + "'").uniqueResult(0); + //任务取消 + if (StrUtil.equals(status, "0")) { + // 取消删除任务 + if (StrUtil.equals(taskObj.getString("task_status"), TaskStatusEnum.FINISHED.getCode())) { + throw new BadRequestException("已完成不能取消!"); + } + String point_code2 = taskObj.getString("point_code2"); + String point_code3 = taskObj.getString("point_code3"); + //说明未二次申请过 + if (ObjectUtil.isEmpty(point_code3)) { + JSONObject json = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + json.put("lock_type", "1"); + pointTab.update(json); + } + taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); + taskObj.put("remark", "已取消"); + taskTab.update(taskObj); + + // 点位解锁 并设置空位 + material_point.put("lock_type", "1"); + material_point.put("point_status", "1"); + pointTab.update(material_point); + } + + if ("1".equals(status)) { + // 更新任务状态为执行中 + taskObj.put("task_status", TaskStatusEnum.EXECUTING.getCode()); + taskObj.put("update_time", DateUtil.now()); + taskObj.put("car_no", taskObj.getString("car_no")); + taskTab.update(taskObj); + } + + if (StrUtil.equals(status, "2")) { + // 更改任务状态为完成 + taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + + JSONObject requestObj = task.getJSONObject("request_param"); + + //区域出入表【st_ivt_regionIO】 + WQLObject regionIoTab = WQLObject.getWQLObject("st_ivt_regionIO"); + JSONObject regionIoObj = new JSONObject(); + regionIoObj.put("iostorinv_id", IdUtil.getLongId()); + regionIoObj.put("bill_code", CodeUtil.getNewCode("IN_STORE_CODE")); + regionIoObj.put("buss_date", DateUtil.today()); + regionIoObj.put("io_type", "2"); + regionIoObj.put("region_id", material_point.getString("region_id")); + regionIoObj.put("region_code", material_point.getString("region_code")); + regionIoObj.put("region_name", material_point.getString("region_name")); + regionIoObj.put("material_id", taskObj.getString("material_id")); + regionIoObj.put("vehicle_code", taskObj.getString("vehicle_code")); + regionIoObj.put("qty", requestObj.getString("material_num")); + regionIoObj.put("bill_status", "3"); + regionIoObj.put("start_point_code", taskObj.getString("point_code1")); + regionIoObj.put("end_point_code", taskObj.getString("point_code2")); + regionIoObj.put("create_mode", "2"); + regionIoObj.put("pcsn", DateUtil.format(DateUtil.parse(DateUtil.today()), "yyyyMMdd")); + regionIoObj.put("create_id", SecurityUtils.getCurrentUserId()); + regionIoObj.put("create_name", SecurityUtils.getCurrentNickName()); + regionIoObj.put("create_time", DateUtil.now()); + regionIoTab.insert(regionIoObj); + + //完成后将仓位库存删掉 + //仓位库存表【ST_IVT_StructIvt】 + WQLObject ivtTab = WQLObject.getWQLObject("ST_IVT_StructIvt"); + ivtTab.delete("point_code = '" + taskObj.getString("point_code1") + "'"); + + // 点位解锁 并设置空位 + material_point.put("lock_type", "1"); + material_point.put("point_status", "1"); + pointTab.update(material_point); + } + + } + + @Override + public void findStartPoint() { + /* + * 根据业务找对应的起点 + */ + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); // 点位表 + JSONArray taskArr = taskTab.query("handle_class = '" + THIS_CLASS + "'and is_delete = '0' and task_status = '" + TaskStatusEnum.SURE_END.getCode() + "'").getResultJSONArray(0); + for (int i = 0; i < taskArr.size(); i++) { + JSONObject taskObj = taskArr.getJSONObject(i); + String material_id = taskObj.getString("material_id"); + String vehicle_type = taskObj.getString("vehicle_type"); + JSONObject param1 = new JSONObject(); + param1.put("flag", "1"); + param1.put("material_id", material_id); + param1.put("region_code", "YSQA01"); + param1.put("vehicle_type", "%" + vehicle_type + "%"); + //1、根据物料id查找养生A区物料点 + JSONObject json1 = WQL.getWO("QSCH_yqxCallMAterial_01").addParamMap(param1).process().uniqueResult(0); + if (ObjectUtil.isNotEmpty(json1)) { + // 拿到点位 + JSONObject material_point = pointTab.query("point_id = '" + json1.getString("point_id") + "' and lock_type = '1'").uniqueResult(0); + if (ObjectUtil.isEmpty(material_point)) throw new BadRequestException("数据错误,请校验!"); + // 物料点位上锁 + material_point.put("lock_type", "2"); + pointTab.update(material_point); + + taskObj.put("point_code1", material_point.getString("point_code")); + taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + taskObj.put("acs_task_type", "2"); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + } else { + taskObj.put("remark", "养生A区无所需物料"); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + } + + } + } + + @Override + public List addTask() { + /* + * 下发给ACS时需要特殊处理 + */ + JSONArray arr = WQLObject.getWQLObject("SCH_BASE_Task").query("handle_class = '" + THIS_CLASS + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and is_delete ='0'").getResultJSONArray(0); + + ArrayList acsTaskArr = new ArrayList<>(); + for (int i = 0; i < arr.size(); i++) { + JSONObject json = arr.getJSONObject(i); + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + String point_code =json.getString("point_code1"); + String newPoint = point_code.substring(0, 4) + "1" + point_code.substring(4, 9); + + AcsTaskDto dto = AcsTaskDto.builder() + .task_id(json.getString("task_id")) + .task_code(json.getString("task_code")) + .task_type(json.getString("acs_task_type")) + .start_device_code(newPoint) + .next_device_code(json.getString("point_code3")) + .vehicle_code(json.getString("vehicle_code")) + .vehicle_type(json.getString("vehicle_type")) + .priority(json.getString("priority")) + .remark(json.getString("remark")) + .build(); + acsTaskArr.add(dto); + } + return acsTaskArr; + } + + @Override + public String createTask(JSONObject whereJson) { + String point_code2 = whereJson.getString("point_code2"); + String vehicle_type = whereJson.getString("vehicle_type"); + String vehicle_code = whereJson.getString("vehicle_code"); + String qty = whereJson.getString("material_num"); + + //生产工单表【PDM_BD_WorkOrder】 + WQLObject workOrderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); + //任务表【SCH_BASE_Task】 + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + //判断当前点是否有未完成的任务 + JSONObject taskObj = taskTab.query("is_delete='0' and point_code2 = '" + point_code2 + "' and task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) throw new BadRequestException("当前点位" + point_code2 + "存在未完成的任务"); + //点位基础表【SCH_BASE_Point】 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); + String device_code = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0).getString("device_code"); + JSONObject workOrderObj = workOrderTab.query("device_code = '" + device_code + "' and order_status = '3' and is_delete ='0'").uniqueResult(0); + if (ObjectUtil.isEmpty(workOrderObj)) throw new BadRequestException("该设备当前未生产或者已删除"); + + SchTaskDto dto = SchTaskDto.builder() + .task_id(IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("task_type") + .task_name("油漆线叫料") + .material_qty(qty) + .task_status(TaskStatusEnum.SURE_END.getCode()) + .point_code2(point_code2) + .vehicle_code(vehicle_code) + .material_info_id(workOrderObj.getLong("workorder_id")) + .material_id(workOrderObj.getLong("material_id")) + .vehicle_type(vehicle_type) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .request_param(whereJson.toJSONString()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + + //创建好立即下发 + this.immediateNotifyAcs(); + return String.valueOf(dto.getTask_id()); + } + + @Override + public void forceFinish(String task_id) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "' and is_delete = '0' and task_status <> " + TaskStatusEnum.FINISHED.getCode()).uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) + this.updateTaskStatus(taskObj,"2"); + else { + throw new BadRequestException("未找到该任务或者任务已完成"); + } + } + + + @Override + public void cancel(String task_id) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "' and is_delete = '0' and task_status <> " + TaskStatusEnum.FINISHED.getCode()).uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) + this.updateTaskStatus(taskObj,"0"); + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/wql/QSCH_yqxCallMAterial_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/wql/QSCH_yqxCallMAterial_01.wql new file mode 100644 index 0000000..16c4b37 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/callMaterial/wql/QSCH_yqxCallMAterial_01.wql @@ -0,0 +1,71 @@ +[交易说明] + 交易名: 共挤线满料请求 + 所属模块: + 功能简述: + 版权所有: + 表引用: + 版本经历: + +[数据库] + --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 + +[IO定义] + ################################################# + ## 表字段对应输入参数 + ################################################# + 输入.flag TYPEAS s_string + 输入.region_code TYPEAS s_string + 输入.material_id TYPEAS s_string + 输入.vehicle_type TYPEAS s_string + + +[临时表] + --这边列出来的临时表就会在运行期动态创建 + +[临时变量] + --所有中间过程变量均可在此处定义 + +[业务过程] + + ########################################## + # 1、输入输出检查 # + ########################################## + + + ########################################## + # 2、主过程前处理 # + ########################################## + + + ########################################## + # 3、业务主过程 # + ########################################## + IF 输入.flag = "1" + QUERY + SELECT + p.point_id, + p.point_code, + p.point_name, + p.block_num, + p.row_num, + p.col_num + FROM + ST_IVT_StructIvt ivt + LEFT JOIN SCH_BASE_Point p on ivt.point_id = p.point_id + WHERE + p.is_used = '1' + AND is_delete = '0' + AND lock_type='1' + OPTION 输入.material_id <> "" + ivt.material_id = 输入.material_id + ENDOPTION + OPTION 输入.region_code <> "" + p.region_code = 输入.region_code + ENDOPTION + OPTION 输入.vehicle_type <> "" + p.can_vehicle_type like 输入.vehicle_type + ENDOPTION + ORDER BY block_num,row_num desc,col_num + ENDSELECT + ENDQUERY + ENDIF \ No newline at end of file diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/cpOut/CpOutTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/cpOut/CpOutTask.java new file mode 100644 index 0000000..99a4a40 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/cpOut/CpOutTask.java @@ -0,0 +1,235 @@ +package org.nl.wms.sch.tasks.cpOut; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.system.util.CodeUtil; +import org.nl.modules.wql.WQL; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.wms.sch.SchTaskDto; +import org.nl.wms.sch.manage.AbstractAcsTask; +import org.nl.wms.sch.manage.TaskStatusEnum; +import org.nl.wms.sch.tasks.AcsTaskDto; +import org.nl.wms.util.IdUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + + +/** + *成品出库 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class CpOutTask extends AbstractAcsTask { + private final String THIS_CLASS = CpOutTask.class.getName(); + + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTaskStatus(JSONObject task, String status) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + WQLObject regionIoTab = WQLObject.getWQLObject("st_ivt_regionIO"); + + String task_id = task.getString("task_id"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); + + //任务取消 + if (StrUtil.equals(status, "0")) { + // 取消删除任务 + if (StrUtil.equals(taskObj.getString("task_status"), TaskStatusEnum.FINISHED.getCode())) { + throw new BadRequestException("已完成不能取消!"); + } + String point_code2 = taskObj.getString("point_code2"); + JSONObject point2Obj = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + + taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); + taskObj.put("remark", "任务已取消"); + taskTab.update(taskObj); + // 释放终点点位 + point2Obj.put("lock_type", "1"); + point2Obj.put("point_status", "1"); + pointTab.update(point2Obj); + } + + if ("1".equals(status)) { + // 更新任务状态为执行中 + taskObj.put("task_status", TaskStatusEnum.EXECUTING.getCode()); + taskObj.put("update_time", DateUtil.now()); + taskObj.put("car_no", taskObj.getString("car_no")); + taskTab.update(taskObj); + } + + if (StrUtil.equals(status, "2")) { + // 更改任务状态为完成 + taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + + // 任务表的点位1 + String point_code1 = taskObj.getString("point_code1"); // 起点编码 + JSONObject point1Obj = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0);// 起点 + + //table_fk_id = 单据id + JSONObject regionIoObject = regionIoTab.query("iostorinv_id = '" + taskObj.getString("table_fk_id") + "'").uniqueResult(0); + + String point_code2 = taskObj.getString("point_code2"); // 终点编码:出库点位 + JSONObject point2Obj = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0);// 终点 + + // 修改区域出入库 - 起点点位解锁、点位状态更新 - 终点解锁、更新状态 + //区域出入表【st_ivt_regionIO】 + regionIoObject.put("end_point_code", point_code2); + regionIoObject.put("start_region_id", point1Obj.getString("region_id")); // 终点区域 + regionIoObject.put("end_region_id", point2Obj.getString("region_id")); // 终点区域 + regionIoObject.put("bill_status", "3"); // 单据状态 + regionIoObject.put("task_id", task_id); // 任务id + regionIoTab.update(regionIoObject); + + //完成后将仓位库存删掉 + //仓位库存表【ST_IVT_StructIvt】 + WQLObject ivtTab = WQLObject.getWQLObject("ST_IVT_StructIvt"); + ivtTab.delete("point_code = '" + taskObj.getString("point_code1") + "'"); + + // 点位解锁 并设置空位 + point1Obj.put("lock_type", "1"); + point1Obj.put("point_status", "1"); + point2Obj.put("lock_type", "1"); + point2Obj.put("point_status", "3"); + pointTab.update(point1Obj); + pointTab.update(point2Obj); + } + + } + + @Override + public void findNextPoint() { + /* + * 根据业务找对应的终点 + */ + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); // 点位表 + JSONArray taskArr = taskTab.query("handle_class = '" + THIS_CLASS + "'and is_delete = '0' and task_status = '" + TaskStatusEnum.SURE_END.getCode() + "'").getResultJSONArray(0); + for (int i = 0; i < taskArr.size(); i++) { + JSONObject taskObj = taskArr.getJSONObject(i); + String material_id = taskObj.getString("material_id"); + JSONObject param1 = new JSONObject(); + param1.put("flag", "1"); + param1.put("material_id", material_id); + param1.put("region_code", "CPCKQ01"); + //1、找空位的终点 + JSONObject endPoint = WQL.getWO("QSCH_cpOut_01").addParamMap(param1).process().uniqueResult(0); + if (ObjectUtil.isNotEmpty(endPoint)) { + // 找到终点,上锁 + taskObj.put("update_time", DateUtil.now()); + taskObj.put("point_code2", endPoint.getString("point_code")); + taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + taskTab.update(taskObj); + + //锁住终点 + endPoint.put("task_id", taskObj.getString("task_id")); + endPoint.put("lock_type", "2"); + pointTab.update(endPoint); + } else { + taskObj.put("remark", "成品出库区无可用货位"); + taskObj.put("update_time", DateUtil.now()); + } + + taskTab.update(taskObj); + + } + } + + @Override + public List addTask() { + /* + * 下发给ACS时需要特殊处理 + */ + JSONArray arr = WQLObject.getWQLObject("SCH_BASE_Task").query("handle_class = '" + THIS_CLASS + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and is_delete ='0'").getResultJSONArray(0); + + ArrayList acsTaskArr = new ArrayList<>(); + for (int i = 0; i < arr.size(); i++) { + JSONObject json = arr.getJSONObject(i); + AcsTaskDto dto = AcsTaskDto.builder() + .task_id(json.getString("task_id")) + .task_code(json.getString("task_code")) + .task_type(json.getString("acs_task_type")) + .start_device_code(json.getString("point_code1")) + .next_device_code(json.getString("point_code3")) + .vehicle_code(json.getString("vehicle_code")) + .vehicle_type(json.getString("vehicle_type")) + .priority(json.getString("priority")) + .remark(json.getString("remark")) + .build(); + acsTaskArr.add(dto); + } + return acsTaskArr; + } + + @Override + public String createTask(JSONObject whereJson) { + WQLObject regionIoTab = WQLObject.getWQLObject("st_ivt_regionIO"); + String point_code1 = whereJson.getString("point_code1"); // 起点 + String vehicle_type = whereJson.getString("vehicle_type"); + String vehicle_code = whereJson.getString("vehicle_code"); + String iostorinv_id = whereJson.getString("iostorinv_id"); + + SchTaskDto dto = SchTaskDto.builder() + .task_id(IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("task_type") + .task_name("成品区出库") + .task_status(TaskStatusEnum.SURE_END.getCode()) + .point_code1(point_code1) + .vehicle_code(vehicle_code) + .vehicle_type(vehicle_type) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .request_param(whereJson.toJSONString()) + .table_name("st_ivt_regionIO") + .table_fk("iostorinv_id") + .table_fk_id(Long.valueOf(iostorinv_id)) + .build(); + //任务表【SCH_BASE_Task】 + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + + // 单据设置执行中 + JSONObject iostorinv = regionIoTab.query("iostorinv_id = '" + iostorinv_id + "'").uniqueResult(0); + iostorinv.put("bill_status", "2"); + regionIoTab.update(iostorinv); + + //创建好立即下发 + this.immediateNotifyAcs(); + return String.valueOf(dto.getTask_id()); + } + + @Override + public void forceFinish(String task_id) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "' and is_delete = '0' and task_status <> " + TaskStatusEnum.FINISHED.getCode()).uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) + this.updateTaskStatus(taskObj,"2"); + else { + throw new BadRequestException("未找到该任务或者任务已完成"); + } + } + + @Override + public void cancel(String task_id) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "' and is_delete = '0' and task_status <> " + TaskStatusEnum.FINISHED.getCode()).uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) + this.updateTaskStatus(taskObj,"0"); + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/cpOut/wql/QSCH_cpOut_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/cpOut/wql/QSCH_cpOut_01.wql new file mode 100644 index 0000000..7546033 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/cpOut/wql/QSCH_cpOut_01.wql @@ -0,0 +1,59 @@ +[交易说明] + 交易名: 成品出库 + 所属模块: + 功能简述: + 版权所有: + 表引用: + 版本经历: + +[数据库] + --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 + +[IO定义] + ################################################# + ## 表字段对应输入参数 + ################################################# + 输入.flag TYPEAS s_string + 输入.region_code TYPEAS s_string + +[临时表] + --这边列出来的临时表就会在运行期动态创建 + +[临时变量] + --所有中间过程变量均可在此处定义 + +[业务过程] + + ########################################## + # 1、输入输出检查 # + ########################################## + + + ########################################## + # 2、主过程前处理 # + ########################################## + + + ########################################## + # 3、业务主过程 # + ########################################## + + IF 输入.flag = "1" + QUERY + SELECT + * + FROM + SCH_BASE_Point + WHERE + is_used = '1' + AND is_delete = '0' + AND lock_type = '1' + AND is_used = '1' + AND point_status = '1' + OPTION 输入.region_code <> "" + region_code = 输入.region_code + ENDOPTION + ORDER BY point_code + ENDSELECT + ENDQUERY + ENDIF \ No newline at end of file diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/HtSendEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/HtSendEmpVehicleTask.java index 344bbae..a5bf266 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/HtSendEmpVehicleTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/HtSendEmpVehicleTask.java @@ -83,6 +83,9 @@ public class HtSendEmpVehicleTask extends AbstractAcsTask { // 更新point_code2:解锁 JSONObject point2 = pointTab.query("point_code = '" + jsonTask.getString("point_code2") + "'").uniqueResult(0); point2.put("lock_type", "1"); + point2.put("vehicle_type", ""); + point2.put("vehicle_code", ""); + point2.put("vehicle_qty", 0); pointTab.update(point2); } else { point_code = jsonTask.getString("point_code2"); @@ -126,6 +129,7 @@ public class HtSendEmpVehicleTask extends AbstractAcsTask { SchTaskDto dto = SchTaskDto.builder().task_id(org.nl.wms.util.IdUtil.getLongId()) .task_code(CodeUtil.getNewCode("TASK_CODE")) .task_type("") + .task_name("电梯送空载具") .task_status(TaskStatusEnum.SURE_START.getCode()) .point_code1(point_code1) .vehicle_code(form.getString("vehicle_code")) @@ -351,7 +355,7 @@ public class HtSendEmpVehicleTask extends AbstractAcsTask { "' and block_num = '" + jsonPoint2.getString("block_num") + "' and col_num = '" + jsonPoint2.getString("col_num") + "' and point_code <> '" + jsonPoint2.getString("point_code") + - "' and point_status = '2' order by in_empty_seq ASC").uniqueResult(0); + "' and point_status = '2' and lock_type = '1' order by in_empty_seq ASC").uniqueResult(0); // 如果为空说明这一列其他货位为空 则入到最后一个货位 if (ObjectUtil.isEmpty(jsonOnePoint)) { @@ -359,7 +363,7 @@ public class HtSendEmpVehicleTask extends AbstractAcsTask { "' and block_num = '" + jsonPoint2.getString("block_num") + "' and col_num = '" + jsonPoint2.getString("col_num") + "' and point_code <> '" + jsonPoint2.getString("point_code") + - "' and point_status = '1' order by in_empty_seq DESC").uniqueResult(0); + "' and point_status = '1' and lock_type = '1' order by in_empty_seq DESC").uniqueResult(0); if (ObjectUtil.isNotEmpty(jsonEmpPoint)) { point_code = jsonEmpPoint.getString("point_code"); @@ -375,7 +379,7 @@ public class HtSendEmpVehicleTask extends AbstractAcsTask { "' and col_num = '" + jsonPoint2.getString("col_num") + "' and point_code <> '" + jsonPoint2.getString("point_code") + "' and in_empty_seq = '" + in_empty_seq + - "' and point_status = '1'").uniqueResult(0); + "' and point_status = '1' and lock_type = '1'").uniqueResult(0); if (ObjectUtil.isNotEmpty(jsonEmpPoint)) { point_code = jsonEmpPoint.getString("point_code"); @@ -383,10 +387,17 @@ public class HtSendEmpVehicleTask extends AbstractAcsTask { taskTab.update(jsonTask); } } - JSONObject jsonEndPoint = pointTab.query("point_code = '" + point_code + "'").uniqueResult(0); - jsonEndPoint.put("lock_type", "2"); - pointTab.update(jsonEndPoint); + if (ObjectUtil.isNotEmpty(point_code)) { + JSONObject jsonEndPoint = pointTab.query("point_code = '" + point_code + "'").uniqueResult(0); + jsonEndPoint.put("lock_type", "2"); + pointTab.update(jsonEndPoint); + } + //判断点位是否属于养生A区 + if (point_code.startsWith("2")) { + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + point_code = point_code.substring(0, 4) + "1" + point_code.substring(4, 9); + } return point_code; } @@ -400,12 +411,21 @@ public class HtSendEmpVehicleTask extends AbstractAcsTask { ArrayList resultList = new ArrayList<>(); for (int i = 0; i < arr.size(); i++) { JSONObject json = arr.getJSONObject(i); + + String point_code3=json.getString("point_code3"); + //判断终点是否属于养生A区 + if (point_code3.startsWith("2")) { + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + point_code3 = point_code3.substring(0, 4) + "1" + point_code3.substring(4, 9); + } + + AcsTaskDto dto = AcsTaskDto.builder() .task_id(json.getString("task_id")) .task_code(json.getString("task_code")) .task_type(json.getString("acs_task_type")) .start_device_code(json.getString("point_code1")) - .next_device_code(json.getString("point_code3")) + .next_device_code(point_code3) .vehicle_code(json.getString("vehicle_code")) .vehicle_type(json.getString("vehicle_type")) .priority(json.getString("priority")) diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/SendEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/SendEmpVehicleTask.java deleted file mode 100644 index b375615..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/SendEmpVehicleTask.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.nl.wms.sch.tasks.sendEmpty; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -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.basedata.service.VehicleService; -import org.nl.wms.basedata.service.dto.VehicleDto; -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.nl.wms.sch.tasks.AcsTaskDto; -import org.nl.wms.sch.tasks.RegionTypeEnum; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.HashMap; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Slf4j -public class SendEmpVehicleTask extends AbstractAcsTask { - private final String THIS_CLASS = SendEmpVehicleTask.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); - - String point_code1 = jsonTask.getString("point_code1"); - - PointService point = SpringContextHolder.getBean(PointService.class); - // 校验起点是否存在 - PointDto startDto = point.findByCode(point_code1); - if (ObjectUtil.isEmpty(startDto)) throw new BadRequestException("未找到可用点位:" + startDto); - // 校验终点是否存在 - PointDto nextDto = point.findByCode(jsonTask.getString("point_code2")); - if (ObjectUtil.isEmpty(nextDto)) throw new BadRequestException("未找到可用点位:" + nextDto); - - } - } - - - - @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 vehicle_code = form.getString("vehicle_code"); - String qty = form.getString("qty"); - String record_uuid = form.getString("record_uuid"); - - String vehicle_type = ""; - // 入库起点不能为空 - if (ObjectUtil.isEmpty(point_code1)) { - throw new BadRequestException("起点不能为空"); - } else { - // 判断起点是否有正在执行的任务 - JSONObject beforTaskObj = taskTab.query("is_delete='0' and point_code1='" + point_code1 + "' 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. 起点确定: 需要找到对应终点,在创建任务 具体找终点货位的规则在findEndPoint()中 - */ - // 起点确定:找终点 - if (ObjectUtil.isEmpty(point_code2)) { - JSONObject param = new JSONObject(); - param.put("point_code1",point_code1); - param.put("vehicle_qty",qty); - param.put("vehicle_code",vehicle_code); - JSONObject json = this.findEndPoint(param); - point_code2 = json.getString("EndPoint_code"); - vehicle_type = json.getString("vehicle_type"); - } else { - // 判断终点是否是空位 - JSONObject jsonPoint = pointTab.query("point_code = '" + point_code2 + "' 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("task_code", CodeUtil.getNewCode("TASK_CODE")); - jsonTask.put("task_type", "03"); - jsonTask.put("task_status", "01"); - jsonTask.put("point_code1", point_code1); - jsonTask.put("point_code2", point_code2); - jsonTask.put("vehicle_type", vehicle_type); - jsonTask.put("vehicle_code", vehicle_code); - jsonTask.put("handle_class", THIS_CLASS); - 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_code2 + "'").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 cancel(String task_id) { - - } - - @Transactional(rollbackFor = Exception.class) - public JSONObject findEndPoint(JSONObject json) { - String point_code1 = json.getString("point_code1"); - String vehicle_qty = json.getString("vehicle_qty"); - String vehicle_code = json.getString("vehicle_code"); - - if (ObjectUtil.isEmpty(point_code1)) 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 velicleTab = WQLObject.getWQLObject("md_pb_storagevehicleinfo"); // 载具表 - // 根据起点区域判断优先的终点区域 - JSONObject jsonPointStart = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0); - if (ObjectUtil.isEmpty(jsonPointStart)) throw new BadRequestException("起点点位不存在"); - JSONObject jsonRegionStart = regionTab.query("region_id ='" + jsonPointStart.getString("region_id") + "'").uniqueResult(0); - - // 根据起点找到对应设备,根据设备查询工单表中 - 正在运行的工单中的载具类型 - String device_code = ""; - if (ObjectUtil.isEmpty(vehicle_code)) { - device_code = point_code1.substring(0, point_code1.indexOf("_")); - } - - String vehicle_type = ""; - - DeviceService deviceBean = SpringContextHolder.getBean(DeviceService.class); - DeviceDto deviceDto = deviceBean.findByCode(device_code); - if (ObjectUtil.isEmpty(deviceDto)) { - // 如果说明是货梯业务:则判断载具号是否为空 - if (ObjectUtil.isEmpty(vehicle_code)) throw new BadRequestException("起点点位错误"); - // 根据载具号找对应的载具类型 - VehicleDto vehicleDto = SpringContextHolder.getBean(VehicleService.class).findByCode(vehicle_code); - if (ObjectUtil.isEmpty(vehicleDto)) throw new BadRequestException("载具不存在"); - vehicle_type = vehicleDto.getVehicle_type(); - } else { - // 不为空说明不是货梯业务:则根据工单找到对应类型 - 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("此设备未在生产中或不存在"); - vehicle_type = jsonOrder.getString("vehicle_type"); - } - - /* - * 空托盘入库业务: - * 1.油漆线 --> 叠盘架A区、养生区A区 (优先级:1叠盘架A区 2.养生A区) - * 2.货梯 --> 叠盘架B区、养生区A区 (优先级:1叠盘架B区 2.养生A区) - */ - String EndPoint_code = ""; - HashMap map = new HashMap<>(); - if (StrUtil.equals(jsonRegionStart.getString("region_code"), RegionTypeEnum.YQQY.getCode())) { - // 油漆线入库:查找叠盘架A区是否有满足的空位 - map.put("flag", "1"); - map.put("vehicle_qty",vehicle_qty); - map.put("vehicle_type",vehicle_type); - map.put("region_code",RegionTypeEnum.DPJQA.getCode()); - JSONObject jsonEndPointDPA = WQL.getWO("ST_VEHICLE_IN_02").addParamMap(map).process().uniqueResult(0); - if (ObjectUtil.isNotEmpty(jsonEndPointDPA)) { - EndPoint_code = jsonEndPointDPA.getString("point_code"); - } else { - // 为空说明没有相同的载具类型 - map.put("flag", "2"); - map.put("vehicle_type",""); - JSONObject jsonEndPointDPA2 = WQL.getWO("ST_VEHICLE_IN_02").addParamMap(map).process().uniqueResult(0); - if (ObjectUtil.isNotEmpty(jsonEndPointDPA2)) { - EndPoint_code = jsonEndPointDPA2.getString("point_code"); - } else { - // 为空说明叠盘架A区上货位不足,则需要入库到养生A区 - map.put("flag", "3"); - map.put("region_code",RegionTypeEnum.YSQA.getCode() ); - JSONObject jsonEndPointYSA = WQL.getWO("ST_VEHICLE_IN_02").addParamMap(map).process().uniqueResult(0); - if (ObjectUtil.isEmpty(jsonEndPointYSA)) throw new BadRequestException("没有满足需求的空位"); - EndPoint_code = jsonEndPointYSA.getString("point_code"); - } - } - } else { - // 货梯入库:查找叠盘架B区是否有满足的空位 - map.put("flag", "1"); - map.put("vehicle_qty",vehicle_qty); - map.put("vehicle_type",vehicle_type); - map.put("region_code",RegionTypeEnum.DPJQB.getCode()); - JSONObject jsonEndPointDPB = WQL.getWO("ST_VEHICLE_IN_02").addParamMap(map).process().uniqueResult(0); - if (ObjectUtil.isNotEmpty(jsonEndPointDPB)) { - EndPoint_code = jsonEndPointDPB.getString("point_code"); - } else { - // 为空说明没有相同的载具类型 - map.put("flag", "2"); - map.put("vehicle_type",""); - JSONObject jsonEndPointDPB2 = WQL.getWO("ST_VEHICLE_IN_02").addParamMap(map).process().uniqueResult(0); - if (ObjectUtil.isNotEmpty(jsonEndPointDPB2)) { - EndPoint_code = jsonEndPointDPB2.getString("point_code"); - } else { - // 为空说明叠盘架B区上货位不足,则需要入库到养生A区 - map.put("flag", "3"); - map.put("region_code", RegionTypeEnum.YSQA.getCode()); - JSONObject jsonEndPointYSA = WQL.getWO("ST_VEHICLE_IN_02").addParamMap(map).process().uniqueResult(0); - if (ObjectUtil.isEmpty(jsonEndPointYSA)) throw new BadRequestException("没有满足需求的空位"); - EndPoint_code = jsonEndPointYSA.getString("point_code"); - } - } - } - JSONObject resuft = new JSONObject(); - resuft.put("EndPoint_code",EndPoint_code); - resuft.put("vehicle_type",vehicle_type); - return resuft; - } - @Override - public List addTask() { - return null; - } -} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/YqxSendEmpVehicleTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/YqxSendEmpVehicleTask.java index 90c5456..4177b9b 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/YqxSendEmpVehicleTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendEmpty/YqxSendEmpVehicleTask.java @@ -1,24 +1,26 @@ package org.nl.wms.sch.tasks.sendEmpty; 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.JSONArray; 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.wms.sch.SchTaskDto; import org.nl.wms.sch.manage.AbstractAcsTask; import org.nl.wms.sch.manage.TaskStatusEnum; import org.nl.wms.sch.tasks.AcsTaskDto; +import org.nl.wms.sch.tasks.RegionTypeEnum; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; @Service @@ -39,6 +41,21 @@ public class YqxSendEmpVehicleTask extends AbstractAcsTask { if (StrUtil.equals(status, "0")) { // 取消删除任务 + if (StrUtil.equals(jsonTask.getString("task_status"), TaskStatusEnum.FINISHED.getCode())) { + throw new BadRequestException("已完成不能取消!"); + } + String point_code3 = jsonTask.getString("point_code3"); + String point_code2 = jsonTask.getString("point_code2"); + if (ObjectUtil.isNotEmpty(point_code3)) { + JSONObject jsonPoint3 = pointTab.query("point_code ='" + point_code3 + "'").uniqueResult(0); + jsonPoint3.put("point_status", "1"); + pointTab.update(jsonPoint3); + } + if (ObjectUtil.isNotEmpty(point_code2)) { + JSONObject jsonPoint2 = pointTab.query("point_code ='" + point_code2 + "'").uniqueResult(0); + jsonPoint2.put("point_status", "1"); + pointTab.update(jsonPoint2); + } taskTab.delete("task_id = '" + task_id + "'"); } @@ -53,15 +70,29 @@ public class YqxSendEmpVehicleTask extends AbstractAcsTask { 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); - String point_code2 = jsonTask.getString("point_code2"); - JSONObject endPoint = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + String point_code3 = jsonTask.getString("point_code3"); + String point_code = ""; + // 更新终点:判断point_code3是否为空,为空就更新point_code2 + if (ObjectUtil.isNotEmpty(point_code3)) { + point_code = point_code3; + // 更新point_code2:解锁 + JSONObject point2 = pointTab.query("point_code = '" + jsonTask.getString("point_code2") + "'").uniqueResult(0); + point2.put("lock_type", "1"); + point2.put("vehicle_type", ""); + point2.put("vehicle_code", ""); + point2.put("vehicle_qty", 0); + pointTab.update(point2); + } else { + point_code = jsonTask.getString("point_code2"); + } + + JSONObject endPoint = pointTab.query("point_code = '" + point_code + "'").uniqueResult(0); + //终点是叠盘架 - if (StrUtil.equals("DPJQB01", endPoint.getString("region_code"))) { + if (StrUtil.equals(endPoint.getString("region_id"), RegionTypeEnum.DPJQB.getId())) { Integer vehicle_qty = endPoint.getInteger("vehicle_qty"); vehicle_qty += jsonTask.getInteger("vehicle_qty"); endPoint.put("lock_type", "1"); @@ -71,55 +102,43 @@ public class YqxSendEmpVehicleTask extends AbstractAcsTask { pointTab.update(endPoint); } else {//非叠盘架 endPoint.put("lock_type", "1"); + endPoint.put("vehicle_code", jsonTask.getString("vehicle_code")); endPoint.put("vehicle_qty", jsonTask.getString("vehicle_qty")); endPoint.put("vehicle_type", jsonTask.getString("vehicle_type")); - endPoint.put("point_status", "1"); + endPoint.put("point_status", "2"); pointTab.update(endPoint); } - } } - @Override @Transactional(rollbackFor = Exception.class) public String createTask(JSONObject form) { - WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + /* + * 1.先生成确定起点的任务 + * 2.通过findNextPoint()找终点 + * 3.下发给ACS + */ + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 String point_code1 = form.getString("point_code1"); - String point_code2 = form.getString("point_code2"); - String vehicle_code = form.getString("vehicle_code"); - String vehicle_type = form.getString("vehicle_type"); - String vehicle_num = form.getString("vehicle_num"); - // 入库起点不能为空 - if (ObjectUtil.isEmpty(point_code1)) { - throw new BadRequestException("起点不能为空"); - } - // 判断起点是否有正在执行的任务 - JSONObject beforTaskObj = taskTab.query("is_delete='0' and point_code1='" + point_code1 + "' and task_status <>'" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); - if (ObjectUtil.isNotEmpty(beforTaskObj)) throw new BadRequestException("存在指令号为'" + beforTaskObj.getString("task_code") + "' 未完成!"); - - // 创建任务 - JSONObject jsonTask = new JSONObject(); - String task_id = IdUtil.getSnowflake(1, 1).nextId() + ""; - jsonTask.put("task_id", task_id); - jsonTask.put("task_code", CodeUtil.getNewCode("TASK_CODE")); - jsonTask.put("task_type", "kzj"); - jsonTask.put("task_status", TaskStatusEnum.SURE_START.getCode()); - jsonTask.put("point_code1", point_code1); - jsonTask.put("point_code2", point_code2); - jsonTask.put("vehicle_type", vehicle_type); - jsonTask.put("vehicle_code", vehicle_code); - jsonTask.put("vehicle_num", vehicle_num); - jsonTask.put("handle_class", THIS_CLASS); - jsonTask.put("create_name", SecurityUtils.getCurrentUsername()); - jsonTask.put("create_id", SecurityUtils.getCurrentUserId()); - jsonTask.put("create_time", DateUtil.now()); - taskTab.insert(jsonTask); - - this.findNextPoint(); - return task_id; + SchTaskDto dto = SchTaskDto.builder().task_id(org.nl.wms.util.IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("") + .task_status(TaskStatusEnum.SURE_START.getCode()) + .point_code1(point_code1) + .vehicle_code(form.getString("vehicle_code")) + .vehicle_type(form.getString("vehicle_type")) + .vehicle_qty(form.getIntValue("qty")) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .build(); + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); +// this.findNextPoint(); + this.immediateNotifyAcs(); + return String.valueOf(dto.getTask_id()); } /** @@ -130,62 +149,243 @@ public class YqxSendEmpVehicleTask extends AbstractAcsTask { */ @Override public void findNextPoint() { + /* + * 根据业务找对应的终点 + */ WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); - JSONArray taskArr = taskTab.query("is_delete = '0' and handle_class = '" + this.THIS_CLASS + "' and task_status = '" + TaskStatusEnum.SURE_START.getCode() + "'").getResultJSONArray(0); + + JSONArray taskArr = taskTab.query("handle_class = '" + THIS_CLASS + "'and is_delete = '0' and task_status = '2'").getResultJSONArray(0); for (int i = 0; i < taskArr.size(); i++) { JSONObject jsonTask = taskArr.getJSONObject(i); - String vehicle_type = jsonTask.getString("vehicle_type"); - Integer vehicle_qty = jsonTask.getInteger("vehicle_qty"); - //TODO 判断叠盘位是否有另外任务,则不生成任务,后续可以考虑托盘数量大于某个数直接去缓存区或者养生A区 - JSONObject taskObj = taskTab.query("is_delete='0' and handle_class='" + this.THIS_CLASS + "' and task_status <>'" + TaskStatusEnum.FINISHED.getCode() + "' and task_id <> " + jsonTask.getLong("task_id")).uniqueResult(0); - if (ObjectUtil.isNotEmpty(taskObj)) continue; - JSONObject dpjPoint = pointTab.query("is_used ='1' and lock_type='00' and is_delete='0' and region_code='DPJQB01' and can_vehicle_type like '%" + vehicle_type + "%'").uniqueResult(0); + // 找终点 + JSONObject param = new JSONObject(); + param.put("vehicle_type", jsonTask.getString("vehicle_type")); + param.put("qty", jsonTask.getString("vehicle_qty")); + String endPoint = this.endPoint(param); - int sum_qty=(dpjPoint.getInteger("vehicle_qty")==null?0:dpjPoint.getInteger("vehicle_qty"))+vehicle_qty; - //超过叠盘架允许的最大托盘数,去托盘缓存区或者去养生A区,后续可以考虑任务的载具数量和叠盘架的载具数量谁比较大,大的先去缓存位或者去养生A区 - if ( sum_qty > dpjPoint.getInteger("vehicle_max_qty")) { - JSONObject endPoint = WQL.getWO("ST_VEHICLE_IN_01").addParam("flag", "1").addParam("vehicle_type", "'%" + vehicle_type + "'").process().uniqueResult(0); - jsonTask.put("point_code2", endPoint.getString("point_code")); - jsonTask.put("task_status", TaskStatusEnum.START_AND_POINT); - jsonTask.put("update_time", DateUtil.now()); - taskTab.update(jsonTask); - - - } else {//去叠盘架 - jsonTask.put("point_code2", dpjPoint.getString("point_code")); - jsonTask.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); - jsonTask.put("update_time", DateUtil.now()); - taskTab.update(jsonTask); + // 如果此时endPoint为空则循环下一个任务 + if (ObjectUtil.isEmpty(endPoint)) { + continue; } - //锁住终点 - JSONObject pointObj = new JSONObject(); - pointObj.put("lock_type", "2"); - pointObj.put("update_time", DateUtil.now()); - pointTab.update(pointObj, "point_code ='" + jsonTask.getString("point_code2") + "'"); + + // 更新任务表point_code2 + jsonTask.put("point_code2", endPoint); + jsonTask.put("task_status", "4"); + taskTab.update(jsonTask); + + // 锁定终点 + JSONObject jsonEnd = pointTab.query("point_code = '" + endPoint + "'").uniqueResult(0); + jsonEnd.put("lock_type", "2"); + pointTab.update(jsonEnd); } } - ; - @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 cancel(String task_id) { } - @Override - public List addTask() { - return null; + + @Transactional(rollbackFor = Exception.class) + public String endPoint(JSONObject param) { + /* + * 1.叠盘架有B对应货位 规则:如果暂存位能放下则放暂存位如果放不下则走2或3 + * 2.叠盘架B没有货位 则去叠盘架暂存位 + * 3.叠盘架暂存位没有货位则去养生A区 + */ + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); // 点位表 + + String end_code = ""; + + String vehicle_type = param.getString("vehicle_type"); + + // 1.找到对应类型的叠盘架 + JSONObject jsonDpjEnd = pointTab.query("region_id = '" + RegionTypeEnum.DPJQB.getId() + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(jsonDpjEnd)) { + // 判断数量 + 叠盘架的数量是否超过此叠盘架的最大数量 + double add_num = NumberUtil.add(param.getIntValue("qty"), jsonDpjEnd.getIntValue("vehicle_qty")); + + if (jsonDpjEnd.getDoubleValue("vehicle_max_qty") >= add_num) { + end_code = jsonDpjEnd.getString("point_code"); + } else { + // 如果数量大于此叠盘架最大数量则查找叠盘架缓存位是否有对应空位 + JSONObject jsonZcwEnd = pointTab.query("region_id = '" + RegionTypeEnum.KTPHCQB.getId() + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and point_status = '1'").uniqueResult(0); + + if (ObjectUtil.isNotEmpty(jsonZcwEnd)) { + end_code = jsonZcwEnd.getString("point_code"); + } else { + // 为空就去养生A区的等待位 + JSONObject jsonEmpWait = pointTab.query("region_id = '" + RegionTypeEnum.YSAQKTPQ01.getId() + "' and row_num = '1' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and point_status = '1'").uniqueResult(0); + + if (ObjectUtil.isNotEmpty(jsonEmpWait)) { + // 判断是否有任务 + boolean is_point = this.isTask(jsonEmpWait.getString("point_code")); + if (is_point) { + JSONArray jsonEmpArr = pointTab.query("region_id = '" + RegionTypeEnum.YSAQKTPQ01.getId() + "' and col_num = '" + jsonEmpWait.getString("col_num") + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and point_status = '1'").getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(jsonEmpArr)) end_code = jsonEmpWait.getString("point_code"); + } + } + } + } + } else { + // 2.叠盘架没有空位去找叠盘暂存位 + JSONObject jsonZcwEnd = pointTab.query("region_id = '" + RegionTypeEnum.KTPHCQB.getId() + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and point_status = '1'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(jsonZcwEnd)) { + end_code = jsonZcwEnd.getString("point_code"); + } else { + // 为空就去养生A区的等待位 + JSONObject jsonEmpWait = pointTab.query("region_id = '" + RegionTypeEnum.YSAQKTPQ01.getId() + "' and row_num = '1' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and point_status = '1'").uniqueResult(0); + + if (ObjectUtil.isNotEmpty(jsonEmpWait)) { + // 判断是否有任务 + boolean is_point = this.isTask(jsonEmpWait.getString("point_code")); + if (is_point) { + JSONArray jsonEmpArr = pointTab.query("region_id = '" + RegionTypeEnum.YSAQKTPQ01.getId() + "' and col_num = '" + jsonEmpWait.getString("col_num") + "' and can_vehicle_type = '" + vehicle_type + "' and lock_type = '1' and is_used = '1' and is_delete = '0' and point_status = '1'").getResultJSONArray(0); + if (ObjectUtil.isNotEmpty(jsonEmpArr)) end_code = jsonEmpWait.getString("point_code"); + } + } + } + } + + return end_code; } + @Transactional(rollbackFor = Exception.class) + public boolean isTask(String point_code) { + /* + * 判断点位是否有任务存在 + */ + WQLObject tab = WQLObject.getWQLObject("SCH_BASE_Task"); + + boolean result; + + JSONObject jsonPointCode1 = tab.query("point_code1 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode2 = tab.query("point_code2 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode3 = tab.query("point_code3 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + JSONObject jsonPointCode4 = tab.query("point_code4 = '" + point_code + "' and task_status <> '7' and is_delete = '0'").uniqueResult(0); + + if (ObjectUtil.isEmpty(jsonPointCode1) && ObjectUtil.isEmpty(jsonPointCode2) && ObjectUtil.isEmpty(jsonPointCode3) && ObjectUtil.isEmpty(jsonPointCode4)) { + result = true; + } else { + result = false; + } + + return result; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public String againApply(String task_id) { + /* + * 再次下发任务处理方法 + * 涉及业务:入空载具、出空载具、入物料、出物料 + */ + + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); // 点位表 + + String point_code = ""; + + JSONObject jsonTask = taskTab.query("task_id ='" + task_id + "'").uniqueResult(0); + JSONObject jsonPoint2 = pointTab.query("point_code = '" + jsonTask.getString("point_code2") + "'").uniqueResult(0); + + // 根据 区域、块、列找到第一个有物料的货位 + JSONObject jsonOnePoint = pointTab.query("region_id = '" + jsonPoint2.getString("region_id") + + "' and block_num = '" + jsonPoint2.getString("block_num") + + "' and col_num = '" + jsonPoint2.getString("col_num") + + "' and point_code <> '" + jsonPoint2.getString("point_code") + + "' and point_status = '2' and lock_type = '1' order by in_empty_seq ASC").uniqueResult(0); + + // 如果为空说明这一列其他货位为空 则入到最后一个货位 + if (ObjectUtil.isEmpty(jsonOnePoint)) { + JSONObject jsonEmpPoint = pointTab.query("region_id = '" + jsonPoint2.getString("region_id") + + "' and block_num = '" + jsonPoint2.getString("block_num") + + "' and col_num = '" + jsonPoint2.getString("col_num") + + "' and point_code <> '" + jsonPoint2.getString("point_code") + + "' and point_status = '1' and lock_type = '1' order by in_empty_seq DESC").uniqueResult(0); + + if (ObjectUtil.isNotEmpty(jsonEmpPoint)) { + point_code = jsonEmpPoint.getString("point_code"); + jsonTask.put("point_code3", point_code); + taskTab.update(jsonTask); + } + } else { + // 找前一位的空位 + double in_empty_seq = NumberUtil.sub(jsonOnePoint.getIntValue("in_empty_seq"), 1); + + JSONObject jsonEmpPoint = pointTab.query("region_id = '" + jsonPoint2.getString("region_id") + + "' and block_num = '" + jsonPoint2.getString("block_num") + + "' and col_num = '" + jsonPoint2.getString("col_num") + + "' and point_code <> '" + jsonPoint2.getString("point_code") + + "' and in_empty_seq = '" + in_empty_seq + + "' and point_status = '1' and lock_type = '1'").uniqueResult(0); + + if (ObjectUtil.isNotEmpty(jsonEmpPoint)) { + point_code = jsonEmpPoint.getString("point_code"); + jsonTask.put("point_code3", point_code); + taskTab.update(jsonTask); + } + } + + if (ObjectUtil.isNotEmpty(point_code)) { + JSONObject jsonEndPoint = pointTab.query("point_code = '" + point_code + "'").uniqueResult(0); + jsonEndPoint.put("lock_type", "2"); + pointTab.update(jsonEndPoint); + } + //判断点位是否属于养生A区 + if (point_code.startsWith("2")) { + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + point_code = point_code.substring(0, 4) + "1" + point_code.substring(4, 9); + } + return point_code; + } + + @Override + public List addTask() { + /* + * 下发给ACS时需要特殊处理 + */ + JSONArray arr = WQLObject.getWQLObject("SCH_BASE_Task").query("handle_class = '" + THIS_CLASS + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and is_delete ='0'").getResultJSONArray(0); + + ArrayList resultList = new ArrayList<>(); + for (int i = 0; i < arr.size(); i++) { + JSONObject json = arr.getJSONObject(i); + String point_code3 = json.getString("point_code3"); + //判断终点是否属于养生A区 + if (point_code3.startsWith("2")) { + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + point_code3 = point_code3.substring(0, 4) + "1" + point_code3.substring(4, 9); + } + + + AcsTaskDto dto = AcsTaskDto.builder() + .task_id(json.getString("task_id")) + .task_code(json.getString("task_code")) + .task_type(json.getString("task_type")) + .start_device_code(json.getString("point_code1")) + .next_device_code(point_code3) + .vehicle_code(json.getString("vehicle_code")) + .vehicle_type(json.getString("vehicle_type")) + .priority(json.getString("priority")) + .remark(json.getString("remark")) + .build(); + resultList.add(dto); + } + return resultList; + } + + } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/GjxSendMaterialTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/GjxSendMaterialTask.java new file mode 100644 index 0000000..b9290ca --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/GjxSendMaterialTask.java @@ -0,0 +1,384 @@ +package org.nl.wms.sch.tasks.sendMaterial; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +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.wms.sch.SchTaskDto; +import org.nl.wms.sch.manage.AbstractAcsTask; +import org.nl.wms.sch.manage.TaskStatusEnum; +import org.nl.wms.sch.tasks.AcsTaskDto; +import org.nl.wms.util.IdUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + + +/** + * 共挤线送料任务服务 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class GjxSendMaterialTask extends AbstractAcsTask { + private final String THIS_CLASS = GjxSendMaterialTask.class.getName(); + + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTaskStatus(JSONObject task, String status) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + + String task_id = task.getString("task_id"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "'").uniqueResult(0); + + //任务取消 + if (StrUtil.equals(status, "0")) { + // 取消删除任务 + if (StrUtil.equals(taskObj.getString("task_status"), TaskStatusEnum.FINISHED.getCode())) { + throw new BadRequestException("已完成不能取消!"); + } + + taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); + taskObj.put("remark", "已取消"); + taskTab.update(taskObj); + + //释放相关电位信息 + JSONObject param1 = new JSONObject(); + param1.put("lock_type", "1"); + param1.put("task_id", ""); + param1.put("material_id", ""); + pointTab.update(param1, "task_id = '" + taskObj.getString("task_id") + "'"); + } + + if ("1".equals(status)) { + // 更新任务状态为执行中 + taskObj.put("task_status", TaskStatusEnum.EXECUTING.getCode()); + taskObj.put("update_time", DateUtil.now()); + taskObj.put("car_no", taskObj.getString("car_no")); + taskTab.update(taskObj); + } + + if (StrUtil.equals(status, "2")) { + + //判断状态, + if (StrUtil.equals("2", taskObj.getString("task_status"))) { + // 更改任务状态为完成 + taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + return; + } + // 更改任务状态为完成 + taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + + + String point_code2 = taskObj.getString("point_code2"); + JSONObject endPoint = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + JSONObject requestObj = task.getJSONObject("request_param"); + //工单标识 + String workorder_id = requestObj.getString("material_info_id"); + //生产工单表【PDM_BD_WorkOrder】 + WQLObject workOrderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); + JSONObject workorderObj = workOrderTab.query("workorder_id", workorder_id).uniqueResult(0); + + + //区域出入表【st_ivt_regionIO】 + WQLObject regionIoTab = WQLObject.getWQLObject("st_ivt_regionIO"); + JSONObject regionIoObj = new JSONObject(); + regionIoObj.put("iostorinv_id", IdUtil.getLongId()); + regionIoObj.put("bill_code", CodeUtil.getNewCode("IN_STORE_CODE")); + regionIoObj.put("buss_date", DateUtil.today()); + regionIoObj.put("io_type", "1"); + regionIoObj.put("region_id", endPoint.getString("region_id")); + regionIoObj.put("region_code", endPoint.getString("region_code")); + regionIoObj.put("region_name", endPoint.getString("region_name")); + regionIoObj.put("material_id", taskObj.getString("material_id")); + regionIoObj.put("vehicle_code", taskObj.getString("vehicle_code")); + regionIoObj.put("qty", requestObj.getString("qty")); + regionIoObj.put("bill_status", "3"); + regionIoObj.put("start_point_code", taskObj.getString("point_code1")); + regionIoObj.put("end_point_code", taskObj.getString("point_code3")); + regionIoObj.put("create_mode", "2"); + regionIoObj.put("pcsn", DateUtil.format(DateUtil.parse(DateUtil.today()), "yyyyMMdd")); + regionIoObj.put("create_id", SecurityUtils.getCurrentUserId()); + regionIoObj.put("create_name", SecurityUtils.getCurrentNickName()); + regionIoObj.put("create_time", DateUtil.now()); + regionIoTab.insert(regionIoObj); + + + //完成后入库 + //仓位库存表【ST_IVT_StructIvt】 + WQLObject ivtTab = WQLObject.getWQLObject("ST_IVT_StructIvt"); + JSONObject ivtObj = new JSONObject(); + ivtObj.put("stockrecord_id", IdUtil.getLongId()); + ivtObj.put("point_id", endPoint.getString("point_id")); + ivtObj.put("point_code", endPoint.getString("point_code")); + ivtObj.put("point_name", endPoint.getString("point_name")); + ivtObj.put("region_id", endPoint.getString("region_id")); + ivtObj.put("region_code", endPoint.getString("region_code")); + ivtObj.put("region_name", endPoint.getString("region_name")); + ivtObj.put("instorage_time", DateUtil.now()); + ivtObj.put("pcsn", DateUtil.format(DateUtil.parse(DateUtil.today()), "yyyyMMdd")); + ivtObj.put("ivt_qty", requestObj.getString("qty")); + ivtObj.put("standing_time", workorderObj.getString("standing_time")); + ivtObj.put("material_id", workorderObj.getString("material_id")); + ivtTab.insert(ivtObj); + + // 点位解锁 + endPoint.put("lock_type", "1"); + endPoint.put("point_status", "3"); + endPoint.put("material_id", taskObj.getString("material_id")); + pointTab.update(endPoint); + //释放整列货位 + JSONObject param = new JSONObject(); + param.put("lock_type", "1"); + pointTab.update(param, "task_id = '" + task_id + "'"); + + } + + } + + @Override + public void findNextPoint() { + //判断共挤线是否有执行中的任务,如果任务数>=3,则不生成任务 + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + /* + * 根据业务找对应的终点 + */ + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + JSONArray taskArr = taskTab.query("handle_class = '" + THIS_CLASS + "'and is_delete = '0' and task_status = '2'").getResultJSONArray(0); + for (int i = 0; i < taskArr.size(); i++) { + JSONObject taskObj = taskArr.getJSONObject(i); + String material_id = taskObj.getString("material_id"); + String vehicle_type = taskObj.getString("vehicle_type"); + JSONObject param1 = new JSONObject(); + param1.put("flag", "1"); + param1.put("material_id", material_id); + param1.put("region_code", "YSQA01"); + param1.put("vehicle_type", "%" + vehicle_type + "%"); + //1、查找库区类是否有响应的载具类型和对应的物料 + JSONObject json1 = WQL.getWO("QSCH_gjxSendMaterial_01").addParamMap(param1).process().uniqueResult(0); + + + //判断是否有到同一列的相同物料SKU的AGV任务,如果有,则等待 + JSONArray taskIngs = taskTab.query("is_delete='0' and material_id = '" + material_id + "' and (task_status = '4' or task_status = '5' or task_status = '6' )").getResultJSONArray(0); + + if (ObjectUtil.isNotEmpty(taskIngs)) { + JSONObject taskIng = taskIngs.getJSONObject(0); + if (ObjectUtil.isNotEmpty(taskIng) && ObjectUtil.isNotEmpty(json1)) { + JSONObject point2 = pointTab.query("point_code = '" + taskIng.getString("point_code2") + "'").uniqueResult(0); + if (StrUtil.equals(point2.getString("block_num"), json1.getString("block_num")) + && StrUtil.equals(point2.getString("col_num"), json1.getString("col_num"))) { + taskObj.put("remark", "相应列有AGV在工作,等待执行!"); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + } + } + } + + + if (ObjectUtil.isNotEmpty(json1)) { + Integer block_num = json1.getInteger("block_num"); + Integer row_num = json1.getInteger("row_num"); + Integer col_num = json1.getInteger("col_num"); + + JSONObject firstRow = pointTab.query("block_num = '" + block_num + "' and col_num = '" + col_num + "' and row_num ='" + (row_num - 1) + "'").uniqueResult(0); + if (ObjectUtil.isEmpty(firstRow)) throw new BadRequestException("数据错误,请校验!"); + taskObj.put("point_code2", firstRow.getString("point_code")); + taskObj.put("update_time", DateUtil.now()); + taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + //二楼普通任务 + taskTab.update(taskObj); + //锁住相关货位 + JSONObject point = new JSONObject(); + point.put("lock_type", "2"); + point.put("task_id", taskObj.getString("task_id")); + pointTab.update(point, "block_num = '" + block_num + "' and col_num = '" + col_num + "' and row_num <= '" + (row_num - 1) + "'"); + + } else {//找空位入 + if (ObjectUtil.isNotEmpty(taskIngs) && taskIngs.size() > 1) { + taskObj.put("remark", "相应列有AGV在工作,等待执行!"); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + continue; + } + + JSONObject param2 = new JSONObject(); + param2.put("flag", "2"); + param2.put("region_code", "YSQA01"); + param2.put("vehicle_type", "%" + vehicle_type + "%"); + //1、查找整列为空的货位 + JSONObject json2 = WQL.getWO("QSCH_gjxSendMaterial_01").addParamMap(param2).process().uniqueResult(0); + if (ObjectUtil.isEmpty(json2)) { + taskObj.put("remark", "养生A区无可用货位"); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + } else { + Integer block_num = json2.getInteger("block_num"); + Integer col_num = json2.getInteger("col_num"); + JSONObject firstRow = pointTab.query("block_num = '" + block_num + "' and col_num = '" + col_num + "' and row_num ='9'").uniqueResult(0); + taskObj.put("point_code2", firstRow.getString("point_code")); + //二楼普通任务 + taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + //锁住相关货位 + JSONObject point = new JSONObject(); + point.put("lock_type", "2"); + point.put("task_id", taskObj.getString("task_id")); + pointTab.update(point, "block_num = '" + block_num + "' and col_num = '" + col_num + "' and row_num <= '" + 9 + "'"); + + } + } + + } + } + + @Override + public List addTask() { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + /* + * 下发给ACS时需要特殊处理 + */ + JSONArray arr = taskTab.query("handle_class = '" + THIS_CLASS + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and is_delete ='0'").getResultJSONArray(0); + + ArrayList acsTaskArr = new ArrayList<>(); + for (int i = 0; i < arr.size(); i++) { + JSONObject json = arr.getJSONObject(i); + + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + String point_code = json.getString("point_code2"); + String newPoint = point_code.substring(0, 4) + "1" + point_code.substring(4, 9); + + AcsTaskDto dto = AcsTaskDto.builder() + .task_id(json.getString("task_id")) + .task_code(json.getString("task_code")) + .task_type(json.getString("acs_task_type")) + .start_device_code(json.getString("point_code1")) + .next_device_code(newPoint) + .vehicle_code(json.getString("vehicle_code")) + .vehicle_type(json.getString("vehicle_type")) + .priority(json.getString("priority")) + .remark(json.getString("remark")) + .build(); + acsTaskArr.add(dto); + } + return acsTaskArr; + } + + @Override + public String createTask(JSONObject whereJson) { + String point_code1 = whereJson.getString("point_code1"); + String vehicle_type = whereJson.getString("vehicle_type"); + String vehicle_code = whereJson.getString("vehicle_code"); + String qty = whereJson.getString("qty"); + + //生产工单表【PDM_BD_WorkOrder】 + WQLObject workOrderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); + //点位基础表【SCH_BASE_Point】 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); + + //任务表【SCH_BASE_Task】 + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + //判断当前点是否有未完成的任务 + JSONObject taskObj = taskTab.query("is_delete='0' and point_code1 = '" + point_code1 + "' and task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) throw new BadRequestException("当前点位" + point_code1 + "存在未完成的任务"); + + String device_code = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0).getString("device_code"); + + + JSONObject workOrderObj = workOrderTab.query("device_code = '" + device_code + "' and order_status = '3' and is_delete ='0'").uniqueResult(0); + if (ObjectUtil.isEmpty(workOrderObj)) throw new BadRequestException("该设备当前未生产或者已删除"); + + + SchTaskDto dto = SchTaskDto.builder() + .task_id(IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("task_type") + .task_name("共挤线满料") + .task_status(TaskStatusEnum.SURE_START.getCode()) + .point_code1(point_code1) + .acs_task_type("2")//2楼AGV普通任务 + .vehicle_code(vehicle_code) + .material_qty(qty) + .material_info_id(workOrderObj.getLong("workorder_id")) + .material_id(workOrderObj.getLong("material_id")) + .vehicle_type(vehicle_type) + .handle_class(THIS_CLASS) + .create_time(DateUtil.now()) + .request_param(whereJson.toJSONString()) + .build(); + + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); + + //创建好立即下发 + this.immediateNotifyAcs(); + return String.valueOf(dto.getTask_id()); + } + + @Override + public void forceFinish(String task_id) { + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "' and is_delete = '0' and task_status < " + TaskStatusEnum.FINISHED.getCode()).uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) { + this.updateTaskStatus(taskObj, "2"); + } else { + throw new BadRequestException("任务已删除或者已完成!"); + } + + } + + + @Override + public void cancel(String task_id) { + + } + + //TODO 暂时不用二次申请 + @Transactional(rollbackFor = Exception.class) + @Override + public String againApply(String task_id) { + /* + * 再次下发任务处理方法 + * 涉及业务:入空载具、出空载具、入物料、出物料 + */ + + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); // 点位表 + + JSONObject taskObj = taskTab.query("task_id ='" + task_id + "'").uniqueResult(0); + + JSONObject jsonPoint3 = pointTab.query("point_code = '" + taskObj.getString("point_code3") + "'").uniqueResult(0); + //提前更新这列货位状态,方便生成往这列的任务 + jsonPoint3.put("point_status", "3"); + jsonPoint3.put("material_id", taskObj.getString("material_id")); + pointTab.update(jsonPoint3); + //释放相关货位 + JSONObject point = new JSONObject(); + point.put("lock_type", "1"); + point.put("task_id", ""); + pointTab.update(point, "task_id = '" + taskObj.getString("task_id") + "'"); + + + //养生A区发给ACS需要新的点位(2101-03-1----->21011-03-1) + String point_code = taskObj.getString("point_code3"); + String newPoint = point_code.substring(0, 4) + "1" + point_code.substring(4, 9); + return newPoint; + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/GjxSendMaterial.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/HkxSendMaterialTask.java similarity index 62% rename from lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/GjxSendMaterial.java rename to lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/HkxSendMaterialTask.java index 19d8f00..3848674 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/GjxSendMaterial.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/HkxSendMaterialTask.java @@ -9,6 +9,7 @@ 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; @@ -25,16 +26,18 @@ import java.util.List; /** - * 共挤线送料任务服务 + * 豪凯自动线线送料任务服务 */ @Service @RequiredArgsConstructor @Slf4j -public class GjxSendMaterial extends AbstractAcsTask { - private final String THIS_CLASS = GjxSendMaterial.class.getName(); +public class HkxSendMaterialTask extends AbstractAcsTask { + + private final String THIS_CLASS = HkxSendMaterialTask.class.getName(); @Override + @Transactional(rollbackFor = Exception.class) public void updateTaskStatus(JSONObject task, String status) { WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); @@ -49,19 +52,17 @@ public class GjxSendMaterial extends AbstractAcsTask { throw new BadRequestException("已完成不能取消!"); } String point_code2 = taskObj.getString("point_code2"); - String point_code3 = taskObj.getString("point_code3"); - //说明未二次申请过 - if (ObjectUtil.isEmpty(point_code3)) { - JSONObject json = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); - json.put("lock_type", "1"); - pointTab.update(json); + if (ObjectUtil.isEmpty(point_code2)) { + JSONObject endPoint = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); + endPoint.put("lock_type", "1"); + pointTab.update(endPoint); } taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); taskObj.put("remark", "已取消"); taskTab.update(taskObj); } - if (TaskStatusEnum.EXECUTING.getCode().equals(status)) { + if ("1".equals(status)) { // 更新任务状态为执行中 taskObj.put("task_status", TaskStatusEnum.EXECUTING.getCode()); taskObj.put("update_time", DateUtil.now()); @@ -69,14 +70,14 @@ public class GjxSendMaterial extends AbstractAcsTask { taskTab.update(taskObj); } - if (StrUtil.equals(status, TaskStatusEnum.FINISHED.getCode())) { + if (StrUtil.equals(status, "2")) { // 更改任务状态为完成 taskObj.put("task_status", TaskStatusEnum.FINISHED.getCode()); taskObj.put("update_time", DateUtil.now()); taskTab.update(taskObj); - String point_code3 = taskObj.getString("point_code3"); - JSONObject point3Obj = pointTab.query("point_code = '" + point_code3 + "'").uniqueResult(0); + String point_code2 = taskObj.getString("point_code2"); + JSONObject point2Obj = pointTab.query("point_code = '" + point_code2 + "'").uniqueResult(0); JSONObject requestObj = task.getJSONObject("request_param"); //工单标识 String workorder_id = requestObj.getString("material_info_id"); @@ -84,14 +85,16 @@ public class GjxSendMaterial extends AbstractAcsTask { WQLObject workOrderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); JSONObject workorderObj = workOrderTab.query("workorder_id", workorder_id).uniqueResult(0); - //区域出入表【st_ivt_regionIO】 WQLObject regionIoTab = WQLObject.getWQLObject("st_ivt_regionIO"); JSONObject regionIoObj = new JSONObject(); - regionIoObj.put("stockrecord_id", IdUtil.getLongId()); + regionIoObj.put("iostorinv_id", IdUtil.getLongId()); regionIoObj.put("bill_code", CodeUtil.getNewCode("IN_STORE_CODE")); regionIoObj.put("buss_date", DateUtil.today()); regionIoObj.put("io_type", "1"); + regionIoObj.put("region_id", point2Obj.getString("region_id")); + regionIoObj.put("region_code", point2Obj.getString("region_code")); + regionIoObj.put("region_name", point2Obj.getString("region_name")); regionIoObj.put("material_id", taskObj.getString("material_id")); regionIoObj.put("vehicle_code", taskObj.getString("vehicle_code")); regionIoObj.put("qty", requestObj.getString("qty")); @@ -100,6 +103,9 @@ public class GjxSendMaterial extends AbstractAcsTask { regionIoObj.put("end_point_code", taskObj.getString("point_code3")); regionIoObj.put("create_mode", "2"); regionIoObj.put("pcsn", DateUtil.format(DateUtil.parse(DateUtil.today()), "yyyyMMdd")); + regionIoObj.put("create_id", SecurityUtils.getCurrentUserId()); + regionIoObj.put("create_name", SecurityUtils.getCurrentNickName()); + regionIoObj.put("create_time", DateUtil.now()); regionIoTab.insert(regionIoObj); @@ -108,18 +114,25 @@ public class GjxSendMaterial extends AbstractAcsTask { WQLObject ivtTab = WQLObject.getWQLObject("ST_IVT_StructIvt"); JSONObject ivtObj = new JSONObject(); ivtObj.put("stockrecord_id", IdUtil.getLongId()); - ivtObj.put("point_id", point3Obj.getString("point_id")); - ivtObj.put("point_code", point3Obj.getString("point_code")); - ivtObj.put("point_name", point3Obj.getString("point_name")); - ivtObj.put("region_id", point3Obj.getString("region_id")); - ivtObj.put("region_code", point3Obj.getString("region_code")); - ivtObj.put("region_name", point3Obj.getString("region_name")); + ivtObj.put("point_id", point2Obj.getString("point_id")); + ivtObj.put("point_code", point2Obj.getString("point_code")); + ivtObj.put("point_name", point2Obj.getString("point_name")); + ivtObj.put("region_id", point2Obj.getString("region_id")); + ivtObj.put("region_code", point2Obj.getString("region_code")); + ivtObj.put("region_name", point2Obj.getString("region_name")); ivtObj.put("instorage_time", DateUtil.now()); ivtObj.put("pcsn", DateUtil.format(DateUtil.parse(DateUtil.today()), "yyyyMMdd")); ivtObj.put("ivt_qty", requestObj.getString("qty")); - ivtObj.put("standing_time", DateUtil.now()); + ivtObj.put("standing_time", workorderObj.getString("standing_time")); ivtObj.put("material_id", workorderObj.getString("material_id")); ivtTab.insert(ivtObj); + + // 终点解锁 + point2Obj.put("lock_type", "1"); + point2Obj.put("point_status", "3"); + // 载具类型 + point2Obj.put("vehicle_type", taskObj.getString("vehicle_type")); + pointTab.update(point2Obj); } } @@ -134,60 +147,30 @@ public class GjxSendMaterial extends AbstractAcsTask { JSONArray taskArr = taskTab.query("handle_class = '" + THIS_CLASS + "'and is_delete = '0' and task_status = '2'").getResultJSONArray(0); for (int i = 0; i < taskArr.size(); i++) { JSONObject taskObj = taskArr.getJSONObject(i); - String material_id = taskObj.getString("material_id"); String vehicle_type = taskObj.getString("vehicle_type"); JSONObject param1 = new JSONObject(); param1.put("flag", "1"); - param1.put("material_id", material_id); - param1.put("region_code", "YSQA01"); - param1.put("vehicle_type", vehicle_type); + param1.put("region_code", "CPQYA01"); + param1.put("vehicle_type", "%" + vehicle_type + "%"); //1、查找库区类是否有响应的载具类型和对应的物料 - JSONObject json1 = WQL.getWO("QSCH_gjxSendMaterial_01").addParamMap(param1).process().uniqueResult(0); - if (ObjectUtil.isNotEmpty(json1)) { - Integer block_num = json1.getInteger("block_num"); - Integer row_num = json1.getInteger("row_num"); - Integer col_num = json1.getInteger("col_num"); - - //拿到第一排 - JSONObject firstRow = pointTab.query("block_num = '" + block_num + "' and col_num = '" + col_num + "' and row_num ='1'").uniqueResult(0); - if (ObjectUtil.isEmpty(firstRow)) throw new BadRequestException("数据错误,请校验!"); - taskObj.put("point_code2", firstRow.getString("point_code")); - taskObj.put("task_status", TaskStatusEnum.START_AND_POINT); + JSONObject endPoint = WQL.getWO("QSCH_hkxSendMaterial_01").addParamMap(param1).process().uniqueResult(0); + if (ObjectUtil.isEmpty(endPoint)) { + taskObj.put("remark", "成品区无可用货位!"); taskObj.put("update_time", DateUtil.now()); - //需要设置等待点 - if (row_num > 2) { - //二楼终点追加任务 - taskObj.put("acs_task_type", "4"); - } else if (row_num == 2) { - //二楼普通任务 - taskObj.put("acs_task_type", "2"); - } - taskTab.update(taskObj); - } else {//找空位入 - JSONObject param2 = new JSONObject(); - param2.put("flag", "1"); - param2.put("region_code", "YSQA01"); - param2.put("vehicle_type", vehicle_type); - //1、查找整列为空的货位 - JSONObject json2 = WQL.getWO("QSCH_gjxSendMaterial_01").addParamMap(param2).process().uniqueResult(0); - if (ObjectUtil.isEmpty(json2)) { - taskObj.put("remark", "养生A区无可用货位"); - taskObj.put("update_time", DateUtil.now()); - taskTab.update(taskObj); - } else { - Integer block_num = json2.getInteger("block_num"); - Integer col_num = json2.getInteger("col_num"); - JSONObject firstRow = pointTab.query("block_num = '" + block_num + "' and col_num = '" + col_num + "' and row_num ='1'").uniqueResult(0); - taskObj.put("point_code2", firstRow.getString("point_code")); - taskObj.put("task_status", TaskStatusEnum.START_AND_POINT); - //二楼终点追加任务 - taskObj.put("acs_task_type", "4"); - taskObj.put("update_time", DateUtil.now()); - taskTab.update(taskObj); - } + } else { + taskObj.put("update_time", DateUtil.now()); + taskObj.put("point_code2", endPoint.getString("point_code")); + taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + taskTab.update(taskObj); + + //锁住终点 + endPoint.put("task_id", taskObj.getString("task_id")); + endPoint.put("lock_type", "2"); + pointTab.update(endPoint); } + } } @@ -224,6 +207,13 @@ public class GjxSendMaterial extends AbstractAcsTask { String vehicle_code = whereJson.getString("vehicle_code"); String qty = whereJson.getString("qty"); + + //任务表【SCH_BASE_Task】 + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + //判断当前点是否有未完成的任务 + JSONObject taskObj = taskTab.query("is_delete='0' and point_code1 = '" + point_code1 + "' and task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) throw new BadRequestException("当前点位" + point_code1 + "存在未完成的任务"); + //生产工单表【PDM_BD_WorkOrder】 WQLObject workOrderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); //点位基础表【SCH_BASE_Point】 @@ -237,17 +227,18 @@ public class GjxSendMaterial extends AbstractAcsTask { .task_id(IdUtil.getLongId()) .task_code(CodeUtil.getNewCode("TASK_CODE")) .task_type("task_type") - .task_status(TaskStatusEnum.SURE_END.getCode()) + .task_name("豪凯线满料") + .material_qty(qty) + .task_status(TaskStatusEnum.SURE_START.getCode()) .point_code1(point_code1) .vehicle_code(vehicle_code) .material_info_id(workOrderObj.getLong("workorder_id")) + .material_id(workOrderObj.getLong("material_id")) .vehicle_type(vehicle_type) .handle_class(THIS_CLASS) .create_time(DateUtil.now()) .request_param(whereJson.toJSONString()) .build(); - //任务表【SCH_BASE_Task】 - WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); taskTab.insert(json); @@ -258,7 +249,10 @@ public class GjxSendMaterial extends AbstractAcsTask { @Override public void forceFinish(String task_id) { - + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + JSONObject taskObj = taskTab.query("task_id = '" + task_id + "' and is_delete = '0' and task_status <> " + TaskStatusEnum.FINISHED.getCode()).uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) + this.updateTaskStatus(taskObj, "2"); } @@ -266,34 +260,4 @@ public class GjxSendMaterial extends AbstractAcsTask { public void cancel(String task_id) { } - - @Transactional(rollbackFor = Exception.class) - @Override - public String againApply(String task_id) { - /* - * 再次下发任务处理方法 - * 涉及业务:入空载具、出空载具、入物料、出物料 - */ - - WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); // 任务表 - WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); // 点位表 - - JSONObject taskObj = taskTab.query("task_id ='" + task_id + "'").uniqueResult(0); - JSONObject jsonPoint2 = pointTab.query("point_code = '" + taskObj.getString("point_code2") + "'").uniqueResult(0); - - // 根据 区域、块、列找到第一个有物料的货位 - JSONObject jsonOnePoint = pointTab.query("region_id = '" + jsonPoint2.getString("region_id") + - "' and block_num = '" + jsonPoint2.getString("block_num") + - "' and col_num = '" + jsonPoint2.getString("col_num") + - "' and point_status = '1' order by row_num").uniqueResult(0); - - if (ObjectUtil.isEmpty(jsonOnePoint)) throw new BadRequestException("该列库存状态有误,请检查!"); - - taskObj.put("point_code3", jsonOnePoint.getString("point_code")); - taskObj.put("remark", "二次申请货位"); - taskObj.put("update_time", DateUtil.now()); - taskTab.update(taskObj); - - return jsonOnePoint.getString("point_code"); - } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/YqxSendMaterialTask.java b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/YqxSendMaterialTask.java index 6e23a71..e71d70a 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/YqxSendMaterialTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/YqxSendMaterialTask.java @@ -1,9 +1,9 @@ package org.nl.wms.sch.tasks.sendMaterial; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; @@ -14,18 +14,18 @@ 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.sch.PointFindUtil; +import org.nl.wms.sch.SchTaskDto; 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.nl.wms.sch.service.impl.PointServiceImpl; import org.nl.wms.sch.tasks.AcsTaskDto; import org.nl.wms.sch.tasks.RegionTypeEnum; +import org.nl.wms.util.IdUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; @@ -47,11 +47,23 @@ public class YqxSendMaterialTask extends AbstractAcsTask { **/ String task_id = taskObj.getString("task_id"); WQLObject taskTab = WQLObject.getWQLObject("sch_base_task"); + //点位基础表【SCH_BASE_Point】 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); JSONObject jsonTask = taskTab.query("task_id='" + task_id + "'").uniqueResult(0); if (StrUtil.equals(status, "0")) { - // 取消删除任务 - taskTab.delete("task_id = '" + task_id + "'"); + //取消任务,释放相关点位的锁 + String point_code1 = jsonTask.getString("point_code1"); + String point_code2 = jsonTask.getString("point_code1"); + JSONObject param = new JSONObject(); + param.put("lock_type", "1"); + param.put("task_id", ""); + pointTab.update(param, "point_code = '" + point_code1 + "'"); + pointTab.update(param, "point_code = '" + point_code2 + "'"); + + jsonTask.put("task_status", TaskStatusEnum.FINISHED.getCode()); + jsonTask.put("remark", "已取消"); + taskTab.update(jsonTask); } if (TaskStatusEnum.EXECUTING.getCode().equals(status)) { @@ -60,12 +72,6 @@ public class YqxSendMaterialTask extends AbstractAcsTask { jsonTask.put("update_time", DateUtil.now()); jsonTask.put("car_no", taskObj.getString("car_no")); taskTab.update(jsonTask); - HashMap map = new HashMap(); - map.put("update_optid", SecurityUtils.getCurrentUserId()); - map.put("update_optname", SecurityUtils.getCurrentNickName()); - map.put("update_time", DateUtil.now()); - map.put("bill_status", "40"); - WQLObject.getWQLObject("ST_IVT_regionIO").update(map, "task_id='" + jsonTask.getString("task_id") + "'"); } if (TaskStatusEnum.FINISHED.getCode().equals(status)) { @@ -74,49 +80,20 @@ public class YqxSendMaterialTask extends AbstractAcsTask { jsonTask.put("taskfinish_mode", taskObj.getString("taskfinish_mode")); jsonTask.put("update_time", DateUtil.now()); jsonTask.put("remark", "任务执行完成"); - ///审核单据 增加库存 改变出入库表的状态 - WQLObject mstTab = WQLObject.getWQLObject("ST_IVT_regionIO"); - JSONObject mstObj = mstTab.query("task_id='" + task_id + "' and is_delete='0'").uniqueResult(0); - //审核 加库存可和用数量 - mstObj.put("bill_status", "50"); - mstObj.put("confirm_optid", SecurityUtils.getCurrentUserId()); - mstObj.put("confirm_optname", SecurityUtils.getCurrentNickName()); - mstObj.put("confirm_time", DateUtil.now()); - mstTab.update(mstObj); - - String iostorinv_id = mstObj.getString("iostorinv_id"); - String bill_code = mstObj.getString("bill_code"); - String bill_type_scode = mstObj.getString("bill_type"); - String point_code2 = mstObj.getString("end_point_code"); - String point_code1 = mstObj.getString("point_code1"); - - - PointServiceImpl pointService = SpringContextHolder.getBean(PointServiceImpl.class); - PointDto nextPointDto = pointService.findByCode(point_code2); - if (ObjectUtil.isNull(nextPointDto)) { - throw new BadRequestException("未找到可用点位:" + point_code2); - } - PointDto startPointDto = pointService.findByCode(point_code1); - if (ObjectUtil.isNull(startPointDto)) { - throw new BadRequestException("未找到可用点位:" + point_code1); - } - // 解锁点位 - String vehicle_code = jsonTask.getString("vehicle_code"); - WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); - JSONObject endpointObj = pointTab.query("point_code='" + jsonTask.getString("point_code2") + "'").uniqueResult(0); - endpointObj.put("lock_type", "1"); - endpointObj.put("point_status", "02"); - endpointObj.put("vehicle_code", vehicle_code); - endpointObj.put("vehicle_type", jsonTask.getString("vehicle_type")); - pointTab.update(endpointObj); taskTab.update(jsonTask); - /* JSONObject startPointObj = pointTab.query("point_code='" + jsonTask.getString("point_code1") + "'").uniqueResult(0); - startPointObj.put("lock_type", "1"); - startPointObj.put("point_status", "00"); - startPointObj.put("vehicle_code", ""); - pointTab.update(startPointObj); - taskTab.update(jsonTask);*/ + + //取消任务,释放相关点位的锁 + String point_code1 = jsonTask.getString("point_code1"); + String point_code2 = jsonTask.getString("point_code1"); + JSONObject param = new JSONObject(); + param.put("lock_type", "1"); + param.put("task_id", ""); + + pointTab.update(param, "point_code = '" + point_code1 + "'"); + + param.put("point_status", "3"); + pointTab.update(param, "point_code = '" + point_code2 + "'"); } } @@ -125,108 +102,84 @@ public class YqxSendMaterialTask extends AbstractAcsTask { public void findNextPoint() { String task_status = TaskStatusEnum.SURE_START.getCode(); WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + //点位基础表【SCH_BASE_Point】 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); JSONArray taskArry = taskTab.query("task_status='" + task_status + "' AND handle_class='" + THIS_CLASS + "' AND is_delete='0' ").getResultJSONArray(0); for (int i = 0; i < taskArry.size(); i++) { JSONObject taskObj = taskArry.getJSONObject(i); String task_id = taskObj.getString("task_id"); - //1 将任务修改为分配 2将终点写入,完成分配,3 加锁点位 - //找一个合适的仓位 - WQLObject ProcedureIOStable = WQLObject.getWQLObject("ST_IVT_regionIO"); - JSONObject IosObj = ProcedureIOStable.query("task_id='" + task_id + "' and is_delete ='0'").uniqueResult(0); - if (ObjectUtil.isEmpty(IosObj)) { - throw new BadRequestException("未找到任务号为'" + taskObj.getString("task_code") + "'的入库单据!"); - } + JSONObject param = new JSONObject(); - param.put("material_id", IosObj.getString("material_id")); - param.put("area_type", IosObj.getString("end_area")); - param.put("vehicle_code", IosObj.getString("vehicle_code")); - JSONObject inStructObj = PointFindUtil.getInStruct(param); - if (ObjectUtil.isEmpty(inStructObj)) { - throw new BadRequestException("未找到合适的入库仓位!"); + param.put("flag", "1"); + JSONObject endPoint = WQL.getWO("QSCH_yqxSendMaterial_01").addParamMap(param).process().uniqueResult(0); + if (ObjectUtil.isEmpty(endPoint)) { + taskObj.put("remark", "电梯无可用点"); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); + } else { + //锁住点位 + endPoint.put("lock_type", "2"); + endPoint.put("task_id", task_id); + pointTab.update(endPoint); + + //修改任务状态 + taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + taskObj.put("update_optid", SecurityUtils.getCurrentUserId()); + taskObj.put("update_optname", SecurityUtils.getCurrentNickName()); + taskObj.put("update_time", DateUtil.now()); + taskTab.update(taskObj); } - //修改单据状态,将终点填入 - IosObj.put("bill_status", "20"); - IosObj.put("end_point_code", inStructObj.getString("struct_code")); - ProcedureIOStable.update(IosObj); - //终点加锁 - HashMap lock_map = new HashMap(); - lock_map.put("lock_type", "2"); - WQLObject.getWQLObject("sch_base_point").update(lock_map, "point_code = '" + inStructObj.getString("struct_code") + "'"); - //修改任务状态 - taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); - taskObj.put("update_optid", SecurityUtils.getCurrentUserId()); - taskObj.put("update_optname", SecurityUtils.getCurrentNickName()); - taskObj.put("update_time", DateUtil.now()); - taskTab.update(taskObj); } } @Override @Transactional(rollbackFor = Exception.class) - public String createTask(JSONObject form) { - //请求参数 载具、起点、终点 - String vehicle_code = form.getString("vehicle_code"); - String vehicle_type = form.getString("vehicle_type"); - String point_code1 = form.getString("point_code1"); - String point_code2 = form.getString("point_code2"); + public String createTask(JSONObject whereJson) { + String point_code1 = whereJson.getString("point_code1"); + String vehicle_type = whereJson.getString("vehicle_type"); + String vehicle_code = whereJson.getString("vehicle_code"); + String qty = whereJson.getString("qty"); - WQLObject taskTable = WQLObject.getWQLObject("SCH_BASE_Task"); - WQLObject iosTable = WQLObject.getWQLObject("ST_IVT_regionIO"); + //生产工单表【PDM_BD_WorkOrder】 + WQLObject workOrderTab = WQLObject.getWQLObject("PDM_BD_WorkOrder"); + //点位基础表【SCH_BASE_Point】 + WQLObject pointTab = WQLObject.getWQLObject("SCH_BASE_Point"); + + //任务表【SCH_BASE_Task】 + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + //判断当前点是否有未完成的任务 + JSONObject taskObj = taskTab.query("is_delete='0' and point_code1 = '" + point_code1 + "' and task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'").uniqueResult(0); + if (ObjectUtil.isNotEmpty(taskObj)) throw new BadRequestException("当前点位" + point_code1 + "存在未完成的任务"); - if (StrUtil.isEmpty(point_code1)) { - throw new BadRequestException("起点不能为空!"); - } - //判断起点有没有未完成的指令 - JSONObject beforTaskObj = taskTable. - query("is_delete='0' and point_code1='" + point_code1 + "' and task_status <>'" + TaskStatusEnum.FINISHED.getCode() + "'") - .uniqueResult(0); - if (ObjectUtil.isNotEmpty(beforTaskObj)) { - throw new BadRequestException("存在指令号为'" + beforTaskObj.getString("task_code") + "' 未完成!"); - } + String device_code = pointTab.query("point_code = '" + point_code1 + "'").uniqueResult(0).getString("device_code"); + JSONObject workOrderObj = workOrderTab.query("device_code = '" + device_code + "' and order_status = '3' and is_delete ='0'").uniqueResult(0); + if (ObjectUtil.isEmpty(workOrderObj)) throw new BadRequestException("该设备当前未生产或者已删除"); - if (StrUtil.isEmpty(point_code2)) { - // 终点为空需要找终点 - JSONObject param = new JSONObject(); - param.put("point_code1", point_code1); - JSONObject endPoint = this.findEndPoint(param); - point_code2 = endPoint.getString("point_code2"); - } + SchTaskDto dto = SchTaskDto.builder() + .task_id(IdUtil.getLongId()) + .task_code(CodeUtil.getNewCode("TASK_CODE")) + .task_type("task_type") + .task_name("油漆线满料") + .task_status(TaskStatusEnum.SURE_START.getCode()) + .point_code1(point_code1) + .vehicle_code(vehicle_code) + .material_info_id(workOrderObj.getLong("workorder_id")) + .material_id(workOrderObj.getLong("material_id")) + .vehicle_type(vehicle_type) + .handle_class(THIS_CLASS) + .material_qty(qty) + .create_time(DateUtil.now()) + .request_param(whereJson.toJSONString()) + .build(); + //任务表【SCH_BASE_Task】 + JSONObject json = JSONObject.parseObject(JSON.toJSONString(dto)); + taskTab.insert(json); - //终点点加锁 - WQLObject pointTable = WQLObject.getWQLObject("sch_base_point"); - JSONObject endPointObj = pointTable.query("point_code='" + point_code2 + "'").uniqueResult(0); - endPointObj.put("lock_type", "2"); - pointTable.update(endPointObj); - - // 创建任务 - PointService pointService = SpringContextHolder.getBean(PointService.class); - - JSONObject taskObj = new JSONObject(); - CodeUtil.getNewCode("TASK_CODE"); - Long task_id = IdUtil.getSnowflake(1, 1).nextId(); - taskObj.put("task_id", task_id); - taskObj.put("task_code", CodeUtil.getNewCode("TASK_CODE")); - taskObj.put("task_type", "01"); - taskObj.put("vehicle_type", vehicle_type); - taskObj.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); - taskObj.put("point_code1", point_code1); - PointDto startPoint = pointService.findByCode(point_code1); - taskObj.put("start_area", startPoint.getRegion_id()); - taskObj.put("request_param", form.toJSONString()); - taskObj.put("point_code2", point_code2); - PointDto nextPoint = pointService.findByCode(point_code2); - taskObj.put("next_area", nextPoint.getRegion_id()); - taskObj.put("vehicle_code", vehicle_code); - taskObj.put("handle_class", THIS_CLASS); - taskObj.put("is_auto_issue", "1"); - taskObj.put("create_name", SecurityUtils.getCurrentUsername()); - taskObj.put("create_id", SecurityUtils.getCurrentUserId()); - taskObj.put("create_time", DateUtil.now()); - taskObj.put("is_delete", "0"); - taskTable.insert(taskObj); - return String.valueOf(task_id); + //创建好立即下发 + this.immediateNotifyAcs(); + return String.valueOf(dto.getTask_id()); } @@ -283,7 +236,28 @@ public class YqxSendMaterialTask extends AbstractAcsTask { @Override public List addTask() { - return null; + /* + * 下发给ACS时需要特殊处理 + */ + JSONArray arr = WQLObject.getWQLObject("SCH_BASE_Task").query("handle_class = '" + THIS_CLASS + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and is_delete ='0'").getResultJSONArray(0); + + ArrayList acsTaskArr = new ArrayList<>(); + for (int i = 0; i < arr.size(); i++) { + JSONObject json = arr.getJSONObject(i); + AcsTaskDto dto = AcsTaskDto.builder() + .task_id(json.getString("task_id")) + .task_code(json.getString("task_code")) + .task_type(json.getString("acs_task_type")) + .start_device_code(json.getString("point_code1")) + .next_device_code(json.getString("point_code3")) + .vehicle_code(json.getString("vehicle_code")) + .vehicle_type(json.getString("vehicle_type")) + .priority(json.getString("priority")) + .remark(json.getString("remark")) + .build(); + acsTaskArr.add(dto); + } + return acsTaskArr; } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_gjxSendMaterial_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_gjxSendMaterial_01.wql index bcc0312..e968122 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_gjxSendMaterial_01.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_gjxSendMaterial_01.wql @@ -44,30 +44,30 @@ IF 输入.flag = "1" QUERY SELECT - p.point_id, - p.point_code, - p.point_name, - p.block_num, - p.row_num, - p.col_num + p.point_id, + p.point_code, + p.point_name, + p.block_num, + p.row_num, + p.col_num FROM - ST_IVT_StructIvt ivt - LEFT JOIN SCH_BASE_Point p on ivt.point_id = p.point_id - WHERE - p.is_used = '1' - AND is_delete = '0' - and lock_type='1' - and p.row_num>1 + SCH_BASE_Point p + where + p.is_used = '1' + AND is_delete = '0' + AND lock_type = '1' + AND point_status = '3' + and row_num>1 OPTION 输入.material_id <> "" - ivt.material_id = 输入.material_id + p.material_id = 输入.material_id ENDOPTION OPTION 输入.region_code <> "" p.region_code = 输入.region_code ENDOPTION OPTION 输入.vehicle_type <> "" - p.can_vehicle_type = 输入.vehicle_type + p.can_vehicle_type like 输入.vehicle_type ENDOPTION - ORDER BY block_num,row_num + ORDER BY block_num,col_num,row_num ENDSELECT ENDQUERY ENDIF @@ -88,7 +88,7 @@ AND lock_type = '1' AND ( row_num = 1 OR row_num ) OPTION 输入.vehicle_type <> "" - p.can_vehicle_type = 输入.vehicle_type + p.can_vehicle_type like 输入.vehicle_type ENDOPTION GROUP BY block_num,col_num HAVING sum = 9 diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_hkxSendMaterial_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_hkxSendMaterial_01.wql new file mode 100644 index 0000000..04707a7 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_hkxSendMaterial_01.wql @@ -0,0 +1,69 @@ +[交易说明] + 交易名: 豪凯线送料请求 + 所属模块: + 功能简述: + 版权所有: + 表引用: + 版本经历: + +[数据库] + --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 + +[IO定义] + ################################################# + ## 表字段对应输入参数 + ################################################# + 输入.flag TYPEAS s_string + 输入.region_code TYPEAS s_string + 输入.material_id TYPEAS s_string + 输入.vehicle_type TYPEAS s_string + + +[临时表] + --这边列出来的临时表就会在运行期动态创建 + +[临时变量] + --所有中间过程变量均可在此处定义 + +[业务过程] + + ########################################## + # 1、输入输出检查 # + ########################################## + + + ########################################## + # 2、主过程前处理 # + ########################################## + + + ########################################## + # 3、业务主过程 # + ########################################## + + IF 输入.flag = "1" + QUERY + SELECT + p.point_id, + p.point_code, + p.point_name + FROM + SCH_BASE_Point p + WHERE + lock_type = '1' + AND is_used = '1' + AND is_delete = '0' + AND point_status = '1' + OPTION 输入.vehicle_type <> "" + p.can_vehicle_type like 输入.vehicle_type + ENDOPTION + OPTION 输入.region_code <> "" + p.region_code = 输入.region_code + ENDOPTION + ORDER BY row_num,col_num,layer_num + ENDSELECT + ENDQUERY + ENDIF + + + diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_yqxSendMaterial_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_yqxSendMaterial_01.wql new file mode 100644 index 0000000..0e1582e --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/sch/tasks/sendMaterial/wql/QSCH_yqxSendMaterial_01.wql @@ -0,0 +1,62 @@ +[交易说明] + 交易名: 油漆线送料请求 + 所属模块: + 功能简述: + 版权所有: + 表引用: + 版本经历: + +[数据库] + --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 + +[IO定义] + ################################################# + ## 表字段对应输入参数 + ################################################# + 输入.flag TYPEAS s_string + 输入.region_code TYPEAS s_string + 输入.material_id TYPEAS s_string + 输入.vehicle_type TYPEAS s_string + + +[临时表] + --这边列出来的临时表就会在运行期动态创建 + +[临时变量] + --所有中间过程变量均可在此处定义 + +[业务过程] + + ########################################## + # 1、输入输出检查 # + ########################################## + + + ########################################## + # 2、主过程前处理 # + ########################################## + + + ########################################## + # 3、业务主过程 # + ########################################## + + IF 输入.flag = "1" + QUERY + SELECT + p.point_id, + p.point_code, + p.point_name + FROM + SCH_BASE_Point p + WHERE + lock_type = '1' + AND is_used = '1' + AND is_delete = '0' + and (point_code = 'SSX01A2' or point_code = 'SSX02A1') + ENDSELECT + ENDQUERY + ENDIF + + + diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/wql/ST_VEHICLE_OUT_01.wql b/lms/nladmin-system/src/main/java/org/nl/wms/sch/wql/ST_VEHICLE_OUT_01.wql deleted file mode 100644 index f820a05..0000000 --- a/lms/nladmin-system/src/main/java/org/nl/wms/sch/wql/ST_VEHICLE_OUT_01.wql +++ /dev/null @@ -1,113 +0,0 @@ -[交易说明] - 交易名: 空载具出库业务 - 所属模块: - 功能简述: - 版权所有: - 表引用: - 版本经历: - -[数据库] - --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 - -[IO定义] - ################################################# - ## 表字段对应输入参数 - ################################################# - 输入.flag TYPEAS s_string - 输入.vehicle_qty TYPEAS s_string - 输入.vehicle_type TYPEAS s_string - 输入.region_code TYPEAS s_string - -[临时表] - --这边列出来的临时表就会在运行期动态创建 - -[临时变量] - --所有中间过程变量均可在此处定义 - -[业务过程] - - ########################################## - # 1、输入输出检查 # - ########################################## - - - ########################################## - # 2、主过程前处理 # - ########################################## - - - ########################################## - # 3、业务主过程 # - ########################################## - - IF 输入.flag = "1" - QUERY - SELECT - p.point_id, - p.point_code, - p.point_name - FROM - SCH_BASE_Point p - WHERE - p.is_used = '1' - AND p.is_delete = '0' - AND p.lock_type = '00' - AND p.point_status = '2' - and region_code in ('KTPHCQB01','YSQA01') - - OPTION 输入.vehicle_type <> "" - p.vehicle_type like 输入.vehicle_type - ENDOPTION - - order by out_empty_seq,p.vehicle_qty - - ENDSELECT - ENDQUERY - ENDIF - - IF 输入.flag = "3" - QUERY - SELECT - point.* - FROM - sch_base_point point - LEFT JOIN SCH_BASE_Region region ON point.region_id = region.region_id - WHERE - point.lock_type = '00' - AND point.point_status = '01' - AND IFNULL(point.vehicle_qty,0) == 输入.vehicle_qty - - OPTION 输入.region_code <> "" - region.region_code = 输入.region_code - ENDOPTION - - OPTION 输入.vehicle_type <> "" - point.vehicle_type = 输入.vehicle_type - ENDOPTION - - order by point.point_code DESC - - ENDSELECT - ENDQUERY - ENDIF - - IF 输入.flag = "2" - QUERY - SELECT - point.* - FROM - sch_base_point point - LEFT JOIN SCH_BASE_Region region ON point.region_id = region.region_id - WHERE - point.lock_type = '00' - AND point.point_status = '00' - - OPTION 输入.region_code <> "" - region.region_code = 输入.region_code - ENDOPTION - - order by point.point_code DESC - - ENDSELECT - ENDQUERY - ENDIF diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/sch/wql/sch.xls b/lms/nladmin-system/src/main/java/org/nl/wms/sch/wql/sch.xls new file mode 100644 index 0000000000000000000000000000000000000000..6efd92458bc899fb554a1ae44d57769239d3ae60 GIT binary patch literal 179712 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
  • 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%0Deu?A6>Ng7g=wA)brG89j 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.OK); } + + @PostMapping("/makeTask") + @Log("生成任务") + @ApiOperation("生成任务") + //@SaCheckPermission("@el.check('regionio:add')") + public ResponseEntity makeTask(@RequestBody JSONArray dto){ + regionioService.makeTask(dto); + return new ResponseEntity<>(HttpStatus.CREATED); + } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/service/RegionIoService.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/service/RegionIoService.java index beeb8c0..7e486f0 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/service/RegionIoService.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/service/RegionIoService.java @@ -64,4 +64,9 @@ public interface RegionIoService { */ void deleteAll(Long[] ids); + /** + * 生成任务 + * @param dto + */ + void makeTask(JSONArray dto); } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/service/impl/RegionIoServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/service/impl/RegionIoServiceImpl.java index e9ec0e4..8a910fc 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/service/impl/RegionIoServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/service/impl/RegionIoServiceImpl.java @@ -4,7 +4,10 @@ import com.alibaba.fastjson.JSON; import lombok.RequiredArgsConstructor; import org.nl.modules.common.exception.BadRequestException; import org.nl.modules.wql.WQL; +import org.nl.modules.wql.util.SpringContextHolder; import org.nl.wms.sch.service.RegionService; +import org.nl.wms.sch.tasks.cpOut.CpOutTask; +import org.nl.wms.sch.tasks.sendMaterial.HkxSendMaterialTask; import org.nl.wms.st.bill.service.RegionIoService; import org.nl.wms.st.bill.service.dto.RegionIoDto; import org.springframework.stereotype.Service; @@ -137,5 +140,29 @@ public class RegionIoServiceImpl implements RegionIoService { } } + /** + * 生成任务 + * + * @param dto + */ + @Override + public void makeTask(JSONArray dto) { + WQLObject regionIoTab = WQLObject.getWQLObject("st_ivt_regionIO"); + for (int i = 0; i < dto.size(); i++) { + JSONObject dtoJSONObject = dto.getJSONObject(i); + JSONObject iostorinv = regionIoTab.query("iostorinv_id = '" + dtoJSONObject.getString("iostorinv_id") + "'").uniqueResult(0); + if (ObjectUtil.equal(iostorinv.getString("bill_status"), "3")) + throw new BadRequestException("没有单据或者已出库"); + JSONObject param = new JSONObject(); + param.put("point_code1", dtoJSONObject.getString("start_point_code")); + param.put("vehicle_code", dtoJSONObject.getString("vehicle_code")); +// param.put("vehicle_type", vehicle_type); + param.put("iostorinv_id", dtoJSONObject.getString("iostorinv_id")); + CpOutTask taskBean = SpringContextHolder.getBean(CpOutTask.class); + String task_id = taskBean.createTask(param); + } + + } + } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/wql/ST_IVT_REGIONIO.wql b/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/wql/ST_IVT_REGIONIO.wql index 2b5a29a..1515d56 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/wql/ST_IVT_REGIONIO.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/bill/wql/ST_IVT_REGIONIO.wql @@ -53,7 +53,7 @@ WHERE regionio.io_type = 输入.io_type AND - start_region_id IN + region_id IN ( SELECT region.region_id FROM sch_base_region region WHERE region.region_code IN 输入.io_region ) diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/rest/StructivtController.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/rest/StructivtController.java index 07ee594..d02ef8c 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/rest/StructivtController.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/rest/StructivtController.java @@ -1,5 +1,6 @@ package org.nl.wms.st.structivt.rest; +import com.alibaba.fastjson.JSONArray; import org.nl.wms.st.structivt.service.StructivtService; import org.nl.wms.st.structivt.service.dto.StructivtDto; import org.springframework.data.domain.Pageable; @@ -62,5 +63,13 @@ public class StructivtController { structivtService.deleteAll(ids); return new ResponseEntity<>(HttpStatus.OK); } + + @PostMapping("/outInventory") + @Log("出库") + @ApiOperation("出库") + public ResponseEntity outInventory(@RequestBody JSONArray jsonArray){ + structivtService.outInventory(jsonArray); + return new ResponseEntity<>(HttpStatus.CREATED); + } } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/service/StructivtService.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/service/StructivtService.java index 9884652..c753bfb 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/service/StructivtService.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/service/StructivtService.java @@ -1,5 +1,6 @@ package org.nl.wms.st.structivt.service; +import com.alibaba.fastjson.JSONArray; import org.nl.wms.st.structivt.service.dto.StructivtDto; import org.springframework.data.domain.Pageable; import java.util.Map; @@ -61,5 +62,11 @@ public interface StructivtService { * @param ids / */ void deleteAll(Long[] ids); + + /** + * 出库 + * @param jsonArray + */ + void outInventory(JSONArray jsonArray); } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/service/impl/StructivtServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/service/impl/StructivtServiceImpl.java index c5456a2..56cd6cd 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/service/impl/StructivtServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/service/impl/StructivtServiceImpl.java @@ -3,6 +3,7 @@ package org.nl.wms.st.structivt.service.impl; import com.alibaba.fastjson.JSON; import lombok.RequiredArgsConstructor; import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.system.util.CodeUtil; import org.nl.modules.wql.WQL; import org.nl.wms.sch.service.PointService; import org.nl.wms.sch.service.RegionService; @@ -42,7 +43,7 @@ public class StructivtServiceImpl implements StructivtService { @Override public Map queryAll(Map whereJson, Pageable page){ - JSONObject map = new JSONObject(); + JSONObject map = new JSONObject(); map.put("flag", "1"); map.put("region_code", "(" + whereJson.get("region_code") + ")"); if (!ObjectUtil.isNull(whereJson.get("point_code"))) { @@ -227,4 +228,50 @@ public class StructivtServiceImpl implements StructivtService { } } + /** + * 出库 + * + * @param jsonArray + */ + @Override + public void outInventory(JSONArray jsonArray) { + WQLObject structIvtTab = WQLObject.getWQLObject("ST_IVT_STRUCTIVT"); + WQLObject regionIoTab = WQLObject.getWQLObject("ST_IVT_REGIONIO"); + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + WQLObject taskTab = WQLObject.getWQLObject("SCH_BASE_Task"); + String in_store_code = CodeUtil.getNewCode("IN_STORE_CODE"); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject structivts = jsonArray.getJSONObject(i); + // 如果是空位或者锁定就跳过 + if (structivts.getString("lock_type").equals("2") || !structivts.getString("point_status").equals("3")) continue; + // 插入regionIO - 未锁定,有料位 + JSONObject regionIoObj = new JSONObject(); + regionIoObj.put("iostorinv_id", IdUtil.getSnowflake(1, 1).nextId()); + regionIoObj.put("bill_code", in_store_code); // 批量新增相同 + regionIoObj.put("buss_date", DateUtil.today()); + regionIoObj.put("io_type", "2"); + regionIoObj.put("material_id", structivts.getString("material_id")); + regionIoObj.put("pcsn", structivts.getString("pcsn")); + regionIoObj.put("vehicle_code", structivts.getString("vehicle_code")); + regionIoObj.put("qty", structivts.getString("ivt_qty")); + regionIoObj.put("qty_unit_id", structivts.getString("qty_unit_id")); + regionIoObj.put("bill_status", "1"); + regionIoObj.put("start_point_code", structivts.getString("point_code")); // 起点 + String start_region_id = pointTab.query("point_code = '" + structivts.getString("point_code") + "'").uniqueResult(0).getString("region_id"); + if (ObjectUtil.isNotEmpty(start_region_id)) + regionIoObj.put("region_id", structivts.getString("region_id")); + regionIoObj.put("region_code", structivts.getString("region_code")); + regionIoObj.put("region_name", structivts.getString("region_name")); + regionIoObj.put("create_mode", "2"); + regionIoObj.put("create_id", SecurityUtils.getCurrentUserId()); + regionIoObj.put("create_name", SecurityUtils.getCurrentNickName()); + regionIoObj.put("create_time", DateUtil.now()); + regionIoTab.insert(regionIoObj); + // 上锁 + JSONObject point = pointTab.query("point_id = '" + structivts.getString("point_id") + "'").uniqueResult(0); + point.put("lock_type", "2"); + pointTab.update(point); + } + } + } diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/wql/ST_IVT_STRUCTIVT.wql b/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/wql/ST_IVT_STRUCTIVT.wql index 8ac05a6..84eaa8e 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/wql/ST_IVT_STRUCTIVT.wql +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/structivt/wql/ST_IVT_STRUCTIVT.wql @@ -21,6 +21,7 @@ 输入.bill_code TYPEAS s_string 输入.bill_status TYPEAS s_string 输入.io_type TYPEAS s_string + 输入.lock_type TYPEAS s_string [临时表] @@ -47,48 +48,48 @@ IF 输入.flag = "1" PAGEQUERY SELECT - cppoint.*, - str.stockrecord_id, - str.pcsn, - str.material_id, - str.ivt_qty, - str.qty_unit_id, - str.instorage_time, - str.standing_time + str.*, + point.vehicle_type, + point.layer_num, + point.row_num, + point.col_num, + point.is_used, + point.lock_type, + point.point_status FROM st_ivt_structivt str - LEFT JOIN sch_base_point cppoint ON str.point_id = cppoint.point_id + LEFT JOIN sch_base_point point ON str.point_id = point.point_id WHERE - cppoint.region_code IN 输入.region_code + point.region_code IN 输入.region_code OPTION 输入.point_code <> "" - point_code LIKE 输入.point_code + point.point_code LIKE 输入.point_code ENDOPTION OPTION 输入.point_status <> "" - point_status = 输入.point_status + point.point_status = 输入.point_status ENDOPTION OPTION 输入.vehicle_type <> "" - vehicle_type = 输入.vehicle_type + point.vehicle_type = 输入.vehicle_type ENDOPTION OPTION 输入.layer_num <> "" - layer_num = 输入.layer_num + point.layer_num = 输入.layer_num ENDOPTION OPTION 输入.row_num <> "" - row_num = 输入.row_num + point.row_num = 输入.row_num ENDOPTION OPTION 输入.col_num <> "" - col_num = 输入.col_num + point.col_num = 输入.col_num ENDOPTION OPTION 输入.lock_type <> "" - YsaPoint.lock_type = 输入.lock_type + point.lock_type = 输入.lock_type ENDOPTION OPTION 输入.is_used <> "" - is_used = 输入.is_used + point.is_used = 输入.is_used ENDOPTION OPTION 输入.begin_time <> "" - instorage_time >= 输入.begin_time + str.instorage_time >= 输入.begin_time ENDOPTION OPTION 输入.end_time <> "" - instorage_time <= 输入.end_time + str.instorage_time <= 输入.end_time ENDOPTION ENDSELECT ENDPAGEQUERY 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 02b9b58258dfcd14dbff6eb5054e72a66f1af417..19d2354bfd85d7d85fa9f307756dd234e1738461 100644 GIT binary patch delta 51490 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 Vx#lgXW+IC~D-f)-&E%PW{{`0P6HNdB delta 48580 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 E1Bl%#SO5S3 diff --git a/lms/nladmin-system/src/main/resources/config/application-dev.yml b/lms/nladmin-system/src/main/resources/config/application-dev.yml index 8d35511..d3cd31b 100644 --- a/lms/nladmin-system/src/main/resources/config/application-dev.yml +++ b/lms/nladmin-system/src/main/resources/config/application-dev.yml @@ -6,8 +6,8 @@ spring: druid: db-type: com.alibaba.druid.pool.DruidDataSource driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy - url: jdbc:log4jdbc:mysql://${DB_HOST:47.111.78.178}:${DB_PORT:3306}/${DB_NAME:yongyu_lms2}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true - # url: jdbc:log4jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:nladmin}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true +# url: jdbc:log4jdbc:mysql://${DB_HOST:47.111.78.178}:${DB_PORT:3306}/${DB_NAME:yongyu_lms2}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true + url: jdbc:log4jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:yongyu_lms2}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true username: ${DB_USER:root} password: ${DB_PWD:P@ssw0rd} # password: ${DB_PWD:12356} diff --git a/lms/nladmin-system/src/main/resources/logback-spring.xml b/lms/nladmin-system/src/main/resources/logback-spring.xml index ac1dd00..dbc1ded 100644 --- a/lms/nladmin-system/src/main/resources/logback-spring.xml +++ b/lms/nladmin-system/src/main/resources/logback-spring.xml @@ -81,37 +81,40 @@ https://juejin.cn/post/6844903775631572999 - - - - - - - - - - + + + + + + + - + - + - + - + + + + + + + @@ -119,27 +122,57 @@ https://juejin.cn/post/6844903775631572999 - + - + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lms/nladmin-ui/src/api/wms/sch/point.js b/lms/nladmin-ui/src/api/wms/sch/point.js index b6030b7..7a78111 100644 --- a/lms/nladmin-ui/src/api/wms/sch/point.js +++ b/lms/nladmin-ui/src/api/wms/sch/point.js @@ -60,4 +60,12 @@ export function changeUsed(data) { }) } -export default { add, edit, del, changeActive, findPoints, getPoint, getRegion, changeUsed } +export function changeLock(data) { + return request({ + url: 'api/point/changeLock', + method: 'post', + data: data + }) +} + +export default { add, edit, del, changeActive, findPoints, getPoint, getRegion, changeUsed, changeLock } diff --git a/lms/nladmin-ui/src/views/wms/pdm/workerorder/index.vue b/lms/nladmin-ui/src/views/wms/pdm/workerorder/index.vue index 652cd87..169fab4 100644 --- a/lms/nladmin-ui/src/views/wms/pdm/workerorder/index.vue +++ b/lms/nladmin-ui/src/views/wms/pdm/workerorder/index.vue @@ -31,23 +31,6 @@ class="filter-item" /> - - - - - - - - - - @@ -195,6 +168,22 @@ /> + + + + + - - - @@ -364,7 +348,7 @@ export default { name: 'Produceshiftorder', components: { pagination, crudOperation, rrOperation, udOperation, MaterDtl, ViewDialog, DeviceDialog }, mixins: [presenter(), header(), form(defaultForm), crud()], - dicts: ['pdm_workorder_status', 'is_used', 'pdm_workorder_type', 'is_or_not', 'vehicle_type', 'workorder_procedure'], + dicts: ['pdm_workorder_status', 'is_used', 'is_or_not', 'vehicle_type', 'workorder_procedure'], cruds() { return CRUD({ title: '工单', url: 'api/workorder', idField: 'workorder_id', sort: 'workorder_id,desc', diff --git a/lms/nladmin-ui/src/views/wms/sch/point/index.vue b/lms/nladmin-ui/src/views/wms/sch/point/index.vue index 83622f3..b1d2d48 100644 --- a/lms/nladmin-ui/src/views/wms/sch/point/index.vue +++ b/lms/nladmin-ui/src/views/wms/sch/point/index.vue @@ -7,7 +7,7 @@ :inline="true" class="demo-form-inline" label-position="right" - label-width="80px" + label-width="90px" label-suffix=":" > @@ -69,22 +69,51 @@ /> - - - + + + + + + + + + + + + + - - + /> @@ -104,6 +133,7 @@ + 禁用 + + + 锁定 + + - 禁用 + 解锁 @@ -240,7 +295,7 @@ - + - - + + - + - -