diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutHeapTask.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutHeapTask.java index 629581818..cde67aa04 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutHeapTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutHeapTask.java @@ -4,10 +4,10 @@ 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 org.nl.b_lms.storage_manage.ios.enums.IOSEnum; -import org.nl.b_lms.storage_manage.ios.service.iostorInv.impl.StIvtIostorinvOutServiceImpl; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.impl.LashManageServiceImpl; import org.nl.common.utils.SecurityUtils; import org.nl.modules.common.exception.BadRequestException; @@ -15,6 +15,7 @@ import org.nl.modules.wql.core.bean.WQLObject; import org.nl.modules.wql.util.SpringContextHolder; import org.nl.system.service.param.impl.SysParamServiceImpl; import org.nl.wms.sch.AcsTaskDto; +import org.nl.wms.sch.AcsUtil; import org.nl.wms.sch.manage.AbstractAcsTask; import org.nl.wms.sch.manage.TaskStatusEnum; import org.springframework.stereotype.Service; @@ -22,8 +23,6 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; /** * 堆垛机点位至行架点位任务(出库) @@ -103,6 +102,8 @@ public class TwoOutHeapTask extends AbstractAcsTask { * 一个行架点位只允许一个任务正在执行或下发中 */ WQLObject wo_Task = WQLObject.getWQLObject("sch_base_task"); + // 点位表 + WQLObject pointTab = WQLObject.getWQLObject("sch_base_point"); ArrayList taskArr = new ArrayList<>(); @@ -145,9 +146,14 @@ public class TwoOutHeapTask extends AbstractAcsTask { if (ObjectUtil.isNotEmpty(twoJsonOne)) { // 进行二次分配 - twoJsonOne.put("point_code2",IOSEnum.OUT_HANGER.code("行架位2")); - wo_Task.update(twoJsonOne); - taskArr.add(twoJsonOne); + // 判断点位是否启用 + JSONObject jsonOne = pointTab.query("point_code = '" + IOSEnum.OUT_HANGER.code("行架位2") + "'") + .uniqueResult(0); + if (jsonOne.getString("is_used").equals("1")) { + twoJsonOne.put("point_code2",IOSEnum.OUT_HANGER.code("行架位2")); + wo_Task.update(twoJsonOne); + taskArr.add(twoJsonOne); + } } } @@ -167,9 +173,13 @@ public class TwoOutHeapTask extends AbstractAcsTask { if (ObjectUtil.isNotEmpty(twoJsonTwo)) { // 进行二次分配 - twoJsonTwo.put("point_code2",IOSEnum.OUT_HANGER.code("行架位1")); - wo_Task.update(twoJsonTwo); - taskArr.add(twoJsonTwo); + JSONObject jsonTwo = pointTab.query("point_code = '" + IOSEnum.OUT_HANGER.code("行架位1") + "'") + .uniqueResult(0); + if (jsonTwo.getString("is_used").equals("1")) { + twoJsonTwo.put("point_code2",IOSEnum.OUT_HANGER.code("行架位1")); + wo_Task.update(twoJsonTwo); + taskArr.add(twoJsonTwo); + } } } } @@ -232,8 +242,8 @@ public class TwoOutHeapTask extends AbstractAcsTask { LashManageServiceImpl bean1 = SpringContextHolder.getBean(LashManageServiceImpl.class); bean1.createLashTask(jsonParam); - // 再次下发 - immediateNotifyAcs(null); + // 再次下发:找相同任务组的下发 + sendTaskAcs(jsonTask.getString("task_group_id")); } } } @@ -296,4 +306,79 @@ public class TwoOutHeapTask extends AbstractAcsTask { JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0); this.updateTaskStatus(taskObj, IOSEnum.IS_NOTANDYES.code("否")); } + + public void sendTaskAcs(String groupTaskId) { + /* + * 下发给ACS时需要特殊处理 + */ + //任务表 + WQLObject wo_Task = WQLObject.getWQLObject("sch_base_task"); + + List taskArrAll = wo_Task + .query("handle_class = '" + THIS_CLASS + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and task_group_id = '" + groupTaskId + "'" + " and is_delete ='0' ORDER BY create_time") + .getResultJSONArray(0).toJavaList(JSONObject.class); + + if (ObjectUtil.isEmpty(taskArrAll)) { + taskArrAll = wo_Task + .query("handle_class = '" + THIS_CLASS + "' and task_status = '" + TaskStatusEnum.START_AND_POINT.getCode() + "' and is_delete ='0' ORDER BY create_time") + .getResultJSONArray(0).toJavaList(JSONObject.class); + } + + // 是否下发多个AGV输送出库任务 + String is_send_many = SpringContextHolder.getBean(SysParamServiceImpl.class).findByCode("is_send_many").getValue(); + // 是否异常出库口任务 + String TWO_EXCEP = SpringContextHolder.getBean(SysParamServiceImpl.class).findByCode("TWO_EXCEP").getValue(); + + List taskArr; + if (TWO_EXCEP.equals(IOSEnum.IS_NOTANDYES.code("否"))) { + if (is_send_many.equals(IOSEnum.IS_NOTANDYES.code("否"))) { + // 只允许每个行架点位有一条任务 + taskArr = sendTask(taskArrAll); + } else { + taskArr = taskArrAll; + } + } else { + taskArr = taskArrAll; + } + + ArrayList resultList = new ArrayList<>(); + for (int i = 0; i < taskArr.size(); i++) { + JSONObject json = taskArr.get(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_code2")) + .vehicle_code2(json.getString("vehicle_code")) + .interaction_json(json.getJSONObject("request_param")) + .priority(json.getString("priority")) + .class_type(IOSEnum.ACS_TYPE.code("RGV输送任务")) + .dtl_type(String.valueOf(dtl_type)) + .product_area(IOSEnum.PRODUCT_AREA.code("BLK")) + .remark(json.getString("remark")) + .build(); + + if (json.getString("vehicle_code2").contains("A")) { + dto.setRoute_plan_code("two"); + } else { + dto.setRoute_plan_code("normal"); + } + resultList.add(dto); + + // 更新任务为下发 + JSONObject paramMap = new JSONObject(); + paramMap.put("task_status", TaskStatusEnum.ISSUE.getCode()); + wo_Task.update(paramMap, "task_id ='" + json.getString("task_id") + "'"); + + // 调用下发 + if (ObjectUtil.isNotEmpty(resultList)) { + JSONArray arr = JSONArray.parseArray(JSON.toJSONString(resultList)); + AcsUtil.notifyAcs("api/wms/task", arr); + } + } + } } diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutTask.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutTask.java index fa820dc8c..10a85d207 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutTask.java +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/TwoOutTask.java @@ -6,11 +6,9 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import lombok.RequiredArgsConstructor; import org.nl.b_lms.storage_manage.ios.enums.IOSEnum; import org.nl.b_lms.storage_manage.ios.service.iostorInv.impl.StIvtIostorinvOutServiceImpl; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.impl.LashManageServiceImpl; -import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.LashManageService; import org.nl.common.utils.SecurityUtils; import org.nl.modules.common.exception.BadRequestException; import org.nl.modules.wql.WQL; @@ -19,16 +17,9 @@ import org.nl.modules.wql.util.SpringContextHolder; import org.nl.wms.sch.AcsTaskDto; import org.nl.wms.sch.manage.AbstractAcsTask; import org.nl.wms.sch.manage.TaskStatusEnum; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import static org.nl.wms.util.TaskUtil.getRoutePlanCode; @@ -59,9 +50,12 @@ public class TwoOutTask extends AbstractAcsTask { .getResultJSONArray(0).toJavaList(JSONObject.class); // 未下发的任务根据任务组进行分组 - Map> groupMap = arr.stream() + Map> sorMap = arr.stream() .collect(Collectors.groupingBy(row -> row.getString("task_group_id"))); + // 任务组按照从大到小排序 + LinkedHashMap> groupMap = sortMap(sorMap); + // 需要下发的集合 List taskArr = new ArrayList<>(); @@ -292,4 +286,30 @@ public class TwoOutTask extends AbstractAcsTask { JSONObject taskObj = WQLObject.getWQLObject("SCH_BASE_Task").query("task_id = '" + task_id + "'").uniqueResult(0); this.updateTaskStatus(taskObj, IOSEnum.IS_NOTANDYES.code("否")); } + + private LinkedHashMap> sortMap(Map> map) { + HashMap intMap = new HashMap<>(); + + for (String key : map.keySet()) { + intMap.put(key,map.get(key).size()); + } + + LinkedHashMap collect = intMap.entrySet() + .stream() + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) + .collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (e1, e2) -> e1, + LinkedHashMap::new + )); + + LinkedHashMap> resultMap = new LinkedHashMap<>(); + + for (String key : collect.keySet()) { + resultMap.put(key, map.get(key)); + } + + return resultMap; + } } diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/impl/StIvtIostorinvOutServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/impl/StIvtIostorinvOutServiceImpl.java index 6c1b82aa7..e5eee6b8c 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/impl/StIvtIostorinvOutServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/impl/StIvtIostorinvOutServiceImpl.java @@ -29,6 +29,7 @@ import org.nl.b_lms.storage_manage.ios.service.iostorInv.dao.mapper.StIvtIostori import org.nl.b_lms.storage_manage.ios.service.iostorInv.dao.mapper.StIvtIostorinvdisMapper; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.InBussManageService; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.OutBussManageService; +import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.TwoInBussManageService; import org.nl.common.utils.IdUtil; import org.nl.common.utils.SecurityUtils; import org.nl.modules.common.exception.BadRequestException; @@ -123,6 +124,12 @@ public class StIvtIostorinvOutServiceImpl extends ServiceImpl executeArr = WQLObject.getWQLObject("SCH_BASE_Task") @@ -268,13 +270,25 @@ public class LashManageServiceImpl implements LashManageService { if (TWO_EXCEP.equals(IOSEnum.IS_NOTANDYES.code("是"))) { next_device_code = IOSEnum.EXCEP_OUT.code("异常出库口"); } else { - List heapOne = Optional.ofNullable(groupPointMap.get(IOSEnum.OUT_HANGER.code("行架位1"))).orElse(new ArrayList<>()); - List heapTwo = Optional.ofNullable(groupPointMap.get(IOSEnum.OUT_HANGER.code("行架位2"))).orElse(new ArrayList<>()); + // 判断是否是启用状态 + List jsonList = pointTab.query("region_code = 'BLKCK' AND is_used = '1'") + .getResultJSONArray(0).toJavaList(JSONObject.class); - - if (heapOne.size() > heapTwo.size()) { - next_device_code = IOSEnum.OUT_HANGER.code("行架位2"); + if (ObjectUtil.isEmpty(jsonList)) { + throw new BadRequestException("请检查CK2012/CK2017是否启用!"); } + if (jsonList.size() == 2) { + List heapOne = Optional.ofNullable(groupPointMap.get(IOSEnum.OUT_HANGER.code("行架位1"))).orElse(new ArrayList<>()); + List heapTwo = Optional.ofNullable(groupPointMap.get(IOSEnum.OUT_HANGER.code("行架位2"))).orElse(new ArrayList<>()); + + + if (heapOne.size() > heapTwo.size()) { + next_device_code = IOSEnum.OUT_HANGER.code("行架位2"); + } + } else { + next_device_code = jsonList.get(0).getString("point_code"); + } + } // 查询木箱对应的载具 @@ -297,7 +311,7 @@ public class LashManageServiceImpl implements LashManageService { TwoOutHeapTask bean = SpringContextHolder.getBean(TwoOutHeapTask.class); bean.createTask(jsonTaskParam); - bean.immediateNotifyAcs(null); + bean.sendTaskAcs(whereJson.getString("task_group_id")); } @Override diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutBussManageServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutBussManageServiceImpl.java index d45db79a3..d72e02b3a 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutBussManageServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/OutBussManageServiceImpl.java @@ -18,6 +18,7 @@ import org.nl.b_lms.storage_manage.ios.service.iostorInv.dao.StIvtIostorinvdis; import org.nl.b_lms.storage_manage.ios.service.iostorInv.dao.StIvtIostorinvdtl; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.InBussManageService; import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.OutBussManageService; +import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.TwoInBussManageService; import org.nl.common.utils.IdUtil; import org.nl.modules.common.exception.BadRequestException; import org.nl.modules.wql.WQL; @@ -91,6 +92,12 @@ public class OutBussManageServiceImpl implements OutBussManageService { @Autowired private IschBaseTaskService ischBaseTaskService; + /** + * 二期入库业务处理接口 + */ + @Autowired + private TwoInBussManageService twoInBussManageService; + @Override @Transactional public void lockStruct(List param, JSONObject json) { @@ -430,7 +437,8 @@ public class OutBussManageServiceImpl implements OutBussManageService { // 移库巷道 moveParam.put("move_block_num",json.getString("block_num")); - JSONObject jsonMove = inBussManageService.getOneStruct(moveParam); + // TODO JSONObject jsonMove = inBussManageService.getOneStruct(moveParam); + JSONObject jsonMove = twoInBussManageService.getOneStruct(moveParam); // 查询移出货位的库存物料 JSONObject jsonMoveIvt = WQL.getWO("ST_OUTIVT03") @@ -577,7 +585,8 @@ public class OutBussManageServiceImpl implements OutBussManageService { // 移库巷道 moveParam.put("move_block_num",json.getString("block_num")); - JSONObject jsonMove = inBussManageService.getOneStruct(moveParam); + // TODO JSONObject jsonMove = inBussManageService.getOneStruct(moveParam); + JSONObject jsonMove = twoInBussManageService.getOneStruct(moveParam); // 查询移出货位的库存物料 JSONObject jsonMoveIvt = WQL.getWO("ST_OUTIVT03") @@ -746,7 +755,8 @@ public class OutBussManageServiceImpl implements OutBussManageService { moveParam.put("vehicle_type", boxDao.getVehicle_type()); // 移库巷道 moveParam.put("move_block_num",jsonPoint.getString("block_num")); - JSONObject jsonMove = inBussManageService.getOneStruct(moveParam); + // TODO JSONObject jsonMove = inBussManageService.getOneStruct(moveParam); + JSONObject jsonMove = twoInBussManageService.getOneStruct(moveParam); if (ObjectUtil.isEmpty(jsonMove)) { throw new BadRequestException("当前【"+jsonPoint.getString("block_num")+"】号巷道没有可用仓位!"); } @@ -867,7 +877,8 @@ public class OutBussManageServiceImpl implements OutBussManageService { moveParam.put("vehicle_type", boxDao.getVehicle_type()); // 移库巷道 moveParam.put("move_block_num",jsonAttr.getString("block_num")); - JSONObject jsonMove = inBussManageService.getOneStruct(moveParam); + // TODO JSONObject jsonMove = inBussManageService.getOneStruct(moveParam); + JSONObject jsonMove = twoInBussManageService.getOneStruct(moveParam); if (ObjectUtil.isEmpty(jsonMove)) { throw new BadRequestException("当前【"+jsonAttr.getString("block_num")+"】号巷道没有可用仓位!"); } diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/TwoInBussManageServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/TwoInBussManageServiceImpl.java new file mode 100644 index 000000000..1c21762ea --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/impl/TwoInBussManageServiceImpl.java @@ -0,0 +1,407 @@ +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 lombok.extern.log4j.Log4j; +import org.nl.b_lms.storage_manage.ios.enums.IOSEnum; +import org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service.TwoInBussManageService; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.wql.WQL; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.modules.wql.util.SpringContextHolder; +import org.nl.system.service.param.impl.SysParamServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@Log4j +public class TwoInBussManageServiceImpl implements TwoInBussManageService { + + /** + * 不需要查询的巷道集合 + */ + private List notInBlockList = new ArrayList<>(); + + @Override + public JSONObject getOneStruct(JSONObject jsonObject) { + /* + * 成品入库规则: + * 1.负载均衡:相同木箱规格(长宽高)、订单、客户、物料的 平均分配在每个巷道 + * 2.相同木箱规格、订单、客户、物料的可以放双伸位,即可以放2个木箱 + * 匹配货位逻辑: + * 1.根据仓库、库区查询所有货位,判断是否有空位 + * 2.确定巷道:查看每个巷道相同木箱规格等 的数量,找到数量最小的那个巷道 + * 1).如果没有相同木箱的,则新开一个巷道(从下往上) + * 2).如果有相同木箱的,则查看有没有空的巷道(优先入空巷道) + * 3.确定哪排:查看每排相同木箱规格等 的数量,找到数量最小的那排 + * 1).如果没有相同木箱的,则新开一个排(从下往上) + * 2).如果有相同木箱的,则查看有没有空的一排(优先入空排) + * 4.确定伸位: + * 1)如果当前仓位为深位则直接入 + * 2)如果当前仓位为浅位,则判断对应深位是否有货,有则入、没有则入深位 + */ + // 仓位表 + WQLObject attrTab = WQLObject.getWQLObject("st_ivt_structattr"); + // 子卷包装关系 + WQLObject subTab = WQLObject.getWQLObject("pdm_bi_subpackagerelation"); + + /* + * 判断是否有仓位 + * 判断条件:库区、仓库、是否启用、是否删除、未锁定、没有载具 + */ + // 是否是移库: 提前确定的巷道 + String block_num = jsonObject.getString("move_block_num"); + + JSONArray attrArry = new JSONArray(); + + if (ObjectUtil.isEmpty(block_num)) { + attrArry = attrTab.query("IFNULL(storagevehicle_code,'') = '' " + + "AND is_used = '" + IOSEnum.IS_NOTANDYES.code("是") + "' AND is_delete = '" + IOSEnum.IS_NOTANDYES.code("否") + "' " + + "AND lock_type = '" + IOSEnum.LOCK_TYPE.code("未锁定") + "' AND stor_id = '" + jsonObject.getString("stor_id") + "' " + + "AND storagevehicle_type = '" + jsonObject.getString("vehicle_type") + "'" + + "AND height IN " + jsonObject.getString("height") + + "AND sect_id = '" + jsonObject.getString("sect_id") + "'").getResultJSONArray(0); + } else { + attrArry = attrTab.query("IFNULL(storagevehicle_code,'') = '' " + + "AND is_used = '" + IOSEnum.IS_NOTANDYES.code("是") + "' AND is_delete = '" + IOSEnum.IS_NOTANDYES.code("否") + "' " + + "AND lock_type = '" + IOSEnum.LOCK_TYPE.code("未锁定") + "' AND stor_id = '" + jsonObject.getString("stor_id") + "' " + + "AND storagevehicle_type = '" + jsonObject.getString("vehicle_type") + "'" + + "AND height IN " + jsonObject.getString("height") + + "AND sect_id = '" + jsonObject.getString("sect_id") + "' AND block_num = '"+block_num+"'") + .getResultJSONArray(0); + + } + + + if (ObjectUtil.isEmpty(attrArry)) { + throw new BadRequestException("仓位不足!"); + } + + /* + * 确定巷道:查看每个巷道相同木箱规格等 的数量,找到数量最小的那个巷道 + */ + // 获取木箱入库巷道 + JSONObject jsonSub = subTab.query("package_box_sn = '" + jsonObject.getString("box_no") + "'").uniqueResult(0); + jsonSub.put("stor_id", jsonObject.getString("stor_id")); + jsonSub.put("sect_id", jsonObject.getString("sect_id")); + jsonSub.put("material_id", jsonObject.getString("material_id")); + jsonSub.put("vehicle_type", jsonObject.getString("vehicle_type")); + jsonSub.put("height", jsonObject.getString("height")); + + // 不是移库则需要找新巷道 + if (ObjectUtil.isEmpty(block_num)) { + block_num = getMinBlock(jsonSub); + } + jsonSub.put("block_num", block_num); + + /* + * 找仓位 + */ + JSONObject jsonAttr = getStruct(jsonSub); + + // 如果是移库空并且仓位为空则报错 + if (ObjectUtil.isNotEmpty(jsonObject.getString("move_block_num")) && ObjectUtil.isEmpty(jsonAttr)) { + throw new BadRequestException("仓位不足!"); + } + + // 为空则新找巷道 + if (ObjectUtil.isEmpty(jsonAttr)) { + + jsonSub.put("flag", "1"); + notInBlockList.add(jsonSub.getString("block_num")); + + String join = "('" + String.join("','", notInBlockList) + "')"; + jsonSub.put("not_block", join); + + List blockList = WQL.getWO("BST_INRULE").addParamMap(jsonSub) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + for (int i = 0; i < blockList.size(); i++) { + JSONObject json = blockList.get(i); + jsonSub.put("block_num",json.getString("block_num")); + + JSONObject jsonAttr_2 = getStruct(jsonSub); + if (ObjectUtil.isNotEmpty(jsonAttr_2)) { + jsonAttr = jsonAttr_2; + break; + } else { + continue; + } + } + } + + // 清空缓存 + notInBlockList.clear(); + return jsonAttr; + } + + /** + * 获取最小巷道 + * + * @param jsonSub { + * jsonSub:木箱信息 + * sect_id:库区 + * stor_id:仓库 + * material_id:物料 + * } + * @return String : 巷道 + */ + private String getMinBlock(JSONObject jsonSub) { + // 获取系统参数不入哪个巷道 + String not_in_block_num = SpringContextHolder.getBean(SysParamServiceImpl.class).findByCode("not_in_block_num").getValue(); + if (!not_in_block_num.equals(IOSEnum.IS_NOTANDYES.code("否"))) { + jsonSub.put("not_in_block_num", not_in_block_num); + } + + jsonSub.put("flag", "1"); + + // 获取仓库、库区有空位的巷道 + List blockList = WQL.getWO("BST_INRULE").addParamMap(jsonSub) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + /* + * 查询所属巷道所有木箱 + */ + String block_in = blockList.stream() + .map(row -> row.getString("block_num")) + .collect(Collectors.joining("','")); + + jsonSub.put("flag", "2"); + jsonSub.put("block_in", "('" + block_in + "')"); + + List boxAllList = WQL.getWO("BST_INRULE").addParamMap(jsonSub) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + // 为空说明没有木箱,返回最小巷道 + if (ObjectUtil.isEmpty(boxAllList)) { + return blockList.get(0).getString("block_num"); + } + + // 不区分木箱规格:最小木箱数的巷道 + JSONObject jsonBlockMin = sumBlockMinNum(blockList, boxAllList); + + /* + * 查询所属巷道所有相同规格的木箱 + */ + jsonSub.put("flag", "3"); + List boxAllLikeList = WQL.getWO("BST_INRULE").addParamMap(jsonSub) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + // 为空说明库内没有相同规格的木箱,则返回不区分木箱规格的最小巷道 + if (ObjectUtil.isEmpty(boxAllLikeList)) { + return jsonBlockMin.getString("block_num"); + } + + // 区分木箱规格:最小木箱的巷道 + JSONObject jsonBlockLikeMin = sumBlockMinNum(blockList, boxAllLikeList); + return jsonBlockLikeMin.getString("block_num"); + } + + /** + * 计算最小巷道木箱数 + * + * @param blockList : 所有巷道 + * @param boxAllList: 所有木箱 + * @return JSONObject:最小木箱数的巷道 JSONObject{block_num,box_num} + */ + private JSONObject sumBlockMinNum(List blockList, List boxAllList) { + + // 统计各巷道木箱数 + ArrayList blockBoxList = new ArrayList<>(); + + for (int i = 0; i < blockList.size(); i++) { + JSONObject jsonBlock = blockList.get(i); + + List box_num = boxAllList.stream() + .filter(row -> row.getString("block_num").equals(jsonBlock.getString("block_num"))) + .collect(Collectors.toList()); + + jsonBlock.put("box_num", String.valueOf(box_num.size())); + blockBoxList.add(jsonBlock); + } + + // 最小木箱数的巷道 + List boxNumList = blockBoxList.stream() + .sorted(Comparator.comparing(row -> row.getIntValue("box_num"))) + .collect(Collectors.toList()); + + return boxNumList.get(0); + } + + + /** + * 获取一个货位公共方法 + * + * @param jsonSub { + * jsonSub:木箱信息 + * sect_id:库区 + * stor_id:仓库 + * material_id:物料 + * block_num: 巷道 + * row_num :排 + * } + * @return JSONObject : 仓位 + */ + private JSONObject getStruct(JSONObject jsonSub) { + // 根据巷道找这一巷道相同订单号、物料的仓位 + JSONObject jsonLikeBox = queryEqualBox(jsonSub); + if (ObjectUtil.isNotEmpty(jsonLikeBox)) { + return jsonLikeBox; + } + + // 获取此仓库、库区、巷道、排的所有空位 根据列、层、深度排序 + jsonSub.put("flag", "55"); + + List rowStructList = WQL.getWO("BST_INRULE").addParamMap(jsonSub) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + // 获取此仓库、库区、巷道、排的所有仓位 + jsonSub.put("flag", "66"); + + List structAllList = WQL.getWO("BST_INRULE").addParamMap(jsonSub) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + JSONObject jsonAttr = new JSONObject(); + + for (int i = 0; i < rowStructList.size(); i++) { + JSONObject json = rowStructList.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("row_num").equals(json.getString("row_num")) && + row.getString("zdepth").equals(IOSEnum.ZDEPTH_STRUCT.code("浅"))) + .collect(Collectors.toList()); + + if (ObjectUtil.isEmpty(lowAttr) || lowAttr.size() != 1) { + notInBlockList.clear(); + throw new BadRequestException("匹配仓位时:" + json.getString("struct_code") + "对应的浅货位错误!"); + } + + // 判断是否有木箱 + JSONObject jsonAttrLow = lowAttr.get(0); + if (ObjectUtil.isEmpty(jsonAttrLow.getString("storagevehicle_code")) && jsonAttrLow.getString("lock_type").equals(IOSEnum.LOCK_TYPE.code("未锁定"))) { + // 没有木箱 + jsonAttr = json; + break; + } else { + continue; + } + } else if (json.getString("zdepth").equals(IOSEnum.ZDEPTH_STRUCT.code("浅"))) { + /* + * 浅货位:判断深货位是否空洞 + */ + // 获取此货位对应的深货位 + List darkAttr = structAllList.stream() + .filter(row -> row.getString("col_num").equals(json.getString("col_num")) && + row.getString("layer_num").equals(json.getString("layer_num")) && + row.getString("row_num").equals(json.getString("row_num")) && + row.getString("zdepth").equals(IOSEnum.ZDEPTH_STRUCT.code("深"))) + .collect(Collectors.toList()); + + if (ObjectUtil.isEmpty(darkAttr) || darkAttr.size() != 1) { + notInBlockList.clear(); + throw new BadRequestException("匹配仓位时:" + json.getString("struct_code") + "对应的深货位错误!"); + } + + // 判断是否有木箱 + JSONObject jsonAttrDark = darkAttr.get(0); + + if (ObjectUtil.isNotEmpty(jsonAttrDark.getString("storagevehicle_code"))) { + + // 判断是否是成品箱,判断内容:是否空托盘、是否空木箱 + if (jsonAttrDark.getString("is_vehicle").equals(IOSEnum.IS_NOTANDYES.code("是")) || + jsonAttrDark.getString("is_packing").equals(IOSEnum.IS_NOTANDYES.code("否")) + ) { + continue; + } + + if (jsonAttrDark.getString("lock_type").equals(IOSEnum.LOCK_TYPE.code("未锁定"))) { + jsonAttr = json; + break; + } else { + continue; + } + + } else { + if (jsonAttrDark.getString("lock_type").equals(IOSEnum.LOCK_TYPE.code("未锁定"))) { + jsonAttr = jsonAttrDark; + break; + } else { + continue; + } + } + } + + } + + return jsonAttr; + } + + /** + * 匹配相同订单、物料的仓位 + * @param jsonSub{子卷包装关系} + * @return JSONObject:要入库的仓位 + */ + private JSONObject queryEqualBox(JSONObject jsonSub) { + // 需要返回的仓位 + JSONObject result = new JSONObject(); + // 1.匹配相同订单号、物料的排(row_num) + jsonSub.put("flag", "77"); + List rowList = WQL.getWO("BST_INRULE").addParamMap(jsonSub) + .process().getResultJSONArray(0).toJavaList(JSONObject.class); + + // 查询此巷道的所有仓位 + List attrRowAllList = WQL.getWO("BST_INRULE").addParam("flag", "88") + .addParam("sect_id", jsonSub.getString("sect_id")) + .addParam("block_num", jsonSub.getString("block_num")).process().getResultJSONArray(0).toJavaList(JSONObject.class); + + for (JSONObject json : rowList) { + // 判断此深仓位是否有货、是否被锁住 + if (ObjectUtil.isEmpty(json.getString("storagevehicle_code")) + || !json.getString("lock_type").equals(IOSEnum.LOCK_TYPE.code("未锁定")) + ) { + continue; + } + + // 找对应的浅货位 + JSONObject darkJson = attrRowAllList.stream() + .filter(row -> row.getString("col_num").equals(json.getString("col_num")) && + row.getString("layer_num").equals(json.getString("layer_num")) && + row.getString("row_num").equals(json.getString("row_num")) && + row.getString("zdepth").equals(IOSEnum.ZDEPTH_STRUCT.code("浅"))) + .findFirst().orElse(null); + + if (ObjectUtil.isEmpty(darkJson)) { + notInBlockList.clear(); + throw new BadRequestException("匹配相同木箱规格仓位时:" + json.getString("struct_code") + "对应的深货位错误!"); + } + + // 判断浅货位是否有货、未锁定 + if (ObjectUtil.isNotEmpty(darkJson.getString("storagevehicle_code")) + || !darkJson.getString("lock_type").equals(IOSEnum.LOCK_TYPE.code("未锁定")) + ) { + continue; + } + + result = darkJson; + break; + } + return result; + } +} diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/service/TwoInBussManageService.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/service/TwoInBussManageService.java new file mode 100644 index 000000000..f551ba7b3 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/service/TwoInBussManageService.java @@ -0,0 +1,29 @@ +package org.nl.b_lms.storage_manage.ios.service.iostorInv.util.service; + +import com.alibaba.fastjson.JSONObject; + +import java.util.ArrayList; + +/** + *

+ * 入库业务处理 服务类 + *

+ * + * @author generator + * @since 2023-11-16 + */ +public interface TwoInBussManageService { + + /** + * 获取一个仓位 + * @param jsonObject: { + * stor_id:仓库标识 + * sect_id:库区标识 + * material_id: 物料标识 + * box_no:木箱号 + * move_block_num: 是否移库:提前确定巷道 + * } + * @return JSONObject 仓位对象 + */ + JSONObject getOneStruct(JSONObject jsonObject); +} diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/wql/BST_INRULE.wql b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/wql/BST_INRULE.wql index 807e756cd..969f0928c 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/wql/BST_INRULE.wql +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/storage_manage/ios/service/iostorInv/util/wql/BST_INRULE.wql @@ -235,6 +235,32 @@ ENDQUERY ENDIF + IF 输入.flag = "55" + QUERY + SELECT + attr.* + FROM + st_ivt_structattr attr + 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 + AND attr.height IN 输入.height + AND attr.storagevehicle_type = 输入.vehicle_type + + OPTION 输入.block_num <> "" + attr.block_num = 输入.block_num + ENDOPTION + + order by attr.zdepth DESC, attr.col_num, attr.layer_num ASC + + ENDSELECT + ENDQUERY + ENDIF + IF 输入.flag = "6" QUERY SELECT @@ -271,6 +297,38 @@ ENDQUERY ENDIF + IF 输入.flag = "66" + QUERY + SELECT + attr.*, + CASE + WHEN IFNULL(box.is_packing,'') = '' THEN '0' + ELSE box.is_packing + END AS is_packing, + CASE + WHEN IFNULL(attr.is_emptyvehicle,'') = '' THEN '0' + ELSE attr.is_emptyvehicle + END AS is_vehicle + + FROM + st_ivt_structattr attr + LEFT JOIN bst_ivt_boxinfo box ON box.box_no = attr.storagevehicle_code + WHERE + attr.is_used = '1' + AND attr.is_delete = '0' + AND attr.stor_id = 输入.stor_id + AND attr.sect_id = 输入.sect_id + AND attr.height IN 输入.height + AND attr.storagevehicle_type = 输入.vehicle_type + + OPTION 输入.block_num <> "" + attr.block_num = 输入.block_num + ENDOPTION + + ENDSELECT + ENDQUERY + ENDIF + IF 输入.flag = "7" QUERY SELECT @@ -308,6 +366,55 @@ ENDQUERY ENDIF + IF 输入.flag = "77" + QUERY + SELECT + attr.* + FROM + st_ivt_structivt ivt + INNER JOIN st_ivt_structattr attr ON ivt.struct_code = attr.struct_code + INNER JOIN pdm_bi_subpackagerelation sub ON attr.storagevehicle_code = sub.package_box_sn AND ivt.pcsn = sub.container_name + 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 + AND attr.height IN 输入.height + AND attr.zdepth = '2' + AND attr.storagevehicle_type = 输入.vehicle_type + + OPTION 输入.block_num <> "" + attr.block_num = 输入.block_num + ENDOPTION + + OPTION 输入.product_name <> "" + sub.product_name = 输入.product_name + ENDOPTION + + OPTION 输入.sale_order_name <> "" + sub.sale_order_name = 输入.sale_order_name + ENDOPTION + + OPTION 输入.box_length <> "" + sub.box_length = 输入.box_length + ENDOPTION + + OPTION 输入.box_width <> "" + sub.box_width = 输入.box_width + ENDOPTION + + OPTION 输入.box_high <> "" + sub.box_high = 输入.box_high + ENDOPTION + + order by attr.col_num,attr.layer_num ASC + + ENDSELECT + ENDQUERY + ENDIF + IF 输入.flag = "8" QUERY @@ -328,3 +435,23 @@ ENDSELECT ENDQUERY ENDIF + + IF 输入.flag = "88" + QUERY + SELECT + attr.* + FROM + st_ivt_structattr attr + WHERE + attr.is_used = '1' + AND attr.is_delete = '0' + AND attr.sect_id = 输入.sect_id + + OPTION 输入.block_num <> "" + attr.block_num = 输入.block_num + ENDOPTION + + ENDOPTION + ENDSELECT + ENDQUERY + ENDIF diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/pda/st/service/impl/ProductInstorServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/pda/st/service/impl/ProductInstorServiceImpl.java index f6b8d138f..a8fcd7631 100644 --- a/lms/nladmin-system/src/main/java/org/nl/wms/pda/st/service/impl/ProductInstorServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/wms/pda/st/service/impl/ProductInstorServiceImpl.java @@ -401,10 +401,26 @@ public class ProductInstorServiceImpl implements ProductInstorService { String task_id = IdUtil.getSnowflake(1, 1).nextId() + ""; //直接分配虚拟区货位,并确认 + if ("BC01".equals(sub_jo.getString("ext_code"))) { + JSONObject jsonObject = WQLObject.getWQLObject("st_ivt_sectattr").query("sect_id = '" + whereJson.getString("sect_id") + "'") + .uniqueResult(0); + + if ("XN01".equals(jsonObject.getString("sect_code"))) { + whereJson.put("sect_id","1712667908095741952"); + } + if ("XN02".equals(jsonObject.getString("sect_code"))) { + whereJson.put("sect_id","1760184056861036544"); + } + if ("TH01".equals(jsonObject.getString("sect_code"))) { + whereJson.put("sect_id","1760183817781514240"); + } + + } + JSONObject struct = WQL.getWO("PDA_ST_01") .addParam("flag", "3") .addParam("stor_id", stor.getString("stor_id")) - .addParam("sect_id", "BC01".equals(sub_jo.getString("ext_code")) ? "1712667908095741952" : whereJson.getString("sect_id")) + .addParam("sect_id", whereJson.getString("sect_id")) .process().uniqueResult(0); if (ObjectUtil.isEmpty(struct)) {