From c9b50abb143f0bcb413bc217a704645a6b63fde1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=ABUmbrella?= <2539020564@qq.com> Date: Wed, 11 Mar 2026 20:15:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../desk/logistics/pojo/entity/Location.java | 5 +- .../desk/logistics/pojo/entity/Station.java | 9 ++ .../service/impl/IOrderBoxServiceImpl.java | 63 ++++++++++--- .../service/impl/OrderBindServiceImpl.java | 2 +- .../impl/TaskExecuteRecordServiceImpl.java | 16 +++- .../logistics/utils/CollectionCheckUtil.java | 91 +++++++++++++++++++ 6 files changed, 171 insertions(+), 15 deletions(-) diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Location.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Location.java index ae4fc3ad..a3e18ca3 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Location.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Location.java @@ -38,7 +38,10 @@ public class Location extends BaseEntity { */ public static final Integer STATUS_FREE = 0; - + /** + * 状态常量:初始架 + */ + public static final Integer ORIGINAL_RACK = 1; /** * 库名称 */ diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java index fd9cc486..b2ab3c49 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java @@ -37,6 +37,15 @@ public class Station extends BaseEntity { */ public static final Integer PRE_STATUS_OCCUPIED = 2; + /** + * 状态常量:收发-只收 + */ + public static final Integer RECEIVE_ONLY = 0; + /** + * 状态常量:收发-同层 + */ + public static final Integer SAME_LAYER = 2; + /** * 取货输送线 站点类型常量 */ diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java index ccef6b71..0e22d284 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java @@ -26,8 +26,9 @@ import java.util.*; import java.util.stream.Collectors; import static org.springblade.desk.logistics.constant.AgvConstant.EQUIPMENT_TYPE_AGV; +import static org.springblade.desk.logistics.pojo.entity.Location.ORIGINAL_RACK; import static org.springblade.desk.logistics.pojo.entity.Station.*; -import static org.springblade.desk.logistics.utils.CollectionCheckUtil.findNotExistInBByStream; +import static org.springblade.desk.logistics.utils.CollectionCheckUtil.*; /** * 订单箱业务实现类 @@ -111,6 +112,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { private final ITaskExecuteRecordService taskExecuteRecordService; // ========================== 构造器注入 ========================== + /** * 构造器注入依赖(Spring官方推荐,避免@Autowired耦合) * @@ -248,6 +250,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { log.warn("【箱条码绑定】{}", errorMsg); return R.fail(errorMsg + ",请重新进行绑定"); } + // 6. // 6. 保存绑定关系 return saveOrderBoxBinding(boxBarcode, new ArrayList<>(orderIdList)); @@ -257,7 +260,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { * 查询回库可选工位列表 *

查询空闲状态的站点关联工位,默认添加输送线回库选项

* - * @return R> 工位VO列表(含默认输送线选项) + * @return R> 工位VO列表(含默认输送线选项) */ @Override public R> returnToWarehouseList() { @@ -401,7 +404,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { endStationCode = DROPOFF_CONVEYOR_LINE; } else { // 5.2 普通工位回库:分配站点/库位 - R locationResult = allocateSiteOrLocation(task); + R locationResult = allocateSiteOrLocation(startStationCode, task); if (!locationResult.isSuccess()) { return locationResult; } @@ -518,6 +521,15 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { List notExistList = findNotExistInBByStream(yieldOrderList, orderCardNoList); return R.fail("以下订单未知:" + notExistList); } + //判断wcid是否一致 + boolean allFieldSame = isAllFieldSame(yieldOrderList, YieldOrder::getWorkCenterId); + if (!allFieldSame) { + return R.fail("订单所属的作业中心不一致"); + } + if (yieldOrderList.get(0).getWorkCenterId() == null) { + return R.fail("订单所属的作业中心不能为空"); + } + return R.data(yieldOrderList); } @@ -595,7 +607,11 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { } // 校验站点是否空闲 if (!stationList.get(0).getStationStatus().equals(STATUS_FREE)) { - return R.fail("站点非空闲状态,无法使用"); + return R.fail("起始站点非空闲状态,无法使用"); + } + // 校验站点是否可以发送数据 + if (stationList.get(0).getStatus().equals(RECEIVE_ONLY)) { + return R.fail("起始站点站码无法当开始站点编码"); } return R.data(startStationCode); } else { @@ -648,18 +664,33 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { /** * 分配站点/库位资源(优先级:站点 → 库位) * - * @param task 任务对象(含工位ID) + * @param startStationCode + * @param task 任务对象(含工位ID) * @return R 分配后的任务对象 */ - private R allocateSiteOrLocation(Task task) { + private R allocateSiteOrLocation(String startStationCode, Task task) { // 1. 尝试分配空闲站点 List freeStationList = stationService.list( new LambdaQueryWrapper() .eq(Station::getWcId, task.getWcId()) .eq(Station::getStationStatus, STATUS_FREE) ); + if (!CollectionUtils.isEmpty(freeStationList)) { - Station station = freeStationList.get(0); + Station station = null; + String stationPosition = ""; + if (station.getStatus() == SAME_LAYER) { + Station startStation = stationService.list(new LambdaQueryWrapper().eq(Station::getStationCode, startStationCode)).get(0); + stationPosition = startStation.getStationPosition(); + station = findByField(freeStationList, "stationPosition", stationPosition); + + + } else { + station = freeStationList.get(0); + } + if (station == null) { + return R.fail("当前班次" + stationPosition + "楼层库位繁忙,请空闲后再试"); + } task.setStationId(station.getId()); // 锁定站点(预占用) station.setStationStatus(PRE_STATUS_OCCUPIED); @@ -670,7 +701,9 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { // 2. 尝试分配空闲库位 List freeLocationList = locationService.list( - new LambdaQueryWrapper().eq(Location::getLocationStatus, STATUS_FREE) + new LambdaQueryWrapper() + .ne(Location::getStatus, ORIGINAL_RACK) + .eq(Location::getLocationStatus, STATUS_FREE) ); if (!CollectionUtils.isEmpty(freeLocationList)) { Location location = freeLocationList.get(0); @@ -693,8 +726,8 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { /** * 校验结束站点状态 * - * @param task 任务对象 - * @param agvSend 是否发送AGV + * @param task 任务对象 + * @param agvSend 是否发送AGV * @return R 结束站点编码(成功)/错误信息(失败) */ private R validateEndStationStatus(Task task, Boolean agvSend) { @@ -710,6 +743,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { locationService.updateById(location); log.info("【资源释放】库位{}已释放", location.getId()); } + taskService.removeById(task); return R.fail("结束站点被占用"); } return R.data(""); @@ -717,6 +751,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { // 有站点ID:校验站点存在性并锁定 Station station = stationService.getById(task.getStationId()); if (Objects.isNull(station)) { + taskService.removeById(task); return R.fail("结束站点不存在"); } // 锁定站点(预占用)- 修复原代码空指针问题(先判空再更新) @@ -746,7 +781,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { List bindList = orderBindService.list( new LambdaQueryWrapper() .eq(OrderBind::getBoxBarcode, boxBarcode) - .eq(false, OrderBind::getBindingStatus, OrderBind.STATUS_UNBINDED) + .ne(OrderBind::getBindingStatus, OrderBind.STATUS_UNBINDED) ); log.info("【任务重量计算】箱{}绑定订单列表:{}", boxBarcode, bindList); @@ -787,12 +822,18 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { } else { // 调度失败:回滚任务 taskService.removeById(task); + List stationList = stationService.list(new LambdaQueryWrapper().eq(Station::getId, task.getStationId())); + stationList.get(0).setStationStatus(STATUS_FREE); + stationService.updateById(stationList.get(0)); log.error("【AGV调度】任务{}调度失败,已回滚", task.getId()); return R.fail("AGV小车调用异常"); } } catch (Exception e) { // 异常处理:回滚任务 taskService.removeById(task); + List stationList = stationService.list(new LambdaQueryWrapper().eq(Station::getId, task.getStationId())); + stationList.get(0).setStationStatus(STATUS_FREE); + stationService.updateById(stationList.get(0)); log.error("【AGV调度】任务{}调度异常,已回滚", task.getId(), e); return R.fail("AGV小车调用异常:" + e.getMessage()); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBindServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBindServiceImpl.java index 6c7edc69..ffb37cf6 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBindServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBindServiceImpl.java @@ -119,7 +119,7 @@ public class OrderBindServiceImpl extends BaseServiceImpl orderBindList = list(new LambdaQueryWrapper() .eq(OrderBind::getBoxBarcode, boxBarcode) - .eq(false,OrderBind::getBindingStatus, STATUS_UNBINDED)); + .ne(OrderBind::getBindingStatus, STATUS_UNBINDED)); // 优化:提示信息更精准 if (orderBindList.isEmpty()) { diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java index c7df7b20..83870d7b 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java @@ -151,18 +151,30 @@ public class TaskExecuteRecordServiceImpl extends BaseServiceImpl 实体类型 + * @param 字段值类型 + * @return true=全部一致 / false=存在不一致 / 空集合/单元素集合返回true + */ + public static boolean isAllFieldSame(List entityList, Function fieldExtractor) { + // 1. 边界校验:空集合或单元素集合,默认一致 + if (CollectionUtils.isEmpty(entityList) || entityList.size() == 1) { + return true; + } + + // 2. 校验字段获取器非空 + if (fieldExtractor == null) { + throw new IllegalArgumentException("字段获取器不能为空"); + } + + // 3. 取第一个元素的字段值作为基准 + V baseValue = fieldExtractor.apply(entityList.get(0)); + + // 4. 遍历所有元素,对比字段值 + for (T entity : entityList) { + V currentValue = fieldExtractor.apply(entity); + // Objects.equals自动处理null值对比(null == null 返回true) + if (!Objects.equals(baseValue, currentValue)) { + return false; + } + } + + return true; + } /** * 判断指定字段的值是否存在于目标集合中 * @@ -62,4 +100,57 @@ public class CollectionCheckUtil { .collect(Collectors.toList()); } + + /** + * 从实体类集合中查找指定属性等于指定值的对象 + * @param collection 实体类集合 + * @param fieldName 要匹配的属性名(注意:区分大小写,要和实体类中的属性名一致) + * @param value 要匹配的属性值 + * @param 实体类泛型 + * @return 匹配的对象,未找到则返回 null + */ + public static T findByField(Collection collection, String fieldName, Object value) { + // 空值校验 + if (collection == null || collection.isEmpty() || fieldName == null || fieldName.isEmpty()) { + return null; + } + + // 遍历集合中的每个对象 + for (T obj : collection) { + if (obj == null) { + continue; + } + + try { + // 通过反射获取属性(包括私有属性) + Field field = obj.getClass().getDeclaredField(fieldName); + // 设置可访问私有属性 + field.setAccessible(true); + // 获取对象的该属性值 + Object fieldValue = field.get(obj); + + // 匹配属性值(处理 null 值的情况) + if (value == null) { + if (fieldValue == null) { + return obj; // 属性值和目标值都为 null,匹配成功 + } + } else { + if (value.equals(fieldValue)) { + return obj; // 属性值匹配成功,返回该对象 + } + } + + } catch (NoSuchFieldException e) { + // 属性名不存在,抛出明确的异常提示 + throw new IllegalArgumentException("实体类中不存在属性:" + fieldName, e); + } catch (IllegalAccessException e) { + // 属性访问失败 + throw new RuntimeException("无法访问属性:" + fieldName, e); + } + } + + // 遍历完未找到匹配的对象,返回 null + return null; + } + }