From 7ebbf67c171575afb32cc7023becba3cfbfcb23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=ABUmbrella?= <2539020564@qq.com> Date: Mon, 9 Mar 2026 09:36:48 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=9B=9E=E5=BA=93=E6=8E=A5=E5=8F=A3bug?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../desk/logistics/controller/OrderBoxController.java | 2 +- .../desk/logistics/service/impl/IOrderBoxServiceImpl.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java index 0efae96b..198984b1 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java @@ -119,7 +119,7 @@ public class OrderBoxController extends BladeController { @PostMapping("/return-warehouse") @ApiOperationSupport(order = 5) @Operation(summary = "回库", description = "调用回库") - public R inventoryReturnToWarehouse(@RequestParam ReturnToWarehouseDto returnToWarehouseDto){ + public R inventoryReturnToWarehouse(@RequestBody ReturnToWarehouseDto returnToWarehouseDto){ return iOrderBoxService.inventoryReturnToWarehouse(returnToWarehouseDto); } /** 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 5982708d..12ba6072 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 @@ -226,7 +226,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { // 查询站点信息(封装为方法,提升可读性) Station targetStation = getStationByCode(stationCode); // 查询有效任务列表 - List validTaskList = getValidTaskList(stationCode); + List validTaskList = getValidTaskList(returnToWarehouseDto.getBoxBarcode()); // 校验站点状态 checkStationStatus(targetStation); // 校验终点信息 @@ -265,14 +265,14 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { /** * 查询有效任务列表(运行中状态,不存在则抛异常) */ - private List getValidTaskList(String stationCode) { + private List getValidTaskList(String boxBarcode) { LambdaQueryWrapper taskQuery = new LambdaQueryWrapper() - .eq(Task::getBoxBarcode, stationCode) + .eq(Task::getBoxBarcode, boxBarcode) .in(Task::getTaskStatus, RUNNING_STATUSES); // RUNNING_STATUSES建议抽取为常量 List taskList = iTaskService.list(taskQuery); if (taskList == null || taskList.isEmpty()) { - log.warn("箱条码数据异常,站点编号:{}", stationCode); + log.warn("箱条码数据异常,箱条码编号:{}", boxBarcode); throw new IllegalArgumentException("箱条码数据异常"); } return taskList; From 963e8ce42fc39e7ee1c21af629da553c6e85fbb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=ABUmbrella?= <2539020564@qq.com> Date: Mon, 9 Mar 2026 19:27:20 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=9B=9E=E5=BA=93=E6=8E=A5=E5=8F=A3bug?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../logistics/pojo/dto/BoxBindingDto.java | 3 +- .../desk/logistics/pojo/dto/OrderBindDto.java | 33 ++ .../pojo/dto/ReturnToWarehouseDto.java | 10 +- .../desk/logistics/pojo/entity/OrderBind.java | 8 + .../desk/logistics/pojo/entity/Task.java | 4 + .../desk/logistics/pojo/vo/OrderBindVO.java | 27 ++ .../controller/OrderBindController.java | 84 ++++ .../controller/OrderBoxController.java | 48 +- .../logistics/mapper/OrderBindMapper.java | 15 + .../desk/logistics/mapper/OrderBindMapper.xml | 23 +- .../logistics/service/IOrderBindService.java | 16 + .../logistics/service/IOrderBoxService.java | 9 +- .../service/IPipelineOrderBoxService.java | 18 - .../logistics/service/IPipelineService.java | 3 +- .../service/impl/IOrderBoxServiceImpl.java | 421 ++++++------------ .../impl/IPipelineOrderBoxServiceImpl.java | 121 ----- .../service/impl/OrderBindServiceImpl.java | 114 +++++ .../service/impl/PipelineServiceImpl.java | 12 +- .../impl/StorageMonitoringServiceImpl.java | 4 +- .../service/impl/TaskServiceImpl.java | 2 +- 20 files changed, 505 insertions(+), 470 deletions(-) create mode 100644 blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/OrderBindDto.java create mode 100644 blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/OrderBindVO.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBindController.java delete mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineOrderBoxService.java delete mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IPipelineOrderBoxServiceImpl.java diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/BoxBindingDto.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/BoxBindingDto.java index f7c4712f..a3d0a76d 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/BoxBindingDto.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/BoxBindingDto.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 orderIdList; - private Long wcId; } diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/OrderBindDto.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/OrderBindDto.java new file mode 100644 index 00000000..e8863ccb --- /dev/null +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/OrderBindDto.java @@ -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; +} diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/ReturnToWarehouseDto.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/ReturnToWarehouseDto.java index 71489fbd..c726cb95 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/ReturnToWarehouseDto.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/ReturnToWarehouseDto.java @@ -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 ; } diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/OrderBind.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/OrderBind.java index d1589561..6f2909a8 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/OrderBind.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/OrderBind.java @@ -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 状态值 diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Task.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Task.java index 2588443e..203f6214 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Task.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Task.java @@ -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主键 diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/OrderBindVO.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/OrderBindVO.java new file mode 100644 index 00000000..cd0093d7 --- /dev/null +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/OrderBindVO.java @@ -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; +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBindController.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBindController.java new file mode 100644 index 00000000..f5732c76 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBindController.java @@ -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> page(@Parameter(hidden = true) OrderBindDto orderBindDto, Query query) { + IPage 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(); + } +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java index 198984b1..4a9e5f92 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java @@ -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); } + } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.java index e0cd51e4..2a9950fd 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.java @@ -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 { + /** + * 自定义分页 + * + * @param page 分页参数 + * @param orderBindDto 查询参数 + * @return List + */ + List selectPage(IPage page, OrderBindDto orderBindDto); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.xml index 2a0fb45a..b6c44fd1 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.xml +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/OrderBindMapper.xml @@ -4,5 +4,26 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBindService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBindService.java index c3ac6cfd..d6a3c632 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBindService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBindService.java @@ -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 { + IPage selectPage(IPage page, OrderBindDto orderBindDto); + /** + * 箱条码解绑操作 + * @param boxBindingDto 解绑请求DTO + * @return 操作结果 + */ + R boxUnbind(BoxBindingDto boxBindingDto) throws BusinessException; + + R getBoxcodelist(); + } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java index 2515fe53..5131e819 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java @@ -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); } \ No newline at end of file diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineOrderBoxService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineOrderBoxService.java deleted file mode 100644 index 20f8fa2e..00000000 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineOrderBoxService.java +++ /dev/null @@ -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); - -} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineService.java index 6f89dbdc..9c55800c 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPipelineService.java @@ -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; /** * 根据物料箱号查询已绑定预估重量 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 5a2dc719..9ab22e13 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 @@ -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小车接口 - *

- * 业务场景:任务结束后释放指定站点,根据终点类型触发不同的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 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 stationQuery = new LambdaQueryWrapper() - .eq(Station::getStationCode, stationCode); - List stationList = iStationService.list(stationQuery); - - if (stationList == null || stationList.isEmpty()) { - log.warn("站点编号不存在,入参:{}", stationCode); - throw new IllegalArgumentException("输入站点编号不存在"); - } - return stationList.get(0); - } - - /** - * 查询有效任务列表(运行中状态,不存在则抛异常) - */ - private List getValidTaskList(String boxBarcode) { - LambdaQueryWrapper taskQuery = new LambdaQueryWrapper() - .eq(Task::getBoxBarcode, boxBarcode) - .in(Task::getTaskStatus, RUNNING_STATUSES); // RUNNING_STATUSES建议抽取为常量 - List 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 orderIdList) { + ArrayList 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 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 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 orderIdList) { + // 查询订单对应的工单列表 + List orderList = iYieldOrderService.list(new LambdaQueryWrapper().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 endStationQuery = new LambdaQueryWrapper() - .eq(Station::getWcId, wcId) - .eq(Station::getStationStatus, STATUS_FREE); - List 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 list = stationList.stream().map(Station::getWcId).distinct().collect(Collectors.toList()); List 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 orderIdList) { - ArrayList 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 stationList = iStationService.list(new LambdaQueryWrapper().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 locationList = iLocationService.list(new LambdaQueryWrapper().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 orderBindList = iOrderBindService.list(new LambdaQueryWrapper().eq(OrderBind::getBoxBarcode, returnToWarehouseDto.getBoxBarcode()).eq(false, OrderBind::getBindingStatus, OrderBind.STATUS_UNBINDED)); + if (orderBindList.isEmpty()) { + task.setWeight(new BigDecimal(0)); + }else { + List 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 orderIdList) { - // 查询订单对应的工单列表 - List orderList = iYieldOrderService.list(new LambdaQueryWrapper().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 list = iStationService.list(new LambdaQueryWrapper().eq(Station::getWcId, task.getWcId()).eq(Station::getStationStatus, STATUS_FREE)); + List list = iStationService.list(new LambdaQueryWrapper().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("当前班次库位繁忙,请空闲后再试"); } + + + /** * 校验箱条码是否存在运行中的任务 * 核心:避免同一箱条码同时存在多个未完成的绑定任务 diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IPipelineOrderBoxServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IPipelineOrderBoxServiceImpl.java deleted file mode 100644 index 2eed85ef..00000000 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IPipelineOrderBoxServiceImpl.java +++ /dev/null @@ -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 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 taskList = iTaskService.list( - new LambdaQueryWrapper().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 orderBindList = iOrderBindService.list(new LambdaQueryWrapper().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(); - } - -} 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 df82a4cb..f3dd2fcb 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 @@ -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 implements IOrderBindService { + @Autowired + private OrderBindMapper orderBindMapper; + + @Override + public IPage selectPage(IPage page, OrderBindDto orderBindDto) { + List 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 orderBindList = list(new LambdaQueryWrapper().eq(OrderBind::getBindingStatus, OrderBind.STATUS_BOUND)); + if (orderBindList.isEmpty()) { + return null; + } + List 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 orderBindList = list(new LambdaQueryWrapper() + .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); + } } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/PipelineServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/PipelineServiceImpl.java index 99791218..d0a4f4f1 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/PipelineServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/PipelineServiceImpl.java @@ -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); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java index 5c67915d..9b6d12e1 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java @@ -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 taskList = taskService.list( new LambdaQueryWrapper() - .eq(Task::getTaskStatus, Task.STATUS_LOCATION) // 任务状态:待库位 + .eq(Task::getTaskStatus, Task.STATUS_TEMPORARY_STORAGE) // 任务状态:待库位 .eq(Task::getWcId, station.getWcId()) // 匹配当前站点的工位ID .orderByAsc(Task::getCreateTime) // 按创建时间升序,优先处理最早创建的任务 ); diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java index db2436d7..e3a18802 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java @@ -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; + /** * 物流任务 服务类