opt:现场问题的一些处理与优化:

先有浅货位出库任务未完成,
后有深货位出库任务,阻挡后生成移库任务,
判断条件有问题,已修复;
料箱库技改,批量下发移库功能;
拣选位均衡分配.
This commit is contained in:
2025-09-10 17:03:46 +08:00
parent 4781928cf2
commit 41fbb8c98f
12 changed files with 190 additions and 77 deletions

View File

@@ -28,6 +28,7 @@ public class TableDataInfo<T> implements Serializable {
*/
private long totalElements;
/**
* 列表数据
*/

View File

@@ -71,7 +71,7 @@ public enum StatusEnum {
/**
* 点位锁类型
*/
LOCK(ForkMap.of("无锁", "00", null, "入库锁", "10", null, "入库盘点锁", "16", null, "出库锁", "20", null, "盘点出库锁", "26", null, "移库锁", "50", null, "异常锁定", "60", null, "空出锁", "70", null)),
LOCK(ForkMap.of("无锁", "00", null, "入库锁", "10", null, "入库盘点锁", "16", null, "出库锁", "20", null, "盘点出库锁", "26", null, "移库锁", "50", null, "异常锁定", "60", null, "空出锁", "70", null,"临时锁", "99", null)),
STRATEGY_TYPE(ForkMap.of("入库", "1", null, "出库", "2", null, "出入库", "3", null)),

View File

@@ -1,18 +1,22 @@
package org.nl.wms.decision_manage.handler.decisioner.impl.diy;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.nl.common.enums.StatusEnum;
import org.nl.common.utils.SpringContextHolder;
import org.nl.wms.decision_manage.handler.decisioner.Decisioner;
import org.nl.wms.dispatch_manage.task.service.ISchBaseTaskService;
import org.nl.wms.dispatch_manage.task.service.dao.SchBaseTask;
import org.nl.wms.stor_manage.struct.service.IStIvtStructattrService;
import org.nl.wms.stor_manage.struct.service.dao.StIvtStructattr;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
*深位优先
@@ -58,17 +62,13 @@ public class DepthPriorityHandler extends Decisioner<StIvtStructattr, JSONObject
}
}
}
if (returnResult.size() > 0) {
if (returnResult.size() < 3) {
return getOtherStructattr(list, param, startTime1, depCollect);
} else {
log.info("深位优先策略:载具号:" + param.getString("vehicle_code") + "分配结果: 存在深位并对应浅位无货的库位,分配仓位:" + returnResult.get(0).getStruct_code());
log.info("深位优先策略:载具号:"+param.getString("vehicle_code")+"获取深货位且浅货位无货仓位耗时:{}", System.currentTimeMillis() - startTime1);
return returnResult;
}
} else {
if (returnResult.isEmpty() || returnResult.size() < 3) {
//深位为空或数量小于3分配有货的浅库位
return getOtherStructattr(list, param, startTime1, depCollect);
}
log.info("深位优先策略:载具号:{} 分配结果: 存在深位并对应浅位无货的库位,分配仓位:{}", param.getString("vehicle_code"), returnResult.get(0).getStruct_code());
log.info("深位优先策略:载具号:{} 获取深货位且浅货位无货仓位耗时:{}", param.getString("vehicle_code"), System.currentTimeMillis() - startTime1);
return returnResult;
}
private static List<StIvtStructattr> getOtherStructattr(List<StIvtStructattr> list, JSONObject param, long startTime1, List<StIvtStructattr> depCollect) {
@@ -80,12 +80,26 @@ public class DepthPriorityHandler extends Decisioner<StIvtStructattr, JSONObject
//浅货位,则需要判断对应
IStIvtStructattrService iStIvtStructattrService = SpringContextHolder.getBean(IStIvtStructattrService.class);
if (list.get(0).getStor_code().equals(StatusEnum.STOCK_INFO.code("料箱库"))) {
//深位有任务不可分配
ISchBaseTaskService iSchBaseTaskService = SpringContextHolder.getBean(ISchBaseTaskService.class);
List<SchBaseTask> taskList = iSchBaseTaskService.list(
new LambdaQueryWrapper<SchBaseTask>()
.lt(SchBaseTask::getStatus, StatusEnum.FORM_STATUS.code("完成"))
.select(SchBaseTask::getPoint_code1, SchBaseTask::getPoint_code2)
);
Set<String> pointCodes = taskList.stream()
.flatMap(t -> Stream.of(t.getPoint_code1(), t.getPoint_code2()))
.filter(Objects::nonNull)
.collect(Collectors.toSet());
List<StIvtStructattr> list1 = iStIvtStructattrService.list(new LambdaUpdateWrapper<StIvtStructattr>()
.in(StIvtStructattr::getRow_num, Arrays.asList(1, 4))
.eq(StIvtStructattr::getStor_code, StatusEnum.STOCK_INFO.code("料箱库"))
.eq(StIvtStructattr::getIs_used, 1)
.eq(StIvtStructattr::getLock_type, StatusEnum.LOCK.code("无锁")));
//先找2排的再找3排的
list1 = list1.stream()
.filter(s -> !pointCodes.contains(s.getStruct_code()))
.collect(Collectors.toList());
//先找1排对应的2排的再找3排对应的4排
if (!list1.isEmpty()) {
List<StIvtStructattr> combinedResult = new ArrayList<>();
//1排
@@ -126,8 +140,10 @@ public class DepthPriorityHandler extends Decisioner<StIvtStructattr, JSONObject
log.info("深位优先策略:载具号:" + param.getString("vehicle_code") + "分配结果: 深货位有货且浅货位无货仓位,无需移库,分配仓位:" + combinedResult.get(0).getStruct_code());
log.info("深位优先策略:获取深货位有货且浅货位无货仓位耗时:{}", System.currentTimeMillis() - startTime1);
return combinedResult;
} else {
log.error("深位优先策略:载具号:" + param.getString("vehicle_code") + "分配结果: 获取深货位有货且浅货位无货仓位失败,无空余仓位!");
return Collections.emptyList();
}
return list;
} else {
return list;
}

View File

@@ -55,6 +55,7 @@ public class MoveStorageTask extends AbstractTask {
JSONObject form_data = from.getJSONObject("form_data");
String start_struct_code = form_data.getString("start_struct_code");
String end_struct_code = form_data.getString("end_struct_code");
String isAllMove = from.getString("isAllMove");
List<SchBaseTask> list = taskService.list(new QueryWrapper<SchBaseTask>().eq("vehicle_code", vehicle_code)
.lt("status", StatusEnum.FORM_STATUS.code("完成")));
if (!CollectionUtils.isEmpty(list)){
@@ -73,25 +74,27 @@ public class MoveStorageTask extends AbstractTask {
SchBaseTask task = new SchBaseTask();
task.setId(IdUtil.getStringId());
task.setPriority(StatusEnum.PRIORITY_TYPE.code("移库"));
task.setTask_code(CodeUtil.getNewCode("TASK_CODE"));
task.setStatus(StatusEnum.FORM_STATUS.code("生成"));
task.setHandle_class(this.getClass().getName());
task.setAcs_type(StatusEnum.ACS_TYPE.code("立库"));
task.setCreate_time(now);
task.setCreate_name(SecurityUtils.getCurrentNickName());
task.setTask_type(from.getString("task_type"));
task.setVehicle_code(vehicle_code);
task.setPoint_code1(start_struct_code);
task.setPoint_code2(end_struct_code);
iMdPbVehicleMaterService.getVehicleMaters(task,true);
task.setTask_code(CodeUtil.getNewCode("TASK_CODE"));
task.setStatus(StatusEnum.FORM_STATUS.code("生成"));
task.setHandle_class(this.getClass().getName());
task.setAcs_type(StatusEnum.ACS_TYPE.code("立库"));
task.setCreate_time(now);
task.setCreate_name(SecurityUtils.getCurrentNickName());
task.setTask_type(from.getString("task_type"));
task.setVehicle_code(vehicle_code);
task.setPoint_code1(start_struct_code);
task.setPoint_code2(end_struct_code);
//批量移库,完成后自动禁用货位的标记
task.setSource_form_id(StringUtils.isNotBlank(isAllMove) ? "99" : null);
iMdPbVehicleMaterService.getVehicleMaters(task, true);
taskService.save(task);
iMdPbVehicleMaterService.update(new LambdaUpdateWrapper<MdPbVehicleMater>()
.set(MdPbVehicleMater::getTask_code,task.getTask_code())
.eq(MdPbVehicleMater::getVehicle_code,task.getVehicle_code())
.eq(MdPbVehicleMater::getIs_delete,false));
.set(MdPbVehicleMater::getTask_code, task.getTask_code())
.eq(MdPbVehicleMater::getVehicle_code, task.getVehicle_code())
.eq(MdPbVehicleMater::getIs_delete, false));
//TODO:是否下发
Boolean isSend = from.getBoolean("is_send");
if (isSend){
if (isSend) {
//参数封装调acs接口
}
return (JSONObject)JSON.toJSON(task);
@@ -105,12 +108,18 @@ public class MoveStorageTask extends AbstractTask {
@Override
public void finish(JSONObject data) {
data.put("status",StatusEnum.FORM_STATUS.code("完成"));
data.put("status", StatusEnum.FORM_STATUS.code("完成"));
this.updateTask(data);
SchBaseTask schBaseTask = taskService.getOne(new QueryWrapper<SchBaseTask>().eq("task_code", data.getString("task_code")));
iStIvtStructattrService.changeStruct(schBaseTask.getPoint_code1(),schBaseTask.getVehicle_code(),schBaseTask.getTask_type(), null,Boolean.FALSE,schBaseTask.getPoint_code2());
iStIvtStructattrService.changeStruct(schBaseTask.getPoint_code2(),schBaseTask.getVehicle_code(),schBaseTask.getTask_type(), null,Boolean.TRUE,schBaseTask.getPoint_code2());
iStIvtStructattrService.changeStruct(schBaseTask.getPoint_code1(), schBaseTask.getVehicle_code(), schBaseTask.getTask_type(), null, Boolean.FALSE, schBaseTask.getPoint_code2());
iStIvtStructattrService.changeStruct(schBaseTask.getPoint_code2(), schBaseTask.getVehicle_code(), schBaseTask.getTask_type(), null, Boolean.TRUE, schBaseTask.getPoint_code2());
if ("99".equals(schBaseTask.getSource_form_id())) {
iStIvtStructattrService.update(
new UpdateWrapper<StIvtStructattr>()
.set("lock_type", StatusEnum.LOCK.code("临时锁"))
.eq("struct_code", schBaseTask.getPoint_code1())
);
}
}
@Override

View File

@@ -177,7 +177,7 @@ public class OutStorageTask extends AbstractTask {
}
} else {
/**
* 1.判断对应浅位是否存在托盘
* 1.判断对应浅位是否存在料箱
* 2.如果有则判断是否存在出库任务
* 3.如果没有则生成移库任务
*/
@@ -187,7 +187,7 @@ public class OutStorageTask extends AbstractTask {
log.info("-----出库分配:深位查询浅位是否有货:{}", block != null);
if (block != null) {
int count = taskService.count(new QueryWrapper<SchBaseTask>()
.eq("point_code1", block.getStor_code())
.eq("point_code1", block.getStruct_code())
.lt("status", StatusEnum.FORM_STATUS.code("完成")));
if (count == 0) {
AtomicReference<String> moveStruct = new AtomicReference<>();

View File

@@ -15,7 +15,6 @@ import org.nl.common.utils.IdUtil;
import org.nl.common.utils.SecurityUtils;
import org.nl.common.utils.SpringContextHolder;
import org.nl.wms.dispatch_manage.point.service.ISchBasePointService;
import org.nl.wms.dispatch_manage.point.service.dao.SchBasePoint;
import org.nl.wms.dispatch_manage.task.handler.AbstractTask;
import org.nl.wms.dispatch_manage.task.service.ISchBaseTaskService;
import org.nl.wms.dispatch_manage.task.service.dao.SchBaseTask;
@@ -67,22 +66,29 @@ public class ToPickPlatformTask extends AbstractTask {
if (start_struct_code.contains("B")) {
target_point = "1311";
} else {
List<SchBasePoint> targetPoints = iSchBasePointService.list(new QueryWrapper<SchBasePoint>()
.eq("region_code", "PICK01").eq("is_used", true));
//通过全局变量获取目标位置
if (CollectionUtils.isEmpty(targetPoints)) {
throw new BadRequestException("当前拣选工位未启用");
}
//轮询
log.info("上次拣选平台分配位置:{},拣选平台开放点:{}", Lask_Point, targetPoints);
for (int i = 0; i < targetPoints.size(); i++) {
String code = targetPoints.get(i).getCode();
if (targetPoints.size() > 1 && !code.equals(Lask_Point)) {
target_point = code;
break;
}
target_point = code;
}
List<SchBaseTask> list = iSchBaseTaskService.list(new QueryWrapper<SchBaseTask>()
.lt("status", StatusEnum.FORM_STATUS.code("完成")));
String pointCode1 = "1308";
String pointCode2 = "1311";
long count1 = list.stream().filter(r -> r.getPoint_code2().equals(pointCode1)).count();
long count2 = list.stream().filter(r -> r.getPoint_code2().equals(pointCode2)).count();
target_point = count1 >= count2 ? pointCode2 : pointCode1;
// List<SchBasePoint> targetPoints = iSchBasePointService.list(new QueryWrapper<SchBasePoint>()
// .eq("region_code", "PICK01").eq("is_used", true));
// //通过全局变量获取目标位置
// if (CollectionUtils.isEmpty(targetPoints)) {
// throw new BadRequestException("当前拣选工位未启用");
// }
// //轮询
// log.info("上次拣选平台分配位置:{},拣选平台开放点:{}", Lask_Point, targetPoints);
// for (int i = 0; i < targetPoints.size(); i++) {
// String code = targetPoints.get(i).getCode();
// if (targetPoints.size() > 1 && !code.equals(Lask_Point)) {
// target_point = code;
// break;
// }
// target_point = code;
// }
}
if (StringUtils.isEmpty(vehicle_code) || StringUtils.isEmpty(target_point)) {
throw new BadRequestException("创建任务失败:方法请求参数不能为空");
@@ -117,8 +123,8 @@ public class ToPickPlatformTask extends AbstractTask {
task.setPriority("1".equals(priority)?StatusEnum.PRIORITY_TYPE.code("加急"):StatusEnum.PRIORITY_TYPE.code("较高"));
iMdPbVehicleMaterService.getVehicleMaters(task,true);
iSchBaseTaskService.save(task);
Lask_Point = target_point;
log.info("当前拣选平台分配位置:{},{}", Lask_Point, target_point);
//Lask_Point = target_point;
// log.info("当前拣选平台分配位置:{},{}", Lask_Point, target_point);
iMdPbVehicleMaterService.update(new LambdaUpdateWrapper<MdPbVehicleMater>()
.set(MdPbVehicleMater::getTask_code, task.getTask_code())
.eq(MdPbVehicleMater::getVehicle_code, task.getVehicle_code())

View File

@@ -166,6 +166,18 @@ public class StIvtStructattrController {
structattrService.createIdleTask(taskList);
return new ResponseEntity<>(HttpStatus.OK);
}
/**
* 批量移库下发
*/
@PostMapping("/createMoveTask")
@Log("批量移库下发")
public ResponseEntity<Object> createMoveTask(@RequestBody List<Map<String, Object>> taskList) {
structattrService.createMoveTask(taskList);
return new ResponseEntity<>(HttpStatus.OK);
}
@PostMapping("/exportFile")

View File

@@ -67,4 +67,7 @@ public interface IStIvtStructattrService extends IService<StIvtStructattr> {
Long getIoBillCounts(String vehicleCode);
void createIdleTask( List<Map<String, Object>> taskList);
void createMoveTask( List<Map<String, Object>> taskList);
}

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
@@ -15,10 +16,9 @@ import org.nl.common.TableDataInfo;
import org.nl.common.domain.entity.PageQuery;
import org.nl.common.domain.exception.BadRequestException;
import org.nl.common.enums.StatusEnum;
import org.nl.common.utils.ErpServiceUtils;
import org.nl.common.utils.IdUtil;
import org.nl.common.utils.SpringContextHolder;
import org.nl.common.utils.*;
import org.nl.wms.decision_manage.handler.decisioner.impl.base.SameBlockNumRuleHandler;
import org.nl.wms.dispatch_manage.task.handler.impl.MoveStorageTask;
import org.nl.wms.dispatch_manage.task.handler.impl.OutStorageTask;
import org.nl.wms.flow_manage.flow.framework.process.nodeType.excess.impl.DecisionHandler;
import org.nl.wms.md_manage.group_dick.service.IMdGruopDickService;
@@ -40,15 +40,14 @@ import org.nl.wms.system_manage.service.param.dao.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
@@ -461,5 +460,49 @@ public class StIvtStructattrServiceImpl extends ServiceImpl<StIvtStructattrMappe
}
}
/**
* 批量移库下发
*/
@Override
@Transactional
public void createMoveTask(List<Map<String, Object>> taskList) {
if (CollectionUtils.isEmpty(taskList)) {
return;
}
String structCode = taskList.get(0).get("struct_code").toString();
QueryWrapper<StIvtStructattr> query = new QueryWrapper<StIvtStructattr>()
.eq("is_used", true)
.likeRight("struct_code", structCode.substring(0, structCode.lastIndexOf("-")))
.eq("stor_code", StatusEnum.STOCK_INFO.code("料箱库"));
List<StIvtStructattr> list = this.list(query);
List<StIvtStructattr> list1 = list.stream().filter(r -> StringUtils.isNotBlank(r.getVehicle_code())).collect(Collectors.toList());
Set<String> list2 = list.stream()
.filter(r -> StringUtils.isBlank(r.getVehicle_code()))
.map(StIvtStructattr::getStruct_code)
.collect(Collectors.toSet());
if (ObjectUtils.isNotEmpty(list1)) {
list1.forEach(r -> {
AtomicReference<String> moveStruct = new AtomicReference<>();
String vehicleCode = r.getVehicle_code();
RedissonUtils.lock(() -> {
System.out.println("---3--" + Thread.currentThread().getName());
//出阻挡说明是同排跟任务一个类型载具
Map process = SpringContextHolder.getBean(DecisionHandler.class).dispenseTransa(ListOf.of("limitStorage", "depthPriority", "alleyAve"), new JSONObject(MapOf.of("is_move", true, "stor_code", r.getStor_code(), "vehicle_code", vehicleCode, "errorTask", "errorTask")));
moveStruct.set(((Map<String, String>) process.get("form_data")).get("end_struct_code"));
}, "1" + r.getStor_code(), 5);
Map moveForm = MapOf.of("task_type", StatusEnum.IOBILL_TYPE_MOVE.code("移库")
, "is_send", false
, "vehicle_code", StringUtils.isEmpty(vehicleCode) ? "YCZJ" + r.getVehicle_code() : vehicleCode, "form_data", new JSONObject(MapOf.of("start_struct_code", r.getStruct_code(), "end_struct_code", moveStruct.get())));
moveForm.put("isAllMove", "1");
SpringContextHolder.getBean(MoveStorageTask.class).createTask(new JSONObject(moveForm));
});
}
if (ObjectUtils.isNotEmpty(list2)) {
LambdaUpdateWrapper<StIvtStructattr> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.set(StIvtStructattr::getLock_type, "99");
lambdaUpdateWrapper.in(StIvtStructattr::getStruct_code, list2);
this.update(lambdaUpdateWrapper);
}
}
}

View File

@@ -127,24 +127,24 @@ public class TaskScheduleService {
delayTaskList.removeAll(waitTaskList);
}
//相同载具号,任务类型的任务不下发
// Map<String, List<SchBaseTask>> grouped = delayTaskList.stream()
// .collect(Collectors.groupingBy(task -> task.getVehicle_code() + "_" + task.getTask_type()));
// List<SchBaseTask> toRemove = new ArrayList<>();
// grouped.forEach((k, t) -> {
// if (t.size() > 1) {
// toRemove.addAll(t.subList(1, t.size()));
// }
// });
// if (toRemove.size() > 0) {
// List<String> taskIds = toRemove.stream().map(SchBaseTask::getId).collect(Collectors.toList());
// LambdaUpdateWrapper<SchBaseTask> updateWrapper = new LambdaUpdateWrapper<>();
// updateWrapper.in(SchBaseTask::getId, taskIds);
// updateWrapper.set(SchBaseTask::getStatus, StatusEnum.FORM_STATUS.code("完成"));
// updateWrapper.set(SchBaseTask::getIs_delete, "1");
// updateWrapper.set(SchBaseTask::getRemark, "前置校验,载具号与任务类型相同,校验完成");
// iSchBaseTaskService.update(updateWrapper);
// delayTaskList.removeAll(toRemove);
// }
Map<String, List<SchBaseTask>> grouped = delayTaskList.stream()
.collect(Collectors.groupingBy(task -> task.getVehicle_code() + "_" + task.getTask_type()));
List<SchBaseTask> toRemove = new ArrayList<>();
grouped.forEach((k, t) -> {
if (t.size() > 1) {
toRemove.addAll(t.subList(1, t.size()));
}
});
if (toRemove.size() > 0) {
List<String> taskIds = toRemove.stream().map(SchBaseTask::getId).collect(Collectors.toList());
LambdaUpdateWrapper<SchBaseTask> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.in(SchBaseTask::getId, taskIds);
updateWrapper.set(SchBaseTask::getStatus, StatusEnum.FORM_STATUS.code("完成"));
updateWrapper.set(SchBaseTask::getIs_delete, "1");
updateWrapper.set(SchBaseTask::getRemark, "前置校验,载具号与任务类型相同,校验完成");
iSchBaseTaskService.update(updateWrapper);
delayTaskList.removeAll(toRemove);
}
if (ObjectUtil.isNotEmpty(delayTaskList)) {
DELAY_EXECUTOR.execute(() -> {
try {

View File

@@ -154,6 +154,15 @@
</el-form-item>
<rrOperation />
</el-form>
<el-button
class="filter-item"
type="success"
icon="el-icon-download"
size="mini"
@click="createMoveTask"
>
批量移库下发
</el-button>
<el-button
class="filter-item"
type="danger"
@@ -391,6 +400,12 @@ export default {
this.crud.notify('呆料库存转运三楼任务下发成功!', CRUD.NOTIFICATION_TYPE.SUCCESS)
this.crud.toQuery()
})
},
createMoveTask() {
structattr.createMoveTask(this.crud.selections).then(res => {
this.crud.notify('批量移库任务下发成功!', CRUD.NOTIFICATION_TYPE.SUCCESS)
this.crud.toQuery()
})
}
}
}

View File

@@ -123,12 +123,20 @@ export function createIdleTask(data) {
data
})
}
export function createMoveTask(data) {
return request({
url: '/api/structattr/createMoveTask',
method: 'post',
data
})
}
export default {
add,
edit,
unlock,
createIdleTask,
createMoveTask,
del,
getVehicleTask,
getIosInvDtl,