|
|
|
|
@ -7,6 +7,7 @@ import cn.hutool.json.JSONUtil; |
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
|
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
import org.springblade.common.exception.BusinessException; |
|
|
|
|
import org.springblade.core.secure.utils.AuthUtil; |
|
|
|
|
@ -16,14 +17,15 @@ import org.springblade.desk.dashboard.service.IBsWorkCenterService; |
|
|
|
|
import org.springblade.desk.logistics.pojo.dto.BoxBindingDto; |
|
|
|
|
import org.springblade.desk.logistics.pojo.dto.ReturnToWarehouseDto; |
|
|
|
|
import org.springblade.desk.logistics.pojo.entity.*; |
|
|
|
|
import org.springblade.desk.logistics.pojo.vo.BoxbarcodeDetailsVO; |
|
|
|
|
import org.springblade.desk.logistics.pojo.vo.BsWorkCenterVO; |
|
|
|
|
import org.springblade.desk.logistics.pojo.vo.QuantityLocationVO; |
|
|
|
|
import org.springblade.desk.logistics.pojo.vo.StationNameBoxBarcodeVO; |
|
|
|
|
import org.springblade.desk.logistics.pojo.vo.*; |
|
|
|
|
import org.springblade.desk.logistics.service.*; |
|
|
|
|
import org.springblade.desk.logistics.utils.AgvTaskTypeUtil; |
|
|
|
|
import org.springblade.desk.order.pojo.entity.YieldOrder; |
|
|
|
|
import org.springblade.desk.order.service.IYieldOrderService; |
|
|
|
|
import org.springblade.desk.produce.pojo.entity.WorkOrder; |
|
|
|
|
import org.springblade.desk.produce.pojo.entity.WorkPlan; |
|
|
|
|
import org.springblade.desk.produce.service.IWorkOrderService; |
|
|
|
|
import org.springblade.desk.produce.service.IWorkPlanService; |
|
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
import org.springframework.util.CollectionUtils; |
|
|
|
|
|
|
|
|
|
@ -116,6 +118,12 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
* 任务执行记录服务:处理AGV调度任务的生成与执行 |
|
|
|
|
*/ |
|
|
|
|
private final ITaskExecuteRecordService taskExecuteRecordService; |
|
|
|
|
private final IWorkOrderService workOrderService; |
|
|
|
|
private final IWorkPlanService workPlanService; |
|
|
|
|
private final IPrWorkPlanService prWorkPlanService; |
|
|
|
|
private final IPrWorkOrderService prWorkOrderService; |
|
|
|
|
private final IStationCenterService stationCenterService; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ========================== 构造器注入 ==========================
|
|
|
|
|
|
|
|
|
|
@ -138,7 +146,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
ILocationService locationService, |
|
|
|
|
AgvTaskTypeUtil agvTaskTypeUtil, |
|
|
|
|
IBsWorkCenterService bsWorkCenterService, |
|
|
|
|
ITaskExecuteRecordService taskExecuteRecordService) { |
|
|
|
|
ITaskExecuteRecordService taskExecuteRecordService, IWorkOrderService workOrderService, IWorkPlanService workPlanService, IPrWorkPlanService prWorkPlanService, IPrWorkOrderService prWorkOrderService, IStationCenterService stationCenterService) { |
|
|
|
|
this.yieldOrderService = yieldOrderService; |
|
|
|
|
this.taskService = taskService; |
|
|
|
|
this.orderBindService = orderBindService; |
|
|
|
|
@ -147,6 +155,11 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
this.agvTaskTypeUtil = agvTaskTypeUtil; |
|
|
|
|
this.bsWorkCenterService = bsWorkCenterService; |
|
|
|
|
this.taskExecuteRecordService = taskExecuteRecordService; |
|
|
|
|
this.workOrderService = workOrderService; |
|
|
|
|
this.workPlanService = workPlanService; |
|
|
|
|
this.prWorkPlanService = prWorkPlanService; |
|
|
|
|
this.prWorkOrderService = prWorkOrderService; |
|
|
|
|
this.stationCenterService = stationCenterService; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ========================== 核心业务方法 ==========================
|
|
|
|
|
@ -214,53 +227,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
* <li>失败:R.fail() - 携带具体失败原因(参数为空/订单已绑定/重量超限等)</li> |
|
|
|
|
* </ul> |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public R<?> boxBinding(BoxBindingDto boxBinding) { |
|
|
|
|
log.info("【箱条码绑定】开始处理 - 绑定参数:{}", boxBinding); |
|
|
|
|
|
|
|
|
|
// 1. 基础参数校验
|
|
|
|
|
R<?> paramCheckResult = validateBoxBindingParams(boxBinding); |
|
|
|
|
if (!paramCheckResult.isSuccess()) { |
|
|
|
|
return paramCheckResult; |
|
|
|
|
} |
|
|
|
|
String boxBarcode = boxBinding.getBoxBarcode(); |
|
|
|
|
List<String> orderCardNoList = boxBinding.getOrderIdList(); |
|
|
|
|
|
|
|
|
|
// 2. 订单有效性校验
|
|
|
|
|
R<?> orderValidResult = validateOrderExist(orderCardNoList); |
|
|
|
|
if (!orderValidResult.isSuccess()) { |
|
|
|
|
return orderValidResult; |
|
|
|
|
} |
|
|
|
|
List<YieldOrder> yieldOrderList = (List<YieldOrder>) orderValidResult.getData(); |
|
|
|
|
List<Long> orderIdList = yieldOrderList.stream() |
|
|
|
|
.map(YieldOrder::getId) |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
|
|
|
|
|
// 3. 校验箱条码是否存在运行中任务
|
|
|
|
|
R<?> boxTaskCheckResult = checkBoxBarcodeRunningTask(boxBarcode); |
|
|
|
|
if (!boxTaskCheckResult.isSuccess()) { |
|
|
|
|
return boxTaskCheckResult; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 4. 校验订单是否已绑定
|
|
|
|
|
R<?> orderBindCheckResult = checkOrderIdBoundStatus(orderIdList); |
|
|
|
|
if (!orderBindCheckResult.isSuccess()) { |
|
|
|
|
return orderBindCheckResult; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 5. 订单重量校验(超限则拒绝绑定)
|
|
|
|
|
BigDecimal totalWeight = calculateOrderTotalWeight(orderIdList); |
|
|
|
|
if (totalWeight.compareTo(MAX_BOX_WEIGHT_THRESHOLD) > 0) { |
|
|
|
|
String errorMsg = String.format("箱条码%s绑定的订单总重量%.2fkg,超过最大阈值%.2fkg", |
|
|
|
|
boxBarcode, totalWeight, MAX_BOX_WEIGHT_THRESHOLD); |
|
|
|
|
log.warn("【箱条码绑定】{}", errorMsg); |
|
|
|
|
return R.fail(errorMsg + ",请重新进行绑定"); |
|
|
|
|
} |
|
|
|
|
// 6.
|
|
|
|
|
|
|
|
|
|
// 6. 保存绑定关系
|
|
|
|
|
return saveOrderBoxBinding(boxBarcode, new ArrayList<>(orderIdList)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 查询回库可选工位列表 |
|
|
|
|
@ -273,10 +240,8 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
log.info("【回库工位查询】开始查询空闲站点关联工位"); |
|
|
|
|
|
|
|
|
|
// 1. 查询空闲状态的站点
|
|
|
|
|
List<Station> freeStationList = stationService.list( |
|
|
|
|
new LambdaQueryWrapper<Station>().eq(Station::getStationStatus, STATUS_FREE) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
List<StationVO> freeStationList = stationService.getStatusStationList(STATUS_FREE, null,CONVEYOR_LINE_RECEIVE_ONLY,false); |
|
|
|
|
// 2. 构建返回列表(默认添加输送线回库选项)
|
|
|
|
|
List<BsWorkCenterVO> resultList = new ArrayList<>(); |
|
|
|
|
BsWorkCenterVO conveyorVO = new BsWorkCenterVO(); |
|
|
|
|
@ -287,10 +252,10 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
// 3. 补充空闲站点关联的工位信息
|
|
|
|
|
if (!CollectionUtils.isEmpty(freeStationList)) { |
|
|
|
|
List<Long> wcIdList = freeStationList.stream() |
|
|
|
|
.map(Station::getWcId) |
|
|
|
|
.map( StationVO::getWcId) |
|
|
|
|
.distinct() |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
List<BsWorkCenterVO> wcVOList = bsWorkCenterService.getByIds(wcIdList); |
|
|
|
|
List<BsWorkCenterVO> wcVOList = bsWorkCenterService.getByIds(wcIdList,freeStationList); |
|
|
|
|
if (!CollectionUtils.isEmpty(wcVOList)) { |
|
|
|
|
resultList.addAll(wcVOList); |
|
|
|
|
log.info("【回库工位查询】查询到{}个空闲工位", wcVOList.size()); |
|
|
|
|
@ -383,7 +348,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
Task task = new Task(); |
|
|
|
|
|
|
|
|
|
// 3. 处理起始站点编码
|
|
|
|
|
R<?> startStationResult = handleStartStationCode(returnToWarehouseDto); |
|
|
|
|
R<?> startStationResult = handleStartStationCode(returnToWarehouseDto,agvSend); |
|
|
|
|
if (!startStationResult.isSuccess()) { |
|
|
|
|
return startStationResult; |
|
|
|
|
} |
|
|
|
|
@ -414,7 +379,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
endStationCode = DROPOFF_CONVEYOR_LINE; |
|
|
|
|
} else { |
|
|
|
|
// 5.2 普通工位回库:分配站点/库位
|
|
|
|
|
R<?> locationResult = allocateSiteOrLocation(startStationCode, task); |
|
|
|
|
R<?> locationResult = allocateSiteOrLocation(startStationCode, task,agvSend); |
|
|
|
|
if (!locationResult.isSuccess()) { |
|
|
|
|
return locationResult; |
|
|
|
|
} |
|
|
|
|
@ -484,11 +449,11 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 3. 查询工位ID
|
|
|
|
|
Long orderId = orderBindList.get(0).getOrderId(); |
|
|
|
|
Long wcId = yieldOrderService.getWcId(orderId); |
|
|
|
|
log.info("【工位ID查询】箱条码{}对应的工位ID:{}", boxBarcode, wcId); |
|
|
|
|
// Long orderId = orderBindList.get(0).getOrderId();
|
|
|
|
|
// Long wcId = yieldOrderService.getWcId(orderId);
|
|
|
|
|
// log.info("【工位ID查询】箱条码{}对应的工位ID:{}", boxBarcode, wcId);
|
|
|
|
|
|
|
|
|
|
return R.data(wcId); |
|
|
|
|
return R.data(orderBindList.get(0).getWcID()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -570,6 +535,26 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
.filter(Objects::nonNull) |
|
|
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add); |
|
|
|
|
} |
|
|
|
|
/** |
|
|
|
|
* 计算订单列表总重量 |
|
|
|
|
* <p>累加订单的实际称重值,过滤null值,初始值为0</p> |
|
|
|
|
* |
|
|
|
|
* @param cardNoList 订单ID列表 |
|
|
|
|
* @return BigDecimal 订单总重量(单位:千克) |
|
|
|
|
*/ |
|
|
|
|
private BigDecimal calculateOrderCardNoTotalWeight(List<String> cardNoList) { |
|
|
|
|
log.info("【订单重量计算】开始计算订单ID列表{}的总重量", cardNoList); |
|
|
|
|
|
|
|
|
|
List<YieldOrder> orderList = yieldOrderService.list( |
|
|
|
|
new LambdaQueryWrapper<YieldOrder>().in(YieldOrder::getCardNo, cardNoList) |
|
|
|
|
); |
|
|
|
|
log.info("【订单重量计算】查询到订单列表:{}", orderList); |
|
|
|
|
|
|
|
|
|
return orderList.stream() |
|
|
|
|
.map(YieldOrder::getActualWeighing) |
|
|
|
|
.filter(Objects::nonNull) |
|
|
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 保存订单与箱条码的绑定关系 |
|
|
|
|
@ -578,7 +563,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
* @param orderIdList 订单ID列表 |
|
|
|
|
* @return R<?> 保存结果 |
|
|
|
|
*/ |
|
|
|
|
private R<?> saveOrderBoxBinding(String boxBarcode, ArrayList<Long> orderIdList) { |
|
|
|
|
private R<?> saveOrderBoxBinding(String boxBarcode, ArrayList<String> orderIdList,Long wcId) { |
|
|
|
|
if (CollectionUtils.isEmpty(orderIdList)) { |
|
|
|
|
return R.fail("订单id不能为空"); |
|
|
|
|
} |
|
|
|
|
@ -589,7 +574,8 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
OrderBind bind = new OrderBind(); |
|
|
|
|
bind.setBindingStatus(OrderBind.STATUS_BOUND); |
|
|
|
|
bind.setBoxBarcode(boxBarcode); |
|
|
|
|
bind.setOrderId(orderId); |
|
|
|
|
bind.setCardNo(orderId); |
|
|
|
|
bind.setWcID(wcId); |
|
|
|
|
return bind; |
|
|
|
|
}) |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
@ -611,7 +597,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
* @param dto 回库任务参数DTO |
|
|
|
|
* @return R<String> 处理后的起始站点编码 |
|
|
|
|
*/ |
|
|
|
|
private R<?> handleStartStationCode(ReturnToWarehouseDto dto) { |
|
|
|
|
private R<?> handleStartStationCode(ReturnToWarehouseDto dto, Boolean agvSend) { |
|
|
|
|
String startStationCode = dto.getStartStationCode(); |
|
|
|
|
if (Objects.nonNull(startStationCode) && !startStationCode.isBlank()) { |
|
|
|
|
// 校验站点是否存在
|
|
|
|
|
@ -627,7 +613,9 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
} |
|
|
|
|
log.info(String.valueOf(stationList.get(0))); |
|
|
|
|
// 校验站点是否可以发送数据
|
|
|
|
|
if (stationList.get(0).getStatus().equals(RECEIVE_ONLY)) { |
|
|
|
|
if (stationList.get(0).getStatus().equals(CONVEYOR_LINE_RECEIVE_ONLY)&&agvSend) { |
|
|
|
|
return R.fail("起始站点站码无法当开始站点编码"); |
|
|
|
|
}else if (!stationList.get(0).getStatus().equals(CONVEYOR_LINE_RECEIVE_ONLY)&&!agvSend) { |
|
|
|
|
return R.fail("起始站点站码无法当开始站点编码"); |
|
|
|
|
} |
|
|
|
|
return R.data(startStationCode); |
|
|
|
|
@ -683,31 +671,26 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
* |
|
|
|
|
* @param startStationCode |
|
|
|
|
* @param task 任务对象(含工位ID) |
|
|
|
|
* @param agvSend |
|
|
|
|
* @return R<Task> 分配后的任务对象 |
|
|
|
|
*/ |
|
|
|
|
private R<Task> allocateSiteOrLocation(String startStationCode, Task task) { |
|
|
|
|
private R<Task> allocateSiteOrLocation(String startStationCode, Task task, Boolean agvSend) { |
|
|
|
|
// 1. 尝试分配空闲站点
|
|
|
|
|
List<Station> freeStationList = stationService.list( |
|
|
|
|
new LambdaQueryWrapper<Station>() |
|
|
|
|
.eq(Station::getWcId, task.getWcId()) |
|
|
|
|
.eq(Station::getStationStatus, STATUS_FREE) |
|
|
|
|
); |
|
|
|
|
// List<Station> freeStationList = stationService.list(
|
|
|
|
|
// new LambdaQueryWrapper<Station>()
|
|
|
|
|
// .eq(Station::getWcId, task.getWcId())
|
|
|
|
|
// .eq(Station::getStationStatus, STATUS_FREE)
|
|
|
|
|
// );
|
|
|
|
|
List<StationVO> freeStationList =null; |
|
|
|
|
if (agvSend) { |
|
|
|
|
freeStationList=stationService.getStatusStationList(STATUS_FREE, task.getWcId(), CONVEYOR_LINE_RECEIVE_ONLY, false); |
|
|
|
|
}else { |
|
|
|
|
freeStationList=stationService.getStatusStationList(STATUS_FREE, task.getWcId(), STATION_RECEIVE_ONLY, false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!CollectionUtils.isEmpty(freeStationList)) { |
|
|
|
|
Station station = null; |
|
|
|
|
String stationPosition = ""; |
|
|
|
|
StationVO station = null; |
|
|
|
|
station = freeStationList.get(0); |
|
|
|
|
if (station.getStatus() == SAME_LAYER) { |
|
|
|
|
station = null; |
|
|
|
|
Station startStation = stationService.list(new LambdaQueryWrapper<Station>().eq(Station::getStationCode, startStationCode)).get(0); |
|
|
|
|
stationPosition = startStation.getStationPosition(); |
|
|
|
|
station = findByField(freeStationList, "stationPosition", stationPosition); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (station == null) { |
|
|
|
|
return R.fail("当前班次" + stationPosition + "楼层库位繁忙,请空闲后再试"); |
|
|
|
|
} |
|
|
|
|
task.setStationId(station.getId()); |
|
|
|
|
// 锁定站点(预占用)
|
|
|
|
|
station.setStationStatus(PRE_STATUS_OCCUPIED); |
|
|
|
|
@ -815,12 +798,18 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
log.info("【任务重量计算】箱{}绑定订单列表:{}", boxBarcode, bindList); |
|
|
|
|
|
|
|
|
|
if (!CollectionUtils.isEmpty(bindList)) { |
|
|
|
|
List<Long> orderIdList = bindList.stream() |
|
|
|
|
// List<Long> orderIdList = bindList.stream()
|
|
|
|
|
// .filter(Objects::nonNull)
|
|
|
|
|
// .map(OrderBind::getOrderId)
|
|
|
|
|
// .filter(Objects::nonNull)
|
|
|
|
|
// .collect(Collectors.toList());
|
|
|
|
|
// taskWeight = calculateOrderTotalWeight(orderIdList);
|
|
|
|
|
List<String> cardNoList = bindList.stream() |
|
|
|
|
.filter(Objects::nonNull) |
|
|
|
|
.map(OrderBind::getOrderId) |
|
|
|
|
.map(OrderBind::getCardNo) |
|
|
|
|
.filter(Objects::nonNull) |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
taskWeight = calculateOrderTotalWeight(orderIdList); |
|
|
|
|
taskWeight = calculateOrderCardNoTotalWeight(cardNoList); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
task.setWeight(taskWeight); |
|
|
|
|
@ -905,17 +894,17 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
* 校验订单是否已绑定 |
|
|
|
|
* <p>避免同一订单被重复绑定到不同箱条码</p> |
|
|
|
|
* |
|
|
|
|
* @param orderIdList 订单ID列表 |
|
|
|
|
* @param cardNo 订单ID列表 |
|
|
|
|
* @return R<?> 校验结果 |
|
|
|
|
*/ |
|
|
|
|
private R<?> checkOrderIdBoundStatus(List<Long> orderIdList) { |
|
|
|
|
if (CollectionUtils.isEmpty(orderIdList)) { |
|
|
|
|
private R<?> checkOrderIdBoundStatus(List<String> cardNoList) { |
|
|
|
|
if (CollectionUtils.isEmpty(cardNoList)) { |
|
|
|
|
return R.success(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 查询订单绑定记录
|
|
|
|
|
List<OrderBind> bindList = orderBindService.list( |
|
|
|
|
new LambdaQueryWrapper<OrderBind>().in(OrderBind::getOrderId, orderIdList) |
|
|
|
|
new LambdaQueryWrapper<OrderBind>().in(OrderBind::getCardNo, cardNoList) |
|
|
|
|
); |
|
|
|
|
if (CollectionUtils.isEmpty(bindList)) { |
|
|
|
|
return R.success(); |
|
|
|
|
@ -972,18 +961,17 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
quantityLocationVO.setBoxBarcode(boxBarcode.trim()); |
|
|
|
|
quantityLocationVO.setQuantity((long) orderBindList.size()); // Long类型可直接自动装箱,无需强制转换
|
|
|
|
|
|
|
|
|
|
// 4. 查询作业中心信息(增加wcId空值校验,避免NPE)
|
|
|
|
|
Long wcId = yieldOrderService.getWcId(firstOrderBind.getOrderId()); |
|
|
|
|
if (wcId == null) { |
|
|
|
|
return R.fail("订单未关联作业中心"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
BsWorkCenterEntity workCenter = bsWorkCenterService.getById(wcId); |
|
|
|
|
BsWorkCenterEntity workCenter = bsWorkCenterService.getById(firstOrderBind.getWcID()); |
|
|
|
|
if (workCenter == null) { |
|
|
|
|
return R.fail("订单所属作业中心异常"); |
|
|
|
|
} |
|
|
|
|
quantityLocationVO.setWcName(workCenter.getWcName()); |
|
|
|
|
|
|
|
|
|
List<StationCenter> stationCenterList = stationCenterService.list(new LambdaQueryWrapper<StationCenter>().eq(StationCenter::getWcId, firstOrderBind.getWcID())); |
|
|
|
|
if (stationCenterList==null||stationCenterList.size()==0) { |
|
|
|
|
return R.fail("获取站点区域有问题"); |
|
|
|
|
} |
|
|
|
|
List<Station> stationList = stationService.list(new LambdaQueryWrapper<Station>().eq(Station::getId, stationCenterList.get(0).getStationId())); |
|
|
|
|
quantityLocationVO.setStationRegion(stationList.get(0).getStationRegion()); |
|
|
|
|
return R.data(quantityLocationVO); |
|
|
|
|
} |
|
|
|
|
@Override |
|
|
|
|
@ -991,28 +979,67 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
if (StringUtils.isBlank(boxBarcode)) { |
|
|
|
|
return R.fail("箱条码不能为空"); |
|
|
|
|
} |
|
|
|
|
List<OrderBind> orderBindList = orderBindService.list(new LambdaQueryWrapper<OrderBind>().eq(OrderBind::getBoxBarcode, boxBarcode).eq(OrderBind::getBindingStatus, OrderBind.STATUS_BOUND)); |
|
|
|
|
if (orderBindList==null||orderBindList.size()==0) { |
|
|
|
|
BoxbarcodeDetailsVO boxbarcodeDetailsVO = new BoxbarcodeDetailsVO(); |
|
|
|
|
boxbarcodeDetailsVO.setBoxBarcode(boxBarcode); |
|
|
|
|
boxbarcodeDetailsVO.setWeight(new BigDecimal(0)); |
|
|
|
|
boxbarcodeDetailsVO.setQuantity(0L); |
|
|
|
|
return R.data(boxbarcodeDetailsVO); |
|
|
|
|
|
|
|
|
|
// 查询已绑定的订单绑定记录
|
|
|
|
|
List<OrderBind> orderBindList = orderBindService.list( |
|
|
|
|
Wrappers.lambdaQuery(OrderBind.class) |
|
|
|
|
.eq(OrderBind::getBoxBarcode, boxBarcode) |
|
|
|
|
.eq(OrderBind::getBindingStatus, OrderBind.STATUS_BOUND) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// 无绑定记录直接返回默认值
|
|
|
|
|
if (CollectionUtils.isEmpty(orderBindList)) { |
|
|
|
|
BoxbarcodeDetailsVO defaultVO = new BoxbarcodeDetailsVO(); |
|
|
|
|
defaultVO.setBoxBarcode(boxBarcode); |
|
|
|
|
defaultVO.setWeight(BigDecimal.ZERO); |
|
|
|
|
defaultVO.setQuantity(0L); |
|
|
|
|
return R.data(defaultVO); |
|
|
|
|
} |
|
|
|
|
List<Long> orderIdList = orderBindList.stream() |
|
|
|
|
.map(OrderBind::getOrderId) |
|
|
|
|
|
|
|
|
|
// 提取公共变量 wcId 为 Long 类型
|
|
|
|
|
OrderBind firstBind = orderBindList.get(0); |
|
|
|
|
Long wcId = firstBind.getWcID(); |
|
|
|
|
|
|
|
|
|
// 提取卡号集合
|
|
|
|
|
List<String> cardNoList = orderBindList.stream() |
|
|
|
|
.map(OrderBind::getCardNo) |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
BigDecimal totalWeight = calculateOrderTotalWeight(orderIdList); |
|
|
|
|
|
|
|
|
|
// 计算总重量 & 查询订单列表
|
|
|
|
|
BigDecimal totalWeight = calculateOrderCardNoTotalWeight(cardNoList); |
|
|
|
|
List<YieldOrder> orderList = yieldOrderService.list( |
|
|
|
|
new LambdaQueryWrapper<YieldOrder>().in(YieldOrder::getId, orderIdList) |
|
|
|
|
Wrappers.lambdaQuery(YieldOrder.class) |
|
|
|
|
.in(YieldOrder::getCardNo, cardNoList) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// 组装返回对象
|
|
|
|
|
BoxbarcodeDetailsVO detailsVO = new BoxbarcodeDetailsVO(); |
|
|
|
|
detailsVO.setBoxBarcode(boxBarcode); |
|
|
|
|
detailsVO.setWeight(totalWeight); |
|
|
|
|
detailsVO.setQuantity((long) orderList.size()); |
|
|
|
|
detailsVO.setYieldOrderList(orderList); |
|
|
|
|
|
|
|
|
|
// ===================== 关键修复:无 Lambda、无报红、空安全 =====================
|
|
|
|
|
// 设置工作中心
|
|
|
|
|
BsWorkCenterEntity workCenter = bsWorkCenterService.getById(wcId); |
|
|
|
|
if (workCenter != null) { |
|
|
|
|
detailsVO.setWcName(workCenter.getWcName()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 设置工位区域
|
|
|
|
|
List<StationCenter> stationCenterList = stationCenterService.list( |
|
|
|
|
new LambdaQueryWrapper<StationCenter>().eq(StationCenter::getWcId, wcId) |
|
|
|
|
); |
|
|
|
|
BoxbarcodeDetailsVO boxbarcodeDetailsVO = new BoxbarcodeDetailsVO(); |
|
|
|
|
boxbarcodeDetailsVO.setBoxBarcode(boxBarcode); |
|
|
|
|
boxbarcodeDetailsVO.setWeight(totalWeight); |
|
|
|
|
boxbarcodeDetailsVO.setQuantity((long) orderList.size()); |
|
|
|
|
boxbarcodeDetailsVO.setYieldOrderList(orderList); |
|
|
|
|
return R.data(boxbarcodeDetailsVO); |
|
|
|
|
|
|
|
|
|
if (stationCenterList!=null||stationCenterList.size()!=0) { |
|
|
|
|
StationCenter stationCenter = stationCenterList.get(0); |
|
|
|
|
Station station = stationService.getById(stationCenter.getStationId()); |
|
|
|
|
if (station != null) { |
|
|
|
|
detailsVO.setStationRegion(station.getStationRegion()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return R.data(detailsVO); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
@ -1036,4 +1063,232 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { |
|
|
|
|
stationNameBoxBarcodeVO.setBoxbarcodeDetailsVO((BoxbarcodeDetailsVO) boxbarcodeDetailsR.getData()); |
|
|
|
|
return R.data(stationNameBoxBarcodeVO); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// public R<?> boxBinding1(BoxBindingDto boxBinding) {
|
|
|
|
|
// log.info("【箱条码绑定】开始处理 - 绑定参数:{}", boxBinding);
|
|
|
|
|
//
|
|
|
|
|
// // 1. 基础参数校验
|
|
|
|
|
// R<?> paramCheckResult = validateBoxBindingParams(boxBinding);
|
|
|
|
|
// if (!paramCheckResult.isSuccess()) {
|
|
|
|
|
// return paramCheckResult;
|
|
|
|
|
// }
|
|
|
|
|
// String boxBarcode = boxBinding.getBoxBarcode();
|
|
|
|
|
// List<String> orderCardNoList = boxBinding.getOrderIdList();
|
|
|
|
|
//
|
|
|
|
|
// // 2. 订单有效性校验
|
|
|
|
|
// R<?> orderValidResult = validateOrderExist(orderCardNoList);
|
|
|
|
|
// if (!orderValidResult.isSuccess()) {
|
|
|
|
|
// return orderValidResult;
|
|
|
|
|
// }
|
|
|
|
|
// List<YieldOrder> yieldOrderList = (List<YieldOrder>) orderValidResult.getData();
|
|
|
|
|
// List<Long> orderIdList = yieldOrderList.stream()
|
|
|
|
|
// .map(YieldOrder::getId)
|
|
|
|
|
// .collect(Collectors.toList());
|
|
|
|
|
//
|
|
|
|
|
// // 3. 校验箱条码是否存在运行中任务
|
|
|
|
|
// R<?> boxTaskCheckResult = checkBoxBarcodeRunningTask(boxBarcode);
|
|
|
|
|
// if (!boxTaskCheckResult.isSuccess()) {
|
|
|
|
|
// return boxTaskCheckResult;
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // 4. 校验订单是否已绑定
|
|
|
|
|
//// R<?> orderBindCheckResult = checkOrderIdBoundStatus(orderIdList);
|
|
|
|
|
//// if (!orderBindCheckResult.isSuccess()) {
|
|
|
|
|
//// return orderBindCheckResult;
|
|
|
|
|
//// }
|
|
|
|
|
//
|
|
|
|
|
// // 5. 订单重量校验(超限则拒绝绑定)
|
|
|
|
|
// BigDecimal totalWeight = calculateOrderTotalWeight(orderIdList);
|
|
|
|
|
// if (totalWeight.compareTo(MAX_BOX_WEIGHT_THRESHOLD) > 0) {
|
|
|
|
|
// String errorMsg = String.format("箱条码%s绑定的订单总重量%.2fkg,超过最大阈值%.2fkg",
|
|
|
|
|
// boxBarcode, totalWeight, MAX_BOX_WEIGHT_THRESHOLD);
|
|
|
|
|
// log.warn("【箱条码绑定】{}", errorMsg);
|
|
|
|
|
// return R.fail(errorMsg + ",请重新进行绑定");
|
|
|
|
|
// }
|
|
|
|
|
// // 6.
|
|
|
|
|
//
|
|
|
|
|
// // 6. 保存绑定关系
|
|
|
|
|
// return saveOrderBoxBinding(boxBarcode, new ArrayList<>(orderIdList));
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
/** |
|
|
|
|
* 箱条码绑定主入口 |
|
|
|
|
* @param boxBinding 绑定请求参数(箱条码 + 订单卡号列表) |
|
|
|
|
* @return 绑定结果 |
|
|
|
|
*/ |
|
|
|
|
public R<?> boxBinding(BoxBindingDto boxBinding) { |
|
|
|
|
log.info("【箱条码绑定】开始处理 - 绑定参数:{}", boxBinding); |
|
|
|
|
|
|
|
|
|
// 1. 基础参数校验
|
|
|
|
|
R<?> paramCheckResult = validateBoxBindingParams(boxBinding); |
|
|
|
|
if (!paramCheckResult.isSuccess()) { |
|
|
|
|
return paramCheckResult; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String boxBarcode = boxBinding.getBoxBarcode(); |
|
|
|
|
ArrayList<String> orderCardNoList = boxBinding.getOrderIdList(); |
|
|
|
|
ArrayList<String> cardNoList = new ArrayList<>(orderCardNoList); |
|
|
|
|
Long wcId = null; |
|
|
|
|
|
|
|
|
|
// 2. 查询箱子是否已有绑定记录,获取已绑定的作业中心ID
|
|
|
|
|
List<OrderBind> orderBindList = orderBindService.lambdaQuery() |
|
|
|
|
.eq(OrderBind::getBoxBarcode, boxBarcode) |
|
|
|
|
.eq(OrderBind::getBindingStatus, OrderBind.STATUS_BOUND) |
|
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
if (orderBindList != null && !orderBindList.isEmpty()) { |
|
|
|
|
wcId = orderBindList.get(0).getWcID(); |
|
|
|
|
// 合并已绑定的卡号
|
|
|
|
|
orderBindList.forEach(bind -> cardNoList.add(bind.getCardNo())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 3. 校验所有订单的作业中心是否一致
|
|
|
|
|
for (String orderCardNo : orderCardNoList) { |
|
|
|
|
R<?> checkResult = checkOrderWorkCenterConsistency(orderCardNo, wcId); |
|
|
|
|
if (!checkResult.isSuccess()) { |
|
|
|
|
|
|
|
|
|
return checkResult; |
|
|
|
|
} |
|
|
|
|
// 从结果中获取最终确定的 wcId(第一次会赋值)
|
|
|
|
|
wcId = (Long) checkResult.getData(); |
|
|
|
|
} |
|
|
|
|
// 4. 校验箱条码是否存在运行中任务
|
|
|
|
|
R<?> boxTaskCheckResult = checkBoxBarcodeRunningTask(boxBarcode); |
|
|
|
|
if (!boxTaskCheckResult.isSuccess()) { |
|
|
|
|
return boxTaskCheckResult; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 5. 校验订单是否已被绑定
|
|
|
|
|
R<?> orderBindCheckResult = checkOrderIdBoundStatus(orderCardNoList); |
|
|
|
|
if (!orderBindCheckResult.isSuccess()) { |
|
|
|
|
return orderBindCheckResult; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 6. 校验总重量是否超限
|
|
|
|
|
BigDecimal totalWeight = calculateOrderCardNoTotalWeight(cardNoList); |
|
|
|
|
if (totalWeight.compareTo(MAX_BOX_WEIGHT_THRESHOLD) > 0) { |
|
|
|
|
String errorMsg = String.format("箱条码%s绑定的订单总重量%.2fkg,超过最大阈值%.2fkg", |
|
|
|
|
boxBarcode, totalWeight, MAX_BOX_WEIGHT_THRESHOLD); |
|
|
|
|
log.warn("【箱条码绑定】{}", errorMsg); |
|
|
|
|
return R.fail(errorMsg + ",请重新进行绑定"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 7. 校验作业中心是否有配送区域
|
|
|
|
|
List<StationCenter> stationCenterList = stationCenterService.lambdaQuery() |
|
|
|
|
.eq(StationCenter::getWcId, wcId) |
|
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
if (stationCenterList == null || stationCenterList.isEmpty()) { |
|
|
|
|
return R.fail("作业中心无配送区域"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 8. 执行绑定保存
|
|
|
|
|
return saveOrderBoxBinding(boxBarcode, orderCardNoList, wcId); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 校验单个订单的作业中心与箱绑定作业中心是否一致(核心逻辑抽离) |
|
|
|
|
*/ |
|
|
|
|
private R<?> checkOrderWorkCenterConsistency(String orderCardNo, Long currentWcId) { |
|
|
|
|
// ====================== 处理标准工单 ======================
|
|
|
|
|
List<WorkOrder> workOrderList = workOrderService.lambdaQuery() |
|
|
|
|
.eq(WorkOrder::getCardNo, orderCardNo) |
|
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
if (workOrderList != null && !workOrderList.isEmpty()) { |
|
|
|
|
WorkOrder workOrder = workOrderList.get(0); |
|
|
|
|
List<WorkPlan> workPlanList = workPlanService.lambdaQuery() |
|
|
|
|
.eq(WorkPlan::getWoId, workOrder.getId()) |
|
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
if (workPlanList == null || workPlanList.isEmpty()) { |
|
|
|
|
log.info("workPlanList"); |
|
|
|
|
return R.fail(orderCardNo + "车间订单异常"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
WorkPlan workPlan = workPlanList.get(0); |
|
|
|
|
Long workCenterId; |
|
|
|
|
|
|
|
|
|
// 根据工序状态判断使用当前工序还是下一道工序
|
|
|
|
|
if (workPlan.getStatus() > 3) { |
|
|
|
|
workCenterId = workPlan.getWorkCenterId(); |
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
List<WorkPlan> nextWorkPlanList = workPlanService.lambdaQuery() |
|
|
|
|
.eq(WorkPlan::getId, workPlan.getNextWpId()) |
|
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
if (nextWorkPlanList == null || nextWorkPlanList.isEmpty()) { |
|
|
|
|
return R.fail(orderCardNo + "车间下一工序订单异常"); |
|
|
|
|
} |
|
|
|
|
workCenterId = nextWorkPlanList.get(0).getWorkCenterId(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return validateWorkCenter(orderCardNo, currentWcId, workCenterId); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ====================== 处理PR工单 ======================
|
|
|
|
|
List<PrWorkOrder> prWorkOrderList = prWorkOrderService.lambdaQuery() |
|
|
|
|
.eq(PrWorkOrder::getCardNo, orderCardNo) |
|
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
if (prWorkOrderList != null && !prWorkOrderList.isEmpty()) { |
|
|
|
|
PrWorkOrder prWorkOrder = prWorkOrderList.get(0); |
|
|
|
|
List<PrWorkPlan> workPlanList = prWorkPlanService.lambdaQuery() |
|
|
|
|
.eq(PrWorkPlan::getWpId, prWorkOrder.getId()) |
|
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
if (workPlanList == null || workPlanList.isEmpty()) { |
|
|
|
|
return R.fail(orderCardNo + "车间订单异常"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PrWorkPlan workPlan = workPlanList.get(0); |
|
|
|
|
Long workCenterId; |
|
|
|
|
|
|
|
|
|
if (workPlan.getStatus() > 3) { |
|
|
|
|
workCenterId = workPlan.getWcId(); |
|
|
|
|
} else { |
|
|
|
|
List<PrWorkPlan> nextWorkPlanList = prWorkPlanService.lambdaQuery() |
|
|
|
|
.eq(PrWorkPlan::getId, workPlan.getNextWpId()) |
|
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
if (nextWorkPlanList == null || nextWorkPlanList.isEmpty()) { |
|
|
|
|
return R.fail(orderCardNo + "车间订单异常"); |
|
|
|
|
} |
|
|
|
|
workCenterId = nextWorkPlanList.get(0).getWcId(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return validateWorkCenter(orderCardNo, currentWcId, workCenterId); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 未找到任何订单
|
|
|
|
|
return R.fail(orderCardNo + "车间订单异常"); |
|
|
|
|
} |
|
|
|
|
/** |
|
|
|
|
* 统一校验作业中心:空值校验 + 一致性校验 |
|
|
|
|
*/ |
|
|
|
|
private R<?> validateWorkCenter(String orderCardNo, Long currentWcId, Long workCenterId) { |
|
|
|
|
if (workCenterId == null) { |
|
|
|
|
return R.fail("请注意:" + orderCardNo + "订单未指派作业中心"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 第一次绑定,赋值作业中心
|
|
|
|
|
if (currentWcId == null) { |
|
|
|
|
return R.data(workCenterId); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 校验是否与已有作业中心一致
|
|
|
|
|
if (!currentWcId.equals(workCenterId)) { |
|
|
|
|
return R.fail(orderCardNo + "作业中心不一致"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return R.data(workCenterId); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |