|
|
|
|
@ -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 { |
|
|
|
|
* 查询回库可选工位列表 |
|
|
|
|
* <p>查询空闲状态的站点关联工位,默认添加输送线回库选项</p> |
|
|
|
|
* |
|
|
|
|
* @return R<List<BsWorkCenterVO>> 工位VO列表(含默认输送线选项) |
|
|
|
|
* @return R<List < BsWorkCenterVO>> 工位VO列表(含默认输送线选项) |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public R<List<BsWorkCenterVO>> 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<String> 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<Task> 分配后的任务对象 |
|
|
|
|
*/ |
|
|
|
|
private R<Task> allocateSiteOrLocation(Task task) { |
|
|
|
|
private R<Task> allocateSiteOrLocation(String startStationCode, Task task) { |
|
|
|
|
// 1. 尝试分配空闲站点
|
|
|
|
|
List<Station> freeStationList = stationService.list( |
|
|
|
|
new LambdaQueryWrapper<Station>() |
|
|
|
|
.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<Station>().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<Location> freeLocationList = locationService.list( |
|
|
|
|
new LambdaQueryWrapper<Location>().eq(Location::getLocationStatus, STATUS_FREE) |
|
|
|
|
new LambdaQueryWrapper<Location>() |
|
|
|
|
.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<String> 结束站点编码(成功)/错误信息(失败) |
|
|
|
|
*/ |
|
|
|
|
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<OrderBind> bindList = orderBindService.list( |
|
|
|
|
new LambdaQueryWrapper<OrderBind>() |
|
|
|
|
.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<Station> stationList = stationService.list(new LambdaQueryWrapper<Station>().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<Station> stationList = stationService.list(new LambdaQueryWrapper<Station>().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()); |
|
|
|
|
} |
|
|
|
|
|