物流改写

liweidong
绫Umbrella 1 month ago
parent 74b0d1bd27
commit 3d9a31d22d
  1. 9
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/OrderBind.java
  2. 258
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/PrWorkOrder.java
  3. 242
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/PrWorkPlan.java
  4. 19
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/Station.java
  5. 42
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/StationCenter.java
  6. 7
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/BoxbarcodeDetailsVO.java
  7. 4
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/BsWorkCenterVO.java
  8. 2
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/QuantityLocationVO.java
  9. 3
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/StationVO.java
  10. 4
      blade-service/blade-desk/src/main/java/org/springblade/desk/dashboard/service/IBsWorkCenterService.java
  11. 21
      blade-service/blade-desk/src/main/java/org/springblade/desk/dashboard/service/impl/BsWorkCenterServiceImpl.java
  12. 1
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java
  13. 41
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/PrWorkOrderMapper.java
  14. 8
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/PrWorkOrderMapper.xml
  15. 41
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/PrWorkPlanMapper.java
  16. 8
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/PrWorkPlanMapper.xml
  17. 41
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/StationCenterMapper.java
  18. 8
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/StationCenterMapper.xml
  19. 4
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/StationMapper.java
  20. 40
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/StationMapper.xml
  21. 41
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPrWorkOrderService.java
  22. 39
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IPrWorkPlanService.java
  23. 39
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IStationCenterService.java
  24. 4
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IStationService.java
  25. 489
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java
  26. 24
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/OrderBindServiceImpl.java
  27. 51
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/PrWorkOrderServiceImpl.java
  28. 46
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/PrWorkPlanServiceImpl.java
  29. 49
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StationCenterServiceImpl.java
  30. 6
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StationServiceImpl.java
  31. 21
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java
  32. 2
      blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java

@ -4,6 +4,7 @@ package org.springblade.desk.logistics.pojo.entity;
* @author: liweidong * @author: liweidong
* @create: 2026-03-03 * @create: 2026-03-03
*/ */
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@ -79,6 +80,14 @@ public class OrderBind extends BaseEntity {
@Schema(description = "箱条码") @Schema(description = "箱条码")
private String boxBarcode; private String boxBarcode;
/**
* 作业中心id
*/
@Schema(description = "作业中心id")
@TableField("WC_ID")
private Long wcID;
@Schema(description = "流程卡号")
private String cardNo;
/** /**
* 获取状态描述 * 获取状态描述
* @return 状态描述 * @return 状态描述

@ -0,0 +1,258 @@
package org.springblade.desk.logistics.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.Date;
/**
* 物流任务实体类
*
* @author: liweidong
* @create: 2026-03-03
*/
@Data
@TableName("PR_WORK_ORDER")
@Schema(description = "车间订单->视图")
@EqualsAndHashCode(callSuper = true)
public class PrWorkOrder extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID主键
*/
@Schema(description = "ID主键")
private Long id;
@Schema(description = "工单ID")
@TableField("WO_ID")
private Long woId;
@Schema(description = "生产订单ID")
@TableField("YO_ID")
private Long yoId;
@Schema(description = "路线卡号")
@TableField("CARD_NO")
private String cardNo;
@Schema(description = "批次号")
@TableField("BATCH_NO")
private String batchNo;
@Schema(description = "工单号")
@TableField("WO_CODE")
private String woCode;
@Schema(description = "生产数量")
@TableField("MAKE_QTY")
private BigDecimal makeQty;
@Schema(description = "计划结束时间")
@TableField("PLAN_END_DATE")
private Date planEndDate;
@Schema(description = "工单计划ID")
@TableField("WP_ID")
private Long wpId;
@Schema(description = "入库数量")
@TableField("INVENTORY_QTY")
private BigDecimal inventoryQty;
@Schema(description = "运行状态")
@TableField("RUN_STATUS")
private Integer runStatus;
@Schema(description = "领料状态")
@TableField("PICKING_STATUS")
private Integer pickingStatus;
@Schema(description = "OEM标识")
@TableField("OEM")
private String oem;
@Schema(description = "优先级")
@TableField("PRIORITY")
private Integer priority;
@Schema(description = "创建时间")
@TableField("CREATE_TIME")
private Date createTime;
@Schema(description = "工单路线ID")
@TableField("WOR_ID")
private Long worId;
@Schema(description = "审批状态")
@TableField("APPROVAL_STATUS")
private Integer approvalStatus;
@Schema(description = "报废数量")
@TableField("SCRAP_QTY")
private BigDecimal scrapQty;
@Schema(description = "外协出库")
@TableField("OEM_OUT")
private String oemOut;
@Schema(description = "外协类型")
@TableField("OEM_TYPE")
private String oemType;
@Schema(description = "返工单号")
@TableField("REWORK_CODE")
private String reworkCode;
@Schema(description = "返工顺序")
@TableField("REWORK_NO")
private Long reworkNo;
@Schema(description = "计划员")
@TableField("PLANNER")
private String planner;
@Schema(description = "调度员")
@TableField("DISPATCHER")
private String dispatcher;
@Schema(description = "打印标识")
@TableField("PRINT_FLAG")
private Integer printFlag;
@Schema(description = "下发时间")
@TableField("SEND_DOWN_TIME")
private Date sendDownTime;
@Schema(description = "打印人")
@TableField("PRINT_MAN")
private String printMan;
@Schema(description = "入库时间")
@TableField("PUT_STORE_TIME")
private Date putStoreTime;
@Schema(description = "返工备注")
@TableField("REWORK_MEMO")
private String reworkMemo;
@Schema(description = "需求日期")
@TableField("DEMAND_DATE")
private Date demandDate;
@Schema(description = "打印时间")
@TableField("PRINT_TIME")
private Date printTime;
@Schema(description = "打印编码")
@TableField("PRINT_CODE")
private String printCode;
@Schema(description = "交接时间")
@TableField("HANDOVER_TIME")
private Date handoverTime;
@Schema(description = "关闭时间")
@TableField("CLOSE_TIME")
private Date closeTime;
@Schema(description = "关闭人")
@TableField("CLOSE_MAN")
private String closeMan;
@Schema(description = "任务单ID")
@TableField("TS_ID")
private Long tsId;
@Schema(description = "OCID")
@TableField("OC_ID")
private Long ocId;
@Schema(description = "检验数量")
@TableField("TEST_QTY")
private BigDecimal testQty;
@Schema(description = "损耗数量")
@TableField("LOSS_QTY")
private BigDecimal lossQty;
@Schema(description = "镀层单定额")
@TableField("PLATE_SINGLE_QUOTA")
private BigDecimal plateSingleQuota;
@Schema(description = "推送标识")
@TableField("PUSH_FLAG")
private Integer pushFlag;
@Schema(description = "镀层物料编码")
@TableField("PLATE_GOODS_CODE")
private String plateGoodsCode;
@Schema(description = "PGRID")
@TableField("PGR_ID")
private Long pgrId;
@Schema(description = "定额异常")
@TableField("QUOTA_EXCEPTIONAL")
private Integer quotaExceptional;
@Schema(description = "MES路线卡号")
@TableField("MES_CARD_NO")
private String mesCardNo;
@Schema(description = "接收时间")
@TableField("RECEPTION_TIME")
private Date receptionTime;
@Schema(description = "出库时间")
@TableField("OUT_TIME")
private Date outTime;
@Schema(description = "协同标识")
@TableField("COLLABORATE")
private String collaborate;
@Schema(description = "最后入库时间")
@TableField("LAST_INSTORE_TIME")
private Date lastInstoreTime;
@Schema(description = "满足周期")
@TableField("MEET_CYCLE")
private BigDecimal meetCycle;
@Schema(description = "备注")
@TableField("MEMO")
private String memo;
@Schema(description = "排产状态")
@TableField("SCHED_STATUS")
private Integer schedStatus;
@Schema(description = "读取状态")
@TableField("READ_STATUS")
private Integer readStatus;
@Schema(description = "质检返工单号")
@TableField("QC_REWORK_CODE")
private String qcReworkCode;
@Schema(description = "旧运行状态")
@TableField("OLD_RUN_STATUS")
private Integer oldRunStatus;
@Schema(description = "重新入库")
@TableField("RE_IN_STORE")
private Integer reInStore;
@Schema(description = "计划开始时间")
@TableField("PLAN_START_DATE")
private Date planStartDate;
}

@ -0,0 +1,242 @@
package org.springblade.desk.logistics.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.Date;
/**
* 物流任务实体类
*
* @author: liweidong
* @create: 2026-03-03
*/
@Data
@TableName("PR_WORK_PLAN")
@Schema(description = "车间订单序号->视图")
@EqualsAndHashCode(callSuper = true)
public class PrWorkPlan extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID主键
*/
@Schema(description = "ID主键")
private Long id;
@Schema(description = "工单计划ID")
@TableField("WP_ID")
private Long wpId;
@Schema(description = "工序计划ID")
@TableField("WPP_ID")
private Long wppId;
@Schema(description = "产品ID")
@TableField("PID")
private Long pid;
@Schema(description = "排序")
@TableField("ORDERS")
private Integer orders;
@Schema(description = "是否需要检验")
@TableField("NEED_CHECK")
private Integer needCheck;
@Schema(description = "准备工时")
@TableField("PREPARE_HOUR")
private BigDecimal prepareHour;
@Schema(description = "加工工时")
@TableField("MAKE_HOUR")
private BigDecimal makeHour;
@Schema(description = "面积数量")
@TableField("AREA_QUANTITY")
private BigDecimal areaQuantity;
@Schema(description = "加工备注")
@TableField("MAKE_MEMO")
private String makeMemo;
@Schema(description = "报工工时")
@TableField("PS_HOUR")
private BigDecimal psHour;
@Schema(description = "设备ID")
@TableField("MAC_ID")
private Long macId;
@Schema(description = "外协标识")
@TableField("OEM")
private String oem;
@Schema(description = "计划开始时间")
@TableField("START_TIME")
private Date startTime;
@Schema(description = "计划结束时间")
@TableField("END_TIME")
private Date endTime;
@Schema(description = "实际开始时间")
@TableField("FACT_START_TIME")
private Date factStartTime;
@Schema(description = "实际结束时间")
@TableField("FACT_END_TIME")
private Date factEndTime;
@Schema(description = "效率")
@TableField("RATE")
private BigDecimal rate;
@Schema(description = "当前状态")
@TableField("CUR_STATUS")
private Integer curStatus;
@Schema(description = "是否锁定")
@TableField("LOCKED")
private Integer locked;
@Schema(description = "外协工单ID")
@TableField("OT_ID")
private Long otId;
@Schema(description = "报工设备")
@TableField("REC_MAC")
private String recMac;
@Schema(description = "报工时间")
@TableField("REC_TIME")
private Date recTime;
@Schema(description = "报工人")
@TableField("REC_MAN")
private String recMan;
@Schema(description = "报工状态")
@TableField("REC_STATUS")
private Integer recStatus;
@Schema(description = "报工排序")
@TableField("REC_ORDERS")
private Integer recOrders;
@Schema(description = "下单时间")
@TableField("ORDER_TIME")
private Date orderTime;
@Schema(description = "备注")
@TableField("MEMO")
private String memo;
@Schema(description = "单位工时")
@TableField("UNIT_HOUR")
private BigDecimal unitHour;
@Schema(description = "报工输出")
@TableField("REC_OUT")
private String recOut;
@Schema(description = "预览工单ID")
@TableField("PREVIEW_WP_ID")
private Long previewWpId;
@Schema(description = "下一个工单ID")
@TableField("NEXT_WP_ID")
private Long nextWpId;
@Schema(description = "计划工时")
@TableField("PLAN_TIME")
private BigDecimal planTime;
@Schema(description = "子项物料号")
@TableField("SUB_PI_NO")
private String subPiNo;
@Schema(description = "外协状态")
@TableField("OEM_STATUS")
private Integer oemStatus;
@Schema(description = "来源")
@TableField("COME_FROM")
private String comeFrom;
@Schema(description = "工作中心ID")
@TableField("WC_ID")
private Long wcId;
@Schema(description = "物料编号")
@TableField("PI_NO")
private String piNo;
@Schema(description = "创建时间")
@TableField("CREATE_TIME")
private Date createTime;
@Schema(description = "更新时间")
@TableField("UPDATE_TIME")
private Date updateTime;
@Schema(description = "旧状态")
@TableField("OLD_STATUS")
private Integer oldStatus;
@Schema(description = "检验工序")
@TableField("CHECK_PROCESS")
private Integer checkProcess;
@Schema(description = "超交数量")
@TableField("OVER_QUANTITY")
private BigDecimal overQuantity;
@Schema(description = "TOOL库工序计划ID")
@TableField("TOOL_WPP_ID")
private Long toolWppId;
@Schema(description = "实际报工工时")
@TableField("ACTURAL_PS_HOUR")
private BigDecimal acturalPsHour;
@Schema(description = "退回原因")
@TableField("BACK_REASON")
private String backReason;
@Schema(description = "是否跳过")
@TableField("SKIP")
private Integer skip;
@Schema(description = "待排标识")
@TableField("WAITING_FLAG")
private Integer waitingFlag;
@Schema(description = "待排操作人")
@TableField("WAITING_FLAG_MAN")
private String waitingFlagMan;
@Schema(description = "调整排产人")
@TableField("ADJUST_SCHEDULE_MAN")
private String adjustScheduleMan;
@Schema(description = "调整排产时间")
@TableField("ADJUST_SCHEDULE_DATE")
private Date adjustScheduleDate;
@Schema(description = "自动生产标识")
@TableField("AUTO_PRODUCTION")
private Integer autoProduction;
@Schema(description = "设备面")
@TableField("MAC_SURFACE")
private String macSurface;
}

@ -38,9 +38,14 @@ public class Station extends BaseEntity {
public static final Integer PRE_STATUS_OCCUPIED = 2; public static final Integer PRE_STATUS_OCCUPIED = 2;
/** /**
* 状态常量收发-只收 * 状态常量输送线发起
*/ */
public static final Integer RECEIVE_ONLY = 0; public static final Integer CONVEYOR_LINE_RECEIVE_ONLY = 0;
/**
* 状态常量站点发起
*/
public static final Integer STATION_RECEIVE_ONLY = 1;
/** /**
* 状态常量收发-同层 * 状态常量收发-同层
*/ */
@ -93,11 +98,11 @@ public class Station extends BaseEntity {
*/ */
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;
/** // /**
* 作业中心ID // * 作业中心ID
*/ // */
@Schema(description = "作业中心ID") // @Schema(description = "作业中心ID")
private Long wcId; // private Long wcId;
/** /**
* 站点区域 * 站点区域
*/ */

@ -0,0 +1,42 @@
package org.springblade.desk.logistics.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import java.io.Serial;
/**
* 物流站点作业中心绑定实体类
* @author: liweidong
* @create: 2026-03-03
*/
@Data
@TableName("LM_STATION_CENTER")
@Schema(description = "物流站点与作业中心绑定对象")
@EqualsAndHashCode(callSuper = true)
public class StationCenter extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID主键
*/
@Schema(description = "ID主键")
private Long id;
/**
* 作业中心ID
*/
@Schema(description = "作业中心ID")
private Long wcId;
/**
* 站点位置id
*/
@Schema(description = "站点位置")
private Long stationId;
}

@ -44,6 +44,13 @@ public class BoxbarcodeDetailsVO implements Serializable {
*/ */
@Schema(description = "订单详情数据") @Schema(description = "订单详情数据")
private List<YieldOrder> yieldOrderList; private List<YieldOrder> yieldOrderList;
/**
* 作业中心
*/
@Schema(description = "作业中心名称")
private String wcName;
@Schema(description = "区域名字")
private String stationRegion;

@ -3,10 +3,14 @@ package org.springblade.desk.logistics.pojo.vo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data @Data
@Schema(description = "wslist返回对象") @Schema(description = "wslist返回对象")
public class BsWorkCenterVO { public class BsWorkCenterVO {
private Long id; private Long id;
private String wcName; private String wcName;
private List<String> stationRegionList;
} }

@ -35,6 +35,8 @@ public class QuantityLocationVO implements Serializable {
*/ */
@Schema(description = "作业中心名字") @Schema(description = "作业中心名字")
private String wcName; private String wcName;
@Schema(description = "区域名字")
private String stationRegion;

@ -16,5 +16,6 @@ public class StationVO extends Station {
*/ */
@Schema(description = "作业中心名称") @Schema(description = "作业中心名称")
private String wcName; private String wcName;
@Schema(description = "作业中心id")
private Long wcId;
} }

@ -31,6 +31,8 @@ import org.springblade.desk.dashboard.pojo.vo.BsWorkCenterVO;
import org.springblade.desk.dashboard.excel.BsWorkCenterExcel; import org.springblade.desk.dashboard.excel.BsWorkCenterExcel;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService; import org.springblade.core.mp.base.BaseService;
import org.springblade.desk.logistics.pojo.vo.StationVO;
import java.util.List; import java.util.List;
/** /**
@ -71,5 +73,5 @@ public interface IBsWorkCenterService extends BaseService<BsWorkCenterEntity> {
*/ */
BsWorkCenterEntity selectBsWorkCenterByWcCode(String wcCode); BsWorkCenterEntity selectBsWorkCenterByWcCode(String wcCode);
List<org.springblade.desk.logistics.pojo.vo.BsWorkCenterVO> getByIds(List<Long> list); List<org.springblade.desk.logistics.pojo.vo.BsWorkCenterVO> getByIds(List<Long> list, List<StationVO> freeStationList);
} }

@ -30,12 +30,14 @@ import org.springblade.desk.dashboard.pojo.vo.BsWorkCenterVO;
import org.springblade.desk.dashboard.excel.BsWorkCenterExcel; import org.springblade.desk.dashboard.excel.BsWorkCenterExcel;
import org.springblade.desk.dashboard.mapper.BsWorkCenterMapper; import org.springblade.desk.dashboard.mapper.BsWorkCenterMapper;
import org.springblade.desk.dashboard.service.IBsWorkCenterService; import org.springblade.desk.dashboard.service.IBsWorkCenterService;
import org.springblade.desk.logistics.pojo.vo.StationVO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.mp.base.BaseServiceImpl;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* 工作中心表 服务实现类 * 工作中心表 服务实现类
@ -75,8 +77,23 @@ public class BsWorkCenterServiceImpl extends BaseServiceImpl<BsWorkCenterMapper,
} }
@Override @Override
public List<org.springblade.desk.logistics.pojo.vo.BsWorkCenterVO> getByIds(List<Long> list) { public List<org.springblade.desk.logistics.pojo.vo.BsWorkCenterVO> getByIds(List<Long> list, List<StationVO> freeStationList) {
return workCenterMapper.selectByIds(list); List<org.springblade.desk.logistics.pojo.vo.BsWorkCenterVO> bsWorkCenterVOList = workCenterMapper.selectByIds(list);
for (org.springblade.desk.logistics.pojo.vo.BsWorkCenterVO bsWorkCenterVO : bsWorkCenterVOList) {
Long id = bsWorkCenterVO.getId();
List<String> result = freeStationList.stream()
// 1. 过滤:只保留【指定字段 == 指定值】的数据(值一致才保留)
.filter(item -> item.getWcId()==id)
// 2. 提取你要的字段
.map(StationVO::getStationRegion)
// 3. 自动去重
.distinct()
// 4. 转成集合返回
.collect(Collectors.toList());
bsWorkCenterVO.setStationRegionList(result);
}
return bsWorkCenterVOList;
} }
} }

@ -83,6 +83,7 @@ public class OrderBoxController extends BladeController {
return iOrderBoxService.returnToWarehouseList(); return iOrderBoxService.returnToWarehouseList();
} }
@PostMapping("/box-binding") @PostMapping("/box-binding")
@ApiOperationSupport(order = 3) @ApiOperationSupport(order = 3)
@Operation( @Operation(

@ -0,0 +1,41 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.desk.logistics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.desk.logistics.pojo.entity.PrWorkOrder;
import org.springblade.desk.logistics.pojo.entity.WeighData;
/**
* 任务分派表 Mapper 接口
*
* @author BladeX
* @since 2025-11-12
*/
public interface PrWorkOrderMapper extends BaseMapper<PrWorkOrder> {
}

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace = "org.springblade.desk.logistics.mapper.PrWorkOrderMapper">
</mapper>

@ -0,0 +1,41 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.desk.logistics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.desk.logistics.pojo.entity.PrWorkOrder;
import org.springblade.desk.logistics.pojo.entity.PrWorkPlan;
/**
* 任务分派表 Mapper 接口
*
* @author BladeX
* @since 2025-11-12
*/
public interface PrWorkPlanMapper extends BaseMapper<PrWorkPlan> {
}

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace = "org.springblade.desk.logistics.mapper.PrWorkPlanMapper">
</mapper>

@ -0,0 +1,41 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.desk.logistics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.desk.logistics.pojo.entity.PrWorkOrder;
import org.springblade.desk.logistics.pojo.entity.StationCenter;
/**
* 任务分派表 Mapper 接口
*
* @author BladeX
* @since 2025-11-12
*/
public interface StationCenterMapper extends BaseMapper<StationCenter> {
}

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace = "org.springblade.desk.logistics.mapper.StationCenterMapper">
</mapper>

@ -3,8 +3,6 @@ package org.springblade.desk.logistics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.springblade.desk.dashboard.pojo.vo.DsTaskingVO;
import org.springblade.desk.logistics.pojo.entity.OrderBind;
import org.springblade.desk.logistics.pojo.entity.Station; import org.springblade.desk.logistics.pojo.entity.Station;
import org.springblade.desk.logistics.pojo.vo.StationVO; import org.springblade.desk.logistics.pojo.vo.StationVO;
@ -17,4 +15,6 @@ public interface StationMapper extends BaseMapper<Station> {
Station selectByStationCode(@Param("StationCode") String StationCode); Station selectByStationCode(@Param("StationCode") String StationCode);
List<StationVO> selectStationList(IPage<StationVO> page, @Param("station") Station station); List<StationVO> selectStationList(IPage<StationVO> page, @Param("station") Station station);
List<StationVO> getStatusStationList(@Param("stationStatus")Integer stationStatus, @Param("wcId")Long wcId,@Param("status")Integer status, @Param("include")boolean include);
} }

@ -16,22 +16,48 @@
</select> </select>
<select id="selectStationList" resultType="org.springblade.desk.logistics.pojo.vo.StationVO"> <select id="selectStationList" resultType="org.springblade.desk.logistics.pojo.vo.StationVO">
select id, station_name, station_code, station_status, status, create_user, create_time, create_dept, update_user, update_time, is_deleted, remark, station_position, wc_id select l.id, l.station_name, l.station_code, l.station_status, l.status, l.create_user, l.create_time, l.create_dept, l.update_user, l.update_time, l.is_deleted, l.remark, l.station_position, r.WC_ID as wcId
from LM_STATION where IS_DELETED = 0 from LM_STATION l left join LM_STATION_CENTER r on l.id = r.STATION_ID
where l.IS_DELETED = 0
<if test="station.stationName != null and station.stationName != ''"> <if test="station.stationName != null and station.stationName != ''">
and STATION_NAME = #{station.stationName} and l.STATION_NAME = #{station.stationName}
</if> </if>
<if test="station.stationCode != null and station.stationCode != ''"> <if test="station.stationCode != null and station.stationCode != ''">
and STATION_CODE = #{station.stationCode} and l.STATION_CODE = #{station.stationCode}
</if> </if>
<if test="station.stationStatus != null and station.stationStatus != ''"> <if test="station.stationStatus != null and station.stationStatus != ''">
and STATION_STATUS = #{station.stationStatus} and l.STATION_STATUS = #{station.stationStatus}
</if> </if>
<if test="station.stationPosition != null and station.stationPosition != ''"> <if test="station.stationPosition != null and station.stationPosition != ''">
and STATION_POSITION = #{station.stationPosition} and l.STATION_POSITION = #{station.stationPosition}
</if> </if>
<if test="station.wcId != null and station.wcId != ''"> <if test="station.wcId != null and station.wcId != ''">
and WC_ID = #{station.wcId} and r.WC_ID = #{station.wcId}
</if>
</select>
<select id="getStatusStationList" resultType="org.springblade.desk.logistics.pojo.vo.StationVO">
select l.*, r.WC_ID as wcId
from LM_STATION l
left join LM_STATION_CENTER r on l.id = r.STATION_ID
where l.IS_DELETED = 0
<if test="stationStatus != null and stationStatus != ''">
and l.STATION_STATUS = #{stationStatus}
</if>
<if test="wcId != null and wcId != ''">
and r.WC_ID = #{wcId}
</if>
<!-- 修正:不等于语法错误 + 格式规范 -->
<if test="status != null and status != ''">
<if test="include">
and l.STATUS = #{status}
</if>
<if test="!include">
and l.STATUS != #{status}
</if>
</if> </if>
</select> </select>
</mapper> </mapper>

@ -0,0 +1,41 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.desk.logistics.service;
import org.springblade.core.mp.base.BaseService;
import org.springblade.desk.logistics.pojo.entity.PrWorkOrder;
import org.springblade.desk.logistics.pojo.entity.WeighData;
import java.math.BigDecimal;
/**
* 车间订单 服务类
*
* @author BladeX
* @since 2025-11-12
*/
public interface IPrWorkOrderService extends BaseService<PrWorkOrder> {
}

@ -0,0 +1,39 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.desk.logistics.service;
import org.springblade.core.mp.base.BaseService;
import org.springblade.desk.logistics.pojo.entity.PrWorkOrder;
import org.springblade.desk.logistics.pojo.entity.PrWorkPlan;
/**
* 车间订单序号 服务类
*
* @author BladeX
* @since 2025-11-12
*/
public interface IPrWorkPlanService extends BaseService<PrWorkPlan> {
}

@ -0,0 +1,39 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.desk.logistics.service;
import org.springblade.core.mp.base.BaseService;
import org.springblade.desk.logistics.pojo.entity.PrWorkOrder;
import org.springblade.desk.logistics.pojo.entity.StationCenter;
/**
* 车间订单 服务类
*
* @author BladeX
* @since 2025-11-12
*/
public interface IStationCenterService extends BaseService<StationCenter> {
}

@ -28,8 +28,6 @@ package org.springblade.desk.logistics.service;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService; import org.springblade.core.mp.base.BaseService;
import org.springblade.core.tool.api.R; import org.springblade.core.tool.api.R;
import org.springblade.desk.dashboard.pojo.vo.DsTaskingVO;
import org.springblade.desk.logistics.pojo.entity.Location;
import org.springblade.desk.logistics.pojo.entity.Station; import org.springblade.desk.logistics.pojo.entity.Station;
import org.springblade.desk.logistics.pojo.vo.StationVO; import org.springblade.desk.logistics.pojo.vo.StationVO;
@ -73,4 +71,6 @@ public interface IStationService extends BaseService<Station> {
* @return * @return
*/ */
boolean updateStation(Station station); boolean updateStation(Station station);
List<StationVO> getStatusStationList(Integer stationStatus, Long wcId,Integer status, boolean include);
} }

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

@ -45,6 +45,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -81,16 +82,20 @@ public class OrderBindServiceImpl extends BaseServiceImpl<OrderBindMapper, Order
Long id = boxBindingDto.getId(); Long id = boxBindingDto.getId();
String boxBarcode = boxBindingDto.getBoxBarcode(); String boxBarcode = boxBindingDto.getBoxBarcode();
// 优化:使用StringUtils.isEmpty避免空指针,提示更精准 // 优化:使用StringUtils.isEmpty避免空指针,提示更精准
if (id == null && StringUtils.isEmpty(boxBarcode)) { if (boxBindingDto.getOrderIdList() == null && StringUtils.isEmpty(boxBarcode)) {
return R.fail("解绑失败:id和箱条码不能同时为空"); return R.fail("解绑失败:流程卡号和箱条码不能同时为空");
} }
// 2. 分场景处理解绑逻辑(优化:提取方法+减少嵌套+统一返回) // 2. 分场景处理解绑逻辑(优化:提取方法+减少嵌套+统一返回)
boolean unbindSuccess; boolean unbindSuccess = false;
if (StringUtils.isNotBlank(boxBarcode)) { if (StringUtils.isNotBlank(boxBarcode)) {
unbindSuccess = unbindByBoxBarcode(boxBarcode); unbindSuccess = unbindByBoxBarcode(boxBarcode);
} else { } else {
unbindSuccess = unbindById(id); ArrayList<String> orderIdList = boxBindingDto.getOrderIdList();
for (String s : orderIdList) {
unbindSuccess = unbindByCardNo((s));
}
} }
// 3. 统一结果返回(优化:消除冗余的if-else) // 3. 统一结果返回(优化:消除冗余的if-else)
@ -147,12 +152,13 @@ public class OrderBindServiceImpl extends BaseServiceImpl<OrderBindMapper, Order
* @param id 记录ID * @param id 记录ID
* @return 解绑是否成功 * @return 解绑是否成功
*/ */
private boolean unbindById(Long id) throws BusinessException { private boolean unbindByCardNo(String CardNo) throws BusinessException {
OrderBind orderBind = getById(id); // OrderBind orderBind = getL(id);
if (orderBind == null) { List<OrderBind> orderBindList = list(new LambdaQueryWrapper<OrderBind>().eq(OrderBind::getCardNo, CardNo).ne(OrderBind::getBindingStatus, STATUS_UNBINDED));
throw new BusinessException("解绑失败:未查询到ID为[" + id + "]的记录"); if (orderBindList == null||orderBindList.size()==0) {
throw new BusinessException("解绑失败:未查询到流程卡号为[" + CardNo + "]的记录");
} }
OrderBind orderBind = orderBindList.get(0);
// 优化:赋值逻辑 // 优化:赋值逻辑
orderBind.setBindingStatus(STATUS_UNBINDED); orderBind.setBindingStatus(STATUS_UNBINDED);
// 可选:补充更新审计字段 // 可选:补充更新审计字段

@ -0,0 +1,51 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.desk.logistics.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.desk.logistics.mapper.PrWorkOrderMapper;
import org.springblade.desk.logistics.mapper.WeighDataMapper;
import org.springblade.desk.logistics.pojo.entity.PrWorkOrder;
import org.springblade.desk.logistics.pojo.entity.WeighData;
import org.springblade.desk.logistics.service.IPrWorkOrderService;
import org.springblade.desk.logistics.service.IWeighDataService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 车间订单 服务实现类
*
* @author BladeX
* @since 2025-11-12
*/
@Service
@Slf4j
public class PrWorkOrderServiceImpl extends BaseServiceImpl<PrWorkOrderMapper, PrWorkOrder> implements IPrWorkOrderService {
}

@ -0,0 +1,46 @@
package org.springblade.desk.logistics.service.impl; /**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.desk.logistics.mapper.PrWorkPlanMapper;
import org.springblade.desk.logistics.pojo.entity.PrWorkPlan;
import org.springblade.desk.logistics.service.IPrWorkPlanService;
import org.springframework.stereotype.Service;
/**
* 车间订单 服务实现类
*
* @author BladeX
* @since 2025-11-12
*/
@Service
@Slf4j
public class PrWorkPlanServiceImpl extends BaseServiceImpl<PrWorkPlanMapper, PrWorkPlan> implements IPrWorkPlanService {
}

@ -0,0 +1,49 @@
package org.springblade.desk.logistics.service.impl; /**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.desk.logistics.mapper.PrWorkPlanMapper;
import org.springblade.desk.logistics.mapper.StationCenterMapper;
import org.springblade.desk.logistics.pojo.entity.PrWorkPlan;
import org.springblade.desk.logistics.pojo.entity.StationCenter;
import org.springblade.desk.logistics.service.IPrWorkPlanService;
import org.springblade.desk.logistics.service.IStationCenterService;
import org.springframework.stereotype.Service;
/**
* 车间订单 服务实现类
*
* @author BladeX
* @since 2025-11-12
*/
@Service
@Slf4j
public class StationCenterServiceImpl extends BaseServiceImpl<StationCenterMapper, StationCenter> implements IStationCenterService {
}

@ -33,7 +33,6 @@ import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.api.R; import org.springblade.core.tool.api.R;
import org.springblade.desk.basic.pojo.entity.WorkCenter; import org.springblade.desk.basic.pojo.entity.WorkCenter;
import org.springblade.desk.basic.service.IWorkCenterService; import org.springblade.desk.basic.service.IWorkCenterService;
import org.springblade.desk.dashboard.pojo.vo.DsTaskingVO;
import org.springblade.desk.logistics.mapper.StationMapper; import org.springblade.desk.logistics.mapper.StationMapper;
import org.springblade.desk.logistics.pojo.entity.Station; import org.springblade.desk.logistics.pojo.entity.Station;
import org.springblade.desk.logistics.pojo.vo.StationVO; import org.springblade.desk.logistics.pojo.vo.StationVO;
@ -118,4 +117,9 @@ public class StationServiceImpl extends BaseServiceImpl<StationMapper, Station>
return true; return true;
} }
@Override
public List<StationVO> getStatusStationList(Integer stationStatus, Long wcId,Integer status, boolean include) {
return baseMapper.getStatusStationList(stationStatus,wcId,status,include);
}
} }

@ -8,6 +8,7 @@ import org.springblade.desk.logistics.pojo.entity.Location;
import org.springblade.desk.logistics.pojo.entity.Station; import org.springblade.desk.logistics.pojo.entity.Station;
import org.springblade.desk.logistics.pojo.entity.Task; import org.springblade.desk.logistics.pojo.entity.Task;
import org.springblade.desk.logistics.pojo.vo.AgvSchedulingTaskVO; import org.springblade.desk.logistics.pojo.vo.AgvSchedulingTaskVO;
import org.springblade.desk.logistics.pojo.vo.StationVO;
import org.springblade.desk.logistics.service.*; import org.springblade.desk.logistics.service.*;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -67,11 +68,12 @@ public class StorageMonitoringServiceImpl implements IStorageMonitoringService {
* @param locationService 库位服务BeanSpring自动注入 * @param locationService 库位服务BeanSpring自动注入
* @param taskExecuteRecordService * @param taskExecuteRecordService
*/ */
public StorageMonitoringServiceImpl(ITaskService taskService, IStationService stationService, ILocationService locationService, ITaskExecuteRecordService taskExecuteRecordService) { public StorageMonitoringServiceImpl(ITaskService taskService, IStationService stationService, ILocationService locationService, ITaskExecuteRecordService taskExecuteRecordService, IStationCenterService stationCenterService) {
this.taskService = taskService; this.taskService = taskService;
this.stationService = stationService; this.stationService = stationService;
this.locationService = locationService; this.locationService = locationService;
this.taskExecuteRecordService = taskExecuteRecordService; this.taskExecuteRecordService = taskExecuteRecordService;
} }
/** /**
@ -94,10 +96,11 @@ public class StorageMonitoringServiceImpl implements IStorageMonitoringService {
@Override // 实现IStorageMonitoringService接口的抽象方法 @Override // 实现IStorageMonitoringService接口的抽象方法
public void monitoringStation() { public void monitoringStation() {
// ========== 步骤1:查询所有空闲状态的站点 ========== // ========== 步骤1:查询所有空闲状态的站点 ==========
List<Station> stationList = stationService.list( // List<Station> stationList = stationService.list(
new LambdaQueryWrapper<Station>() // new LambdaQueryWrapper<Station>()
.eq(Station::getStationStatus, Station.STATUS_FREE) // 筛选条件:站点状态为空闲 // .eq(Station::getStationStatus, Station.STATUS_FREE) // 筛选条件:站点状态为空闲
); // );
List<StationVO> stationList = stationService.getStatusStationList(Station.STATUS_FREE, null, null, false);
// 日志打印空闲站点数量,便于监控和问题排查 // 日志打印空闲站点数量,便于监控和问题排查
log.info("【仓储监控】定时任务执行 - 查询到空闲站点数量:{}", stationList == null ? 0 : stationList.size()); log.info("【仓储监控】定时任务执行 - 查询到空闲站点数量:{}", stationList == null ? 0 : stationList.size());
@ -110,10 +113,13 @@ public class StorageMonitoringServiceImpl implements IStorageMonitoringService {
// ========== 步骤2:遍历空闲站点处理关联任务 ========== // ========== 步骤2:遍历空闲站点处理关联任务 ==========
int processedCount = 0; // 统计成功处理的站点数量 int processedCount = 0; // 统计成功处理的站点数量
for (Station station : stationList) { ArrayList<String> stationNameList = new ArrayList<>();
for (StationVO station : stationList) {
// 打印当前处理的站点信息,便于定位单站点异常 // 打印当前处理的站点信息,便于定位单站点异常
log.info("【仓储监控】开始处理站点 - 站点ID:{},工位ID:{}", station.getId(), station.getWcId()); log.info("【仓储监控】开始处理站点 - 站点ID:{},工位ID:{}", station.getId(), station.getWcId());
if (stationNameList.contains(station.getStationCode())) {
continue;
}
try { try {
// ========== 步骤2.1:查询对应工位的待库位任务(按创建时间升序) ========== // ========== 步骤2.1:查询对应工位的待库位任务(按创建时间升序) ==========
List<Task> taskList = taskService.list( List<Task> taskList = taskService.list(
@ -211,6 +217,7 @@ public class StorageMonitoringServiceImpl implements IStorageMonitoringService {
boolean record = taskExecuteRecordService.inboundRecord(ctuSchedulingTask, firstTask,null); boolean record = taskExecuteRecordService.inboundRecord(ctuSchedulingTask, firstTask,null);
if (record){ if (record){
taskIdList.add(firstTask.getId()); taskIdList.add(firstTask.getId());
stationNameList.add(station.getStationCode());
} }

@ -83,7 +83,7 @@ public class TaskExecuteRecordServiceImpl extends BaseServiceImpl<TaskExecuteRec
* - 失败R.fail(错误信息) * - 失败R.fail(错误信息)
*/ */
@Override @Override
public R agvCallback(AGVCallBackDto agvCallBack) { public R agvCallback(AGVCallBackDto agvCallBack) {
// 记录AGV回调入参,便于问题排查 // 记录AGV回调入参,便于问题排查
log.info("agv小车接口调用参数入参:{}", agvCallBack); log.info("agv小车接口调用参数入参:{}", agvCallBack);

Loading…
Cancel
Save