diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java index 79536840..da1ea356 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java @@ -23,12 +23,12 @@ public class Station extends BaseEntity { private static final long serialVersionUID = 1L; /** - * 状态常量:占用 + * 状态常量:空闲 */ public static final Integer STATUS_OCCUPIED = 0; /** - * 状态常量:空闲 + * 状态常量:占用 */ public static final Integer STATUS_FREE = 1; @@ -56,9 +56,9 @@ public class Station extends BaseEntity { private String stationCode; /** - * 当前状态 0:占用 1:空闲 + * 当前状态 0:空闲 1:占用 */ - @Schema(description = "当前状态 0:占用 1:空闲") + @Schema(description = "当前状态 0:空闲 1:占用") private Integer stationStatus; /** 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 66a13cec..08978103 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 @@ -96,7 +96,11 @@ public class Task extends BaseEntity { */ @Schema(description = "临时库位ID") private Long locationId; - + /** + * 作业中心ID + */ + @Schema(description = "作业中心ID") + private Long wcId; /** * 当前状态 0:退回(超重) 1:站点 2:库位 3:等待 4:回库 5:结束 */ diff --git a/blade-service/blade-desk/pom.xml b/blade-service/blade-desk/pom.xml index 89f917c6..858cfae3 100644 --- a/blade-service/blade-desk/pom.xml +++ b/blade-service/blade-desk/pom.xml @@ -141,6 +141,10 @@ 1.9.13 compile + + com.qcloud + cos_api + 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 8958cea1..363d3990 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 @@ -11,7 +11,8 @@ import org.springblade.desk.dashboard.pojo.entity.BsWorkCenterEntity; import org.springblade.desk.dashboard.service.IBsWorkCenterService; import org.springblade.desk.dashboard.wrapper.BsWorkCenterWrapper; import org.springblade.desk.logistics.pojo.entity.BoxBinding; -import org.springblade.desk.logistics.service.OrderBoxService; +import org.springblade.desk.logistics.service.IOrderBoxService; + import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; @@ -28,7 +29,7 @@ import java.util.List; @RequestMapping("/order") @Tag(name = "订单箱子", description = "订单箱子称重接口") public class OrderBoxController extends BladeController { - private final OrderBoxService orderBoxService; + private final IOrderBoxService iOrderBoxService; private final IBsWorkCenterService bsWorkCenterService; @@ -51,7 +52,7 @@ public class OrderBoxController extends BladeController { if (actualWeight == null || new BigDecimal(actualWeight).compareTo(BigDecimal.ZERO) < 0) { return R.fail("实际重量必须为非负数"); } - return orderBoxService.upholdOrderPartWeight(cardNo,new BigDecimal(actualWeight)); + return iOrderBoxService.upholdOrderPartWeight(cardNo,new BigDecimal(actualWeight)); } @GetMapping("/bs-list") @@ -63,11 +64,11 @@ public class OrderBoxController extends BladeController { public R getBSWORKCENTER(){ return R.data(bsWorkCenterService.list(new LambdaQueryWrapper().eq(BsWorkCenterEntity::getIsDeleted, 0))); } - @GetMapping("/box-binding") + @PostMapping("/box-binding") @ApiOperationSupport(order = 3) @Operation( - summary = "获取作业中心", - description = "获取当前作业中心名称" + summary = "绑定箱条码和订单", + description = "绑定箱条码和订单信息内容" ) public R boxBinding(@RequestBody BoxBinding boxBinding){ // 1.参数合法性校验 @@ -78,7 +79,7 @@ public class OrderBoxController extends BladeController { return R.fail("箱条码不能为空"); } - return orderBoxService.boxBinding(boxBinding); + return iOrderBoxService.boxBinding(boxBinding); } } 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 2f1bde0e..e20a4c50 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 @@ -9,5 +9,7 @@ public interface IOrderBoxService { R upholdOrderPartWeight(String cardNo, BigDecimal actualWeight); R boxBinding(BoxBinding boxBinding); + R boxOrderUnbind(String boxBarcode); + } 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 new file mode 100644 index 00000000..1872ce62 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java @@ -0,0 +1,277 @@ +package org.springblade.desk.logistics.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springblade.core.tool.api.R; +import org.springblade.desk.logistics.pojo.entity.*; +import org.springblade.desk.logistics.service.*; +import org.springblade.desk.order.pojo.entity.YieldOrder; +import org.springblade.desk.order.service.IYieldOrderService; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +import static org.springblade.desk.logistics.pojo.entity.OrderBind.STATUS_UNBINDED; +import static org.springblade.desk.logistics.pojo.entity.Station.STATUS_OCCUPIED; +import static org.springblade.desk.logistics.pojo.entity.Task.STATUS_FINISHED; + +/** + * 订单箱子 控制器 + * + * @author qyl + * @since 2026-01-08 + */ +@Service +@Slf4j +public class IOrderBoxServiceImpl implements IOrderBoxService { + private final IYieldOrderService iYieldOrderService; + private final ITaskService iTaskService; + private final IOrderBindService iOrderBindService; + private final IStationService iStationService; + private final ILocationService iLocationService; + + + + private static final Set RUNNING_STATUSES = new HashSet<>(); + static { + RUNNING_STATUSES.add(Task.STATUS_START); + RUNNING_STATUSES.add(Task.STATUS_CONVEYOR_START); + RUNNING_STATUSES.add(Task.STATUS_CONVEYOR_END); + RUNNING_STATUSES.add(Task.STATUS_STATION); + 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 IOrderBoxServiceImpl(IYieldOrderService iYieldOrderService, ITaskService iTaskService, IOrderBindService iOrderBindService, IStationService iStationService, ILocationService iLocationService) { + this.iYieldOrderService = iYieldOrderService; + this.iTaskService = iTaskService; + this.iOrderBindService = iOrderBindService; + this.iStationService = iStationService; + this.iLocationService = iLocationService; + } + + @Override + public R upholdOrderPartWeight(String cardNo, BigDecimal actualWeight) { + log.info("接收到实际重量:{},对应的流程卡号:{}",actualWeight,cardNo); + //获取流程卡号 + List list = iYieldOrderService.list(new QueryWrapper().eq("CARD_NO", cardNo).orderByDesc("UPDATE_TIME")); + + //修改重量 + list.get(0).setActualWeighing(actualWeight); + + return iYieldOrderService.updateById(list.get(0))? R.success():R.fail("实际称重维护:卡号维护失败"); + } + + @Override + public R boxBinding(BoxBinding boxBinding) { + log.info("接收到箱绑定实际参数:{}", boxBinding); + + // 1. 入参非空校验(基础防护) + if (boxBinding == null || boxBinding.getBoxBarcode() == null) { + log.warn("箱绑定参数为空或箱条码缺失"); + return R.fail("箱条码不能为空"); + } + String boxBarcode = boxBinding.getBoxBarcode(); + + // 2. 校验箱条码是否存在运行中的任务(封装为独立方法,提升可读性) + R taskCheckResult = checkBoxBarcodeRunningTask(boxBarcode); + if (!taskCheckResult.isSuccess()) { + return taskCheckResult; + } + + // 3. 校验订单是否已绑定(封装为独立方法) + R orderCheckResult = checkOrderIdBoundStatus(boxBinding.getOrderIdList()); + if (!orderCheckResult.isSuccess()) { + return orderCheckResult; + } + Long wcId = boxBinding.getWcId(); + Task task = new Task(); + task.setBoxBarcode(boxBinding.getBoxBarcode()); + task.setWcId(wcId); + // 4. 获取当前站点位置 + R location = getSiteLocation(task); + if (!location.isSuccess()) { + return location; + } + // 5. 保存记录到数据库中 + task= (Task) location.getData(); + task.setTaskStatus(Task.STATUS_START); + task.setCreateTime(new Date()); + boolean orderBool = boxBinding.getOrderIdList() == null || boxBinding.getOrderIdList().size() == 0; + if (orderBool) { + task.setWeight(new BigDecimal(0)); + }else { + task.setWeight(getWeightByOrderIdList(boxBinding.getOrderIdList())); + } + if (task.getWeight().compareTo(BigDecimal.valueOf(50)) < 0) { + R.fail("箱条码绑定的订单重量过重,请重新进行绑定"); + } + if (!iTaskService.save(task)) { + R.fail("保存绑定箱条码异常"); + } + if (orderBool) { + return R.success(); + }else { + return saveOrderBindingList(task.getId(),boxBinding.getOrderIdList()); + + } + } + + @Override + public R boxOrderUnbind(String boxBarcode) { + if (boxBarcode.isEmpty()) { + log.warn("箱绑定参数为空或箱条码缺失"); + return R.fail("箱条码不能为空"); + } + // 1. 根据箱条码查询数据 + List taskList = iTaskService.list( + new LambdaQueryWrapper().eq(Task::getBoxBarcode, boxBarcode).in(Task::getTaskStatus,RUNNING_STATUSES) + ); + for (Task task : taskList) { + if (task.getStationId()!=null&&task.getStationId()!=0) { + Station station = iStationService.getById(task.getStationId()); + station.setStationStatus(STATUS_OCCUPIED); + iStationService.updateById(station); + } + if (task.getLocationId()!=null&&task.getLocationId()!=0) { + Location location = iLocationService.getById(task.getLocationId()); + location.setLocationStatus(STATUS_OCCUPIED); + iLocationService.updateById(location); + } + List orderBindList = iOrderBindService.list(new LambdaQueryWrapper().eq(OrderBind::getTaskId, task.getId())); + if (orderBindList!=null&&orderBindList.size()!=0) { + for (OrderBind orderBind : orderBindList) { + orderBind.setBindingStatus(STATUS_UNBINDED); + iOrderBindService.updateById(orderBind); + } + } + task.setTaskStatus(STATUS_FINISHED); + iTaskService.updateById(task); + } + + return R.success(); + } + + 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); + orderBind.setOrderId(orderId); + orderBindList.add(orderBind); + } + if (iOrderBindService.saveBatch(orderBindList)) { + return R.success(); + }else { + iTaskService.removeById(taskId); + return R.fail("订单绑定箱条码异常"); + } + } + + private BigDecimal getWeightByOrderIdList(ArrayList orderIdList) { + List orderList = iYieldOrderService.list(new LambdaQueryWrapper().in(YieldOrder::getId, orderIdList)); + return orderList.stream() + .map(YieldOrder::getActualWeighing) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } + + private R getSiteLocation(Task task) { + List list = iStationService.list(new LambdaQueryWrapper().eq(Station::getWcId, task.getWcId()).eq(Station::getStationStatus, STATUS_OCCUPIED)); + if (list!=null&&list.size()!=0) { + task.setStationId(list.get(0).getId()); + Station station = list.get(0); + station.setStationStatus(Station.PRE_STATUS_OCCUPIED); + iStationService.updateById(station); + return R.data(task); + } + List locationList = iLocationService.list(new LambdaQueryWrapper().eq(Location::getLocationStatus, Location.STATUS_OCCUPIED)); + if (locationList!=null&&locationList.size()!=0) { + task.setLocationId(locationList.get(0).getId()); + Location location = locationList.get(0); + location.setLocationStatus(Location.STATUS_FREE); + iLocationService.updateById(location); + return R.data(task); + } + return R.fail("当前班次库位繁忙,请空闲后再试"); + } + + /** + * 校验箱条码是否存在运行中的任务 + */ + private R checkBoxBarcodeRunningTask(String boxBarcode) { + // 查询箱条码对应的任务(MyBatis-Plus的list方法返回空列表,非null,无需判null) + List taskList = iTaskService.list( + new LambdaQueryWrapper().eq(Task::getBoxBarcode, boxBarcode) + ); + + // 无任务数据,直接通过校验 + if (CollectionUtils.isEmpty(taskList)) { + return R.success(); + } + + // 判断是否有运行中的任务(流式操作简化,无冗余map) + boolean hasRunningTask = taskList.stream() + .map(Task::getTaskStatus) + .filter(status -> status != null) // 过滤null状态,避免NPE + .anyMatch(RUNNING_STATUSES::contains); + + if (hasRunningTask) { + log.warn("箱条码{}存在运行中的任务,绑定异常", boxBarcode); + return R.fail("该箱条码在运行中,箱条码异常"); + } + return R.success(); + } + + + /** + * 校验订单号是否已绑定(核心优化:减少遍历次数,流式收集数据) + */ + private R checkOrderIdBoundStatus(List orderIdList) { + // 无订单号,直接通过校验 + if (CollectionUtils.isEmpty(orderIdList)) { + return R.success(); + } + + // 查询订单绑定记录 + List orderBindList = iOrderBindService.list( + new LambdaQueryWrapper().in(OrderBind::getOrderId, orderIdList) + ); + if (CollectionUtils.isEmpty(orderBindList)) { + return R.success(); + } + + // 步骤1:过滤出已绑定的订单ID(流式收集,替代循环) + List boundOrderIds = orderBindList.stream() + .filter(orderBind -> OrderBind.STATUS_BOUND.equals(orderBind.getBindingStatus())) + .map(OrderBind::getOrderId) + .filter(orderId -> orderId != null) // 过滤null订单ID + .distinct() // 去重,避免重复查询 + .collect(Collectors.toList()); + + // 无已绑定订单,直接通过 + if (CollectionUtils.isEmpty(boundOrderIds)) { + return R.success(); + } + + // 步骤2:查询已绑定订单对应的流程卡号(流式收集,替代循环) + List boundCardNos = iYieldOrderService.list( + new LambdaQueryWrapper().in(YieldOrder::getId, boundOrderIds) + ).stream() + .map(YieldOrder::getCardNo) + .filter(cardNo -> cardNo != null) // 过滤null卡号 + .collect(Collectors.toList()); + + // 构造异常信息并返回 + String errorMsg = String.format("以下流程卡号处于绑定状态,绑定异常:{%s}", String.join(",", boundCardNos)); + log.warn(errorMsg); + return R.fail(errorMsg); + } +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBoxServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBoxServiceImpl.java deleted file mode 100644 index 8b3da4a5..00000000 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBoxServiceImpl.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.springblade.desk.logistics.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.extern.slf4j.Slf4j; -import org.springblade.core.tool.api.R; -import org.springblade.desk.jobtransfer.service.ICertificateMaintenanceService; -import org.springblade.desk.logistics.pojo.entity.BoxBinding; -import org.springblade.desk.logistics.pojo.entity.OrderBind; -import org.springblade.desk.logistics.pojo.entity.Task; -import org.springblade.desk.logistics.service.OrderBindService; -import org.springblade.desk.logistics.service.OrderBoxService; - -import org.springblade.desk.logistics.service.TaskService; -import org.springblade.desk.order.pojo.entity.YieldOrder; -import org.springblade.desk.order.service.IYieldOrderService; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * 订单箱子 控制器 - * - * @author qyl - * @since 2026-01-08 - */ -@Service -@Slf4j -public class OrderBoxServiceImpl implements OrderBoxService { - private final IYieldOrderService yieldOrderService; - private final TaskService taskService; - private final OrderBindService orderBindService; - private final OrderBindService orderBindService; - - public OrderBoxServiceImpl(IYieldOrderService yieldOrderService, TaskService taskService, OrderBindService orderBindService) { - this.yieldOrderService = yieldOrderService; - this.taskService = taskService; - this.orderBindService = orderBindService; - } - private static final Set RUNNING_STATUSES = new HashSet<>(); - static { - RUNNING_STATUSES.add(Task.STATUS_STATION); - RUNNING_STATUSES.add(Task.STATUS_LOCATION); - RUNNING_STATUSES.add(Task.STATUS_WAITING); - RUNNING_STATUSES.add(Task.STATUS_BACK_TO_STORAGE); - } - private static final Set ORDER_STATUSES = new HashSet<>(); - static { - ORDER_STATUSES.add(OrderBind.STATUS_BOUND); - } - - @Override - public R upholdOrderPartWeight(String cardNo, BigDecimal actualWeight) { - log.info("接收到实际重量:{},对应的流程卡号:{}",actualWeight,cardNo); - //获取流程卡号 - List list = yieldOrderService.list(new QueryWrapper().eq("CARD_NO", cardNo).orderByDesc("UPDATE_TIME")); - - //修改重量 - list.get(0).setActualWeighing(actualWeight); - - return yieldOrderService.updateById(list.get(0))? R.success():R.fail("实际称重维护:卡号维护失败"); - } - - @Override - public R boxBinding(BoxBinding boxBinding) { - log.info("接收到箱绑定实际参数:{}", boxBinding); - - // 1. 入参非空校验(基础防护) - if (boxBinding == null || boxBinding.getBoxBarcode() == null) { - log.warn("箱绑定参数为空或箱条码缺失"); - return R.fail("箱条码不能为空"); - } - String boxBarcode = boxBinding.getBoxBarcode(); - - // 2. 校验箱条码是否存在运行中的任务(封装为独立方法,提升可读性) - R taskCheckResult = checkBoxBarcodeRunningTask(boxBarcode); - if (!taskCheckResult.isSuccess()) { - return taskCheckResult; - } - - // 3. 校验订单是否已绑定(封装为独立方法) - R orderCheckResult = checkOrderIdBoundStatus(boxBinding.getOrderIdList()); - if (!orderCheckResult.isSuccess()) { - return orderCheckResult; - } - //TODO:判断班次与库位记得写 - - //5.保存记录到数据库中 - Task task = new Task(); - task.setBoxBarcode(boxBinding.getBoxBarcode()); - task.setTaskStatus(1); - - task.set - return null; - } - /** - * 校验箱条码是否存在运行中的任务 - */ - private R checkBoxBarcodeRunningTask(String boxBarcode) { - // 查询箱条码对应的任务(MyBatis-Plus的list方法返回空列表,非null,无需判null) - List taskList = taskService.list( - new LambdaQueryWrapper().eq(Task::getBoxBarcode, boxBarcode) - ); - - // 无任务数据,直接通过校验 - if (CollectionUtils.isEmpty(taskList)) { - return R.success(); - } - - // 判断是否有运行中的任务(流式操作简化,无冗余map) - boolean hasRunningTask = taskList.stream() - .map(Task::getTaskStatus) - .filter(status -> status != null) // 过滤null状态,避免NPE - .anyMatch(RUNNING_STATUSES::contains); - - if (hasRunningTask) { - log.warn("箱条码{}存在运行中的任务,绑定异常", boxBarcode); - return R.fail("该箱条码在运行中,箱条码异常"); - } - return R.success(); - } - - - /** - * 校验订单号是否已绑定(核心优化:减少遍历次数,流式收集数据) - */ - private R checkOrderIdBoundStatus(List orderIdList) { - // 无订单号,直接通过校验 - if (CollectionUtils.isEmpty(orderIdList)) { - return R.success(); - } - - // 查询订单绑定记录 - List orderBindList = orderBindService.list( - new LambdaQueryWrapper().in(OrderBind::getOrderId, orderIdList) - ); - if (CollectionUtils.isEmpty(orderBindList)) { - return R.success(); - } - - // 步骤1:过滤出已绑定的订单ID(流式收集,替代循环) - List boundOrderIds = orderBindList.stream() - .filter(orderBind -> OrderBind.STATUS_BOUND.equals(orderBind.getBindingStatus())) - .map(OrderBind::getOrderId) - .filter(orderId -> orderId != null) // 过滤null订单ID - .distinct() // 去重,避免重复查询 - .collect(Collectors.toList()); - - // 无已绑定订单,直接通过 - if (CollectionUtils.isEmpty(boundOrderIds)) { - return R.success(); - } - - // 步骤2:查询已绑定订单对应的流程卡号(流式收集,替代循环) - List boundCardNos = yieldOrderService.list( - new LambdaQueryWrapper().in(YieldOrder::getId, boundOrderIds) - ).stream() - .map(YieldOrder::getCardNo) - .filter(cardNo -> cardNo != null) // 过滤null卡号 - .collect(Collectors.toList()); - - // 构造异常信息并返回 - String errorMsg = String.format("以下流程卡号处于绑定状态,绑定异常:{%s}", String.join(",", boundCardNos)); - log.warn(errorMsg); - return R.fail(errorMsg); - } -}