From 01b8f430847453901b9812cc63974960f238e602 Mon Sep 17 00:00:00 2001 From: liuxy Date: Fri, 2 Feb 2024 15:33:56 +0800 Subject: [PATCH] =?UTF-8?q?add=EF=BC=9A=E6=9C=A8=E7=AE=B1=E5=87=BA?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nl/b_lms/sch/tasks/TwoMoveBoxTask.java | 190 ++++++++ .../org/nl/b_lms/sch/tasks/TwoOutBoxTask.java | 177 +++++++ .../storage_manage/ios/enums/IOSEnum.java | 2 +- .../util/impl/InBoxManageServiceImpl.java | 5 +- .../util/impl/OutBoxManageServiceImpl.java | 449 ++++++++++++++++++ .../impl/OutVehicleManageServiceImpl.java | 4 +- .../util/service/OutBoxManageService.java | 27 ++ .../service/iostorInv/util/wql/BST_OUTBOX.wql | 294 ++++++++++++ .../outbill/rest/CheckOutBillController.java | 8 + 9 files changed, 1151 insertions(+), 5 deletions(-) create mode 100644 lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoMoveBoxTask.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutBoxTask.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutBoxManageServiceImpl.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/service/OutBoxManageService.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/wql/BST_OUTBOX.wql diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoMoveBoxTask.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoMoveBoxTask.java new file mode 100644 index 000000000..1f695df2b --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoMoveBoxTask.java @@ -0,0 +1,190 @@ +package org.nl.b_lms.sch.tasks; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.nl.b_lms.storage_manage.ios.enums.IOSEnum; +import org.nl.common.utils.SecurityUtils; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.wms.sch.AcsTaskDto; +import org.nl.wms.sch.manage.AbstractAcsTask; +import org.nl.wms.sch.manage.TaskStatusEnum; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * 二期空木箱移库任务类 + * Created by Lxy on 2024/1/19. + */ +public class TwoMoveBoxTask extends AbstractAcsTask { + + /** + * 处理类 + */ + private final String THIS_CLASS = TwoMoveBoxTask.class.getName(); + + @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); + + char dtl_type = json.getString("task_type").charAt(json.getString("task_type").length() - 1); + AcsTaskDto dto = AcsTaskDto.builder() + .ext_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_code2")) + .vehicle_code(json.getString("vehicle_code")) + .priority(json.getString("priority")) + .class_type(json.getString("task_type")) + .dtl_type(String.valueOf(dtl_type)) + .remark(json.getString("remark")) + .build(); + resultList.add(dto); + } + return resultList; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTaskStatus(JSONObject taskObj, String status) { + + // 仓位表 + WQLObject attrTab = WQLObject.getWQLObject("st_ivt_structattr"); + // 载具扩展属性表 + WQLObject veExtTab = WQLObject.getWQLObject("md_pb_storagevehicleext"); + + // 更新任务的参数 + JSONObject map = new JSONObject(); + + /* + * 1-执行中, 2-完成 ,0-acs取消 + */ + // 执行中 + if (status.equals(TaskStatusEnum.EXECUTING.getCode())) { + + map.put("task_status", TaskStatusEnum.EXECUTING.getCode()); + } + + // 完成 + if (status.equals(TaskStatusEnum.FINISHED.getCode())) { + + map.put("task_status", TaskStatusEnum.FINISHED.getCode()); + + // 更新起点 + JSONObject jsonAttrStar = attrTab.query("struct_code = '" + taskObj.getString("point_code1") + "'").uniqueResult(0); + jsonAttrStar.put("lock_type",IOSEnum.LOCK_TYPE.code("未锁定")); + jsonAttrStar.put("storagevehicle_code",""); + attrTab.update(jsonAttrStar); + + // 更新终点 + JSONObject jsonAttrEnd = attrTab.query("struct_code = '" + taskObj.getString("point_code2") + "'").uniqueResult(0); + jsonAttrEnd.put("lock_type",IOSEnum.LOCK_TYPE.code("未锁定")); + jsonAttrEnd.put("storagevehicle_code",taskObj.getString("vehicle_code")); + attrTab.update(jsonAttrEnd); + } + + // 取消 + if (status.equals(IOSEnum.IS_NOTANDYES.code("否"))) { + + if (taskObj.getIntValue("task_status") > Integer.valueOf(TaskStatusEnum.ISSUE.getCode())) { + throw new BadRequestException("任务已执行不能取消"); + } + + // 更新任务表删除字段 + map.put("is_delete", IOSEnum.IS_NOTANDYES.code("是")); + + // 解锁起点 + JSONObject jsonAttrStar = attrTab.query("struct_code = '" + taskObj.getString("point_code1") + "'").uniqueResult(0); + jsonAttrStar.put("lock_type",IOSEnum.LOCK_TYPE.code("未锁定")); + attrTab.update(jsonAttrStar); + + // 解锁终点 + JSONObject jsonAttrEnd = attrTab.query("struct_code = '" + taskObj.getString("point_code2") + "'").uniqueResult(0); + jsonAttrEnd.put("lock_type",IOSEnum.LOCK_TYPE.code("未锁定")); + attrTab.update(jsonAttrEnd); + + } + + map.put("update_optid", SecurityUtils.getCurrentUserId()); + map.put("update_optname", SecurityUtils.getCurrentNickName()); + map.put("update_time", DateUtil.now()); + + WQLObject.getWQLObject("SCH_BASE_Task").update(map, "task_id = '" + taskObj.getString("task_id") + "'"); + } + + @Override + public void findStartPoint() { + + } + + @Override + public void findNextPoint() { + + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String createTask(JSONObject form) { + + if (StrUtil.isBlank(form.getString("task_type"))) { + throw new BadRequestException("业务类型不能为空!"); + } + + if (StrUtil.isBlank(form.getString("start_device_code"))) { + throw new BadRequestException("起点不能为空!"); + } + + if (StrUtil.isBlank(form.getString("next_device_code"))) { + throw new BadRequestException("终点不能为空!"); + } + + if (StrUtil.isBlank(form.getString("vehicle_code"))) { + throw new BadRequestException("木箱号不能为空!"); + } + + JSONObject json = new JSONObject(); + json.put("task_id", IdUtil.getSnowflake(1, 1).nextId()); + json.put("task_code", IdUtil.getSnowflake(1, 1).nextId()); + json.put("task_type", form.getString("task_type")); + json.put("vehicle_code", form.getString("vehicle_code")); + json.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + json.put("task_group_id", form.getLongValue("task_group_id")); + json.put("point_code1", form.getString("start_device_code")); + json.put("point_code2", form.getString("next_device_code")); + json.put("handle_class", this.getClass().getName()); + json.put("create_id", SecurityUtils.getCurrentUserId()); + json.put("create_name", SecurityUtils.getCurrentUsername()); + json.put("create_time", DateUtil.now()); + json.put("priority", "1"); + json.put("acs_task_type", "7"); + + WQLObject.getWQLObject("SCH_BASE_Task").insert(json); + return json.getString("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) { + JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0); + this.updateTaskStatus(taskObj, IOSEnum.ACS_RESULT.code("取消")); + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutBoxTask.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutBoxTask.java new file mode 100644 index 000000000..7361d2f36 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutBoxTask.java @@ -0,0 +1,177 @@ +package org.nl.b_lms.sch.tasks; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.nl.b_lms.storage_manage.ios.enums.IOSEnum; +import org.nl.common.utils.SecurityUtils; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.wms.sch.AcsTaskDto; +import org.nl.wms.sch.manage.AbstractAcsTask; +import org.nl.wms.sch.manage.TaskStatusEnum; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * 二期空木箱出库任务类 + * Created by Lxy on 2024/1/19. + */ +public class TwoOutBoxTask extends AbstractAcsTask { + + /** + * 处理类 + */ + private final String THIS_CLASS = TwoOutBoxTask.class.getName(); + + @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); + + char dtl_type = json.getString("task_type").charAt(json.getString("task_type").length() - 1); + AcsTaskDto dto = AcsTaskDto.builder() + .ext_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_code2")) + .vehicle_code(json.getString("vehicle_code")) + .priority(json.getString("priority")) + .class_type(json.getString("task_type")) + .dtl_type(String.valueOf(dtl_type)) + .remark(json.getString("remark")) + .build(); + resultList.add(dto); + } + return resultList; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateTaskStatus(JSONObject taskObj, String status) { + + // 仓位表 + WQLObject attrTab = WQLObject.getWQLObject("st_ivt_structattr"); + + // 更新任务的参数 + JSONObject map = new JSONObject(); + + /* + * 1-执行中, 2-完成 ,0-acs取消 + */ + // 执行中 + if (status.equals(TaskStatusEnum.EXECUTING.getCode())) { + + map.put("task_status", TaskStatusEnum.EXECUTING.getCode()); + } + + // 完成 + if (status.equals(TaskStatusEnum.FINISHED.getCode())) { + + map.put("task_status", TaskStatusEnum.FINISHED.getCode()); + + // 更新仓位 + JSONObject jsonAttr = attrTab.query("struct_code = '" + taskObj.getString("point_code1") + "'").uniqueResult(0); + jsonAttr.put("lock_type",IOSEnum.LOCK_TYPE.code("未锁定")); + jsonAttr.put("storagevehicle_code",""); + attrTab.update(jsonAttr); + } + + // 取消 + if (status.equals(IOSEnum.IS_NOTANDYES.code("否"))) { + + if (taskObj.getIntValue("task_status") > Integer.valueOf(TaskStatusEnum.ISSUE.getCode())) { + throw new BadRequestException("任务已执行不能取消"); + } + + // 更新任务表删除字段 + map.put("is_delete", IOSEnum.IS_NOTANDYES.code("是")); + + // 解锁仓位 + JSONObject jsonAttr = attrTab.query("struct_code = '" + taskObj.getString("point_code1") + "'").uniqueResult(0); + jsonAttr.put("lock_type",IOSEnum.LOCK_TYPE.code("未锁定")); + attrTab.update(jsonAttr); + } + + map.put("update_optid", SecurityUtils.getCurrentUserId()); + map.put("update_optname", SecurityUtils.getCurrentNickName()); + map.put("update_time", DateUtil.now()); + + WQLObject.getWQLObject("SCH_BASE_Task").update(map, "task_id = '" + taskObj.getString("task_id") + "'"); + } + + @Override + public void findStartPoint() { + + } + + @Override + public void findNextPoint() { + + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String createTask(JSONObject form) { + + if (StrUtil.isBlank(form.getString("task_type"))) { + throw new BadRequestException("业务类型不能为空!"); + } + + if (StrUtil.isBlank(form.getString("start_device_code"))) { + throw new BadRequestException("起点不能为空!"); + } + + if (StrUtil.isBlank(form.getString("next_device_code"))) { + throw new BadRequestException("终点不能为空!"); + } + + if (StrUtil.isBlank(form.getString("vehicle_code"))) { + throw new BadRequestException("木箱号不能为空!"); + } + + JSONObject json = new JSONObject(); + json.put("task_id", IdUtil.getSnowflake(1, 1).nextId()); + json.put("task_code", IdUtil.getSnowflake(1, 1).nextId()); + json.put("task_type", form.getString("task_type")); + json.put("vehicle_code", form.getString("vehicle_code")); + json.put("vehicle_type", form.getString("vehicle_type")); + json.put("task_status", TaskStatusEnum.START_AND_POINT.getCode()); + json.put("task_group_id", form.getLongValue("task_group_id")); + json.put("point_code1", form.getString("start_device_code")); + json.put("point_code2", form.getString("next_device_code")); + json.put("handle_class", this.getClass().getName()); + json.put("create_id", SecurityUtils.getCurrentUserId()); + json.put("create_name", SecurityUtils.getCurrentUsername()); + json.put("create_time", DateUtil.now()); + json.put("priority", "1"); + json.put("acs_task_type", "7"); + + WQLObject.getWQLObject("SCH_BASE_Task").insert(json); + return json.getString("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) { + JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0); + this.updateTaskStatus(taskObj, IOSEnum.ACS_RESULT.code("取消")); + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/enums/IOSEnum.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/enums/IOSEnum.java index a47f0d5d1..5095d75c0 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/enums/IOSEnum.java +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/enums/IOSEnum.java @@ -60,7 +60,7 @@ public enum IOSEnum { //仓位锁定类型 LOCK_TYPE(MapOf.of("未锁定", "1", "入库锁", "2", "出库锁", "3", "空托盘出库锁", "4", - "空托盘入库锁", "5", "移出锁", "6", "移入锁", "7","木箱入库锁","8", "其它", "99" + "空托盘入库锁", "5", "移出锁", "6", "移入锁", "7","木箱入库锁","8","木箱出库锁","9", "其它", "99" )), //仓库id diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/InBoxManageServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/InBoxManageServiceImpl.java index 5cd0ea734..3bc611975 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/InBoxManageServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/InBoxManageServiceImpl.java @@ -158,7 +158,7 @@ public class InBoxManageServiceImpl implements InBoxManageService { * } * @return JSONObject : 仓位对象 */ - private JSONObject getStruct(JSONObject jsonParam) { + public JSONObject getStruct(JSONObject jsonParam) { // 仓位表 WQLObject attrTab = WQLObject.getWQLObject("st_ivt_structattr"); @@ -220,7 +220,8 @@ public class InBoxManageServiceImpl implements InBoxManageService { } } } - + notInRowList.clear(); + notInBlockList.clear(); return jsonAttr; } diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutBoxManageServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutBoxManageServiceImpl.java new file mode 100644 index 000000000..f826dbaf7 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutBoxManageServiceImpl.java @@ -0,0 +1,449 @@ +package org.nl.b_lms.storage_manage.ios.service.iostorInv.util.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.nl.b_lms.sch.tasks.TwoMoveBoxTask; +import org.nl.b_lms.sch.tasks.TwoOutBoxTask; +import org.nl.b_lms.storage_manage.ios.enums.IOSEnum; +import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.OutBoxManageService; +import org.nl.common.utils.IdUtil; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.wql.WQL; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.wms.pda.mps.eum.RegionTypeEnum; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 空载具业务处理 服务实现类 + *

+ * + * @author generator + * @since 2023-11-10 + */ +@Service +public class OutBoxManageServiceImpl implements OutBoxManageService { + + /** + * 出库不需要查询的排集合 + */ + private List notOutRowList = new ArrayList<>(); + + /** + * 出库不需要查询的巷道集合 + */ + private List notOutBlockList = new ArrayList<>(); + + @Override + @Transactional + public void outBox(JSONObject whereJson) { + /* + * 1.找到符合条件的空木箱 + */ + // 点位表 + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); + // 仓位表 + WQLObject attrTab = WQLObject.getWQLObject("st_ivt_structattr"); + + whereJson.put("stor_id", IOSEnum.STOR_ID.code("二期")); + whereJson.put("sect_id", RegionTypeEnum.TWO_MX01.getId()); + + // 判断起点点位是否存在 + JSONObject jsonPoint = pointTab.query("point_code = '" + whereJson.getString("device_code") + "' AND is_delete = '" + + IOSEnum.IS_NOTANDYES.code("否") + "' AND is_used = '" + + IOSEnum.IS_NOTANDYES.code("是") + "'") + .uniqueResult(0); + + if (ObjectUtil.isEmpty(jsonPoint)) { + throw new BadRequestException("终点点位不存在或未启用!"); + } + + JSONObject jsonAttr = getStruct(whereJson); + + if (ObjectUtil.isEmpty(jsonAttr)) { + notOutRowList.clear(); + notOutBlockList.clear(); + throw new BadRequestException("没有符合规格的木箱!"); + } + + // 生成任务 + JSONObject jsonTaskParam = new JSONObject(); + jsonTaskParam.put("task_type", "010504"); + jsonTaskParam.put("start_device_code", jsonAttr.getString("struct_code")); + jsonTaskParam.put("next_device_code", whereJson.getString("device_code")); + jsonTaskParam.put("vehicle_code", jsonAttr.getString("storagevehicle_code")); + jsonTaskParam.put("task_group_id", jsonAttr.getString("task_group_id")); + + TwoOutBoxTask taskBean = new TwoOutBoxTask(); + taskBean.createTask(jsonTaskParam); + taskBean.immediateNotifyAcs(null); + + // 锁定起点 + jsonAttr.put("lock_type", IOSEnum.LOCK_TYPE.code("木箱出库锁")); + attrTab.update(jsonAttr); + + // 清空缓存 + notOutRowList.clear(); + notOutBlockList.clear(); + } + + /** + * 找一个空木箱 + * @param whereJson { + * device_code:终点 + * box_length: 长 + * box_width: 宽 + * box_high: 高 + * num: 子卷数 + * } + * @return JSONObject: 仓位对象 + */ + private JSONObject getStruct(JSONObject whereJson) { + /* + * 判断是否有相同规格的木箱 + * 判断条件:库区、仓库、是否启用、是否删除、未锁定、有载具、相同规格的木箱 + */ + whereJson.put("flag", "6"); + JSONArray structArray = WQL.getWO("BST_OUTBOX").addParamMap(whereJson).process().getResultJSONArray(0); + + if (ObjectUtil.isEmpty(structArray)) { + notOutRowList.clear(); + notOutBlockList.clear(); + throw new BadRequestException("没有相同规格的木箱!"); + } + + // 确定巷道:找相同规格木箱的最多的巷道 + String block_num = getMaxBlock(whereJson); + + // 确定排:找某一巷道规格木箱的最多排 + whereJson.put("block_num", block_num); + String row_num = getMaxRow(whereJson); + + // 确定仓位 + whereJson.put("row_num", row_num); + JSONObject jsonAttr = getBox(whereJson); + + // 为空则新找巷道 + if (ObjectUtil.isEmpty(jsonAttr)) { + + whereJson.put("flag", "1"); + notOutBlockList.add(whereJson.getString("block_num")); + + String join = "('" + String.join("','", notOutBlockList) + "')"; + whereJson.put("not_block_id", join); + + List blockList = WQL.getWO("BST_OUTBOX").addParamMap(whereJson) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + for (int i = 0; i < blockList.size(); i++) { + JSONObject json = blockList.get(i); + json.put("stor_id", whereJson.getString("stor_id")); + json.put("sect_id", whereJson.getString("sect_id")); + json.put("box_length", whereJson.getString("box_length")); + json.put("box_width", whereJson.getString("box_width")); + json.put("box_high", whereJson.getString("box_high")); + json.put("num", whereJson.getString("num")); + + String row_num_2 = getMaxRow(json); + json.put("row_num",row_num_2); + JSONObject jsonAttr_2 = getBox(json); + + if (ObjectUtil.isNotEmpty(jsonAttr_2)) { + jsonAttr = jsonAttr_2; + break; + } else { + continue; + } + } + } + return jsonAttr; + } + + /** + * 找相同规格木箱的最多的巷道 + * @param whereJson { + * box_length: 长 + * box_width: 宽 + * box_high: 高 + * num: 子卷数 + * } + * @return block_num: 巷道 + */ + private String getMaxBlock(JSONObject whereJson) { + whereJson.put("flag", "1"); + + // 查询所有相同规格木箱的巷道集合 + List allBlockList = WQL.getWO("BST_OUTBOX").addParamMap(whereJson) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + if (ObjectUtil.isEmpty(allBlockList)) { + notOutRowList.clear(); + notOutBlockList.clear(); + throw new BadRequestException("没有相同规格的木箱!"); + } + + // 查询所有相同规格木箱巷道的仓位 + String block_num_in = allBlockList.stream() + .map(row -> row.getString("block_num")) + .collect(Collectors.joining("','")); + + whereJson.put("flag", "2"); + whereJson.put("block_num_in", "('"+block_num_in+"')"); + + List likeAttrList = WQL.getWO("BST_OUTBOX").addParamMap(whereJson) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + // 计算每个巷道的数量 + ArrayList blockBoxList = new ArrayList<>(); + + for (int i = 0; i < allBlockList.size(); i++) { + JSONObject jsonBlock = allBlockList.get(i); + + List blockAttrNum = likeAttrList.stream() + .filter(row -> row.getString("block_num").equals(jsonBlock.getString("block_num"))) + .collect(Collectors.toList()); + + jsonBlock.put("box_num", String.valueOf(blockAttrNum.size())); + blockBoxList.add(jsonBlock); + } + + // 最大木箱数的巷道 + List boxNumList = blockBoxList.stream() + .sorted(Comparator.comparing(row -> row.getString("box_num"))) + .collect(Collectors.toList()); + + String block_num = ""; + if (ObjectUtil.isNotEmpty(boxNumList)) { + block_num = boxNumList.get(boxNumList.size() - 1).getString("block_num"); + } + + return block_num ; + } + + /** + * 找到某一巷道相同规格木箱的最多的排 + * @param whereJson { + * box_length: 长 + * box_width: 宽 + * box_high: 高 + * num: 子卷数 + * block_num: 巷道 + * } + * @return String: 排 + */ + private String getMaxRow(JSONObject whereJson) { + whereJson.put("flag", "3"); + + // 查询所有某一巷道相同规格木箱的排集合 + List allRowList = WQL.getWO("BST_OUTBOX").addParamMap(whereJson) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + if (ObjectUtil.isEmpty(allRowList)) { + throw new BadRequestException("请当前排列任务执行完后在试!"); + } + + // 查询某一巷道所有相同规格木箱排的仓位 + String row_num_in = allRowList.stream() + .map(row -> row.getString("row_num")) + .collect(Collectors.joining("','")); + + whereJson.put("flag", "2"); + whereJson.put("row_num_in", "('"+row_num_in+"')"); + + List likeAttrList = WQL.getWO("BST_OUTBOX").addParamMap(whereJson) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + // 计算每个排的数量 + ArrayList blockBoxList = new ArrayList<>(); + + for (int i = 0; i < allRowList.size(); i++) { + JSONObject jsonRow = allRowList.get(i); + + List blockAttrNum = likeAttrList.stream() + .filter(row -> row.getString("row_num").equals(jsonRow.getString("row_num"))) + .collect(Collectors.toList()); + + jsonRow.put("box_num", String.valueOf(blockAttrNum.size())); + blockBoxList.add(jsonRow); + } + + // 最大木箱数的排 + List boxNumList = blockBoxList.stream() + .sorted(Comparator.comparing(row -> row.getString("box_num"))) + .collect(Collectors.toList()); + + String row_num = ""; + if (ObjectUtil.isNotEmpty(boxNumList)) { + row_num = boxNumList.get(boxNumList.size() - 1).getString("row_num"); + } + + return row_num; + } + + /** + * 找一个空木箱 + * @param whereJson { + * box_length: 长 + * box_width: 宽 + * box_high: 高 + * num: 子卷数 + * block_num: 巷道 + * row_num: 排 + * } + * @return JSONObject: 需要出库的空木箱 + */ + private JSONObject getBox(JSONObject whereJson) { + // 确定仓位:找一个未锁定的空木箱 + JSONObject jsonAttr = getBoxOne(whereJson); + + // 为空找此巷道新的一排 + if (ObjectUtil.isEmpty(jsonAttr)) { + notOutRowList.add(whereJson.getString("row_num")); + + String join = "('" + String.join("','", notOutRowList) + "')"; + whereJson.put("not_row_in", join); + + // 新的一排 + String row_num_new = this.getMaxRow(whereJson); + whereJson.put("row_num",row_num_new); + + jsonAttr = this.getBoxOne(whereJson); + } + + return jsonAttr; + } + + /** + * 确定巷道、确定排,找一个空木箱 + * @param whereJson { + * box_length: 长 + * box_width: 宽 + * box_high: 高 + * num: 子卷数 + * block_num: 巷道 + * row_num: 排 + * } + * @return JSONObject: 空木箱 + */ + private JSONObject getBoxOne(JSONObject whereJson) { + // 查相同规格木箱某一巷道某一排的所有木箱 + whereJson.put("flag", "4"); + + List allAttrList = WQL.getWO("BST_OUTBOX").addParamMap(whereJson) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + // 获取此仓库、库区、巷道、排的所有仓位 + whereJson.put("flag", "5"); + + List structAllList = WQL.getWO("BST_OUTBOX").addParamMap(whereJson) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + JSONObject jsonAttr = new JSONObject(); + + for (int i = 0; i < allAttrList.size(); i++){ + JSONObject json = allAttrList.get(i); + + if (json.getString("zdepth").equals(IOSEnum.ZDEPTH_STRUCT.code("无"))) { + jsonAttr = json; + break; + } else if (json.getString("zdepth").equals(IOSEnum.ZDEPTH_STRUCT.code("深"))) { + /* + * 深货位: 判断浅货位是否被锁定 + */ + // 获取此货位对应的浅货位 + List lowAttr = structAllList.stream() + .filter(row -> row.getString("col_num").equals(json.getString("col_num")) && + row.getString("layer_num").equals(json.getString("layer_num")) && + row.getString("zdepth").equals(IOSEnum.ZDEPTH_STRUCT.code("浅"))) + .collect(Collectors.toList()); + + if (ObjectUtil.isEmpty(lowAttr) || lowAttr.size() != 1) { + notOutRowList.clear(); + notOutBlockList.clear(); + throw new BadRequestException("仓位:" + json.getString("struct_code") + "对应的浅货位错误!"); + } + + // 判断浅货位是否有木箱 + if (ObjectUtil.isEmpty(lowAttr.get(0).getString("storagevehicle_code"))) { + // 判断是否被锁定 + if (lowAttr.get(0).getString("lock_type").equals(IOSEnum.LOCK_TYPE.code("未锁定"))) { + jsonAttr = json; + break; + } else { + continue; + } + } else { + // 判断是否被锁定 + if (lowAttr.get(0).getString("lock_type").equals(IOSEnum.LOCK_TYPE.code("未锁定"))) { + // 创建木箱移库单 + String task_group_id = createBoxMove(lowAttr.get(0)); + + json.put("task_group_id",task_group_id); + jsonAttr = json; + break; + } else { + jsonAttr = json; + break; + } + } + } else if (json.getString("zdepth").equals(IOSEnum.ZDEPTH_STRUCT.code("浅"))) { + /* + * 浅货位: 直接出 + */ + jsonAttr = json; + break; + } + } + return jsonAttr; + } + + /** + * 创建木箱移库任务 + * @param jsonObject : 需要移库的仓位对象 + * @return String: 任务组标识 + */ + private String createBoxMove(JSONObject jsonObject) { + WQLObject attrTab = WQLObject.getWQLObject("st_ivt_structattr"); + + // 找一个空的仓位 + JSONObject paramIn = new JSONObject(); + paramIn.put("stor_id", IOSEnum.STOR_ID.code("二期")); + paramIn.put("sect_id", RegionTypeEnum.TWO_MX01.getId()); + + JSONObject jsonAttr = new InBoxManageServiceImpl().getStruct(paramIn); + + if (ObjectUtil.isEmpty(jsonAttr)) { + throw new BadRequestException("木箱移库任务生成失败,没有空位!"); + } + + // 锁定起点 + jsonObject.put("lock_type", IOSEnum.LOCK_TYPE.code("移出锁")); + attrTab.update(jsonObject); + + // 锁定终点 + jsonAttr.put("lock_type",IOSEnum.LOCK_TYPE.code("移入锁")); + attrTab.update(jsonAttr); + + // 生成任务 + JSONObject jsonTaskParam = new JSONObject(); + jsonTaskParam.put("task_type", "010505"); + jsonTaskParam.put("start_device_code", jsonObject.getString("struct_code")); + jsonTaskParam.put("next_device_code", jsonAttr.getString("struct_code")); + jsonTaskParam.put("vehicle_code", jsonObject.getString("storagevehicle_code")); + jsonTaskParam.put("task_group_id", IdUtil.getLongId()); + + TwoMoveBoxTask taskBan = new TwoMoveBoxTask(); + taskBan.createTask(jsonTaskParam); + taskBan.immediateNotifyAcs(null); + + return jsonTaskParam.getString("task_group_id"); + } + +} diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutVehicleManageServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutVehicleManageServiceImpl.java index e5fc90f4f..342591ecc 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutVehicleManageServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutVehicleManageServiceImpl.java @@ -81,14 +81,14 @@ public class OutVehicleManageServiceImpl implements OutVehicleManageService { jsonTaskParam.put("task_type", "010504"); jsonTaskParam.put("start_device_code", jsonAttr.getString("struct_code")); jsonTaskParam.put("next_device_code", whereJson.getString("device_code")); - jsonTaskParam.put("vehicle_code", jsonAttr.getString("storagevehicle_type")); + jsonTaskParam.put("vehicle_code", jsonAttr.getString("storagevehicle_code")); jsonTaskParam.put("vehicle_type", whereJson.getString("vehicle_type")); TwoOutEmpTask taskBean = new TwoOutEmpTask(); taskBean.createTask(jsonTaskParam); taskBean.immediateNotifyAcs(null); - // 锁定终点 + // 锁定起点 jsonAttr.put("lock_type", IOSEnum.LOCK_TYPE.code("空托盘出库锁")); attrTab.update(jsonAttr); diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/service/OutBoxManageService.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/service/OutBoxManageService.java new file mode 100644 index 000000000..7ac4a7b35 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/service/OutBoxManageService.java @@ -0,0 +1,27 @@ +package org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service; + +import com.alibaba.fastjson.JSONObject; + +/** + *

+ * 空木箱业务处理 服务类 + *

+ * + * @author generator + * @since 2023-11-16 + */ +public interface OutBoxManageService { + + /** + * 出空木箱 + * @param whereJson { + * device_code:终点 + * box_length: 长 + * box_width: 宽 + * box_high: 高 + * num: 子卷数 + * } + */ + void outBox(JSONObject whereJson); + +} diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/wql/BST_OUTBOX.wql b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/wql/BST_OUTBOX.wql new file mode 100644 index 000000000..9b30a0e8b --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/wql/BST_OUTBOX.wql @@ -0,0 +1,294 @@ +[交易说明] + 交易名: 木箱出库逻辑 + 所属模块: + 功能简述: + 版权所有: + 表引用: + 版本经历: + +[数据库] + --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 + +[IO定义] + ################################################# + ## 表字段对应输入参数 + ################################################# + 输入.flag TYPEAS s_string + 输入.stor_id TYPEAS s_string + 输入.sect_id TYPEAS s_string + 输入.block_num TYPEAS s_string + 输入.row_num TYPEAS s_string + 输入.block_num_in TYPEAS f_string + 输入.row_num_in TYPEAS f_string + 输入.not_row_in TYPEAS f_string + 输入.not_block_id TYPEAS f_string + + 输入.box_length TYPEAS s_string + 输入.box_width TYPEAS s_string + 输入.box_high TYPEAS s_string + 输入.num TYPEAS s_string + +[临时表] + --这边列出来的临时表就会在运行期动态创建 + +[临时变量] + --所有中间过程变量均可在此处定义 + +[业务过程] + + ########################################## + # 1、输入输出检查 # + ########################################## + + + ########################################## + # 2、主过程前处理 # + ########################################## + + + ########################################## + # 3、业务主过程 # + ########################################## + + IF 输入.flag = "1" + QUERY + SELECT + attr.block_num + FROM + st_ivt_structattr attr + INNER JOIN bst_ivt_boxinfo box ON attr.storagevehicle_code = box.box_no + WHERE + attr.is_used = '1' + AND attr.is_delete = '0' + AND attr.lock_type = '1' + AND IFNULL(attr.storagevehicle_code,'') <> '' + AND attr.stor_id = 输入.stor_id + AND attr.sect_id = 输入.sect_id + + OPTION 输入.not_block_id <> "" + attr.block_num not in = 输入.not_block_id + ENDOPTION + + + OPTION 输入.box_length <> "" + box.box_length = 输入.box_length + ENDOPTION + + OPTION 输入.box_width <> "" + box.box_width = 输入.box_width + ENDOPTION + + OPTION 输入.box_high <> "" + box.box_high = 输入.box_high + ENDOPTION + + OPTION 输入.num <> "" + box.num = 输入.num + ENDOPTION + + group by attr.block_num + order by attr.block_num + + ENDSELECT + ENDQUERY + ENDIF + + IF 输入.flag = "2" + QUERY + SELECT + attr.* + FROM + st_ivt_structattr attr + INNER JOIN bst_ivt_boxinfo box ON attr.storagevehicle_code = box.box_no + WHERE + attr.is_used = '1' + AND attr.is_delete = '0' + AND attr.lock_type = '1' + AND IFNULL(attr.storagevehicle_code,'') <> '' + AND attr.stor_id = 输入.stor_id + AND attr.sect_id = 输入.sect_id + + OPTION 输入.block_num <> "" + attr.block_num = 输入.block_num + ENDOPTION + + OPTION 输入.block_num_in <> "" + attr.block_num in 输入.block_num_in + ENDOPTION + + OPTION 输入.row_num_in <> "" + attr.row_num in 输入.row_num_in + ENDOPTION + + + OPTION 输入.box_length <> "" + box.box_length = 输入.box_length + ENDOPTION + + OPTION 输入.box_width <> "" + box.box_width = 输入.box_width + ENDOPTION + + OPTION 输入.box_high <> "" + box.box_high = 输入.box_high + ENDOPTION + + OPTION 输入.num <> "" + box.num = 输入.num + ENDOPTION + + ENDSELECT + ENDQUERY + ENDIF + + IF 输入.flag = "3" + QUERY + SELECT + attr.row_num + FROM + st_ivt_structattr attr + INNER JOIN bst_ivt_boxinfo box ON attr.storagevehicle_code = box.box_no + WHERE + attr.is_used = '1' + AND attr.is_delete = '0' + AND attr.lock_type = '1' + AND IFNULL(attr.storagevehicle_code,'') <> '' + AND attr.stor_id = 输入.stor_id + AND attr.sect_id = 输入.sect_id + + OPTION 输入.block_num <> "" + attr.block_num = 输入.block_num + ENDOPTION + + OPTION 输入.not_row_in <> "" + attr.row_num not in 输入.not_row_in + ENDOPTION + + + OPTION 输入.box_length <> "" + box.box_length = 输入.box_length + ENDOPTION + + OPTION 输入.box_width <> "" + box.box_width = 输入.box_width + ENDOPTION + + OPTION 输入.box_high <> "" + box.box_high = 输入.box_high + ENDOPTION + + OPTION 输入.num <> "" + box.num = 输入.num + ENDOPTION + + group by attr.row_num + order by attr.row_num + + ENDSELECT + ENDQUERY + ENDIF + + IF 输入.flag = "4" + QUERY + SELECT + attr.* + FROM + st_ivt_structattr attr + INNER JOIN bst_ivt_boxinfo box ON attr.storagevehicle_code = box.box_no + WHERE + attr.is_used = '1' + AND attr.is_delete = '0' + AND attr.lock_type = '1' + AND IFNULL(attr.storagevehicle_code,'') <> '' + AND attr.stor_id = 输入.stor_id + AND attr.sect_id = 输入.sect_id + + OPTION 输入.block_num <> "" + attr.block_num = 输入.block_num + ENDOPTION + + + OPTION 输入.row_num <> "" + attr.row_num = 输入.row_num + ENDOPTION + + OPTION 输入.box_length <> "" + box.box_length = 输入.box_length + ENDOPTION + + OPTION 输入.box_width <> "" + box.box_width = 输入.box_width + ENDOPTION + + OPTION 输入.box_high <> "" + box.box_high = 输入.box_high + ENDOPTION + + OPTION 输入.num <> "" + box.num = 输入.num + ENDOPTION + + order by attr.col_num, attr.zdepth, attr.layer_num + + ENDSELECT + ENDQUERY + ENDIF + + IF 输入.flag = "5" + QUERY + SELECT + attr.* + FROM + st_ivt_structattr attr + WHERE + attr.is_used = '1' + AND attr.is_delete = '0' + AND attr.stor_id = 输入.stor_id + AND attr.sect_id = 输入.sect_id + + OPTION 输入.block_num <> "" + attr.block_num = 输入.block_num + ENDOPTION + + OPTION 输入.row_num <> "" + attr.row_num = 输入.row_num + ENDOPTION + + ENDSELECT + ENDQUERY + ENDIF + + IF 输入.flag = "6" + QUERY + SELECT + attr.* + FROM + st_ivt_structattr attr + INNER JOIN bst_ivt_boxinfo box ON attr.storagevehicle_code = box.box_no + WHERE + attr.is_used = '1' + AND attr.is_delete = '0' + AND attr.lock_type = '1' + AND IFNULL(storagevehicle_code,'') <> '' + AND attr.stor_id = 输入.stor_id + AND attr.sect_id = 输入.sect_id + + OPTION 输入.box_length <> "" + box.box_length = 输入.box_length + ENDOPTION + + OPTION 输入.box_width <> "" + box.box_width = 输入.box_width + ENDOPTION + + OPTION 输入.box_high <> "" + box.box_high = 输入.box_high + ENDOPTION + + OPTION 输入.num <> "" + box.num = 输入.num + ENDOPTION + + ENDSELECT + ENDQUERY + ENDIF diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/outbill/rest/CheckOutBillController.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/outbill/rest/CheckOutBillController.java index f4b9a163e..88b3c0fe2 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/st/outbill/rest/CheckOutBillController.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/outbill/rest/CheckOutBillController.java @@ -7,6 +7,7 @@ import org.nl.b_lms.storage_manage.ios.enums.IOSEnum; import org.nl.b_lms.storage_manage.ios.service.iostorInv.IStIvtIostorinvOutService; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.impl.InBoxManageServiceImpl; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.impl.InVehicleManageServiceImpl; +import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.impl.OutBoxManageServiceImpl; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.impl.OutVehicleManageServiceImpl; import org.nl.modules.logging.annotation.Log; import org.nl.wms.st.inbill.service.CheckOutBillService; @@ -385,4 +386,11 @@ public class CheckOutBillController { return new ResponseEntity<>(HttpStatus.OK); } + @PostMapping("/testOutBox") + @Log("木箱出库测试") + public ResponseEntity testOutBox(@RequestBody JSONObject whereJson) { + new OutBoxManageServiceImpl().outBox(whereJson); + return new ResponseEntity<>(HttpStatus.OK); + } + }