回库接口bug修复

liweidong
绫Umbrella 1 month ago
parent e70e98b467
commit 963e8ce42f
  1. 3
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/BoxBindingDto.java
  2. 33
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/OrderBindDto.java
  3. 10
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/ReturnToWarehouseDto.java
  4. 8
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/OrderBind.java
  5. 4
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Task.java
  6. 27
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/OrderBindVO.java
  7. 84
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBindController.java
  8. 48
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java
  9. 15
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.java
  10. 23
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.xml
  11. 16
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBindService.java
  12. 9
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java
  13. 18
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineOrderBoxService.java
  14. 3
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineService.java
  15. 421
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java
  16. 121
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IPipelineOrderBoxServiceImpl.java
  17. 114
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBindServiceImpl.java
  18. 12
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/PipelineServiceImpl.java
  19. 4
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java
  20. 2
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java

@ -1,6 +1,7 @@
package org.springblade.desk.logistics.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.ArrayList;
@ -9,6 +10,6 @@ import java.util.ArrayList;
@Schema(description = "箱绑定接收表")
public class BoxBindingDto {
private String boxBarcode;
private Long id;
private ArrayList<Long> orderIdList;
private Long wcId;
}

@ -0,0 +1,33 @@
package org.springblade.desk.logistics.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.util.ArrayList;
import java.util.Date;
@Data
@Schema(description = "箱绑定接收表")
public class OrderBindDto {
/**
* 箱条码
*/
@Schema(description = "箱条码")
private String boxBarcode;
/**
* 开始时间
*/
@Schema(description = "开始时间")
private Date startTime;
/**
* 结束时间
*/
@Schema(description = "结束时间")
private Date endTime;
/**
* 状态 0:未绑定 1:已绑定 2:已解绑
*/
@Schema(description = "状态 0:未绑定 1:已绑定 2:已解绑")
private Integer bindingStatus;
}

@ -5,17 +5,13 @@ import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
@Schema(description = "出库操作")
@Schema(description = "任务操作")
public class ReturnToWarehouseDto {
//箱条码
@NotBlank(message = "箱条码不能为空")
private String boxBarcode;
//站点id
@NotBlank(message = "站点编号不能为空")
private String stationCode;
private String startStationCode;
//终点id
private Long endLocationId ;
//终点名称
private String endName;
private Long endWcId ;
}

@ -72,6 +72,13 @@ public class OrderBind extends BaseEntity {
@Schema(description = "备注")
private String remark;
/**
* 箱条码
*/
@Schema(description = "箱条码")
private String boxBarcode;
/**
* 获取状态描述
* @return 状态描述
@ -80,6 +87,7 @@ public class OrderBind extends BaseEntity {
return getStatusDesc(this.bindingStatus);
}
/**
* 根据状态值获取状态描述
* @param status 状态值

@ -48,6 +48,10 @@ public class Task extends BaseEntity {
* 失败
*/
public static final Integer STATUS_FAILING = 5;
/**
* 暂存
*/
public static final Integer STATUS_TEMPORARY_STORAGE= 6;
/**
* ID主键

@ -0,0 +1,27 @@
package org.springblade.desk.logistics.pojo.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.desk.logistics.pojo.entity.OrderBind;
import org.springblade.desk.logistics.pojo.entity.Task;
import java.io.Serial;
@Data
@EqualsAndHashCode(callSuper = true)
public class OrderBindVO extends OrderBind {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 流程卡号
*/
private String cardNo;
}

@ -0,0 +1,84 @@
package org.springblade.desk.logistics.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.common.exception.BusinessException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.desk.logistics.pojo.dto.BoxBindingDto;
import org.springblade.desk.logistics.pojo.dto.OrderBindDto;
import org.springblade.desk.logistics.pojo.dto.TaskDto;
import org.springblade.desk.logistics.pojo.vo.OrderBindVO;
import org.springblade.desk.logistics.pojo.vo.TaskVO;
import org.springblade.desk.logistics.service.IOrderBindService;
import org.springblade.desk.logistics.service.IOrderBoxService;
import org.springframework.web.bind.annotation.*;
/**
* 订单绑定对象控制器
*
* @author BladeX
* @since 2026-03-03
*/
@RestController
@AllArgsConstructor
@RequestMapping("/order-bind")
@Tag(name = "订单绑定对象接口", description = "订单绑定对象接口")
public class OrderBindController {
private final IOrderBindService iOrderBindService;
private final IOrderBoxService iOrderBoxService;
@PostMapping("/box-binding")
@ApiOperationSupport(order = 1)
@Operation(
summary = "绑定箱条码和订单",
description = "绑定箱条码和订单信息内容"
)
public R boxBinding(@RequestBody BoxBindingDto boxBinding) {
if (boxBinding == null || boxBinding.getBoxBarcode().trim().isEmpty()) {
return R.fail("箱条码不能为空");
}
return iOrderBoxService.boxBinding(boxBinding);
}
@GetMapping("/page")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "")
@Parameters({
@Parameter(name = "boxBarcode", description = "箱条码", in = ParameterIn.QUERY, schema = @Schema(type = "String")),
@Parameter(name = "startTime", description = "开始时间", in = ParameterIn.QUERY, schema = @Schema(type = "Date")),
@Parameter(name = "endTime", description = "结束时间", in = ParameterIn.QUERY, schema = @Schema(type = "Date"))
})
public R<IPage<OrderBindVO>> page(@Parameter(hidden = true) OrderBindDto orderBindDto, Query query) {
IPage<OrderBindVO> pages = iOrderBindService.selectPage(Condition.getPage(query), orderBindDto);
return R.data(pages);
}
@PostMapping("/box-unbind")
@ApiOperationSupport(order = 3)
@Operation(
summary = "绑定箱条码和订单",
description = "绑定箱条码和订单信息内容"
)
public R boxUnbind(@RequestBody BoxBindingDto boxBindingDto) throws BusinessException {
return iOrderBindService.boxUnbind(boxBindingDto);
}
@GetMapping("/list")
@ApiOperationSupport(order = 4)
@Operation(
summary = "查询箱条码",
description = "查询箱条码"
)
public R getBoxcodelist() throws BusinessException {
return iOrderBindService.getBoxcodelist();
}
}

@ -1,4 +1,5 @@
package org.springblade.desk.logistics.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
@ -41,7 +42,6 @@ import java.math.BigDecimal;
@Tag(name = "订单箱子", description = "订单箱子称重接口")
public class OrderBoxController extends BladeController {
private final IOrderBoxService iOrderBoxService;
private final IBsWorkCenterService bsWorkCenterService;
private final ITaskService taskService;
@ -64,41 +64,37 @@ public class OrderBoxController extends BladeController {
if (actualWeight == null || new BigDecimal(actualWeight).compareTo(BigDecimal.ZERO) < 0) {
return R.fail("实际重量必须为非负数");
}
return iOrderBoxService.upholdOrderPartWeight(cardNo,new BigDecimal(actualWeight));
return iOrderBoxService.upholdOrderPartWeight(cardNo, new BigDecimal(actualWeight));
}
@GetMapping("/bs-list")
@ApiOperationSupport(order = 2)
@Operation(
summary = "获取作业中心",
description = "获取当前作业中心名称"
)
public R getBSWORKCENTER(){
return iOrderBoxService.getBSWORKCENTER();
public R getBSWORKCENTER() {
return iOrderBoxService.getBSWORKCENTER();
}
@PostMapping("/box-binding")
@ApiOperationSupport(order = 3)
@Operation(
summary = "绑定箱条码和订单",
description = "绑定箱条码和订单信息内容"
summary = "任务号开始",
description = "任务号开始"
)
public R boxBinding(@RequestBody BoxBindingDto boxBinding){
// 1.参数合法性校验
if (boxBinding == null || boxBinding.getBoxBarcode().trim().isEmpty()) {
return R.fail("箱条码不能为空");
}
if (boxBinding == null || boxBinding.getWcId()==null||boxBinding.getWcId()==0) {
return R.fail("箱条码不能为空");
}
public R boxBinding(@RequestBody ReturnToWarehouseDto returnToWarehouseDto) {
return iOrderBoxService.boxBinding(boxBinding);
return iOrderBoxService.saveTask(returnToWarehouseDto,true);
}
/**
* 任务表 自定义分页
*/
@GetMapping("/page")
@ApiOperationSupport(order = 4)
@Operation(summary = "分页", description = "")
@Operation(summary = "分页", description = "")
@Parameters({
@Parameter(name = "boxBarcode", description = "箱条码", in = ParameterIn.QUERY, schema = @Schema(type = "String")),
@Parameter(name = "stationId", description = "站点ID", in = ParameterIn.QUERY, schema = @Schema(type = "Long")),
@ -113,32 +109,26 @@ public class OrderBoxController extends BladeController {
return R.data(pages);
}
/**
* 回库
*/
@PostMapping("/return-warehouse")
@ApiOperationSupport(order = 5)
@Operation(summary = "回库", description = "调用回库")
public R inventoryReturnToWarehouse(@RequestBody ReturnToWarehouseDto returnToWarehouseDto){
return iOrderBoxService.inventoryReturnToWarehouse(returnToWarehouseDto);
}
/**
* 回调作业中心list
*/
@GetMapping("/return-warehouse-list")
@ApiOperationSupport(order = 6)
@Operation(summary = "回调作业中心list", description = "回调作业中心list")
public R inventoryReturnToWarehouseList(){
@Operation(summary = "回调作业中心list", description = "回调作业中心list")
public R inventoryReturnToWarehouseList() {
return iOrderBoxService.returnToWarehouseList();
}
/**
* 回调作业中心list
*/
@GetMapping("/receive")
@ApiOperationSupport(order = 7)
@Operation(summary = "接收", description = "接收释放站点")
public R receive(@RequestParam String stationCode){
@Operation(summary = "接收", description = "接收释放站点")
public R receive(@RequestParam String stationCode) {
return iOrderBoxService.receive(stationCode);
}
}

@ -1,8 +1,23 @@
package org.springblade.desk.logistics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.desk.logistics.pojo.dto.OrderBindDto;
import org.springblade.desk.logistics.pojo.dto.TaskDto;
import org.springblade.desk.logistics.pojo.entity.OrderBind;
import org.springblade.desk.logistics.pojo.entity.Task;
import org.springblade.desk.logistics.pojo.vo.OrderBindVO;
import org.springblade.desk.logistics.pojo.vo.TaskVO;
import java.util.List;
public interface OrderBindMapper extends BaseMapper<OrderBind> {
/**
* 自定义分页
*
* @param page 分页参数
* @param orderBindDto 查询参数
* @return List<EquipmentVO>
*/
List<OrderBindVO> selectPage(IPage page, OrderBindDto orderBindDto);
}

@ -4,5 +4,26 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace = "org.springblade.desk.logistics.mapper.OrderBindMapper">
<select id="selectPage" resultType="org.springblade.desk.logistics.pojo.vo.OrderBindVO">
SELECT O.*,
Y.CARD_NO AS cardNo
FROM LM_ORDER_BIND O
left join MES_YIELD_ORDER Y
on O.ORDER_ID=Y.ID
WHERE O.IS_DELETED = 0 <!-- 关键修复:添加 l. 表别名 -->
<!-- 以下筛选条件保持不变 -->
<if test="orderBindDto.boxBarcode != null and orderBindDto.boxBarcode != ''">
AND O.BOX_BARCODE LIKE CONCAT('%', #{orderBindDto.boxBarcode}, '%')
</if>
<if test="orderBindDto.bindingStatus != null and orderBindDto.bindingStatus != ''">
AND O.BINDING_STATUS = #{bindingStatus.bindingStatus}
</if>
<if test="orderBindDto.startTime != null and orderBindDto.startTime != ''">
AND O.CREATE_TIME &gt;= #{orderBindDto.startTime}
</if>
<if test="orderBindDto.endTime != null and orderBindDto.endTime != ''">
AND O.CREATE_TIME &lt;= #{orderBindDto.endTime}
</if>
ORDER BY O.CREATE_TIME DESC
</select>
</mapper>

@ -25,9 +25,15 @@
*/
package org.springblade.desk.logistics.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.common.exception.BusinessException;
import org.springblade.core.mp.base.BaseService;
import org.springblade.core.tool.api.R;
import org.springblade.desk.logistics.pojo.dto.BoxBindingDto;
import org.springblade.desk.logistics.pojo.dto.OrderBindDto;
import org.springblade.desk.logistics.pojo.entity.Location;
import org.springblade.desk.logistics.pojo.entity.OrderBind;
import org.springblade.desk.logistics.pojo.vo.OrderBindVO;
/**
* 订单绑定实体类 服务类
@ -37,4 +43,14 @@ import org.springblade.desk.logistics.pojo.entity.OrderBind;
*/
public interface IOrderBindService extends BaseService<OrderBind> {
IPage<OrderBindVO> selectPage(IPage<OrderBindVO> page, OrderBindDto orderBindDto);
/**
* 箱条码解绑操作
* @param boxBindingDto 解绑请求DTO
* @return 操作结果
*/
R boxUnbind(BoxBindingDto boxBindingDto) throws BusinessException;
R getBoxcodelist();
}

@ -39,17 +39,12 @@ public interface IOrderBoxService {
R boxBinding(BoxBindingDto boxBinding);
/**
* 释放站点并调用AGV小车接口优化后的核心方法
* 业务场景任务结束后释放站点触发AGV小车相关操作
* @param ReturnToWarehouseDto returnToWarehouseDto
* @return 统一返回结果
*/
R inventoryReturnToWarehouse(ReturnToWarehouseDto returnToWarehouseDto);
R returnToWarehouseList();
R getBSWORKCENTER();
R receive(String stationCode);
R saveTask(ReturnToWarehouseDto returnToWarehouseDto,Boolean agvSend);
}

@ -1,18 +0,0 @@
package org.springblade.desk.logistics.service;
import org.springblade.core.tool.api.R;
import org.springblade.desk.logistics.pojo.entity.Task;
public interface IPipelineOrderBoxService {
/**
* 箱条码与订单解绑
* 功能解除指定箱条码对应的所有订单绑定关系支持箱的重新绑定或回收
*
* @param boxBarcode 箱条码唯一标识需要解绑的箱子
* @return R<?> 通用返回结果
* - 成功R.success()携带解绑成功的提示或解绑的订单数量
* - 失败R.fail()携带失败原因如箱条码不存在解绑数据异常等
*/
R boxOrderUnbind(String boxBarcode);
}

@ -25,6 +25,7 @@
*/
package org.springblade.desk.logistics.service;
import org.springblade.common.exception.BusinessException;
import org.springblade.core.tool.api.R;
import org.springblade.desk.logistics.pojo.entity.Station;
import org.springblade.desk.logistics.pojo.entity.Task;
@ -47,7 +48,7 @@ public interface IPipelineService {
* @param returnStatus 退回状态
* @return
*/
boolean verifyConveyorBoxWeighing(String boxBarcode, BigDecimal actualWeight, BigDecimal ratedWeight, Integer returnStatus);
boolean verifyConveyorBoxWeighing(String boxBarcode, BigDecimal actualWeight, BigDecimal ratedWeight, Integer returnStatus) throws BusinessException;
/**
* 根据物料箱号查询已绑定预估重量

@ -70,10 +70,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService {
static {
// 初始化运行中任务状态
RUNNING_STATUSES.add(Task.STATUS_START); // 任务启动
RUNNING_STATUSES.add(Task.STATUS_RETURNED); // 退回
RUNNING_STATUSES.add(Task.STATUS_CONVEYOR_END); // 配送
RUNNING_STATUSES.add(Task.STATUS_FINISHED); // 结束
RUNNING_STATUSES.add(Task.STATUS_FAILING); // 失败
}
public IOrderBoxServiceImpl(IYieldOrderService iYieldOrderService, ITaskService iTaskService, IOrderBindService iOrderBindService, IStationService iStationService, ILocationService iLocationService, AgvTaskTypeUtil agvTaskTypeUtil, IBsWorkCenterService bsWorkCenterService, ITaskExecuteRecordService iTaskExecuteRecordService) {
@ -122,9 +119,12 @@ public class IOrderBoxServiceImpl implements IOrderBoxService {
return iYieldOrderService.updateById(list.get(0)) ? R.success() : R.fail("实际称重维护:卡号维护失败");
}
/**
* 箱条码与订单绑定核心方法
* 流程参数校验 任务状态校验 订单绑定状态校验 站点/库位分配 任务创建 订单绑定
* 流程参数校验 任务状态校验 订单绑定状态校验 任务创建 订单绑定
*
* @param boxBinding 箱绑定参数包含箱条码订单ID列表工位ID等
* @return R<?> 绑定结果
@ -153,255 +153,65 @@ public class IOrderBoxServiceImpl implements IOrderBoxService {
if (!orderCheckResult.isSuccess()) {
return orderCheckResult;
}
// 4. 构建任务基础信息
Long wcId = boxBinding.getWcId();
Task task = new Task();
task.setBoxBarcode(boxBarcode);
task.setWcId(wcId);
// 5. 获取当前可用的站点/库位并分配
R location = getSiteLocation(task);
if (!location.isSuccess()) {
return location;
}
// 6. 完善任务信息并保存
task = (Task) location.getData();
task.setTaskStatus(Task.STATUS_START); // 设置任务初始状态为启动
task.setCreateTime(new Date()); // 设置任务创建时间
task.setCreateUser(AuthUtil.getUserId());
// 7. 计算订单总重量(无订单则重量为0)
// 4. 计算订单总重量(无订单则重量为0)
boolean orderBool = boxBinding.getOrderIdList() == null || boxBinding.getOrderIdList().size() == 0;
if (orderBool) {
task.setWeight(new BigDecimal(0));
} else {
task.setWeight(getWeightByOrderIdList(boxBinding.getOrderIdList()));
}
// 8. 重量校验(小于50kg才允许绑定,避免超重)
if (task.getWeight().compareTo(BigDecimal.valueOf(50)) > 0) {
return R.fail("箱条码绑定的订单重量过重,请重新进行绑定");
}
// 9. 保存任务记录
if (!iTaskService.save(task)) {
return R.fail("保存绑定箱条码异常");
}
// 10. 无订单则直接返回成功,有订单则执行订单绑定
if (orderBool) {
return R.success();
} else {
return saveOrderBindingList(task.getId(), boxBinding.getOrderIdList());
}
}
/**
* 释放站点并调用AGV小车接口
* <p>
* 业务场景任务结束后释放指定站点根据终点类型触发不同的AGV小车调度逻辑
* 核心流程
* 1. 校验入参和基础数据站点任务终点信息
* 2. 分两种场景处理AGV调度
* - 场景1仅指定终点名称下料输送线 直接调度AGV到下料线
* - 场景2指定终点站点ID 调度AGV到目标空闲站点
* 3. AGV调用失败时自动回滚站点状态保证数据一致性
*
* @param returnToWarehouseDto 回库请求参数DTO
* @return 统一返回结果
* @throws IllegalArgumentException 入参无效基础数据不存在时抛出
*/
@Override
public R inventoryReturnToWarehouse(ReturnToWarehouseDto returnToWarehouseDto) {
// ========== 1. 入参和基础数据校验(前置校验,提前失败) ==========
// 校验DTO非空
Assert.notNull(returnToWarehouseDto, "回库请求参数不能为空");
String stationCode = returnToWarehouseDto.getStationCode();
Assert.hasText(stationCode, "站点编号不能为空");
// 查询站点信息(封装为方法,提升可读性)
Station targetStation = getStationByCode(stationCode);
// 查询有效任务列表
List<Task> validTaskList = getValidTaskList(returnToWarehouseDto.getBoxBarcode());
// 校验站点状态
checkStationStatus(targetStation);
// 校验终点信息
checkEndLocationInfo(returnToWarehouseDto);
// ========== 2. 分场景处理AGV调度 ==========
try {
if (isDropoffConveyorLineScenario(returnToWarehouseDto)) {
// 场景1:仅指定下料输送线名称 → 调度AGV到下料线
return handleDropoffConveyorLineScenario(targetStation, validTaskList);
} else {
// 场景2:指定终点站点ID → 调度AGV到目标站点
return handleTargetStationScenario(targetStation, returnToWarehouseDto, validTaskList);
if (!orderBool) {
BigDecimal weightByOrderIdList = getWeightByOrderIdList(boxBinding.getOrderIdList());
if (weightByOrderIdList.compareTo(BigDecimal.valueOf(50)) > 0) {
return R.fail("箱条码绑定的订单重量过重,请重新进行绑定");
}
} catch (Exception e) {
log.error("库存回库-AGV调度异常,站点编号:{}", stationCode, e);
return R.fail("库存回库操作失败:" + e.getMessage());
}
}
/**
* 根据站点编号查询站点信息不存在则抛异常
*/
private Station getStationByCode(String stationCode) {
LambdaQueryWrapper<Station> stationQuery = new LambdaQueryWrapper<Station>()
.eq(Station::getStationCode, stationCode);
List<Station> stationList = iStationService.list(stationQuery);
if (stationList == null || stationList.isEmpty()) {
log.warn("站点编号不存在,入参:{}", stationCode);
throw new IllegalArgumentException("输入站点编号不存在");
}
return stationList.get(0);
}
/**
* 查询有效任务列表运行中状态不存在则抛异常
*/
private List<Task> getValidTaskList(String boxBarcode) {
LambdaQueryWrapper<Task> taskQuery = new LambdaQueryWrapper<Task>()
.eq(Task::getBoxBarcode, boxBarcode)
.in(Task::getTaskStatus, RUNNING_STATUSES); // RUNNING_STATUSES建议抽取为常量
List<Task> taskList = iTaskService.list(taskQuery);
if (taskList == null || taskList.isEmpty()) {
log.warn("箱条码数据异常,箱条码编号:{}", boxBarcode);
throw new IllegalArgumentException("箱条码数据异常");
}
return taskList;
}
/**
* 校验站点状态必须为空闲
*/
private void checkStationStatus(Station station) {
if (!STATUS_FREE.equals(station.getStationStatus())) {
log.warn("站点被占用,站点编号:{},当前状态:{}", station.getStationCode(), station.getStationStatus());
throw new IllegalArgumentException("该站点正在被使用,请使用其他站点");
}
// 5. 保存箱订单表
return saveOrderBindingList(boxBinding.getBoxBarcode(), boxBinding.getOrderIdList());
}
/**
* 校验终点信息终点ID/名称不能为空
* 批量保存订单与任务的绑定关系
* 核心创建订单绑定记录并批量插入插入失败则回滚任务删除已创建的任务
*
* @param boxBarcode 箱条码
* @param orderIdList 订单ID列表
* @return R<?> 保存结果
* - 成功R.success()
* - 失败R.fail()删除任务并返回异常信息
*/
private void checkEndLocationInfo(ReturnToWarehouseDto dto) {
Long endLocationId = dto.getEndLocationId();
String endName = dto.getEndName();
// 终点ID和名称都为空 → 异常
if ((endLocationId == null || endLocationId == 0) && (endName == null || endName.isBlank())) {
throw new IllegalArgumentException("请检查运送线终点,运送线终点为空");
}
// 仅终点ID为空 → 校验终点名称是否为下料线
if ((endLocationId == null || endLocationId == 0) && !DROPOFF_CONVEYOR_LINE_NAME.equals(endName)) {
throw new IllegalArgumentException("请检查运送线终点位置异常");
private R saveOrderBindingList(String boxBarcode, ArrayList<Long> orderIdList) {
ArrayList<OrderBind> orderBindList = new ArrayList<>();
// 构建订单绑定记录
for (Long orderId : orderIdList) {
OrderBind orderBind = new OrderBind();
orderBind.setBindingStatus(OrderBind.STATUS_BOUND); // 绑定状态:已绑定
orderBind.setBoxBarcode(boxBarcode); // 关联箱条码
orderBind.setOrderId(orderId); // 关联订单ID
orderBindList.add(orderBind);
}
}
/**
* 判断是否为下料输送线场景
*/
private boolean isDropoffConveyorLineScenario(ReturnToWarehouseDto dto) {
Long endLocationId = dto.getEndLocationId();
return endLocationId == null || endLocationId == 0;
}
/**
* 处理下料输送线场景的AGV调度
*/
private R<?> handleDropoffConveyorLineScenario(Station targetStation, List<Task> taskList) {
String stationCode = targetStation.getStationCode();
// 1. 占用站点
updateStationStatus(targetStation, STATUS_OCCUPIED);
try {
// 2. 获取AGV任务类型并调用调度接口
String taskType = agvTaskTypeUtil.getTaskTypeByPositions(stationCode,DROPOFF_CONVEYOR_LINE);
boolean agvResult = iTaskExecuteRecordService.genAgvSchedulingTask(
taskType, stationCode, DROPOFF_CONVEYOR_LINE, EQUIPMENT_TYPE_AGV, taskList.get(0)
);
if (agvResult) {
log.info("AGV调度成功(下料线场景),站点编号:{}", stationCode);
return R.success();
} else {
throw new RuntimeException("调用AGV小车异常");
}
} catch (Exception e) {
// 3. AGV调用失败 → 回滚站点状态
updateStationStatus(targetStation, STATUS_FREE);
throw e;
// 批量插入绑定记录,失败则删除任务
if (iOrderBindService.saveBatch(orderBindList)) {
return R.success();
} else {
return R.fail("订单绑定箱条码异常");
}
}
/**
* 处理目标站点场景的AGV调度
* 根据订单ID列表计算订单总重量
* 逻辑查询订单对应的工单 累加实际称重值过滤null值
*
* @param orderIdList 订单ID列表
* @return BigDecimal 订单总重量单位业务约定如千克
*/
private R<?> handleTargetStationScenario(Station targetStation, ReturnToWarehouseDto dto, List<Task> taskList) {
String sourceStationCode = targetStation.getStationCode();
Long endLocationId = dto.getEndLocationId();
// 1. 查询终点空闲站点
Station endStation = getFreeStationByWcId(endLocationId);
// 2. 占用源站点 + 预占用终点站点
updateStationStatus(targetStation, STATUS_OCCUPIED);
updateStationStatus(endStation, PRE_STATUS_OCCUPIED);
try {
// 3. 获取AGV任务类型并调用调度接口
String taskType = agvTaskTypeUtil.getTaskTypeByPositions(sourceStationCode,endStation.getStationCode());
boolean agvResult = iTaskExecuteRecordService.genAgvSchedulingTask(
taskType, sourceStationCode, endStation.getStationCode(), EQUIPMENT_TYPE_AGV, taskList.get(0)
);
private BigDecimal getWeightByOrderIdList(List<Long> orderIdList) {
// 查询订单对应的工单列表
List<YieldOrder> orderList = iYieldOrderService.list(new LambdaQueryWrapper<YieldOrder>().in(YieldOrder::getId, orderIdList));
if (agvResult) {
log.info("AGV调度成功(目标站点场景),源站点:{},终点站点:{}", sourceStationCode, endStation.getStationCode());
return R.success();
} else {
throw new RuntimeException("调用AGV小车异常");
}
} catch (Exception e) {
// 4. AGV调用失败 → 回滚两个站点状态
updateStationStatus(targetStation, STATUS_FREE);
updateStationStatus(endStation, STATUS_FREE);
throw e;
}
// 流式累加实际称重值(过滤null,初始值为0)
return orderList.stream()
.map(YieldOrder::getActualWeighing)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
/**
* 根据WCID查询空闲的终点站点不存在则抛异常
*/
private Station getFreeStationByWcId(Long wcId) {
LambdaQueryWrapper<Station> endStationQuery = new LambdaQueryWrapper<Station>()
.eq(Station::getWcId, wcId)
.eq(Station::getStationStatus, STATUS_FREE);
List<Station> endStationList = iStationService.list(endStationQuery);
if (endStationList == null || endStationList.isEmpty()) {
log.warn("结束站点异常,WCID:{}", wcId);
throw new IllegalArgumentException("结束站点异常");
}
return endStationList.get(0);
}
/**
* 统一更新站点状态封装重复逻辑
*/
private void updateStationStatus(Station station, Integer newStatus) {
station.setStationStatus(newStatus);
boolean updateResult = iStationService.updateById(station);
if (!updateResult) {
log.error("站点状态更新失败,站点编号:{},目标状态:{}", station.getStationCode(), newStatus);
throw new RuntimeException("站点状态更新失败");
}
log.debug("站点状态更新成功,站点编号:{},状态:{}", station.getStationCode(), newStatus);
}
@Override
public R returnToWarehouseList() {
@ -415,7 +225,9 @@ public class IOrderBoxServiceImpl implements IOrderBoxService {
List<Long> list = stationList.stream().map(Station::getWcId).distinct().collect(Collectors.toList());
List<BsWorkCenterVO> bwList = bsWorkCenterService.getByIds(list);
if (!bwList.isEmpty()) {
bwList.forEach(s->{bsWorkCenterVOList.add(s);});
bwList.forEach(s -> {
bsWorkCenterVOList.add(s);
});
}
}
@ -450,54 +262,104 @@ public class IOrderBoxServiceImpl implements IOrderBoxService {
return R.fail("站点切换空闲异常");
}
/**
* 批量保存订单与任务的绑定关系
* 核心创建订单绑定记录并批量插入插入失败则回滚任务删除已创建的任务
*
* @param taskId 任务ID关联箱条码
* @param orderIdList 订单ID列表
* @return R<?> 保存结果
* - 成功R.success()
* - 失败R.fail()删除任务并返回异常信息
*/
private R saveOrderBindingList(Long taskId, ArrayList<Long> orderIdList) {
ArrayList<OrderBind> orderBindList = new ArrayList<>();
// 构建订单绑定记录
for (Long orderId : orderIdList) {
OrderBind orderBind = new OrderBind();
orderBind.setBindingStatus(OrderBind.STATUS_BOUND); // 绑定状态:已绑定
orderBind.setTaskId(taskId); // 关联任务ID
orderBind.setOrderId(orderId); // 关联订单ID
orderBindList.add(orderBind);
@Override
public R saveTask(ReturnToWarehouseDto returnToWarehouseDto,Boolean agvSend) {
if (returnToWarehouseDto.getEndWcId()==null) {
R.fail("结束位置不能都为空");
}
String stationCode="";
String endStationCode="";
if (!returnToWarehouseDto.getStartStationCode().isEmpty()) {
List<Station> stationList = iStationService.list(new LambdaQueryWrapper<Station>().eq(Station::getStationCode, returnToWarehouseDto.getStartStationCode()));
if (stationList.isEmpty()) {
return R.fail("站点编码不存在");
}
if (!stationList.get(0).getStationStatus().equals(STATUS_FREE)) {
return R.fail("站点编码不存在");
}
stationCode= returnToWarehouseDto.getStartStationCode();
}else {
stationCode=Station.PICKUP_CONVEYOR_LINE;
}
Task task = new Task();
//判断箱条码是否为空,如果不为空判断是否在使用
if (!returnToWarehouseDto.getBoxBarcode().isEmpty()) {
R taskCheckResult = checkBoxBarcodeRunningTask(returnToWarehouseDto.getBoxBarcode());
if (!taskCheckResult.isSuccess()) {
return taskCheckResult;
}
// 批量插入绑定记录,失败则删除任务
if (iOrderBindService.saveBatch(orderBindList)) {
}
task.setBoxBarcode(returnToWarehouseDto.getBoxBarcode().isEmpty()?"":returnToWarehouseDto.getBoxBarcode());
task.setWcId(returnToWarehouseDto.getEndWcId());
if (returnToWarehouseDto.getEndWcId()==0) {
//todo:查看输送线回库
task.setWcId(0L);
endStationCode= DROPOFF_CONVEYOR_LINE;
}else {
// 5. 获取当前可用的站点/库位并分配
R locationResult = getSiteLocation(task);
if (!locationResult.isSuccess()) {
return locationResult;
}
// 6. 完善任务信息并保存
task = (Task) locationResult.getData();
if (task.getStationId()==null&&agvSend) {
List<Location> locationList = iLocationService.list(new LambdaQueryWrapper<Location>().eq(Location::getId, task.getLocationId()));
if (!CollectionUtils.isEmpty(locationList)) {
Location location = locationList.get(0);
location.setLocationStatus(Location.STATUS_FREE);
iLocationService.updateById(location);
}
return R.fail("结束站点被占用");
}else {
endStationCode=iStationService.getById(task.getStationId()).getStationCode();
}
}
task.setTaskStatus(Task.STATUS_START); // 设置任务初始状态为启动
task.setCreateTime(new Date()); // 设置任务创建时间
task.setCreateUser(AuthUtil.getUserId());
if (!returnToWarehouseDto.getBoxBarcode().isEmpty()) {
List<OrderBind> orderBindList = iOrderBindService.list(new LambdaQueryWrapper<OrderBind>().eq(OrderBind::getBoxBarcode, returnToWarehouseDto.getBoxBarcode()).eq(false, OrderBind::getBindingStatus, OrderBind.STATUS_UNBINDED));
if (orderBindList.isEmpty()) {
task.setWeight(new BigDecimal(0));
}else {
List<Long> orderIdsList = orderBindList.stream()
.filter(Objects::nonNull)
.map(OrderBind::getOrderId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
task.setWeight(getWeightByOrderIdList(orderIdsList));
}
}else {
task.setWeight(new BigDecimal(0));
}
if (!iTaskService.save(task)) {
return R.fail("保存任务表异常");
}
if (agvSend) {
String taskType = agvTaskTypeUtil.getTaskTypeByPositions(stationCode,endStationCode);
boolean agvResult = iTaskExecuteRecordService.genAgvSchedulingTask(
taskType, stationCode, endStationCode, EQUIPMENT_TYPE_AGV, task);
if (agvResult) {
return R.success();
}else {
return R.fail("AGV小车调用异常");
}
}else {
return R.success();
} else {
iTaskService.removeById(taskId); // 回滚:删除已创建的任务
return R.fail("订单绑定箱条码异常");
}
}
/**
* 根据订单ID列表计算订单总重量
* 逻辑查询订单对应的工单 累加实际称重值过滤null值
*
* @param orderIdList 订单ID列表
* @return BigDecimal 订单总重量单位业务约定如千克
*/
private BigDecimal getWeightByOrderIdList(ArrayList<Long> orderIdList) {
// 查询订单对应的工单列表
List<YieldOrder> orderList = iYieldOrderService.list(new LambdaQueryWrapper<YieldOrder>().in(YieldOrder::getId, orderIdList));
// 流式累加实际称重值(过滤null,初始值为0)
return orderList.stream()
.map(YieldOrder::getActualWeighing)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
/**
* 获取当前工位可用的站点/库位并分配
* 优先级先分配站点 站点无可用则分配库位 均无则返回失败
@ -509,7 +371,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService {
*/
private R getSiteLocation(Task task) {
// 1. 查询当前工位可用的站点(状态为占用的站点)
List<Station> list = iStationService.list(new LambdaQueryWrapper<Station>().eq(Station::getWcId, task.getWcId()).eq(Station::getStationStatus, STATUS_FREE));
List<Station> list = iStationService.list(new LambdaQueryWrapper<Station>().eq(Station::getWcId, task.getWcId()).eq(Station::getStationStatus, STATUS_OCCUPIED));
if (!CollectionUtils.isEmpty(list)) {
task.setStationId(list.get(0).getId()); // 分配第一个可用站点
// 更新站点状态为预占用(锁定站点)
@ -534,6 +396,9 @@ public class IOrderBoxServiceImpl implements IOrderBoxService {
return R.fail("当前班次库位繁忙,请空闲后再试");
}
/**
* 校验箱条码是否存在运行中的任务
* 核心避免同一箱条码同时存在多个未完成的绑定任务

@ -1,121 +0,0 @@
package org.springblade.desk.logistics.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.api.R;
import org.springblade.desk.logistics.pojo.entity.Location;
import org.springblade.desk.logistics.pojo.entity.OrderBind;
import org.springblade.desk.logistics.pojo.entity.Station;
import org.springblade.desk.logistics.pojo.entity.Task;
import org.springblade.desk.logistics.service.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.springblade.desk.logistics.pojo.entity.OrderBind.STATUS_UNBINDED;
import static org.springblade.desk.logistics.pojo.entity.Station.STATUS_OCCUPIED;
@Service
@Slf4j
public class IPipelineOrderBoxServiceImpl implements IPipelineOrderBoxService {
/**
* 任务服务处理箱绑定任务的创建状态更新删除等
*/
private final ITaskService iTaskService;
/**
* 站点服务处理站点状态占用/空闲管理
*/
private final IStationService iStationService;
/**
* 库位服务处理库位状态占用/空闲管理
*/
private final ILocationService iLocationService;
/**
* 订单绑定服务处理订单与任务的绑定关系维护
*/
private final IOrderBindService iOrderBindService;
/**
* 任务运行中状态集合包含任务从启动到待入库的所有中间状态
* 用于判断箱条码是否存在未完成的运行任务
*/
private static final Set<Integer> RUNNING_STATUSES = new HashSet<>();
static {
// // 初始化运行中任务状态
// RUNNING_STATUSES.add(Task.STATUS_START); // 任务启动
// RUNNING_STATUSES.add(Task.STATUS_CONVEYOR_END); // 输送机结束
// RUNNING_STATUSES.add(Task.STATUS_LOCATION); // 库位状态
// RUNNING_STATUSES.add(Task.STATUS_WAITING); // 等待状态
// RUNNING_STATUSES.add(Task.STATUS_STATION_RECEIVE);// 站点接收
// RUNNING_STATUSES.add(Task.STATUS_BACK_TO_STORAGE);// 返库状态
}
public IPipelineOrderBoxServiceImpl(ITaskService iTaskService, IStationService iStationService, ILocationService iLocationService, IOrderBindService iOrderBindService) {
this.iTaskService = iTaskService;
this.iStationService = iStationService;
this.iLocationService = iLocationService;
this.iOrderBindService = iOrderBindService;
}
/**
* 箱条码与订单解绑
* 流程参数校验 查询运行中任务 重置站点/库位状态 解绑订单 结束任务
*
* @param boxBarcode 箱条码
* @return R<?> 解绑结果
* - 成功R.success()
* - 失败R.fail()携带具体失败原因如箱条码为空
*/
@Override
public R boxOrderUnbind(String boxBarcode) {
// 1. 参数非空校验
if (boxBarcode.isEmpty()) {
log.warn("箱绑定参数为空或箱条码缺失");
return R.fail("箱条码不能为空");
}
// 2. 查询该箱条码对应的运行中任务
List<Task> taskList = iTaskService.list(
new LambdaQueryWrapper<Task>().eq(Task::getBoxBarcode, boxBarcode).in(false, Task::getTaskStatus, RUNNING_STATUSES)
);
// 3. 遍历任务,重置站点/库位状态 + 解绑订单 + 结束任务
for (Task task : taskList) {
// 3.1 重置站点状态为占用(释放站点)
if (task.getStationId() != null && task.getStationId() != 0) {
Station station = iStationService.getById(task.getStationId());
station.setStationStatus(STATUS_OCCUPIED);
iStationService.updateById(station);
}
// 3.2 重置库位状态为占用(释放库位)
if (task.getLocationId() != null && task.getLocationId() != 0) {
Location location = iLocationService.getById(task.getLocationId());
location.setLocationStatus(STATUS_OCCUPIED);
iLocationService.updateById(location);
}
// 3.3 解绑订单(更新绑定状态为未绑定)
List<OrderBind> orderBindList = iOrderBindService.list(new LambdaQueryWrapper<OrderBind>().eq(OrderBind::getTaskId, task.getId()));
if (!CollectionUtils.isEmpty(orderBindList)) {
for (OrderBind orderBind : orderBindList) {
orderBind.setBindingStatus(STATUS_UNBINDED);
iOrderBindService.updateById(orderBind);
}
}
// // 3.4 结束任务(更新任务状态为已完成)
// task.setTaskStatus(STATUS_FINISHED);
// iTaskService.updateById(task);
}
return R.success();
}
}

@ -25,13 +25,29 @@
*/
package org.springblade.desk.logistics.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.exception.BusinessException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.api.R;
import org.springblade.desk.logistics.mapper.OrderBindMapper;
import org.springblade.desk.logistics.pojo.dto.BoxBindingDto;
import org.springblade.desk.logistics.pojo.dto.OrderBindDto;
import org.springblade.desk.logistics.pojo.entity.OrderBind;
import org.springblade.desk.logistics.pojo.vo.OrderBindVO;
import org.springblade.desk.logistics.pojo.vo.TaskVO;
import org.springblade.desk.logistics.service.IOrderBindService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static org.springblade.desk.logistics.pojo.entity.OrderBind.STATUS_UNBINDED;
/**
* 订单绑定 服务实现类
*
@ -41,6 +57,104 @@ import org.springframework.stereotype.Service;
@Service
@Slf4j
public class OrderBindServiceImpl extends BaseServiceImpl<OrderBindMapper, OrderBind> implements IOrderBindService {
@Autowired
private OrderBindMapper orderBindMapper;
@Override
public IPage<OrderBindVO> selectPage(IPage<OrderBindVO> page, OrderBindDto orderBindDto) {
List<OrderBindVO> orderBindVOList = orderBindMapper.selectPage(page, orderBindDto);
return page.setRecords(orderBindVOList);
}
/**
* 箱条码解绑操作
* @param boxBindingDto 解绑请求DTO
* @return 操作结果
*/
@Override
public R boxUnbind(BoxBindingDto boxBindingDto) throws BusinessException {
// 1. 入参校验(优化:解决空指针+更精准的提示)
if (boxBindingDto == null) {
return R.fail("请求参数不能为空");
}
Long id = boxBindingDto.getId();
String boxBarcode = boxBindingDto.getBoxBarcode();
// 优化:使用StringUtils.isEmpty避免空指针,提示更精准
if (id == null && StringUtils.isEmpty(boxBarcode)) {
return R.fail("解绑失败:id和箱条码不能同时为空");
}
// 2. 分场景处理解绑逻辑(优化:提取方法+减少嵌套+统一返回)
boolean unbindSuccess;
if (StringUtils.isNotBlank(boxBarcode)) {
unbindSuccess = unbindByBoxBarcode(boxBarcode);
} else {
unbindSuccess = unbindById(id);
}
// 3. 统一结果返回(优化:消除冗余的if-else)
return unbindSuccess ? R.success("解绑成功") : R.fail("解绑失败:数据库更新异常");
}
@Override
public R getBoxcodelist() {
List<OrderBind> orderBindList = list(new LambdaQueryWrapper<OrderBind>().eq(OrderBind::getBindingStatus, OrderBind.STATUS_BOUND));
if (orderBindList.isEmpty()) {
return null;
}
List<String> boxCodeNameList = orderBindList.stream()
.filter(obj -> obj != null) // 过滤空对象,避免NPE
.map(OrderBind::getBoxBarcode) // 提取指定字段
.filter(field -> field != null) // 过滤字段空值(可选,根据业务需求)
.distinct() // 去重(依赖字段的equals/hashCode方法)
.collect(Collectors.toList());
return R.data(boxCodeNameList);
}
/**
* 按箱条码批量解绑
* @param boxBarcode 箱条码
* @return 解绑是否成功
*/
private boolean unbindByBoxBarcode(String boxBarcode) throws BusinessException {
// 优化:查询条件优化(eq(false)改为动态条件,语义更清晰)
List<OrderBind> orderBindList = list(new LambdaQueryWrapper<OrderBind>()
.eq(OrderBind::getBoxBarcode, boxBarcode)
.eq(false,OrderBind::getBindingStatus, STATUS_UNBINDED));
// 优化:提示信息更精准
if (orderBindList.isEmpty()) {
throw new BusinessException("解绑失败:未查询到[" + boxBarcode + "]对应的绑定中记录");
}
// 优化:批量赋值(保持简洁,可添加更新人/更新时间)
orderBindList.forEach(orderBind -> {
orderBind.setBindingStatus(STATUS_UNBINDED);
// 可选:补充更新审计字段
orderBind.setUpdateTime(new Date());
// orderBind.setUpdateBy(getCurrentUserId());
});
// 优化:批量更新(建议指定批次大小,默认1000)
return updateBatchById(orderBindList, 500);
}
/**
* 按ID单条解绑
* @param id 记录ID
* @return 解绑是否成功
*/
private boolean unbindById(Long id) throws BusinessException {
OrderBind orderBind = getById(id);
if (orderBind == null) {
throw new BusinessException("解绑失败:未查询到ID为[" + id + "]的记录");
}
// 优化:赋值逻辑
orderBind.setBindingStatus(STATUS_UNBINDED);
// 可选:补充更新审计字段
// orderBind.setUpdateTime(LocalDateTime.now());
return updateById(orderBind);
}
}

@ -26,8 +26,10 @@
package org.springblade.desk.logistics.service.impl;
import groovy.lang.Lazy;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.exception.BusinessException;
import org.springblade.core.tool.api.R;
import org.springblade.desk.logistics.constant.AgvConstant;
import org.springblade.desk.logistics.pojo.dto.BoxBindingDto;
import org.springblade.desk.logistics.pojo.entity.*;
import org.springblade.desk.logistics.pojo.vo.AgvSchedulingTaskVO;
import org.springblade.desk.logistics.service.*;
@ -60,9 +62,9 @@ public class PipelineServiceImpl implements IPipelineService {
@Autowired
ILocationService locationService;
@Autowired
IPipelineOrderBoxService iPipelineOrderBoxService;
// IOrderBoxService orderBoxService;
@Autowired
IOrderBindService iOrderBindService;
@Autowired
@ -73,7 +75,7 @@ public class PipelineServiceImpl implements IPipelineService {
@Override
public boolean verifyConveyorBoxWeighing(String boxBarcode, BigDecimal actualWeight, BigDecimal ratedWeight, Integer returnStatus) {
public boolean verifyConveyorBoxWeighing(String boxBarcode, BigDecimal actualWeight, BigDecimal ratedWeight, Integer returnStatus) throws BusinessException {
// 1. 判断是否超重
if (WeighData.RETURN_STATUS_RETURNED.equals(returnStatus)) {
@ -81,7 +83,9 @@ public class PipelineServiceImpl implements IPipelineService {
taskService.savePipelineWeigh(boxBarcode,actualWeight);
// 3.超重处理,解绑
R ret = iPipelineOrderBoxService.boxOrderUnbind(boxBarcode);
BoxBindingDto boxBindingDto = new BoxBindingDto();
boxBindingDto.setBoxBarcode(boxBarcode);
R ret = iOrderBindService.boxUnbind(boxBindingDto);
if(!ret.isSuccess()){
throw new ServiceException("解绑失败: "+boxBarcode);
}

@ -89,7 +89,7 @@ public class StorageMonitoringServiceImpl implements IStorageMonitoringService {
* - 库位ID/任务/库位信息空值校验跳过异常数据
* - 状态未变化时跳过更新减少数据库IO
*/
// @Scheduled(cron = "0 * * * * ?") // Spring定时任务注解,cron表达式控制执行频率
@Scheduled(cron = "0 0/5 * * * ?")
@Override // 实现IStorageMonitoringService接口的抽象方法
public void monitoringStation() {
// ========== 步骤1:查询所有空闲状态的站点 ==========
@ -116,7 +116,7 @@ public class StorageMonitoringServiceImpl implements IStorageMonitoringService {
// ========== 步骤2.1:查询对应工位的待库位任务(按创建时间升序) ==========
List<Task> taskList = taskService.list(
new LambdaQueryWrapper<Task>()
.eq(Task::getTaskStatus, Task.STATUS_LOCATION) // 任务状态:待库位
.eq(Task::getTaskStatus, Task.STATUS_TEMPORARY_STORAGE) // 任务状态:待库位
.eq(Task::getWcId, station.getWcId()) // 匹配当前站点的工位ID
.orderByAsc(Task::getCreateTime) // 按创建时间升序,优先处理最早创建的任务
);

@ -40,7 +40,7 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
import static org.springblade.desk.logistics.pojo.entity.Task.getStatusDesc;
/**
* 物流任务 服务类

Loading…
Cancel
Save