Browse Source

feat:派工完善,后续增加派工时生成领料单

lumaojun 2 weeks ago
parent
commit
70eef632e6

+ 1 - 1
easydo-mes/src/main/java/easydo/technology/controller/ProductOrderDispatchController.java

@@ -55,7 +55,7 @@ public class ProductOrderDispatchController {
         if (orderId == null || orderId.trim().isEmpty()) {
             return new ResponseEntity<>("orderId 不能为空", HttpStatus.BAD_REQUEST);
         }
-        Map<String, Object> result = productOrderDispatchService.getDispatchSummary(orderId);
+        Object result = productOrderDispatchService.getDispatchSummary(orderId);
         return new ResponseEntity<>(result, HttpStatus.OK);
     }
 }

+ 14 - 3
easydo-mes/src/main/java/easydo/technology/enums/MESEnum.java

@@ -65,6 +65,7 @@ public enum MESEnum {
 
     FLOW_NO_TYPE_PRODUCT_PLAN("product_plan", "生产计划"),
     FLOW_NO_TYPE_PRODUCT_ORDER("product_order", "工单"),
+    FLOW_NO_TYPE_PRODUCT_ORDER_DISPATCH("product_order_dispatch", "派工单"),
 
     PRODUCT_PLAN_OF_STATUS_PENDING("pending", "待进行"),
     PRODUCT_PLAN_OF_STATUS_PROCESSING("processing", "进行中"),
@@ -79,11 +80,21 @@ public enum MESEnum {
     PRODUCT_ORDER_OF_PRIORITY_MEDIUM("medium", "中"),
     PRODUCT_ORDER_OF_PRIORITY_LOW("low", "低"),
 
-    PRODUCT_ORDER_DISPATCH_OF_STATUS_PENDING("pending", "待开始"),
-    PRODUCT_ORDER_DISPATCH_OF_STATUS_PROCESSING("processing", "进行中"),
-    PRODUCT_ORDER_DISPATCH_OF_STATUS_COMPLETED("completed", "已完成"),
+    // 派工单状态
+    PRODUCT_ORDER_DISPATCH_OF_STATUS_PENDING("pending", "未开始"),
+    PRODUCT_ORDER_DISPATCH_OF_STATUS_PROCESSING("processing", "生产中"),
+    PRODUCT_ORDER_DISPATCH_OF_STATUS_COMPLETED("completed", "已完工"),
     PRODUCT_ORDER_DISPATCH_OF_STATUS_REWORK("rework", "待返工"),
     
+    // 领料单状态
+    MATERIAL_REQUISITION_OF_STATUS_PENDING("pending", "未领料"),
+    MATERIAL_REQUISITION_OF_STATUS_COMPLETE("complete", "已领料"),
+    
+    // 报工单状态
+    WORK_REPORT_OF_STATUS_PENDING("pending", "未开始"),
+    WORK_REPORT_OF_STATUS_PARTIALLY("partially", "部分报工"),
+    WORK_REPORT_OF_STATUS_COMPLETE("complete", "已完工"),
+    
     PURCHASE_PLAN_OF_STATUS_PENDING("pending", "待进行"),
     PURCHASE_PLAN_OF_STATUS_PROCESSING("processing", "进行中"),
     PURCHASE_PLAN_OF_STATUS_COMPLETE("complete", "已完成"),

+ 2 - 2
easydo-mes/src/main/java/easydo/technology/model/DispatchUserItem.java

@@ -21,8 +21,8 @@ public class DispatchUserItem extends CommonModel {
     
     // 以下字段为冗余字段,方便后续扩展每个用户的派工数据
     private String orderId;
-    private String beginTime;
-    private String endTime;
+    private String beginDate;
+    private String endDate;
     private String status;
     private String routeId;
     private String bomId;

+ 2 - 0
easydo-mes/src/main/java/easydo/technology/model/ProductOrder.java

@@ -34,4 +34,6 @@ public class ProductOrder extends CommonModel {
     private List<ProductOrderBom> bomList;
     @NotTableField
     private List<ProductOrderDevice> deviceList;
+    @NotTableField
+    private Boolean canDispatch;
 }

+ 5 - 2
easydo-mes/src/main/java/easydo/technology/model/ProductOrderDispatch.java

@@ -15,9 +15,11 @@ import java.util.List;
 @Data
 public class ProductOrderDispatch extends CommonModel {
     private String id;
+    private String code;
+    private String name;
     private String orderId;
-    private String beginTime;
-    private String endTime;
+    private String beginDate;
+    private String endDate;
     private String status;
     private String routeId;
     private String bomId;
@@ -31,6 +33,7 @@ public class ProductOrderDispatch extends CommonModel {
     private Boolean isReview;
     private Boolean isReport;
     private Boolean isRound;
+    private Boolean isInspection;
     private String tenantId;
     private String createTime;
     private Long createId;

+ 4 - 3
easydo-mes/src/main/java/easydo/technology/model/vo/DispatchVO.java

@@ -10,16 +10,17 @@ import java.util.List;
 @Data
 public class DispatchVO {
     private String orderId;              // 工单ID
-    private String bomId;                // BOM ID(必填)
     private List<DispatchItem> items;    // 派工明细列表
 
     @Data
     public static class DispatchItem {
         private String id;               // 派工ID(有值=修改/删除,无值=新增)
+        private String bomId;            // BOM ID(必填)
         private String stageId;          // 工序ID
         private List<Long> userIds;      // 操作工ID列表(支持多个用户)
         private Integer orderNum;        // 派工数量
-        private String beginTime;        // 计划开始时间
-        private String endTime;          // 计划结束时间
+        private Boolean isInspection;    // 是否质检
+        private String beginDate;        // 计划开始日期
+        private String endDate;          // 计划结束日期
     }
 }

+ 14 - 35
easydo-mes/src/main/java/easydo/technology/model/vo/ProductOrderDispatchVO.java

@@ -1,5 +1,9 @@
 package easydo.technology.model.vo;
 
+import easydo.technology.model.ProcessStage;
+import easydo.technology.model.ProductBom;
+import easydo.technology.model.ProductOrder;
+import easydo.technology.model.ProductOrderBom;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -12,6 +16,8 @@ import java.util.List;
 @Data
 public class ProductOrderDispatchVO {
     private String id;
+    private String code;
+    private String name;
     private String orderId;
     private String bomId;
     private String stageId;
@@ -26,46 +32,19 @@ public class ProductOrderDispatchVO {
     private Boolean isReport;
     private Boolean isReview;
     private Boolean isRound;
-    private String beginTime;
-    private String endTime;
+    private Boolean isInspection;
+    private String beginDate;
+    private String endDate;
     private String createTime;
     private String tenantId;
     
-    // 关联对象(简化)
-    private SimpleProductOrder productOrder;
-    private SimpleProductOrderBom productOrderBom;
-    private SimpleStage stage;
+    // 关联对象(返回整表对象)
+    private ProductOrder productOrder;
+    private ProductOrderBom productOrderBom;
+    private ProductBom productBom;
+    private ProcessStage stage;
     private List<SimpleDispatchUserItem> userItems;
     
-    @Data
-    public static class SimpleProductOrder {
-        private String id;
-        private String code;
-        private String name;
-    }
-    
-    @Data
-    public static class SimpleProductOrderBom {
-        private String id;
-        private String bomId;
-        private Double number;
-        private SimpleProductBom productBom;
-    }
-    
-    @Data
-    public static class SimpleProductBom {
-        private String id;
-        private String bomCode;
-        private String materialName;
-    }
-    
-    @Data
-    public static class SimpleStage {
-        private String id;
-        private String name;
-        private String code;
-    }
-    
     @Data
     public static class SimpleDispatchUserItem {
         private String id;

+ 57 - 0
easydo-mes/src/main/java/easydo/technology/service/FlowNoService.java

@@ -39,6 +39,7 @@ public class FlowNoService {
     private final Object productPlanLock = new Object();
     private final Object purchaseOrderLock = new Object();
     private final Object productOrderLock = new Object();
+    private final Object productOrderDispatchLock = new Object();
 
 
     /**
@@ -761,6 +762,62 @@ public class FlowNoService {
         }
     }
 
+    /**
+     * 生成派工单编码 (ProductOrderDispatch) - 独立解耦实现
+     */
+    public String generateProductOrderDispatchCode(ProductOrderDispatch model, Connection connection) throws Exception {
+        synchronized (productOrderDispatchLock) {
+            String manualCode = model.getCode();
+            String tenantId = model.getTenantId();
+            if (StringUtil.isNotEmpty(manualCode)) {
+                Map<String, Object> checkMap = new HashMap<>();
+                checkMap.put("code", manualCode);
+                checkMap.put("tenantId", tenantId);
+                int count = (int) jdbcClient.getJdbcCountByMap(checkMap, ProductOrderDispatch.class, connection);
+                if (count > 0) {
+                    throw new BizException("派工单编号已存在: " + manualCode);
+                }
+                return manualCode;
+            }
+
+            while (true) {
+                FlowNo flowNo = new FlowNo();
+                flowNo.setType(MESEnum.FLOW_NO_TYPE_PRODUCT_ORDER_DISPATCH.getValue());
+                flowNo.setTenantId(tenantId);
+                flowNo = jdbcClient.getJdbcModel(flowNo, connection);
+                if (flowNo == null) throw new BizException("未配置派工单流水号规则");
+
+                String currDate = DFY_MD.format(LocalDateTime.now());
+                String currDate2 = DFY_MD_2.format(LocalDateTime.now());
+                if (StringUtil.isEmpty(flowNo.getCurrDate()) || !flowNo.getCurrDate().equals(currDate)) {
+                    flowNo.setCurrDate(currDate);
+                    flowNo.setCurrSeq(1);
+                } else {
+                    flowNo.setCurrSeq(flowNo.getCurrSeq() + 1);
+                }
+
+                String no;
+                if (StringUtil.isEmpty(flowNo.getCurrDate())) {
+                    no = (flowNo.getPrefix() != null ? flowNo.getPrefix() : "") + String.format("%06d", flowNo.getCurrSeq());
+                } else {
+                    no = (flowNo.getPrefix() != null ? flowNo.getPrefix() : "") + currDate2 + String.format("%05d", flowNo.getCurrSeq());
+                }
+                flowNo.setCurrNo(no);
+
+                Map<String, Object> updateMap = new HashMap<>();
+                updateMap.put("type", MESEnum.FLOW_NO_TYPE_PRODUCT_ORDER_DISPATCH.getValue());
+                updateMap.put("tenantId", tenantId);
+                jdbcClient.jdbcUpdate(flowNo, updateMap, connection);
+
+                Map<String, Object> checkMap = new HashMap<>();
+                checkMap.put("code", no);
+                checkMap.put("tenantId", tenantId);
+                int count = (int) jdbcClient.getJdbcCountByMap(checkMap, ProductOrderDispatch.class, connection);
+                if (count == 0) return no;
+            }
+        }
+    }
+
     /**
      * 原始流水号生成方法
      */

+ 2 - 1
easydo-mes/src/main/java/easydo/technology/service/ProductOrderDispatchService.java

@@ -2,6 +2,7 @@ package easydo.technology.service;
 
 import easydo.technology.model.vo.DispatchVO;
 
+import java.util.List;
 import java.util.Map;
 
 public interface ProductOrderDispatchService {
@@ -19,5 +20,5 @@ public interface ProductOrderDispatchService {
     /**
      * 查询工单的派工统计(每道工序已派工/未派工数量)
      */
-    Map<String, Object> getDispatchSummary(String orderId) throws Exception;
+    List<Map<String, Object>> getDispatchSummary(String orderId) throws Exception;
 }

+ 74 - 74
easydo-mes/src/main/java/easydo/technology/service/impl/ProductOrderDispatchServiceImpl.java

@@ -6,6 +6,7 @@ import easydo.technology.exception.BizException;
 import easydo.technology.model.*;
 import easydo.technology.model.vo.DispatchVO;
 import easydo.technology.model.vo.ProductOrderDispatchVO;
+import easydo.technology.service.FlowNoService;
 import easydo.technology.service.ProductOrderDispatchService;
 import easydo.technology.system.model.SysUser;
 import easydo.technology.utils.SecurityUtils;
@@ -28,6 +29,8 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
     private JdbcClient jdbcClient;
     @Resource
     private DataSource dataSource;
+    @Resource
+    private FlowNoService flowNoService;
 
     private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 
@@ -51,6 +54,8 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                 
                 // 复制主要字段
                 vo.setId(model.getId());
+                vo.setCode(model.getCode());
+                vo.setName(model.getName());
                 vo.setOrderId(model.getOrderId());
                 vo.setBomId(model.getBomId());
                 vo.setStageId(model.getStageId());
@@ -65,66 +70,54 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                 vo.setIsReport(model.getIsReport());
                 vo.setIsReview(model.getIsReview());
                 vo.setIsRound(model.getIsRound());
-                vo.setBeginTime(model.getBeginTime());
-                vo.setEndTime(model.getEndTime());
+                vo.setIsInspection(model.getIsInspection());
+                vo.setBeginDate(model.getBeginDate());
+                vo.setEndDate(model.getEndDate());
                 vo.setCreateTime(model.getCreateTime());
                 vo.setTenantId(model.getTenantId());
                 
-                // 查询并设置工单信息
+                // 查询并设置工单信息(返回整表对象)
                 if (model.getOrderId() != null) {
                     ProductOrder orderParam = new ProductOrder();
                     orderParam.setId(model.getOrderId());
                     ProductOrder order = jdbcClient.getJdbcModelById(orderParam, connection);
                     if (order != null) {
-                        ProductOrderDispatchVO.SimpleProductOrder simpleOrder = new ProductOrderDispatchVO.SimpleProductOrder();
-                        simpleOrder.setId(order.getId());
-                        simpleOrder.setCode(order.getCode());
-                        simpleOrder.setName(order.getName());
-                        vo.setProductOrder(simpleOrder);
+                        vo.setProductOrder(order);
                     }
                 }
                 
-                // 查询并设置工序信息
+                // 查询并设置工序信息(返回整表对象)
                 if (model.getStageId() != null) {
                     ProcessStage stageParam = new ProcessStage();
                     stageParam.setId(model.getStageId());
                     ProcessStage stage = jdbcClient.getJdbcModelById(stageParam, connection);
                     if (stage != null) {
-                        ProductOrderDispatchVO.SimpleStage simpleStage = new ProductOrderDispatchVO.SimpleStage();
-                        simpleStage.setId(stage.getId());
-                        simpleStage.setName(stage.getName());
-                        simpleStage.setCode(stage.getCode());
-                        vo.setStage(simpleStage);
+                        vo.setStage(stage);
                     }
                 }
                 
                 // 查询并设置 BOM 信息
                 if (model.getBomId() != null) {
-                    ProductOrderBom bomParam = new ProductOrderBom();
-                    bomParam.setId(model.getBomId());
-                    ProductOrderBom bom = jdbcClient.getJdbcModelById(bomParam, connection);
-                    
-                    if (bom != null) {
-                        ProductOrderDispatchVO.SimpleProductOrderBom simpleBom = new ProductOrderDispatchVO.SimpleProductOrderBom();
-                        simpleBom.setId(bom.getId());
-                        simpleBom.setBomId(bom.getBomId());
-                        simpleBom.setNumber(bom.getNumber());
-                        
-                        // 查询产品 BOM 信息
+                    // 注意:派工表中的 bomId 对应 product_order_bom.bom_id(产品BOM主键),不是 product_order_bom.id
+                    ProductOrderBom bomQueryParam = new ProductOrderBom();
+                    bomQueryParam.setOrderId(model.getOrderId());
+                    bomQueryParam.setBomId(model.getBomId());
+                    List<ProductOrderBom> bomList = jdbcClient.getJdbcList(bomQueryParam, connection);
+
+                    if (bomList != null && !bomList.isEmpty()) {
+                        ProductOrderBom bom = bomList.get(0);
+
+                        vo.setProductOrderBom(bom);
+
+                        // 查询产品 BOM 信息(返回整表对象)
                         if (bom.getBomId() != null) {
                             ProductBom productBomParam = new ProductBom();
                             productBomParam.setId(bom.getBomId());
                             ProductBom productBom = jdbcClient.getJdbcModelById(productBomParam, connection);
                             if (productBom != null) {
-                                ProductOrderDispatchVO.SimpleProductBom simpleProductBom = new ProductOrderDispatchVO.SimpleProductBom();
-                                simpleProductBom.setId(productBom.getId());
-                                simpleProductBom.setBomCode(productBom.getBomCode());
-                                simpleProductBom.setMaterialName(productBom.getMaterialName());
-                                simpleBom.setProductBom(simpleProductBom);
+                                vo.setProductBom(productBom);
                             }
                         }
-                        
-                        vo.setProductOrderBom(simpleBom);
                     }
                 }
                 
@@ -193,36 +186,18 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
 
             // 2. 获取租户ID
             String tenantId = order.getTenantId();
-            
-            // 3. 校验 bomId 必填
-            if (vo.getBomId() == null || vo.getBomId().isEmpty()) {
-                throw new BizException("bomId 不能为空");
-            }
-            
-            // 4. 查询 BOM 并获取 routeId
-            ProductOrderBom bomParam = new ProductOrderBom();
-            bomParam.setId(vo.getBomId());
-            ProductOrderBom bom = jdbcClient.getJdbcModelById(bomParam, connection);
-            if (bom == null) {
-                throw new BizException("BOM不存在");
-            }
-            
-            // 从 BOM 获取 routeId
-            String routeId = bom.getRouteId();
-            if (routeId == null || routeId.isEmpty()) {
-                throw new BizException("BOM 未关联工艺路线");
-            }
 
-            // 5. 按明细处理:新增 / 修改 / 删除
+            // 3. 按明细处理:新增 / 修改 / 删除
             if (vo.getItems() != null && !vo.getItems().isEmpty()) {
                 for (DispatchVO.DispatchItem item : vo.getItems()) {
                     boolean hasId = item.getId() != null && !item.getId().trim().isEmpty();
                     boolean deleteOnly = hasId
+                            && (item.getBomId() == null || item.getBomId().trim().isEmpty())
                             && (item.getStageId() == null || item.getStageId().trim().isEmpty())
                             && (item.getUserIds() == null || item.getUserIds().isEmpty())
                             && item.getOrderNum() == null
-                            && (item.getBeginTime() == null || item.getBeginTime().trim().isEmpty())
-                            && (item.getEndTime() == null || item.getEndTime().trim().isEmpty());
+                            && (item.getBeginDate() == null || item.getBeginDate().trim().isEmpty())
+                            && (item.getEndDate() == null || item.getEndDate().trim().isEmpty());
 
                     // 删除:仅传派工id
                     if (deleteOnly) {
@@ -249,6 +224,9 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                     }
 
                     // 新增/修改都需要完整基础字段
+                    if (item.getBomId() == null || item.getBomId().trim().isEmpty()) {
+                        throw new BizException("bomId 不能为空");
+                    }
                     if (item.getStageId() == null || item.getStageId().trim().isEmpty()) {
                         throw new BizException("工序不能为空");
                     }
@@ -256,6 +234,22 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                         throw new BizException("派工人员不能为空");
                     }
 
+                    // 校验 BOM 是否存在于工单中,并获取 routeId
+                    ProductOrderBom bomQueryParam = new ProductOrderBom();
+                    bomQueryParam.setOrderId(vo.getOrderId());
+                    bomQueryParam.setBomId(item.getBomId());
+                    List<ProductOrderBom> bomList = jdbcClient.getJdbcList(bomQueryParam, connection);
+                    
+                    if (bomList == null || bomList.isEmpty()) {
+                        throw new BizException("工单中不存在该BOM: " + item.getBomId());
+                    }
+                    
+                    ProductOrderBom bom = bomList.get(0);
+                    String routeId = bom.getRouteId();
+                    if (routeId == null || routeId.isEmpty()) {
+                        throw new BizException("BOM 未关联工艺路线: " + item.getBomId());
+                    }
+
                     // 校验工序是否存在
                     ProcessStage stageParam = new ProcessStage();
                     stageParam.setId(item.getStageId());
@@ -277,11 +271,12 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                         }
 
                         existDispatch.setRouteId(routeId);
-                        existDispatch.setBomId(vo.getBomId());
+                        existDispatch.setBomId(item.getBomId());
                         existDispatch.setStageId(item.getStageId());
                         existDispatch.setOrderNum(item.getOrderNum());
-                        existDispatch.setBeginTime(item.getBeginTime());
-                        existDispatch.setEndTime(item.getEndTime());
+                        existDispatch.setIsInspection(item.getIsInspection() != null ? item.getIsInspection() : false);
+                        existDispatch.setBeginDate(item.getBeginDate());
+                        existDispatch.setEndDate(item.getEndDate());
                         jdbcClient.jdbcUpdateById(existDispatch, connection);
 
                         // 子表先删后插,确保人员同步
@@ -294,11 +289,12 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                             userItem.setDispatchId(existDispatch.getId());
                             userItem.setOrderId(vo.getOrderId());
                             userItem.setUserId(userIdItem);
-                            userItem.setBomId(vo.getBomId());
+                            userItem.setRouteId(routeId);
+                            userItem.setBomId(item.getBomId());
                             userItem.setStageId(item.getStageId());
                             userItem.setOrderNum(item.getOrderNum());
-                            userItem.setBeginTime(item.getBeginTime());
-                            userItem.setEndTime(item.getEndTime());
+                            userItem.setBeginDate(item.getBeginDate());
+                            userItem.setEndDate(item.getEndDate());
                             userItem.setStatus(existDispatch.getStatus());
                             userItem.setIsReport(false);
                             userItem.setIsReview(false);
@@ -312,12 +308,16 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                         // 新增:不传派工id
                         ProductOrderDispatch dispatch = new ProductOrderDispatch();
                         dispatch.setOrderId(vo.getOrderId());
+                        dispatch.setTenantId(tenantId);
+                        String dispatchCode = flowNoService.generateProductOrderDispatchCode(dispatch, connection);
+                        dispatch.setCode(dispatchCode);
                         dispatch.setRouteId(routeId);
-                        dispatch.setBomId(vo.getBomId());
+                        dispatch.setBomId(item.getBomId());
                         dispatch.setStageId(item.getStageId());
                         dispatch.setOrderNum(item.getOrderNum());
-                        dispatch.setBeginTime(item.getBeginTime());
-                        dispatch.setEndTime(item.getEndTime());
+                        dispatch.setIsInspection(item.getIsInspection() != null ? item.getIsInspection() : false);
+                        dispatch.setBeginDate(item.getBeginDate());
+                        dispatch.setEndDate(item.getEndDate());
                         dispatch.setStatus(MESEnum.PRODUCT_ORDER_DISPATCH_OF_STATUS_PENDING.getValue());
                         dispatch.setIsReport(false);
                         dispatch.setIsReview(false);
@@ -333,11 +333,12 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                             userItem.setDispatchId(dispatch.getId());
                             userItem.setOrderId(vo.getOrderId());
                             userItem.setUserId(userIdItem);
-                            userItem.setBomId(vo.getBomId());
+                            userItem.setRouteId(routeId);
+                            userItem.setBomId(item.getBomId());
                             userItem.setStageId(item.getStageId());
                             userItem.setOrderNum(item.getOrderNum());
-                            userItem.setBeginTime(item.getBeginTime());
-                            userItem.setEndTime(item.getEndTime());
+                            userItem.setBeginDate(item.getBeginDate());
+                            userItem.setEndDate(item.getEndDate());
                             userItem.setStatus(MESEnum.PRODUCT_ORDER_DISPATCH_OF_STATUS_PENDING.getValue());
                             userItem.setIsReport(false);
                             userItem.setIsReview(false);
@@ -351,7 +352,7 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                 }
             }
 
-            // 6. 更新工单状态为进行中(如果当前是待进行状态)
+            // 4. 更新工单状态为进行中(如果当前是待进行状态)
             if (MESEnum.PRODUCT_ORDER_OF_STATUS_PENDING.getValue().equals(order.getStatus())) {
                 order.setStatus(MESEnum.PRODUCT_ORDER_OF_STATUS_PROCESSING.getValue());
                 jdbcClient.jdbcUpdateById(order, connection);
@@ -368,7 +369,7 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
     }
 
     @Override
-    public Map<String, Object> getDispatchSummary(String orderId) throws Exception {
+    public List<Map<String, Object>> getDispatchSummary(String orderId) throws Exception {
         Connection connection = dataSource.getConnection();
         try {
             // 1. 查询该工单的所有派工记录(从主表 product_order_dispatch)
@@ -385,6 +386,7 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                     
                     // 基本字段
                     dispatchInfo.put("id", dispatch.getId());
+                    dispatchInfo.put("code", dispatch.getCode());
                     dispatchInfo.put("orderId", dispatch.getOrderId());
                     dispatchInfo.put("bomId", dispatch.getBomId());
                     dispatchInfo.put("stageId", dispatch.getStageId());
@@ -399,8 +401,9 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                     dispatchInfo.put("isReport", dispatch.getIsReport());
                     dispatchInfo.put("isReview", dispatch.getIsReview());
                     dispatchInfo.put("isRound", dispatch.getIsRound());
-                    dispatchInfo.put("beginTime", dispatch.getBeginTime());
-                    dispatchInfo.put("endTime", dispatch.getEndTime());
+                    dispatchInfo.put("isInspection", dispatch.getIsInspection());
+                    dispatchInfo.put("beginDate", dispatch.getBeginDate());
+                    dispatchInfo.put("endDate", dispatch.getEndDate());
                     dispatchInfo.put("createTime", dispatch.getCreateTime());
                     
                     // 3. 查询关联的用户信息(从子表 dispatch_user_item)
@@ -427,10 +430,7 @@ public class ProductOrderDispatchServiceImpl implements ProductOrderDispatchServ
                 }
             }
             
-            Map<String, Object> result = new HashMap<>();
-            result.put("dispatches", dispatches);
-            
-            return result;
+            return dispatches;
         } catch (Exception e) {
             throw new BizException(e.getMessage());
         } finally {

+ 131 - 0
easydo-mes/src/main/java/easydo/technology/service/impl/ProductOrderServiceImpl.java

@@ -12,6 +12,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import javax.sql.DataSource;
 import java.sql.Connection;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -38,6 +39,15 @@ public class ProductOrderServiceImpl implements ProductOrderService {
                 return result;
             }
 
+            // 1.1) 收集所有工单ID,用于批量查询派工记录
+            List<String> orderIds = new ArrayList<>();
+            for (ProductOrder model : list) {
+                orderIds.add(model.getId());
+            }
+            
+            // 1.2) 批量查询所有工单的派工记录
+            Map<String, List<ProductOrderDispatch>> orderDispatchMap = batchQueryDispatchRecords(orderIds, connection);
+
             for (ProductOrder model : list) {
                 // 2) 查询并回填工单的附件
                 jdbcClient.getMinioFile(model, connection);
@@ -124,6 +134,11 @@ public class ProductOrderServiceImpl implements ProductOrderService {
                     }
                 }
                 model.setDeviceList(deviceList);
+
+                // 6) 判断是否可以派工(使用批量查询的结果)
+                List<ProductOrderDispatch> dispatchList = orderDispatchMap.get(model.getId());
+                boolean canDispatch = checkCanDispatch(model, dispatchList);
+                model.setCanDispatch(canDispatch);
             }
 
             return result;
@@ -296,4 +311,120 @@ public class ProductOrderServiceImpl implements ProductOrderService {
             connection.close();
         }
     }
+
+    /**
+     * 批量查询多个工单的派工记录
+     * 
+     * @param orderIds 工单ID列表
+     * @param connection 数据库连接
+     * @return Map<工单ID, 派工记录列表>
+     */
+    private Map<String, List<ProductOrderDispatch>> batchQueryDispatchRecords(List<String> orderIds, Connection connection) throws Exception {
+        Map<String, List<ProductOrderDispatch>> resultMap = new HashMap<>();
+        
+        if (orderIds == null || orderIds.isEmpty()) {
+            return resultMap;
+        }
+        
+        // 使用 IN 查询批量获取派工记录
+        Map<String, Object> queryMap = new HashMap<>();
+        queryMap.put("orderId_in", orderIds);
+        List<ProductOrderDispatch> allDispatches = jdbcClient.getJdbcList(queryMap, ProductOrderDispatch.class, connection);
+        
+        // 按工单ID分组
+        if (allDispatches != null) {
+            for (ProductOrderDispatch dispatch : allDispatches) {
+                String orderId = dispatch.getOrderId();
+                resultMap.computeIfAbsent(orderId, k -> new ArrayList<>()).add(dispatch);
+            }
+        }
+        
+        return resultMap;
+    }
+
+    /**
+     * 判断工单是否可以派工
+     * 
+     * @param order 工单对象
+     * @param dispatchList 该工单的派工记录列表(已批量查询)
+     * @return true-可以派工,false-不可以派工
+     */
+    private boolean checkCanDispatch(ProductOrder order, List<ProductOrderDispatch> dispatchList) {
+        // 1. 工单状态必须是待进行或进行中
+        String status = order.getStatus();
+        if (status == null || 
+            (!MESEnum.PRODUCT_ORDER_OF_STATUS_PENDING.getValue().equals(status) && 
+             !MESEnum.PRODUCT_ORDER_OF_STATUS_PROCESSING.getValue().equals(status))) {
+            return false;
+        }
+
+        // 2. 必须有 BOM 列表
+        List<ProductOrderBom> bomList = order.getBomList();
+        if (bomList == null || bomList.isEmpty()) {
+            return false;
+        }
+
+        // 3. 每个 BOM 必须关联工艺路线,且工艺路线必须有工序
+        for (ProductOrderBom bom : bomList) {
+            // 3.1 检查是否有工艺路线
+            if (bom.getRouteId() == null || bom.getRouteId().trim().isEmpty()) {
+                return false;
+            }
+
+            // 3.2 检查工艺路线是否有工序明细
+            ProcessRoute route = bom.getProcessRoute();
+            if (route == null) {
+                return false;
+            }
+
+            List<ProcessRouteDetail> detailList = route.getDetailList();
+            if (detailList == null || detailList.isEmpty()) {
+                return false;
+            }
+        }
+
+        // 4. 检查是否还有未派完工的工序
+        // 统计每个 (bomId, stageId) 组合的已派工数量
+        Map<String, Double> dispatchedQuantityMap = new HashMap<>();
+        if (dispatchList != null) {
+            for (ProductOrderDispatch dispatch : dispatchList) {
+                // 使用 bomId(product_bom 的 ID)作为 key
+                String key = dispatch.getBomId() + "_" + dispatch.getStageId();
+                double currentQty = dispatchedQuantityMap.getOrDefault(key, 0.0);
+                // orderNum 是派工数量(计划数量)
+                if (dispatch.getOrderNum() != null) {
+                    currentQty += dispatch.getOrderNum().doubleValue();
+                }
+                dispatchedQuantityMap.put(key, currentQty);
+            }
+        }
+        
+        // 检查是否存在未派完工的工序
+        for (ProductOrderBom bom : bomList) {
+            // BOM 的总数量
+            Double bomTotalQty = bom.getNumber();
+            if (bomTotalQty == null || bomTotalQty <= 0) {
+                continue;
+            }
+            
+            ProcessRoute route = bom.getProcessRoute();
+            if (route != null && route.getDetailList() != null) {
+                for (ProcessRouteDetail detail : route.getDetailList()) {
+                    if (detail.getStageId() != null) {
+                        // 使用 bomId(product_bom 的 ID)而不是 product_order_bom 的 id
+                        String key = bom.getBomId() + "_" + detail.getStageId();
+                        double dispatchedQty = dispatchedQuantityMap.getOrDefault(key, 0.0);
+                        
+                        // 使用容差比较,避免浮点数精度问题
+                        if (dispatchedQty < bomTotalQty - 0.0001) {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        
+        // 所有工序的数量都已派完,不能再派工
+        return false;
+    }
 }