24282 1 year ago
parent
commit
3d76fb1967

+ 24 - 0
sd-business/src/main/java/com/sd/business/controller/work/WorkOrderController.java

@@ -43,4 +43,28 @@ public class WorkOrderController {
         return workOrderService.detail(dto.getId());
     }
 
+    /**
+     * 聚合订单
+     */
+    @PostMapping("/scheduling")
+    public void scheduling() {
+        workOrderService.scheduling();
+    }
+
+    /**
+     * 聚合尾单
+     */
+    @PostMapping("/schedulingRemaining")
+    public void schedulingRemaining() {
+        workOrderService.schedulingRemaining();
+    }
+
+    /**
+     * 获取未排版sku规格数量
+     */
+    @PostMapping("/notSchedulingSkuNum")
+    public Integer notSchedulingSkuNum() {
+        return workOrderService.notSchedulingSkuNum();
+    }
+
 }

+ 15 - 0
sd-business/src/main/java/com/sd/business/entity/work/dto/WorkOrderSelectDto.java

@@ -14,4 +14,19 @@ import lombok.Setter;
 @Setter
 public class WorkOrderSelectDto extends BaseSelectDto {
 
+    /**
+     * 是否同步生产
+     */
+    private Integer syncProduction;
+
+    /**
+     * 主材bom规格id
+     */
+    private Long masterBomSpecId;
+
+    /**
+     * 打印纸bom规格id
+     */
+    private Long printingPaperBomSpecId;
+
 }

+ 0 - 5
sd-business/src/main/java/com/sd/business/entity/work/po/WorkOrder.java

@@ -65,9 +65,4 @@ public class WorkOrder extends BasePo {
      */
     private Integer syncProduction;
 
-    /**
-     * 是否铺满
-     */
-    private Integer integrity;
-
 }

+ 20 - 0
sd-business/src/main/java/com/sd/business/entity/work/vo/WorkOrderVo.java

@@ -14,4 +14,24 @@ import lombok.Setter;
 @Setter
 public class WorkOrderVo extends WorkOrder {
 
+    /**
+     * 主材bom规格编号
+     */
+    private String masterBomSpecCode;
+
+    /**
+     * 主材bom规格名称
+     */
+    private String masterBomSpecName;
+
+    /**
+     * 打印纸bom规格编号
+     */
+    private String printingPaperBomSpecCode;
+
+    /**
+     * 打印纸bom规格名称
+     */
+    private String printingPaperBomSpecName;
+
 }

+ 9 - 0
sd-business/src/main/java/com/sd/business/service/work/WorkOrderService.java

@@ -32,5 +32,14 @@ public interface WorkOrderService extends BaseService<WorkOrder> {
      */
     void scheduling();
 
+    /**
+     * 聚合尾单
+     */
+    void schedulingRemaining();
+
+    /**
+     * 获取未排版sku规格数量
+     */
+    Integer notSchedulingSkuNum();
 
 }

+ 219 - 170
sd-business/src/main/java/com/sd/business/service/work/impl/WorkOrderServiceImpl.java

@@ -8,6 +8,7 @@ import com.google.common.collect.HashBasedTable;
 import com.ruoyi.common.constant.StatusConstant;
 import com.ruoyi.common.core.domain.BaseIdPo;
 import com.ruoyi.common.exception.ServiceException;
+import com.sd.business.entity.bom.po.BomSpec;
 import com.sd.business.entity.order.po.OrderSku;
 import com.sd.business.entity.sku.po.SkuSpec;
 import com.sd.business.entity.work.constant.MaterialsConstant;
@@ -17,6 +18,7 @@ import com.sd.business.entity.work.po.WorkOrder;
 import com.sd.business.entity.work.po.WorkOrderDetail;
 import com.sd.business.entity.work.vo.WorkOrderVo;
 import com.sd.business.mapper.work.WorkOrderMapper;
+import com.sd.business.service.bom.BomSpecService;
 import com.sd.business.service.order.OrderSkuService;
 import com.sd.business.service.sku.SkuSpecService;
 import com.sd.business.service.work.WorkOrderDetailService;
@@ -39,8 +41,10 @@ import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 
 /**
@@ -57,6 +61,9 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
     private static final ReentrantLock schedulingLock = new ReentrantLock();
 
     @Autowired
+    private BomSpecService bomSpecService;
+
+    @Autowired
     private SkuSpecService skuSpecService;
 
     @Autowired
@@ -70,10 +77,41 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
 
         Page<WorkOrderVo> page = Sql.create(WorkOrderVo.class)
                 .selectAll(WorkOrder.class)
+
                 .from(WorkOrder.class)
+
                 .orderByDesc(WorkOrder::getId)
+                .eq(WorkOrder::getSyncProduction, dto.getSyncProduction())
+                .eq(WorkOrder::getMasterBomSpecId, dto.getMasterBomSpecId())
+                .eq(WorkOrder::getPrintingPaperBomSpecId, dto.getPrintingPaperBomSpecId())
+                .between(WorkOrder::getCreateTime, dto.getBeginTime(), dto.getEndTime())
                 .page(dto);
 
+        List<WorkOrderVo> records = page.getRecords();
+        if (records.isEmpty()) {
+            return page;
+        }
+
+        Set<Long> bomSpecIdSet = records.stream()
+                .flatMap(item -> Stream.of(item.getMasterBomSpecId(), item.getPrintingPaperBomSpecId()))
+                .collect(Collectors.toSet());
+
+        Map<Long, BomSpec> map = bomSpecService.mapKEntity(BaseIdPo::getId, q -> q.in(BaseIdPo::getId, bomSpecIdSet));
+
+        for (WorkOrderVo vo : records) {
+            BomSpec masterBomSpec = map.get(vo.getMasterBomSpecId());
+            if (masterBomSpec != null) {
+                vo.setMasterBomSpecCode(masterBomSpec.getCode());
+                vo.setMasterBomSpecName(masterBomSpec.getName());
+            }
+
+            BomSpec printingPaperBomSpec = map.get(vo.getPrintingPaperBomSpecId());
+            if (printingPaperBomSpec != null) {
+                vo.setPrintingPaperBomSpecCode(printingPaperBomSpec.getCode());
+                vo.setPrintingPaperBomSpecName(printingPaperBomSpec.getName());
+            }
+        }
+
         return page;
     }
 
@@ -93,71 +131,36 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
 
     @Override
     public void scheduling() {
-        boolean b = schedulingLock.tryLock();
-
-        if (!b) {
-            throw new ServiceException("正在排版中,请稍后刷新数据");
-        }
-
-        try {
-
-            // 查找未排版完成的订单sku
-            List<OrderSku> list = orderSkuService.list(q -> q.eq(OrderSku::getCompleteScheduling, StatusConstant.NO));
-
-            if (list.isEmpty()) {
-                return;
-            }
-
-            // 根据主材和打印纸区分订单sku
-            HashBasedTable<Long, Long, List<OrderSku>> map = HashBasedTable.create();
-            for (OrderSku orderSku : list) {
-                List<OrderSku> itemList = map.get(orderSku.getBomSpecId(), orderSku.getPrintingPaperBomSpecId());
-                if (itemList == null) {
-                    itemList = new ArrayList<>();
-                    map.put(orderSku.getBomSpecId(), orderSku.getPrintingPaperBomSpecId(), itemList);
-                }
-                itemList.add(orderSku);
-            }
+        commonScheduling(this::scheduling);
+    }
 
-            // 排版
-            for (Long bomSpecId : map.rowKeySet()) {
-                for (Long printingPaperBomSpecId : map.columnKeySet()) {
-                    List<OrderSku> orderSkuList = map.get(bomSpecId, printingPaperBomSpecId);
-                    scheduling(bomSpecId, printingPaperBomSpecId, orderSkuList);
-                }
-            }
+    @Override
+    public void schedulingRemaining() {
+        commonScheduling((bomSpecId, printingPaperBomSpecId, notFixationList, skuSpecMap) ->
+                notFixationScheduling(bomSpecId, printingPaperBomSpecId, notFixationList, skuSpecMap, false));
+    }
 
-        } catch (Exception e) {
-            log.error("排版业务发生异常", e);
-            throw new ServiceException("排版业务发生异常");
-        } finally {
-            schedulingLock.unlock();
-        }
+    @Override
+    public Integer notSchedulingSkuNum() {
+        List<OrderSku> orderSkuList = orderSkuService.list(q -> q.eq(OrderSku::getCompleteScheduling, StatusConstant.NO));
+        return orderSkuList.stream().mapToInt(item -> item.getQuantity().subtract(item.getSchedulingNum()).intValue()).sum();
     }
 
     /**
      * 排版
-     *
-     * @param bomSpecId              主材规格id
-     * @param printingPaperBomSpecId 打印纸规格id
-     * @param list                   排版列表
      */
-    private void scheduling(Long bomSpecId, Long printingPaperBomSpecId, List<OrderSku> list) {
+    private void scheduling(Long bomSpecId, Long printingPaperBomSpecId, List<OrderSku> list, Map<Long, SkuSpec> skuSpecMap) {
 
         if (ObjectUtil.isNotEmpty(list)) {
             return;
         }
 
-        // 固定排版订单
+        // 固定排版订单集合
         List<OrderSku> fixationList = new ArrayList<>();
 
-        // 不固定排版订单
+        // 不固定排版订单集合
         List<OrderSku> notFixationList = new ArrayList<>();
 
-        // 获取需要排版的sku规格
-        List<Long> skuSpecIdList = list.stream().map(OrderSku::getSkuSpecId).collect(Collectors.toList());
-        Map<Long, SkuSpec> skuSpecMap = skuSpecService.mapKEntity(BaseIdPo::getId, q -> q.in(BaseIdPo::getId, skuSpecIdList));
-
         for (OrderSku orderSku : list) {
             Long skuSpecId = orderSku.getSkuSpecId();
             SkuSpec skuSpec = skuSpecMap.get(skuSpecId);
@@ -168,24 +171,18 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
             } else {
                 notFixationList.add(orderSku);
             }
-
         }
-
         // 固定排版
-        fixationScheduling(bomSpecId, printingPaperBomSpecId, skuSpecMap, fixationList);
-
+        fixationScheduling(bomSpecId, printingPaperBomSpecId, fixationList, skuSpecMap);
         // 非固定排版
-        notFixationScheduling(bomSpecId, printingPaperBomSpecId, skuSpecMap, notFixationList);
-
+        notFixationScheduling(bomSpecId, printingPaperBomSpecId, notFixationList, skuSpecMap, true);
     }
 
     /**
      * 固定排版
      */
-    private void fixationScheduling(Long bomSpecId,
-                                    Long printingPaperBomSpecId,
-                                    Map<Long, SkuSpec> skuSpecMap,
-                                    List<OrderSku> list) {
+    private void fixationScheduling(Long bomSpecId, Long printingPaperBomSpecId,
+                                    List<OrderSku> list, Map<Long, SkuSpec> skuSpecMap) {
 
         if (ObjectUtil.isNotEmpty(list)) {
             return;
@@ -194,16 +191,7 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
         // 根据固定排版规则区分
         Map<WorkOrderFixationSpecEnum, List<OrderSku>> map = list.stream().collect(Collectors.groupingBy(
                 item -> {
-                    SkuSpec skuSpec = skuSpecMap.get(item.getSkuSpecId());
-                    if (skuSpec == null) {
-                        throw new ServiceException("未知Sku规格");
-                    }
-                    if (skuSpec.getLength() == null) {
-                        throw new ServiceException("品号为【" + skuSpec.getCode() + "】的sku未定义长度");
-                    }
-                    if (skuSpec.getWidth() == null) {
-                        throw new ServiceException("品号为【" + skuSpec.getCode() + "】的sku未定义宽度");
-                    }
+                    SkuSpec skuSpec = getAndVerifySkuSpec(item.getSkuSpecId(), skuSpecMap);
                     return WorkOrderFixationSpecEnum.getEnum(skuSpec.getLength(), skuSpec.getWidth());
                 }
         ));
@@ -213,24 +201,119 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
     }
 
     /**
+     * 固定排版
+     */
+    private void doFixationScheduling(Long bomSpecId, Long printingPaperBomSpecId,
+                                      WorkOrderFixationSpecEnum workOrderFixationSpecEnum, List<OrderSku> list) {
+
+        // 本次所需排版数量
+        int schedulingNum = workOrderFixationSpecEnum.getMaxNum();
+
+        // 未排单数量
+        int notSchedulingNum = list.stream().map(item -> item.getQuantity().subtract(item.getSchedulingNum()))
+                .reduce(BigDecimal.ZERO, BigDecimal::add).intValue();
+
+        // 如果未排版数量小于本次所需排版数量,则不排单
+        if (notSchedulingNum < schedulingNum) {
+            return;
+        }
+
+        FixationStrategy fixationStrategy = FixationFactory.get(workOrderFixationSpecEnum);
+
+        // 生产工单
+        WorkOrder workOrder = new WorkOrder();
+        workOrder.setId(IdWorker.getId());
+        workOrder.setCode(CodeEnum.WORK_ORDER_CODE.getCode());
+        workOrder.setType(1);
+        workOrder.setFixationSpec(workOrderFixationSpecEnum.getLength() + "*" + workOrderFixationSpecEnum.getWidth());
+        workOrder.setMasterBomSpecId(bomSpecId);
+        workOrder.setPrintingPaperBomSpecId(printingPaperBomSpecId);
+        workOrder.setSyncProduction(StatusConstant.NO);
+
+        // 生产工单明细
+        List<WorkOrderDetail> workOrderDetailList = new ArrayList<>();
+
+        for (OrderSku orderSku : list) {
+
+            // 此单未排版数量
+            int itemSchedulingNum = orderSku.getQuantity().subtract(orderSku.getSchedulingNum()).intValue();
+
+            // 未排排数量小于等于本次所需排版数量
+            if (itemSchedulingNum <= schedulingNum) {
+
+                // 赋值排版数量等于sku数量
+                orderSku.setSchedulingNum(orderSku.getQuantity());
+                orderSku.setCompleteScheduling(StatusConstant.YES);
+
+                for (int i = 0; i < itemSchedulingNum; i++) {
+                    addWorkOrderDetail(fixationStrategy, workOrder, workOrderDetailList, orderSku);
+                }
+
+                // 重新计算需要排版数量
+                schedulingNum -= itemSchedulingNum;
+            }
+
+            // 未排排数量大于本次所需排版数量
+            else {
+                orderSku.setSchedulingNum(orderSku.getSchedulingNum().add(new BigDecimal(schedulingNum)));
+                orderSku.setCompleteScheduling(StatusConstant.NO);
+
+                for (int i = 0; i < schedulingNum; i++) {
+                    addWorkOrderDetail(fixationStrategy, workOrder, workOrderDetailList, orderSku);
+                }
+
+                break;
+            }
+
+        }
+
+        workOrder.setSchedulingNum(fixationStrategy.getSchedulingNum());
+        workOrder.setUseRatio(fixationStrategy.getUseRatio());
+        workOrder.setMaxLength(fixationStrategy.getMaxLength());
+
+        // 保存数据
+        TransactionUtil.execute(() -> {
+            orderSkuService.updateBatchById(list);
+            save(workOrder);
+            workOrderDetailService.saveBatch(workOrderDetailList);
+        });
+
+        // 再次执行判断是否还可以排版
+        doFixationScheduling(bomSpecId, printingPaperBomSpecId, workOrderFixationSpecEnum, list);
+    }
+
+    /**
+     * 添加排版明细
+     */
+    private void addWorkOrderDetail(FixationStrategy fixationStrategy, WorkOrder workOrder,
+                                    List<WorkOrderDetail> workOrderDetailList, OrderSku orderSku) {
+        CoordinateBo coordinateBo = fixationStrategy.next();
+        WorkOrderDetail workOrderDetail = new WorkOrderDetail();
+        workOrderDetail.setWorkOrderId(workOrder.getId());
+        workOrderDetail.setOrderInfoId(orderSku.getOrderId());
+        workOrderDetail.setOrderSkuId(orderSku.getId());
+        workOrderDetail.setLength(coordinateBo.getLength());
+        workOrderDetail.setWidth(coordinateBo.getWidth());
+        workOrderDetail.setBleedingLength(coordinateBo.getBleedingLength());
+        workOrderDetail.setBleedingWidth(coordinateBo.getBleedingWidth());
+        workOrderDetail.setRotate(coordinateBo.getHasRotate() ? StatusConstant.YES : StatusConstant.NO);
+        workOrderDetail.setX(coordinateBo.getX());
+        workOrderDetail.setY(coordinateBo.getY());
+        workOrderDetailList.add(workOrderDetail);
+    }
+
+    /**
      * 非固定排版
      */
-    private void notFixationScheduling(Long bomSpecId,
-                                       Long printingPaperBomSpecId,
-                                       Map<Long, SkuSpec> skuSpecMap,
-                                       List<OrderSku> list) {
+    private void notFixationScheduling(Long bomSpecId, Long printingPaperBomSpecId, List<OrderSku> list,
+                                       Map<Long, SkuSpec> skuSpecMap, boolean carpeting) {
 
         if (ObjectUtil.isNotEmpty(list)) {
             return;
         }
 
         Item[] items = list.stream().flatMap(item -> {
-            Long skuSpecId = item.getSkuSpecId();
-            SkuSpec skuSpec = skuSpecMap.get(skuSpecId);
-            if (skuSpec == null) {
-                throw new ServiceException("未知sku规格,id:" + skuSpecId);
-            }
-
+            SkuSpec skuSpec = getAndVerifySkuSpec(item.getSkuSpecId(), skuSpecMap);
             int schedulingNum = item.getQuantity().subtract(item.getSchedulingNum()).intValue();
 
             List<Item> itemList = new ArrayList<>();
@@ -248,7 +331,7 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
         Solution solve = GA.solve(MaterialsConstant.MASTER_LENGTH, MaterialsConstant.MASTER_WIDTH, items);
 
         List<PlaceItem> placeItemList = solve.getPlaceItemList();
-        if (placeItemList.size() == list.size()) {
+        if (carpeting && placeItemList.size() == items.length) {
             return;
         }
 
@@ -265,7 +348,6 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
         workOrder.setUseRatio(BigDecimal.valueOf(solve.getUseRatio() * 100));
         workOrder.setMaxLength(BigDecimal.valueOf(solve.getMaxLength()));
         workOrder.setSyncProduction(StatusConstant.NO);
-        workOrder.setIntegrity(StatusConstant.YES);
 
         // 生产工单明细
         List<WorkOrderDetail> workOrderDetailList = placeItemList.stream().map(item -> {
@@ -273,20 +355,20 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
 
             BigDecimal schedulingNum = orderSku.getSchedulingNum().add(BigDecimal.ONE);
             orderSku.setSchedulingNum(schedulingNum);
-            if (schedulingNum.compareTo(BigDecimal.ZERO) == 0) {
+            if (schedulingNum.compareTo(orderSku.getQuantity()) == 0) {
                 orderSku.setCompleteScheduling(StatusConstant.YES);
             }
 
             WorkOrderDetail workOrderDetail = new WorkOrderDetail();
             workOrderDetail.setWorkOrderId(workOrder.getId());
             workOrderDetail.setOrderInfoId(orderSku.getOrderId());
-            workOrderDetail.setOrderSkuId(item.getId());
+            workOrderDetail.setOrderSkuId(orderSku.getId());
             workOrderDetail.setX(BigDecimal.valueOf(item.getX()));
             workOrderDetail.setY(BigDecimal.valueOf(item.getY()));
-            workOrderDetail.setBleedingLength(BigDecimal.valueOf(item.getLength()));
-            workOrderDetail.setBleedingWidth(BigDecimal.valueOf(item.getLength()));
             workOrderDetail.setLength(BigDecimal.valueOf(item.getLength() - MaterialsConstant.RESERVE));
             workOrderDetail.setWidth(BigDecimal.valueOf(item.getWidth() - MaterialsConstant.RESERVE));
+            workOrderDetail.setBleedingLength(BigDecimal.valueOf(item.getLength()));
+            workOrderDetail.setBleedingWidth(BigDecimal.valueOf(item.getLength()));
             workOrderDetail.setRotate(item.isRotate() ? StatusConstant.YES : StatusConstant.NO);
             return workOrderDetail;
         }).collect(Collectors.toList());
@@ -301,109 +383,76 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
     }
 
     /**
-     * 固定排版
+     * 公共排版方法
      */
-    private void doFixationScheduling(Long bomSpecId,
-                                      Long printingPaperBomSpecId,
-                                      WorkOrderFixationSpecEnum workOrderFixationSpecEnum,
-                                      List<OrderSku> list) {
-
-        // 本次所需排版数量
-        int schedulingNum = workOrderFixationSpecEnum.getMaxNum();
-
-        // 未排单数量
-        int notSchedulingNum = list.stream().map(item -> item.getQuantity().subtract(item.getSchedulingNum()))
-                .reduce(BigDecimal.ZERO, BigDecimal::add).intValue();
+    private void commonScheduling(CommonSchedulingFunInterface commonSchedulingFunInterface) {
+        boolean b = schedulingLock.tryLock();
 
-        // 如果未排版数量小于本次所需排版数量,则不排单
-        if (notSchedulingNum < schedulingNum) {
-            return;
+        if (!b) {
+            throw new ServiceException("正在排版中,请稍后刷新数据");
         }
 
-        FixationStrategy fixationStrategy = FixationFactory.get(workOrderFixationSpecEnum);
-
-        // 生产工单
-        WorkOrder workOrder = new WorkOrder();
-        workOrder.setId(IdWorker.getId());
-        workOrder.setCode(CodeEnum.WORK_ORDER_CODE.getCode());
-        workOrder.setType(1);
-        workOrder.setFixationSpec(workOrderFixationSpecEnum.getLength() + "*" + workOrderFixationSpecEnum.getWidth());
-        workOrder.setMasterBomSpecId(bomSpecId);
-        workOrder.setPrintingPaperBomSpecId(printingPaperBomSpecId);
-        workOrder.setSyncProduction(StatusConstant.NO);
-        workOrder.setIntegrity(StatusConstant.YES);
-
-        // 生产工单明细
-        List<WorkOrderDetail> workOrderDetailList = new ArrayList<>();
-
-        for (OrderSku orderSku : list) {
+        try {
 
-            // 此单未排版数量
-            int itemSchedulingNum = orderSku.getQuantity().subtract(orderSku.getSchedulingNum()).intValue();
+            // 查找未排版完成的订单sku
+            List<OrderSku> list = orderSkuService.list(q -> q.eq(OrderSku::getCompleteScheduling, StatusConstant.NO));
 
-            // 未排排数量小于本次所需排版数量
-            if (schedulingNum >= itemSchedulingNum) {
+            if (list.isEmpty()) {
+                return;
+            }
 
-                // 赋值排版数量等于sku数量
-                orderSku.setSchedulingNum(orderSku.getQuantity());
-                orderSku.setCompleteScheduling(StatusConstant.YES);
+            // 获取需要排版的sku规格
+            List<Long> skuSpecIdList = list.stream().map(OrderSku::getSkuSpecId).collect(Collectors.toList());
+            Map<Long, SkuSpec> skuSpecMap = skuSpecService.mapKEntity(BaseIdPo::getId, q -> q.in(BaseIdPo::getId, skuSpecIdList));
 
-                for (int i = 0; i < itemSchedulingNum; i++) {
-                    addWorkOrderDetail(fixationStrategy, workOrder, workOrderDetailList, orderSku);
+            // 根据主材和打印纸区分订单sku
+            HashBasedTable<Long, Long, List<OrderSku>> map = HashBasedTable.create();
+            for (OrderSku orderSku : list) {
+                List<OrderSku> itemList = map.get(orderSku.getBomSpecId(), orderSku.getPrintingPaperBomSpecId());
+                if (itemList == null) {
+                    itemList = new ArrayList<>();
+                    map.put(orderSku.getBomSpecId(), orderSku.getPrintingPaperBomSpecId(), itemList);
                 }
+                itemList.add(orderSku);
+            }
 
-                // 重新计算需要排版数量
-                schedulingNum -= itemSchedulingNum;
-            } else {
-                orderSku.setSchedulingNum(new BigDecimal(itemSchedulingNum - schedulingNum));
-                orderSku.setCompleteScheduling(StatusConstant.NO);
-
-                for (int i = 0; i < schedulingNum; i++) {
-                    addWorkOrderDetail(fixationStrategy, workOrder, workOrderDetailList, orderSku);
+            // 排版
+            for (Long bomSpecId : map.rowKeySet()) {
+                for (Long printingPaperBomSpecId : map.columnKeySet()) {
+                    List<OrderSku> orderSkuList = map.get(bomSpecId, printingPaperBomSpecId);
+                    commonSchedulingFunInterface.run(bomSpecId, printingPaperBomSpecId, orderSkuList, skuSpecMap);
                 }
-
-                break;
             }
 
+        } catch (Exception e) {
+            log.error("排版业务发生异常", e);
+            throw new ServiceException("排版业务发生异常");
+        } finally {
+            schedulingLock.unlock();
         }
 
-        workOrder.setSchedulingNum(fixationStrategy.getSchedulingNum());
-        workOrder.setUseRatio(fixationStrategy.getUseRatio());
-        workOrder.setMaxLength(fixationStrategy.getMaxLength());
-
-        // 保存数据
-        TransactionUtil.execute(() -> {
-            orderSkuService.updateBatchById(list);
-            save(workOrder);
-            workOrderDetailService.saveBatch(workOrderDetailList);
-        });
-
-        // 再次执行判断是否还可以排版
-        doFixationScheduling(bomSpecId, printingPaperBomSpecId, workOrderFixationSpecEnum, list);
-
     }
 
-
-    private void addWorkOrderDetail(FixationStrategy fixationStrategy, WorkOrder workOrder,
-                                    List<WorkOrderDetail> workOrderDetailList, OrderSku orderSku) {
-
-        CoordinateBo coordinateBo = fixationStrategy.next();
-
-        WorkOrderDetail workOrderDetail = new WorkOrderDetail();
-        workOrderDetail.setWorkOrderId(workOrder.getId());
-        workOrderDetail.setOrderInfoId(orderSku.getOrderId());
-        workOrderDetail.setOrderSkuId(orderSku.getId());
-
-        workOrderDetail.setLength(coordinateBo.getLength());
-        workOrderDetail.setWidth(coordinateBo.getWidth());
-        workOrderDetail.setBleedingLength(coordinateBo.getBleedingLength());
-        workOrderDetail.setBleedingWidth(coordinateBo.getBleedingWidth());
-        workOrderDetail.setRotate(coordinateBo.getHasRotate() ? StatusConstant.YES : StatusConstant.NO);
-        workOrderDetail.setX(coordinateBo.getX());
-        workOrderDetail.setY(coordinateBo.getY());
-
-        workOrderDetailList.add(workOrderDetail);
+    /**
+     * 获取并验证sku规格
+     */
+    private SkuSpec getAndVerifySkuSpec(Long skuSpecId, Map<Long, SkuSpec> skuSpecMap) {
+        SkuSpec skuSpec = skuSpecMap.get(skuSpecId);
+        if (skuSpec == null) {
+            throw new ServiceException("未知sku规格,id:" + skuSpecId);
+        }
+        if (skuSpec.getLength() == null) {
+            throw new ServiceException("品号为【" + skuSpec.getCode() + "】的sku未定义长度");
+        }
+        if (skuSpec.getWidth() == null) {
+            throw new ServiceException("品号为【" + skuSpec.getCode() + "】的sku未定义宽度");
+        }
+        return skuSpec;
     }
 
+    @FunctionalInterface
+    private interface CommonSchedulingFunInterface {
+        void run(Long bomSpecId, Long printingPaperBomSpecId, List<OrderSku> list, Map<Long, SkuSpec> skuSpecMap);
+    }
 
 }