package com.ximai.mes.pro.service.impl.proWorkOrder;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ximai.common.constant.DataConstans;
import com.ximai.common.constant.HttpStatus;
import com.ximai.common.constant.UserConstants;
import com.ximai.common.core.domain.entity.SysUser;
import com.ximai.common.exception.ServiceException;
import com.ximai.common.utils.SecurityUtils;
import com.ximai.common.utils.data.DataUtil;
import com.ximai.common.utils.data.DateUtils;
import com.ximai.common.utils.data.ExceptionUtil;
import com.ximai.common.utils.data.StringUtils;
import com.ximai.mes.constant.*;
import com.ximai.mes.face.ep.EpService;
import com.ximai.mes.md.domain.MdItem;
import com.ximai.mes.md.domain.MdProductBom;
import com.ximai.mes.md.mapper.MdItemMapper;
import com.ximai.mes.md.service.IMdBaseInfoService;
import com.ximai.mes.md.service.IMdItemService;
import com.ximai.mes.md.service.IMdProductBomService;
import com.ximai.mes.pro.domain.*;
import com.ximai.mes.pro.domain.ep.EPDtoProWorkOrder;
import com.ximai.mes.pro.domain.ep.EPDtoProWorkOrderBom;
import com.ximai.mes.pro.domain.proWorkOrder.*;
import com.ximai.mes.pro.domain.productionSolution.ProProductionSolution;
import com.ximai.mes.pro.domain.productionSolution.ProProductionSolutionProcess;
import com.ximai.mes.pro.domain.productionSolution.ProProductionSolutionProcessItem;
import com.ximai.mes.pro.domain.productionSolution.ProProductionSolutionSpecificationSheet;
import com.ximai.mes.pro.domain.sap.*;
import com.ximai.mes.pro.domain.task.*;
import com.ximai.mes.pro.domain.vo.*;
import com.ximai.mes.pro.domain.vo.proWorkOrder.*;
import com.ximai.mes.pro.mapper.ProProcessMapper;
import com.ximai.mes.pro.mapper.proWorkOrder.*;
import com.ximai.mes.pro.mapper.productionSolution.ProProductionSolutionMapper;
import com.ximai.mes.pro.mapper.productionSolution.ProProductionSolutionProcessMapper;
import com.ximai.mes.pro.mapper.task.ProTaskAssistProcessMapper;
import com.ximai.mes.pro.mapper.task.ProTaskWorkorderMapper;
import com.ximai.mes.pro.service.*;
import com.ximai.mes.pro.service.impl.task.ProPackagePrintRecordServiceImpl;
import com.ximai.mes.pro.service.proWorkOrder.*;
import com.ximai.mes.pro.service.productionSolution.IProProductionSolutionProcessService;
import com.ximai.mes.pro.service.productionSolution.IProProductionSolutionService;
import com.ximai.mes.pro.service.productionSolution.IProProductionSolutionSpecificationSheetService;
import com.ximai.mes.pro.service.task.IProPackagePrintRecordService;
import com.ximai.mes.pro.service.task.IProTaskService;
import com.ximai.mes.pro.service.task.IProTaskWorkunitService;
import com.ximai.mes.tm.domain.TmTool;
import com.ximai.mes.tm.mapper.TmToolMapper;
import com.ximai.mes.wm.domain.WmIssueHeader;
import com.ximai.mes.wm.domain.tx.WmIssueLineJoinBean;
import com.ximai.mes.wm.mapper.WmIssueHeaderMapper;
import com.ximai.mes.wm.mapper.WmIssueLineMapper;
import com.ximai.system.service.ISysDictDataService;
import com.ximai.system.service.ISysUserService;
import com.ximai.system.strategy.AutoCodeUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.ximai.common.constant.Constants.DateConstant.DATETIME_PATTERN;
import static com.ximai.common.constant.Constants.DateConstant.YYYY_MM_DD;
import static com.ximai.common.utils.data.DataUtil.getNormalData;
import static com.ximai.mes.constant.TaskStatusEnum.FINISHED;
import static com.ximai.mes.util.BusinessUtil.getTheStandardTime;

/**
 * 生产工单Service业务层处理
 *
 * @date 2022-05-09
 */
@Slf4j
@Data
@Service
public class ProWorkorderServiceImpl implements IProWorkorderService {


    @Autowired
    private EpService epService;

    @Autowired
    private MdItemMapper mdItemMapper;

    @Autowired
    private ProWorkorderMapper proWorkorderMapper;

    @Autowired
    private IProWorkorderService proWorkorderService;

    @Autowired
    private ProProductionSolutionProcessMapper solutionProcessMapper;

    @Autowired
    private ProWorkOrderBomMapper proWorkOrderBomMapper;

    @Autowired
    private IProWorkOrderBomService proWorkOrderBomService;

    @Autowired
    private IProWorkOrderProcessService proWorkOrderProcessService;
    @Resource
    private ProProcessMapper proProcessMapper;
    @Autowired
    private ProWorkOrderProcessMapper proWorkOrderProcessMapper;

    @Autowired
    private ProWorkOrderProcessItemMapper proWorkOrderProcessItemMapper;
    @Resource
    private ProTaskAssistProcessMapper taskAssistProcessMapper;
    @Autowired
    private IProWorkOrderProcessItemService proWorkOrderProcessItemService;

    @Autowired
    private AutoCodeUtil autoCodeUtil;

    @Autowired
    private ProWorkOrderProcessQcindexMapper proWorkOrderProcessQcindexMapper;


    @Autowired
    private IProWorkOrderProcessQcindexService proWorkOrderProcessQcindexService;

    @Autowired
    private ProWorkOrderProcessToolMapper proWorkOrderProcessToolMapper;

    @Autowired
    private IProWorkOrderProcessToolService proWorkOrderProcessToolService;

    @Autowired
    private ProWorkOrderSoDirectiveMapper proWorkOrderSoDirectiveMapper;

    @Autowired
    private ProWorkOrderSoSizeItemMapper proWorkOrderSoSizeItemMapper;

    @Autowired
    private IProWorkOrderSoSizeItemService proWorkOrderSoSizeItemService;

    @Autowired
    private IMdBaseInfoService mdBaseInfoService;

    @Autowired
    private TmToolMapper tmToolMapper;

    @Autowired
    private IProTaskService proTaskService;

    @Autowired
    private ProTaskWorkorderMapper proTaskWorkorderMapper;

    @Autowired
    private ISysDictDataService dictDataService;
    @Resource
    private WmIssueHeaderMapper wmIssueHeaderMapper;

    @Autowired
    private IProMaterialRequestService proMaterialRequestService;

    @Autowired
    private IProTaskWorkunitService proTaskWorkunitService;

    @Autowired
    private IProFeedbackService proFeedbackService;


    @Resource
    private ProTaskAssistProcessMapper proTaskAssistProcessMapper;
    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private IMdProductBomService mdProductBomService;

    @Autowired
    private IProMaterialReturnService proMaterialReturnService;

    @Autowired
    private WmIssueLineMapper wmIssueLineMapper;

    @Autowired
    private IProCombinationService proCombinationService;

    @Autowired
    private IProArrangeService proArrangeService;

    @Autowired
    private ProProductionSolutionMapper proProductionSolutionMapper;

    @Autowired
    private IProWorkOrderChangeRecordService proWorkOrderChangeRecordService;

    @Autowired
    private IProProductionSolutionService proProductionSolutionService;


    @Autowired
    private IProProductionSolutionProcessService proProductionSolutionProcessService;

    @Autowired
    private IProProductionSolutionSpecificationSheetService specificationSheetService;

    @Autowired
    private IProWorkOrderSoDirectiveService proWorkOrderSoDirectiveService;

    @Autowired
    private IProPackagePrintRecordService proFdPackagePrintRecordService;

    @Autowired
    private IMdItemService mdItemService;

    @Autowired
    private IProWorkOrderArrangeRuleValService proWorkOrderArrangeRuleValService;

    @Autowired
    private IProScheduleSetupRuleValService proScheduleSetupRuleValService;

    public static String printDateFormat(Date date) {
        if (date == null) {
            return null;
        }
        return DateUtils.parseDateToStr(YYYY_MM_DD, date);
    }

    private static String buildLabelQrcode(String prefix, String orderNo, String itemCode, Integer packNum, Integer index) {
        String product = StringUtils.leftPad(itemCode.replaceFirst("0*", ""), 10, '0');
        String workorder = StringUtils.leftPad(orderNo, 12, '0');
        String indexStr = StringUtils.leftPad(index + "", 3, '0');
        return prefix + product + workorder + indexStr;
    }

    //合并相同分组数据
    private static List<WorkorderPackage.QuantityDistribute> merge(List<WorkorderPackage.QuantityDistribute> distributeList) {
        List<WorkorderPackage.QuantityDistribute> rst = new ArrayList<WorkorderPackage.QuantityDistribute>();
        distributeList.forEach(s -> {
            Optional<WorkorderPackage.QuantityDistribute> temp = rst.stream().filter(s2 -> {
                return ObjectUtil.equals(s.getDirectiveId(), s2.getDirectiveId()) && ObjectUtil.equals(s.getSizeId(), s2.getSizeId());
            }).findFirst();
            if (temp.isPresent()) {
                temp.get().setPackageNum(temp.get().getPackageNum() + s.getPackageNum());
                temp.get().setLossNum(temp.get().getLossNum() + s.getLossNum());
            } else {
                rst.add(s);
            }
        });
        return rst;
    }

    /**
     * 计算包装标签
     *
     * @param quantity             总数量
     * @param packageNum           包装数量
     * @param lossNum              loss数量
     * @param lossIndividuallyWrap loos是否独立包装
     * @return 包装标签
     */
    private static List<WorkorderPackage> splitPackage(Integer quantity, Integer packageNum, Integer lossNum, boolean lossIndividuallyWrap) {
        List<WorkorderPackage> rst = new ArrayList<WorkorderPackage>();
        int sheet = 0;
        if (lossIndividuallyWrap) {
            sheet = (int) Math.ceil((double) (quantity - lossNum) / packageNum);
        } else {
            sheet = (int) Math.ceil((double) quantity / packageNum);
        }
        int sheet2 = (quantity - lossNum) / packageNum;
        int sheet3 = (int) Math.ceil((double) (quantity - lossNum) / packageNum);
        for (int i = 1; i <= sheet; i++) {
            WorkorderPackage workorderPackage = new WorkorderPackage();
            workorderPackage.setSheetCount(i);
            workorderPackage.setTotalCount(sheet);
            if (sheet != sheet2 && sheet2 + 1 == i) {//分页借用了LOSS数量
                Integer tempPackageNum = packageNum;
                if (i == sheet && quantity % packageNum != 0) {
                    tempPackageNum = quantity % packageNum;
                }
                int needLossNum = tempPackageNum - (quantity - lossNum) % packageNum;
                workorderPackage.setPackageNum(tempPackageNum - needLossNum);
                workorderPackage.setLossNum(needLossNum);
                lossNum = lossNum - needLossNum;
            } else {
                workorderPackage.setPackageNum(packageNum);
            }
            //如果为最后一页=工单|指令|SIZE数量%装箱数
            if (i == sheet) {
                //LOSS不是单独包装，最后一页拆分LOSS数
                if (lossIndividuallyWrap) {
                    workorderPackage.setLossNum(0);
                } else {
                    if (sheet3 != sheet) {
                        workorderPackage.setPackageNum(0);
                    }
                    if (workorderPackage.getLossNum() == null || workorderPackage.getLossNum() == 0) {
                        workorderPackage.setLossNum(lossNum);
                    }
                }
            }
            rst.add(workorderPackage);
        }
        return rst;
    }

    private static List<WorkorderPackage> splitPackage(List<PackageBasicData> list, boolean mergePack, PackageType packageType) {
        List<WorkorderPackage> rst = new ArrayList<WorkorderPackage>();
        //指令包装不合并LOSS数量
        boolean mergeLoss = packageType != PackageType.DIRECTIVE;
        if (packageType == PackageType.DIRECTIVE && mergePack) {
            throw new ServiceException("按指令包装不允许合并包装");
        }
        List<PackageBasicResult> tempList = ProWorkorderServiceImpl.splitPackageBasic(list, mergeLoss, mergePack);
        for (int i = 1; i <= tempList.size(); i++) {
            PackageBasicResult temp = tempList.get(i - 1);
            WorkorderPackage workorderPackage = new WorkorderPackage();
            workorderPackage.setTotalCount(tempList.size());
            workorderPackage.setSheetCount(i);
            workorderPackage.setPackageNum(temp.getPackageNum());
            workorderPackage.setLossNum(temp.getLossNum());
            if (temp.getDistributes().size() == 1) {
                if (packageType == PackageType.DIRECTIVE) {
                    workorderPackage.setWorkorderSoDirectiveId(temp.getDistributes().get(0).getId());
                } else if (packageType == PackageType.SIZE) {
                    workorderPackage.setWorkorderSoSizeItemId(temp.getDistributes().get(0).getId());
                }
            } else {
                List<WorkorderPackage.QuantityDistribute> distributes = new ArrayList<WorkorderPackage.QuantityDistribute>();
                workorderPackage.setDistributes(distributes);
                temp.getDistributes().forEach(s -> {
                    WorkorderPackage.QuantityDistribute tempDistribute = new WorkorderPackage.QuantityDistribute(packageType == PackageType.DIRECTIVE ? s.getId() : null, packageType == PackageType.SIZE ? s.getId() : null, s.getPackageNum(), s.getLossNum());
                    distributes.add(tempDistribute);
                });
            }
            rst.add(workorderPackage);
        }
        return rst;
    }

    /**
     * 基础拆分包装数量
     *
     * @param list      包装数据源
     * @param mergeLoss 是否合并包装LOSS数量
     * @param mergePack 是否合并包装
     *                  如果为合并包装，每组包装数量必须一致，取默认第一组包装数量
     * @return
     */
    private static List<PackageBasicResult> splitPackageBasic(List<PackageBasicData> list, boolean mergeLoss, boolean mergePack) {
        List<PackageBasicResult> rst = new ArrayList<PackageBasicResult>();
        //独立包装数据记录
        PackageBasicResult individuallyWrap = new PackageBasicResult();
        PackageBasicResult tempPackage = new PackageBasicResult();
        int tempPackageNum = list.get(0).getPackageNum();//混合包装默认第一包包装数量
        for (PackageBasicData basicData : list) {
            if (!mergePack) {
                tempPackageNum = basicData.getPackageNum();
            }
            boolean lossIndividuallyWrap = basicData.isLossIndividuallyWrap();
            int tempBasicNum = basicData.getQuantity() - basicData.getLossNum();
            int tempBasicLossNum = basicData.getLossNum();
            if (lossIndividuallyWrap) {
                if (basicData.getLossNum() > 0) {
                    if (mergeLoss) {
                        individuallyWrap.getDistributes().add(new PackageBasicResult.QuantityDistribute(basicData.getId(), 0, basicData.getLossNum()));
                    }
                }
                tempBasicLossNum = 0;
            }
            while (true) {
                int remainNum = tempPackageNum - tempBasicNum;
                if (remainNum >= 0) {//包装数量耗尽
                    int lossRemainNum = remainNum - tempBasicLossNum;
                    int lossUseNum = remainNum;
                    remainNum = lossRemainNum;
                    if (remainNum >= 0) {//LOSS数耗尽
                        tempPackageNum = remainNum;
                        tempPackage.getDistributes().add(new PackageBasicResult.QuantityDistribute(basicData.getId(), tempBasicNum, tempBasicLossNum));
                    } else {
                        tempPackageNum = 0;
                        tempPackage.getDistributes().add(new PackageBasicResult.QuantityDistribute(basicData.getId(), tempBasicNum, lossUseNum));
                    }
                    //不是混合包添加到结果
                    if (!mergePack || tempPackageNum <= 0) {
                        tempPackage.copyAppend(rst);
                        tempPackageNum = basicData.getPackageNum();//复原包装数量
                    }
                    //判断是否添加LOSS包装
                    if (lossIndividuallyWrap) {
                        if (basicData.getLossNum() > 0) {
                            if (!mergeLoss) {
                                tempPackage.getDistributes().add(new PackageBasicResult.QuantityDistribute(basicData.getId(), 0, basicData.getLossNum()));
                                tempPackage.copyAppend(rst);
                            }
                        }
                    }

                    if (remainNum < 0) {
                        if (mergePack) {
                            tempPackageNum = tempPackageNum - Math.abs(lossRemainNum);
                        }
                        tempPackage.getDistributes().add(new PackageBasicResult.QuantityDistribute(basicData.getId(), 0, Math.abs(lossRemainNum)));
                        if (!mergePack) {
                            tempPackage.copyAppend(rst);
                        }
                    }
                    break;
                } else if (remainNum < 0) {//单批足包
                    tempPackage.getDistributes().add(new PackageBasicResult.QuantityDistribute(basicData.getId(), tempPackageNum, 0));
                    tempBasicNum = Math.abs(remainNum);
                    tempPackageNum = basicData.getPackageNum();//复原包装数量
                    tempPackage.copyAppend(rst);
                }
            }
        }
        if (tempPackage.getDistributes().size() > 0) {
            tempPackage.copyAppend(rst);
        }
        if (individuallyWrap.getDistributes().size() > 0) {
            individuallyWrap.copyAppend(rst);
        }
        //合并明细数量
        rst.forEach(s -> {
            if (s.getDistributes().size() == 1) {
                s.setPackageNum(s.getDistributes().get(0).getPackageNum());
                s.setLossNum(s.getDistributes().get(0).getLossNum());
            } else {
                s.setPackageNum(s.getDistributes().stream().mapToInt(s2 -> s2.getPackageNum()).sum());
                s.setLossNum(s.getDistributes().stream().mapToInt(s2 -> s2.getLossNum()).sum());
            }
        });
        return rst;
    }

    @Override
    public Map<Object, Object> quantityWaitSum(Map<String, String> map) {
        String workorderCode = map.get("workorderCode");
        String taskWorkunitId = map.get("taskWorkunitId");

        List<ProWorkorder> proWorkorders = new ArrayList<>();
        if (StringUtils.isNotEmpty(workorderCode)) {
            proWorkorders = proWorkorderMapper.selectListByQw(new QueryWrapper<ProWorkorder>().eq("workorder_code", workorderCode));
        } else {
            List<Long> ids = proWorkorderMapper.selectIdsByQw(new QueryWrapper<ProWorkorder>().eq("task_workunit_id", taskWorkunitId));
            proWorkorders = proWorkorderMapper.selectListByQw(new QueryWrapper<ProWorkorder>().in("workorder_id", ids));
        }

        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(proWorkorders), "未匹配到数据");

        Double v = 0d;
        BigDecimal quantity = BigDecimal.ZERO;
        BigDecimal subtract = BigDecimal.ZERO;

        if (proWorkorders.size() > 1) {
            DoubleSummaryStatistics sum = proWorkorders.stream().map(x -> getNormalData(x.getQuantity()).doubleValue()).collect(Collectors.summarizingDouble(x -> x));
            v = proFeedbackService.selectQuantityQualifySum(new ProFeedback(null, null, null, Long.parseLong(taskWorkunitId)));
            quantity = BigDecimal.valueOf(sum.getSum());
            subtract = quantity.subtract(BigDecimal.valueOf(v));
        } else if (proWorkorders.size() == 1) {
            ProWorkorder proWorkorder = proWorkorders.get(0);
            v = proFeedbackService.selectQuantityQualifySum(new ProFeedback(null, proWorkorder.getWorkorderId(), null, Long.parseLong(taskWorkunitId)));
            quantity = proWorkorder.getQuantity();
            subtract = quantity.subtract(BigDecimal.valueOf(v));
        }
//
//        List<Long> workorderIds = proWorkorders.stream().map(ProWorkorder::getWorkorderId).collect(Collectors.toList());
//        List<ProTaskAssistProcess> proTaskAssistProcesses = proTaskAssistProcessMapper.selectListByQw(new QueryWrapper<ProTaskAssistProcess>().in("workorder_id", workorderIds));
//        if (CollectionUtil.isNotEmpty(proTaskAssistProcesses)) {
//            DoubleSummaryStatistics collect = proTaskAssistProcesses.stream().map(x -> getNormalData(x.getQuantity()).doubleValue()).collect(Collectors.summarizingDouble(x -> x));
//            subtract = quantity.subtract(BigDecimal.valueOf(collect.getSum()));
//        }

//        {
//  "code": 200,
//  "msg": "操作成功",
//  "data":{
//    "workorderFeedbackSum":  6.0,
//    "workorderUnfeedbackSum":  6.0,
//    "workorderQualify":  6.0,
//    "workorderUnQualify":  6.0
//  }
//}

        Map<Object, Object> hashMap = new HashMap<>();
        hashMap.put("workorderFeedbackSum", v);
        hashMap.put("workorderUnfeedbackSum", subtract);
        hashMap.put("workorderQualify", v);
        // 是否超报工
        if (subtract.doubleValue() < 0) {
            hashMap.put("overFeedback", 1);
        } else {
            hashMap.put("overFeedback", 0);
        }
        hashMap.put("workorderUnQualify", "");
        return hashMap;
    }

    @Override
    public int updateObject(ProWorkorderVo proWorkorderVo) {
        if (Objects.equals(proWorkorderVo.getStatus(), WorkorderStatusEnum.CLOSE.getValue())) {
            ProWorkorder proWorkorder = proWorkorderVo.deepCopyObj(ProWorkorder.class);
            return this.clossAndDeleteObjV2(proWorkorder);
        } else {
            Long workorderId = proWorkorderVo.getWorkorderId();
            ProWorkorderVo workorder = proWorkorderService.selectProWorkorderByWorkorderId(workorderId);
            int ret = proWorkorderService.updateProWorkorderWithBomAndProcess(proWorkorderVo);

            //判断bom和工序是否有主键id，有则修改，无则新增
            //如果是产品和数量发生变化则需要重新生成BOM组成
            if (ret > 0) {
                if (workorder.getProductId().longValue() != proWorkorderVo.getProductId().longValue() || workorder.getQuantity().compareTo(proWorkorderVo.getQuantity()) != 0) {
                    proWorkorderService.generateBomLine(workorderId);
                }
            }
            return ret;
        }

    }

    @Override
    public List<ProWorkorderVo> getFeedBackRecord(ProWorkorderQuery proWorkorder) {
        List<ProWorkorder> proWorkorders = proWorkorderMapper.selectListByQw(new QueryWrapper<ProWorkorder>().eq("arrange_code", proWorkorder.getArrangeCode()));
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(proWorkorders), "没有查询到对应的工单");


        List<ProWorkorderVo> rst = new ArrayList<>();
        proWorkorders.forEach(workorder -> {
            ProWorkorderVo workorderVo = workorder.deepCopyObj(ProWorkorderVo.class);

            ProWorkOrderSoDirective queryDirective = new ProWorkOrderSoDirective();
            queryDirective.setWorkorderId(workorder.getWorkorderId());
            List<ProWorkOrderSoDirective> directiveList = proWorkOrderSoDirectiveService.selectProWorkOrderSoDirectiveList(queryDirective);
            workorderVo.setSaleDirectiveList(directiveList);
            if(!directiveList.isEmpty()){
                workorderVo.setLossIndividuallyWrap(StringUtils.defaultString(directiveList.get(0).getLossPack(), "N"));
                workorderVo.setPackType(directiveList.get(0).getPackType());
                workorderVo.setPackUnitOfMeasure(directiveList.get(0).getPackUnit());
            }
            //装箱数量默认取指令数据，多条时取随机取一条
            if (workorder.getUsageEncasementNum() == null && directiveList.size() > 0) {
                ProWorkOrderSoDirective directive = directiveList.get(0);
                if (directive != null) {
                    if (NumberUtil.isNumber(directive.getPackingNum())) {
                        workorderVo.setUsageEncasementNum(new BigDecimal(directive.getPackingNum()).intValue());
                    }
                }
            }

            if (CollectionUtil.isNotEmpty(directiveList) && directiveList.size() == 1) {
                if (directiveList.get(0).getPackNum() != null && workorder.getUsagePackNum() == null) {
                    workorderVo.setUsagePackNum(directiveList.get(0).getPackNum().intValue());
                }
            }

            Double v = proFeedbackService.selectQuantityQualifySum(new ProFeedback(null, workorderVo.getWorkorderId(), null, null));

            double val = workorderVo.getQuantity().doubleValue() - v;
            workorderVo.setQuantityWait(BigDecimal.valueOf(val < 0 ? 0 : val));
            rst.add(workorderVo);
        });


        ProProductionSolutionProcessVo processVo = solutionProcessMapper.selectObjByTwIdAndPIdAndWoId(proWorkorder.getTaskWorkunitId(), proWorkorder.getProcessId());

        if (processVo != null) {
            for (ProWorkorderVo proWorkorderVo : rst) {
                proWorkorderVo.setUnitOfConvert(processVo.getUnitConvert() == null || processVo.getUnitConvert().doubleValue() == 0 ? "1" : processVo.getUnitConvert().toString());
            }
        }
        return rst;
    }


    @Transactional
    @Override
    public void proofMakeProduction(WorkorderProofMakeProduction workorderProofMakeProduction) {
        //工单状态更新
        ProWorkorder proWorkorder = proWorkorderService.selectWorkorderById(workorderProofMakeProduction.getWorkorderId());
        proWorkorder.setStatus(WorkorderStatusEnum.SCHEDULED.getValue());
        proWorkorderService.updateProWorkorder(proWorkorder);

        BigDecimal quantity = proWorkorder.getQuantity();
        Long workorderId = proWorkorder.getWorkorderId();
        // 获取工序列表
        QueryWrapper<ProWorkOrderProcessVo> query = new QueryWrapper<>();
        query.eq("pwop.workorder_id", workorderId);
        List<ProWorkOrderProcessVo> proWorkOrderProcessVoList = proWorkOrderProcessMapper.selectProWorkOrderProcess(query);
        //保存编排单号
        String arrangeCode = autoCodeUtil.genSerialCode(UserConstants.ARRANGE_CODE, null);
        ProArrange proArrange = new ProArrange();
        proArrange.setWorkorderCode(proWorkorder.getWorkorderCode());
        proArrange.setWorkorderId(proWorkorder.getWorkorderId());
        proArrange.setArrangeCode(arrangeCode);
        proArrange.setArrangeSort(1);
        proArrangeService.insertProArrange(proArrange);

        //保存组合单号
        String combinationCode = autoCodeUtil.genSerialCode(UserConstants.COMBINATION_CODE, "");
        ProCombination proCombination = new ProCombination();
        proCombination.setWorkorderCode(proWorkorder.getWorkorderCode());
        proCombination.setWorkorderId(proWorkorder.getWorkorderId());
        proCombination.setCombinationCode(combinationCode);
        proCombination.setCombinationSort(1L);
        proCombinationService.insertProCombination(proCombination);
        // 根据工序创建任务单
        int i = 1;
        for (ProWorkOrderProcessVo proWorkOrderProcessVo : proWorkOrderProcessVoList) {
            WorkorderProofMakeProduction.WorkorderProofMakeProductionProcess proofMakeProductionProcess = workorderProofMakeProduction.getProcessData().stream().filter(s -> s.getWorkorderProcessId().equals(proWorkOrderProcessVo.getWorkorderProcessId())).findFirst().get();
            // 验证工序
            ProProcess proProcess = proProcessMapper.selectProProcessByProcessId(proWorkOrderProcessVo.getProcessId());
            if (proProcess == null) {
                throw new ServiceException("未找到工序基础信息");
            }
            ProTask proTask = new ProTask();
            // 封装
            proTask.setWorkstationId(proWorkOrderProcessVo.getWorkstationId());
            proTask.setProcessId(proWorkOrderProcessVo.getProcessId());
            proTask.setItemId(proWorkorder.getProductId());
            proTask.setSpecification(proWorkorder.getProductSpc());
            proTask.setUnitOfMeasure(proWorkorder.getUnitOfMeasure());
            proTask.setQuantity(quantity);
            proTask.setOrdinal(i);
            //首工序，待加工数等于排产数
            if (i == 1) {
                proTask.setQuantityWait(quantity);
            } else {
                proTask.setQuantityWait(BigDecimal.ZERO);
            }

            //末道工序
            if (i == proWorkOrderProcessVoList.size()) {
                proTask.setIsLastProcess(1);
            } else {
                proTask.setIsLastProcess(0);
            }
            proTask.setColorCode(proWorkOrderProcessVo.getColorCode());
            proTask.setStatus(TaskStatusEnum.PREPARE.getStatus()); // 设置状态为草稿(待确认)
            proTask.setArrangeCode(arrangeCode);
            proTask.setTaskBatch(arrangeCode + "-001");
            // 保存工序任务
            proTaskService.insertProTask(proTask);
            Long taskId = proTask.getTaskId();

            // 保存到合并表
            ProTaskWorkorder proTaskWorkorder = new ProTaskWorkorder();
            proTaskWorkorder.setTaskId(taskId);
            proTaskWorkorder.setIdx((long) i);
            proTaskWorkorder.setWorkorderId(proWorkorder.getWorkorderId());
            proTaskWorkorderMapper.insertProTaskWorkorder(proTaskWorkorder);
            ProTaskVo proTaskVo = new ProTaskVo();
            BeanUtil.copyProperties(proTask, proTaskVo);
            proTaskVo.setStartTime(proofMakeProductionProcess.getScheduleStartTime());
            proTaskVo.setEndTime(proofMakeProductionProcess.getScheduleEndTime());
            proTaskVo.setWorkunitId(proofMakeProductionProcess.getWorkunitId());
            //保存派工表
            proTaskService.manualSchedule(proTaskVo);
            i++;
        }

        //生成编排单号
        ProWorkorder proWorkorderUpdate = new ProWorkorder();
        proWorkorderUpdate.setStatus(WorkorderStatusEnum.ISSUED.getValue());
        proWorkorderUpdate.setArrangeCode(arrangeCode);
        proWorkorderUpdate.setCombinationCode(combinationCode);
        proWorkorderUpdate.setWorkorderId(workorderId);
        proWorkorderMapper.updateProWorkorder(proWorkorderUpdate);
    }


    @Override
    public int closeObj(ProWorkorder proWorkorder) {
        QueryWrapper<ProWorkorder> proWorkorderQueryWrapper = new QueryWrapper<>();
        proWorkorderQueryWrapper.eq(StringUtils.isNotEmpty(proWorkorder.getArrangeCode()), "t1.arrange_code", proWorkorder.getArrangeCode());
        proWorkorderQueryWrapper.eq(StringUtils.isNotEmpty(proWorkorder.getWorkorderId()), "t1.workorder_id", proWorkorder.getWorkorderId());
        proWorkorderQueryWrapper.eq(StringUtils.isNotEmpty(proWorkorder.getWorkorderCode()), "t1.workorder_code", proWorkorder.getWorkorderCode());
        List<ProWorkorder> proWorkorders = proWorkorderMapper.selectListByQw(proWorkorderQueryWrapper);
        Optional<ProWorkorder> first = proWorkorders.stream().filter(x -> !Objects.equals(x.getStatus(), WorkorderStatusEnum.CLOSE.getValue()) || !Objects.equals(x.getStatus(), WorkorderStatusEnum.FINISHED.getValue())).findFirst();
        ExceptionUtil.checkTrueThrowException(!first.isPresent(), "需要关闭的工单,已经关闭或者已经完成");

        double v1 = first.get().getQuantity().doubleValue();
        if (CollectionUtil.isNotEmpty(proWorkorder.getTaskVos())) {
            for (ProTaskVo proTaskVo : proWorkorder.getTaskVos()) {
                double quantityWaitSize = proTaskVo.getQuantityWait().doubleValue();
                double quantitySize = proTaskVo.getQuantity().doubleValue();
                double v = v1;
                if (quantityWaitSize != 0) {
                    if (quantityWaitSize > v) {
                        v = quantityWaitSize - v;
                    } else {
                        v = 0;
                    }
                    proTaskVo.setQuantityWait(BigDecimal.valueOf(v));
                }
                proTaskVo.setQuantity(BigDecimal.valueOf(quantitySize - v1));
            }
            proTaskService.closeObj(proWorkorder.getTaskVos());
        }


        List<ProTaskWorkunit> proTaskWorkunits = proWorkorder.getProTaskWorkunits();
        if (CollectionUtil.isNotEmpty(proTaskWorkunits)) {
            for (ProTaskWorkunit proTaskWorkunit : proTaskWorkunits) {
                proTaskWorkunit.setQuantity(BigDecimal.valueOf(proTaskWorkunit.getQuantity().doubleValue() - v1));
            }
            proTaskWorkunitService.closeObj(proTaskWorkunits);
        }

        proWorkorder.setStatus(WorkorderStatusEnum.CLOSE.getValue());
        return this.updateProWorkorder(proWorkorder);
    }

    @Override
    public List<ProWorkorder> selectSaleAndWorkorderList(ProWorkorder proWorkorder) {
        QueryWrapper<ProWorkorder> queryWrapper = new QueryWrapper<>();
        // pw.arrange_code,pw.workorder_code,pw@sd.sales_voucher,pwsd.sales_voucher_item
        queryWrapper.eq(proWorkorder.getWorkorderCode() != null, "pw.workorder_code", proWorkorder.getWorkorderCode());
        queryWrapper.eq(proWorkorder.getArrangeCode() != null, "pw.arrange_code", proWorkorder.getArrangeCode());
        queryWrapper.eq(proWorkorder.getSalesVoucher() != null, "pwsd.sales_voucher", proWorkorder.getSalesVoucher());
        queryWrapper.eq(proWorkorder.getSalesVoucherItem() != null, "pwsd.sales_voucher_item", proWorkorder.getSalesVoucherItem());
        return proWorkorderMapper.selectSaleAndWorkorderList(queryWrapper);
    }

    // signature
    @Override
    public List<ProWorkorderPrintTab> selectWorkorderPrintTab(ProWorkorderQuery proWorkorder) {
        List<ProWorkorder> proWorkorders = this.selectListByQw(new QueryWrapper<ProWorkorder>().in("t1.workorder_id", proWorkorder.getWorkorderIds().stream().filter(Objects::nonNull).collect(Collectors.toSet())));
        Set<Long> workorderIds = proWorkorders.stream().map(ProWorkorder::getWorkorderId).filter(Objects::nonNull).collect(Collectors.toSet());


        List<ProWorkorderPrintTab> objects = new ArrayList<>();
        for (Long workorderId : workorderIds) {
            ProWorkorderVo proWorkorderVo = this.selectProWorkorderByWorkorderId(workorderId);
            List<ProWorkOrderSoSizeItem> sizeList = proWorkorderVo.getSizeList();
            List<ProWorkOrderProcessVo> processList = proWorkorderVo.getProcessList();
            List<ProWorkOrderSoDirective> saleDirectiveList = proWorkorderVo.getSaleDirectiveList();
            ProProductionSolution proProductionSolution = proWorkorderVo.getProProductionSolution();
            ProProductionSolutionSpecificationSheet sheet = proWorkorderVo.getProProductionSolutionSpecificationSheet();

            if (proProductionSolution == null) {
                continue;
            }


            List<ProWorkorderPrintTab.WorkOrderTable.Process> printProcessList = new ArrayList<>();
            List<ProWorkorderPrintTab.WorkOrderTable.ProcessItem> printProcessItemList = new ArrayList<>();
            for (ProWorkOrderProcessVo vo : processList) {
                ProWorkorderPrintTab.WorkOrderTable.Process process = new ProWorkorderPrintTab.WorkOrderTable.Process();
                process.setProcessName(vo.getProcessName());
                process.setDesc(vo.getRemark());
                process.setRemark(vo.getRemark());
                process.setQuantity(vo.getQuantity());
                printProcessList.add(process);
                ProProductionSolutionProcess proProductionSolutionProcess = vo.getProProductionSolutionProcess();

                if (proProductionSolutionProcess != null) {
                    if (vo.getProcessItemList() == null) {
                        continue;
                    }

                    for (ProWorkOrderProcessItem processItem : vo.getProcessItemList()) {
                        ProWorkorderPrintTab.WorkOrderTable.ProcessItem item = new ProWorkorderPrintTab.WorkOrderTable.ProcessItem();
                        BigDecimal quantity = processItem.getQuantity();
                        BigDecimal stdWorkingTime = proProductionSolutionProcess.getStdWorkingTime();
                        String stdWorkingTimeUom = proProductionSolutionProcess.getStdWorkingTimeUom();
                        BigDecimal theStandardTime = getTheStandardTime(stdWorkingTimeUom, stdWorkingTime, quantity);

                        item.setItemCode(processItem.getItemCode());
                        item.setItemType(processItem.getItemTypeName());
                        item.setItemName(processItem.getItemName());
                        item.setUnit(stdWorkingTimeUom);
                        item.setStandardDosage(theStandardTime);
                        item.setQuantity(quantity);
                        item.setProcessName(processItem.getProcessName());
                        item.setRemark(processItem.getRemark());
                        printProcessItemList.add(item);
                    }
                }
            }

            ProWorkorderPrintTab proWorkorderPrintTab = new ProWorkorderPrintTab();
            ProWorkorderPrintTab.PageHeader pageHeader1 = new ProWorkorderPrintTab.PageHeader();
            BigDecimal quantity = DataUtil.getNormalData(proWorkorderVo.getQuantity());
            BigDecimal length = DataUtil.getNormalData(sheet.getLength());

            ProWorkorderPrintTab.WorkOrderTable.Body workorderBody = new ProWorkorderPrintTab.WorkOrderTable.Body();
            ProWorkorderPrintTab.WorkOrderTable.WorkOrderInfo workOrderInfo = new ProWorkorderPrintTab.WorkOrderTable.WorkOrderInfo();
            workOrderInfo.setProductCode(proWorkorderVo.getProductCode());
            workOrderInfo.setProductName(proWorkorderVo.getProductName());
            workOrderInfo.setUnit(proWorkorderVo.getUnitOfMeasure());
            workOrderInfo.setQuantity(quantity);
            BigDecimal weight = DataUtil.getNormalData(sheet.getWeight());
            workOrderInfo.setMaterialWeight(quantity.multiply(weight));
            workOrderInfo.setSingleLayerThick(sheet.getSingleLayerThick());
            workOrderInfo.setDispatchQuantity(quantity);
            workOrderInfo.setReferenceQuantity(quantity);

            workorderBody.setProcessList(printProcessList);
            workorderBody.setProcessItemList(printProcessItemList);
            if (saleDirectiveList.size() > 0) {
                List<ProWorkorderPrintTab.WorkOrderTable.SoDirective> directiveList = new ArrayList<>();
                for (ProWorkOrderSoDirective proWorkOrderSoDirective : saleDirectiveList) {
//                    ProWorkOrderSoDirective proWorkOrderSoDirective = saleDirectiveList.get(0);
                    pageHeader1.setPrintingDirection(proWorkOrderSoDirective.getPrintingDirection());

                    ProWorkorderPrintTab.WorkOrderTable.SoDirective soDirective = proWorkOrderSoDirective.deepCopyObj(ProWorkorderPrintTab.WorkOrderTable.SoDirective.class);
                    soDirective.setProductSpec(sheet.getProductMaterial());
                    soDirective.setRemark(sheet.getRemark());
                    soDirective.setFrontColorName(sheet.getFrontColorName());
                    soDirective.setOppositeColorName(sheet.getOppositeColorName());
                    soDirective.setProductSpec(proWorkOrderSoDirective.getProdSpec());
//                soDirective.setSegment(proWorkOrderSoDirective.getSegment());
//                soDirective.setSalePath(proWorkOrderSoDirective.getSalePath());
//                soDirective.setWholeSize(proWorkOrderSoDirective.getWholeSize());
//                soDirective.setQuarter(proWorkOrderSoDirective.getQuarter());
//                soDirective.setPoNo(proWorkOrderSoDirective.getPoNo());
//                soDirective.setWipNo(proWorkOrderSoDirective.getWipNo());
//                soDirective.setSkNo(proWorkOrderSoDirective.getSkNo());
//                soDirective.setPatentNo(proWorkOrderSoDirective.getPatentNo());
//                soDirective.setMaterialDesc(proWorkOrderSoDirective.getMaterialDesc());
//                soDirective.setShipToId(proWorkOrderSoDirective.getShipToId());
//                soDirective.setCycle(proWorkOrderSoDirective.getCycle());
//                soDirective.setPackingNum(proWorkOrderSoDirective.getPackingNum());
                    directiveList.add(soDirective);
                }

                workorderBody.setSoDirectives(directiveList);
            }


            Map<String, String> clientMap = saleDirectiveList.stream().filter(x -> x.getClientCmd() != null && x.getColorNo() != null).collect(Collectors.toMap(ProWorkOrderSoDirective::getClientCmd, ProWorkOrderSoDirective::getColorNo));
            // 指令展示, 如果指令号 只有指令号 就显示指令,  如果有尺码则显示尺码,
            // 如果有尺码则显示尺码 , 尺码散列table
            List<ProWorkorderPrintTab.WorkOrderTable.SoDirective> soDirectives = workorderBody.getSoDirectives();
            if (soDirectives.size() == 1) {
                List<ProWorkorderPrintTab.WorkOrderTable.SoSize> soSizes = new ArrayList<>();
                for (ProWorkOrderSoSizeItem proWorkOrderSoSizeItem : sizeList) {
                    String colorNo = clientMap.get(proWorkOrderSoSizeItem.getClientCmd());
                    ProWorkorderPrintTab.WorkOrderTable.SoSize soSize = proWorkOrderSoSizeItem.deepCopyObj(ProWorkorderPrintTab.WorkOrderTable.SoSize.class);
//                soSize.setClientCmd(proWorkOrderSoSizeItem.getClientCmd());
                    soSize.setColorNo(DataUtil.getNormalData(colorNo));
//                soSize.setQuantity(proWorkOrderSoSizeItem.getQuantity());
//                soSize.setLossNum(proWorkOrderSoSizeItem.getLossNum());
                    soSizes.add(soSize);
                }

                if (soSizes.size() == 0) {
                    for (ProWorkOrderSoDirective proWorkOrderSoDirective : saleDirectiveList) {
                        ProWorkorderPrintTab.WorkOrderTable.SoSize soSize = proWorkOrderSoDirective.deepCopyObj(ProWorkorderPrintTab.WorkOrderTable.SoSize.class);
//                    soSize.setColorNo(proWorkOrderSoDirective.getColorNo());
//                    soSize.setClientCmd(proWorkOrderSoDirective.getClientCmd());
//                    soSize.setQuantity(proWorkOrderSoDirective.getQuantity());
//                    soSize.setLossNum(proWorkOrderSoDirective.getLossNum());
                        soSizes.add(soSize);
                    }
                }


                workorderBody.setSoSizeList(soSizes);

            }

            ProWorkorderPrintTab.WorkOrderTable.Img img = new ProWorkorderPrintTab.WorkOrderTable.Img();
            img.setFrontImg(sheet.getFrontImg());
            img.setBackImg(sheet.getBackImg());
            workorderBody.setImg(img);


            ProWorkorderPrintTab.ProductionSolutionTable.Body productionSolutionBody = new ProWorkorderPrintTab.ProductionSolutionTable.Body();
            productionSolutionBody.setProcesses(printProcessList);
            MdItem mdItem = proWorkorderVo.getMdItem();
            if (mdItem != null) {
                String itemTypeName = mdItem.getItemTypeName();
                String itemCode = mdItem.getItemCode();
                productionSolutionBody.setItemTypeName(itemTypeName);
                productionSolutionBody.setItemCode(itemCode);
                productionSolutionBody.setItemName(mdItem.getItemName());
            }

            productionSolutionBody.setUnit(sheet.getUnitOfMeasure());
            productionSolutionBody.setEnName(sheet.getEnName());
            productionSolutionBody.setBrandName(sheet.getBrandName());
            productionSolutionBody.setPurchaseUnit(sheet.getPurchaseUnit());
            productionSolutionBody.setConversionValue(sheet.getConversionValue());
            if (soDirectives.size() == 1) {
                ProWorkorderPrintTab.WorkOrderTable.SoDirective soDirective = soDirectives.get(0);
                productionSolutionBody.setSizeGroup(soDirective.getSizeGroup());

            }
            productionSolutionBody.setRowNum(sheet.getRowNum());

            productionSolutionBody.setLength(length);
            productionSolutionBody.setSingleLayerThick(sheet.getSingleLayerThick());
            productionSolutionBody.setSingleWeight(sheet.getSingleWeight());
            productionSolutionBody.setLayerNum(sheet.getLayerNum());
            productionSolutionBody.setHeight(sheet.getHeight());
            productionSolutionBody.setWidth(sheet.getWidth());
            productionSolutionBody.setPrintingPaperlenth(sheet.getPrintingPaperlenth());
            productionSolutionBody.setPrintPaperwidth(sheet.getPrintPaperwidth());
            productionSolutionBody.setStorePlace(sheet.getStorePlace());
            productionSolutionBody.setDispatchMultiple(sheet.getSendworkMultiple());
            productionSolutionBody.setIsCreateSpec(sheet.getIsCreateSpec());
            productionSolutionBody.setIsNeedShoeImg(sheet.getIsNeedShoeImg());
            productionSolutionBody.setIsAddSimple(sheet.getIsAddSimple());
            productionSolutionBody.setIsUniqueCode(sheet.getIsUniqueCode());
            productionSolutionBody.setIsConsiderColor(sheet.getIsConsiderColor());
            productionSolutionBody.setProductMaterial(sheet.getProductMaterial());
            productionSolutionBody.setFormula(sheet.getFormula());
            productionSolutionBody.setFrontColorName(sheet.getFrontColorName());
            productionSolutionBody.setOppositeColorName(sheet.getOppositeColorName());
            productionSolutionBody.setFrontImg(sheet.getFrontImg());
            productionSolutionBody.setBackImg(sheet.getBackImg());
            productionSolutionBody.setCustomerApprover(sheet.getCustomerConfirmedBy());
            productionSolutionBody.setCustomerApprovedTime(printDateFormat(sheet.getCustomerConfirmedDate()));
            productionSolutionBody.setRDApproverd(sheet.getRdApprovedBy());
            productionSolutionBody.setRDChecked(sheet.getRdReviewedBy());
            productionSolutionBody.setRDPrepared(sheet.getRdPreparedBy());

            if (Objects.equals(proWorkorderVo.getWorkorderType(), WorkorderConst.WORK_ORDER_PROTO_TYPE)) {
                productionSolutionBody.setWorkorderProofingCode(proWorkorderVo.getWorkorderCode());
            }

            Date expiryDate = proProductionSolution.getExpiryDate();
            if (expiryDate != null) {
                Date date = new Date();
                if (expiryDate.equals(date)) {
                    productionSolutionBody.setIsEnable("禁用");
                } else {
                    if (expiryDate.before(date)) {
                        productionSolutionBody.setIsEnable("禁用");
                    } else {
                        productionSolutionBody.setIsEnable("启用");
                    }
                }
            }


            Optional<BigDecimal> reduce = saleDirectiveList.stream().map(ProWorkOrderSoDirective::getLossNum).filter(Objects::nonNull).reduce(BigDecimal::add);
            BigDecimal lossNum = BigDecimal.ZERO;
            if (reduce.isPresent()) {
                lossNum = reduce.get();
            }
            workOrderInfo.setLossNum(DataUtil.getNormalData(lossNum));

            ProWorkorderPrintTab.WorkOrderTable workOrderTable = new ProWorkorderPrintTab.WorkOrderTable();
            pageHeader1.setClientName(proWorkorderVo.getClientName());
            pageHeader1.setArrangeCode(proWorkorderVo.getArrangeCode());
            pageHeader1.setRowNum(proWorkorderVo.getRowNum());
            pageHeader1.setDispatchMultiple(sheet.getSendworkMultiple());
            if (mdItem != null) {
                String itemTypeName = mdItem.getItemTypeName();
                pageHeader1.setItemTypeName(itemTypeName);
            }
            pageHeader1.setProductionSolutionCode(proProductionSolution.getProductionSolutionCode());
            String finishTime = printDateFormat(proWorkorderVo.getRequestDate());
            pageHeader1.setFinishTime(finishTime);
            pageHeader1.setMaterialLength(length.multiply(quantity));
            pageHeader1.setPackMode(dictDataService.getDictLabel("pro_pack_type", proWorkorderVo.getPackType()));
            String processDesc = processList.stream().sorted(Comparator.comparing(ProWorkOrderProcessVo::getIdx)).map(ProWorkOrderProcessVo::getProcessName).collect(Collectors.joining("-"));
            processDesc = DataUtil.getNormalData(processDesc);
            processDesc = processDesc.length() == 0 ? "" : processDesc.substring(0, processDesc.length() - 1);
//            pageHeader1.setRouteDesc(processDesc);
            pageHeader1.setProcessDesc(processDesc);
            workOrderTable.setPageHeader(pageHeader1);
            workorderBody.setWorkOrderInfo(workOrderInfo);
            workOrderTable.setBody(workorderBody);
            ProWorkorderPrintTab.PageFooter pageFooter = new ProWorkorderPrintTab.PageFooter();
            pageFooter.setEntryTime(printDateFormat(proWorkorderVo.getCreateTime()));
            pageFooter.setPrintUsername(SecurityUtils.getUsername());
            pageFooter.setAuditors("");
            pageFooter.setMerchandiser("");
            pageFooter.setProductionManagement("");
            workOrderTable.setPageFooter(pageFooter);

            ProWorkorderPrintTab.ProductionSolutionTable productionSolutionTable = new ProWorkorderPrintTab.ProductionSolutionTable();
            ProWorkorderPrintTab.PageHeader pageHeader2 = new ProWorkorderPrintTab.PageHeader();
            pageHeader2.setProductionSolutionCode(proProductionSolution.getProductionSolutionCode());
            ProWorkorderPrintTab.PageFooter pageFooter2 = new ProWorkorderPrintTab.PageFooter();
            pageFooter2.setEntryTime(printDateFormat(proWorkorderVo.getCreateTime()));
            productionSolutionTable.setPageFooter(pageFooter2);
            productionSolutionTable.setBody(productionSolutionBody);
            productionSolutionTable.setPageHeader(pageHeader2);


            proWorkorderPrintTab.setWorkOrderTable(workOrderTable);
            proWorkorderPrintTab.setProductionSolutionTable(productionSolutionTable);
            objects.add(proWorkorderPrintTab);
        }

        return objects;
    }


    @Override
    public List<Map<String, String>> getWorkorderProcessInfo(String workorderCode) {
        String processNameKey = "processName";
        String processStatusKey = "processStatus";
        String finishTimeKey = "finishTime";
        String kuhanaKey = "kuhana";

        List<ProTask> proTasks = proTaskService.selectProTaskByWorkorderCode(workorderCode);
        List<Map<String, String>> objects = new ArrayList<>();
        if (proTasks.size() == 0) {

            QueryWrapper<ProWorkorder> proWorkorderQueryWrapper = new QueryWrapper<>();
            proWorkorderQueryWrapper.eq("t1.workorder_code", workorderCode);
            List<ProWorkorder> proWorkorders = proWorkorderMapper.selectListByQw(proWorkorderQueryWrapper);
            ProWorkorder proWorkorder = proWorkorders.get(0);
            QueryWrapper<ProWorkOrderProcess> proWorkOrderProcessQueryWrapper = new QueryWrapper<>();
            proWorkOrderProcessQueryWrapper.eq("t1.workorder_id", proWorkorder.getWorkorderId());
            List<ProWorkOrderProcess> proWorkOrderProcesses = proWorkOrderProcessService.selectListByQw(proWorkOrderProcessQueryWrapper);

            for (ProWorkOrderProcess proWorkOrderProcess : proWorkOrderProcesses) {
                Map<String, String> map = new HashMap<>();
                String statusNomalCn = TaskStatusEnum.getStatusNomalCn(null);
                map.put(processNameKey, proWorkOrderProcess.getProcessName());
                map.put(processStatusKey, statusNomalCn);
                map.put(finishTimeKey, "");
                map.put(kuhanaKey, "");
                objects.add(map);
            }

            return objects;
        }

        List<Long> taskIds = proTasks.stream().map(ProTask::getTaskId).collect(Collectors.toList());
        ProTaskWorkunit proTaskWorkunit = new ProTaskWorkunit();
        proTaskWorkunit.setTaskIds(taskIds);
        List<ProTaskWorkunit> proTaskWorkunits = proTaskWorkunitService.selectProTaskWorkunitList(proTaskWorkunit);
        String statusCn = null;
        if (proTaskWorkunits.size() == 0) {
            for (ProTask proTask : proTasks) {
                Map<String, String> map = new HashMap<>();
                String statusNomalCn = TaskStatusEnum.getStatusNomalCn(proTask.getStatus());
                map.put(processNameKey, proTask.getProcessName());
                map.put(processStatusKey, statusNomalCn);
                map.put(finishTimeKey, "");
                map.put(kuhanaKey, "");
                objects.add(map);
            }
            return objects;
        }


        Map<Long, ProTaskWorkunit> taskStatusMap = proTaskWorkunits.stream().collect(Collectors.toMap(ProTaskWorkunit::getTaskId, x -> x));
        for (ProTask proTask : proTasks) {
            Map<String, String> map = new HashMap<>();
            ProTaskWorkunit taskWorkunit = taskStatusMap.get(proTask.getTaskId());
            String processName = proTask.getProcessName();

            if (taskWorkunit != null) {
                if (taskWorkunit.getQuantity().equals(taskWorkunit.getQuantityProduced())) {
                    statusCn = FINISHED.getStatusCn();
                } else {
                    statusCn = TaskStatusEnum.getStatusNomalCn(proTask.getStatus());
                }

                QueryWrapper<ProFeedback> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("task_workunit_id", taskWorkunit.getTaskWorkunitId());
                List<ProFeedback> proFeedbacks = proFeedbackService.selectProFeedbackList(queryWrapper);
                map.put(processNameKey, processName);
                map.put(processStatusKey, statusCn);
                map.put(finishTimeKey, "");
                map.put(kuhanaKey, "");

                if (proFeedbacks.size() > 0) {
                    ProFeedback proFeedback = proFeedbacks.stream().sorted(Comparator.comparing(ProFeedback::getFeedbackTime)).collect(Collectors.toList()).get(0);
                    Date feedbackTime = proFeedback.getFeedbackTime();
                    String theDayStr = DateUtil.format(feedbackTime, DATETIME_PATTERN);

                    map.put(finishTimeKey, theDayStr);
                    map.put(kuhanaKey, proFeedback.getUserName());
                }
            } else {
                map.put(processNameKey, processName);
                statusCn = TaskStatusEnum.getStatusNomalCn(proTask.getStatus());
                map.put(processStatusKey, statusCn);
                map.put(finishTimeKey, "");
                map.put(kuhanaKey, "");
            }
            objects.add(map);
        }

        Set<String> usernames = objects.stream().map(x -> x.get(kuhanaKey)).filter(Objects::nonNull).collect(Collectors.toSet());
        SysUser sysUser = new SysUser();
        sysUser.setUsernames(usernames);
        Map<String, String> nickNameMap = sysUserService.selectApiUserList(sysUser).stream().collect(Collectors.toMap(SysUser::getUserName, SysUser::getNickName));
        objects.forEach(map -> {
            String s = map.get(kuhanaKey);
            if (!Objects.equals(s, "") && s != null) {
                String s1 = nickNameMap.get(s);
                map.put(kuhanaKey, s1);
            }
        });


        return objects;
    }

    @Transactional
    @Override
    public String sapUpdateObj(SAPDtoProWorkOrder sapDtoProWorkOrder, ProWorkorder workorder) {
        ExceptionUtil.checkTrueThrowException(!StringUtils.isNotNull(workorder) || !StringUtils.isNotNull(sapDtoProWorkOrder), WorkorderConst.WorkOrderErrorConst.ERROR_1);

        // 封装主数据
        ProWorkorder proWorkorder = sapDtoProWorkOrder.deepCopyObj(ProWorkorder.class);
        Long workorderId = workorder.getWorkorderId();
        String workorderCode = proWorkorder.getWorkorderCode();
        proWorkorder.setWorkorderId(workorderId);

        String sapItemCode = proWorkorder.getSapItemCode();
        String groupCounter = proWorkorder.getGroupCounter();
        String groupKey = proWorkorder.getGroupKey();

// 获取任务清单组键值和组计数器
        ExceptionUtil.checkTrueThrowException(!StringUtils.isNotNull(groupKey) && !StringUtils.isNotNull(groupCounter) && !StringUtils.isNotNull(sapItemCode), WorkorderConst.WorkOrderErrorConst.ERROR_3);


        List<SAPDtoProWorkOrderBom> bomList = sapDtoProWorkOrder.getBomList();
        List<SAPDtoProWorkOrderProcess> processList = sapDtoProWorkOrder.getProcessList();
        List<SAPDtoProWorkOrderSoDirective> saleList = sapDtoProWorkOrder.getSaleList();
        List<SAPDtoProWorkOrderSoSizeItem> sizeList = sapDtoProWorkOrder.getSizeList();
        if (processList.size() > 0) {
            Set<String> processSortList = processList.stream().map(SAPDtoProWorkOrderProcess::getProcessRef).filter(Objects::nonNull).collect(Collectors.toSet());
            ExceptionUtil.checkTrueThrowException(processSortList.size() < processList.size(), "工序顺序重复," + JSON.toJSONString(processList.stream().map(SAPDtoProWorkOrderProcess::getProcessRef).collect(Collectors.toList())));
        }


        Set<String> collect = bomList.stream().map(SAPDtoProWorkOrderBom::getSapItemCode).collect(Collectors.toSet());
        collect.add(sapItemCode);
        QueryWrapper<MdItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("sap_item_code", collect);
        Map<String, MdItem> itemMap = mdItemMapper.selectListByQw(queryWrapper).stream().collect(Collectors.toMap(MdItem::getSapItemCode, x -> x));


        List<ProWorkOrderBom> boms = new ArrayList<>();
        // 保存BOM信息
        if (CollectionUtil.isNotEmpty(bomList)) {
            proWorkOrderBomService.deleteByWorkorderCode(workorderCode);
            for (SAPDtoProWorkOrderBom bom : bomList) {
                MdItem mdItem = itemMap.get(bom.getSapItemCode());
                ExceptionUtil.checkTrueThrowException(StringUtils.isNull(mdItem), WorkorderConst.WorkOrderErrorConst.ERROR_2);
                ProWorkOrderBom proWorkOrderBom = bom.deepCopyObj(ProWorkOrderBom.class);
                proWorkOrderBom.setWorkorderId(workorderId);
                proWorkOrderBom.setWorkorderCode(workorderCode);
                proWorkOrderBom.setItemId(mdItem.getItemId());
                proWorkOrderBom.setItemName(mdItem.getItemName());
                proWorkOrderBom.setQuantity(getNormalData(bom.getQuantity(), BigDecimal.class));
                String unitUsage = bom.getUnitUsage();
                proWorkOrderBom.setUnitUsage(getNormalData(unitUsage));
                String isBackFlush = "N";
                if (Objects.equals(bom.getIsBackflush(), "X")) {
                    isBackFlush = "Y";
                }
                proWorkOrderBom.setIsBackflush(isBackFlush);
                proWorkOrderBom.setApiFlag(true);
                proWorkOrderBomService.insertProWorkOrderBom(proWorkOrderBom);

                proWorkOrderBom.setSapDtoProWorkOrderBom(bom);
                boms.add(proWorkOrderBom);
            }
        }

        Map<String, List<ProWorkOrderBom>> bomMap = boms.stream().collect(Collectors.groupingBy(ProWorkOrderBom::getProcessRef));
        Map<String, SAPDtoProWorkOrderProcess> processMap = processList.stream().collect(Collectors.toMap(SAPDtoProWorkOrderProcess::getProcessRef, x -> x));


        // 根据SAP编码查询产品信息
        MdItem item = itemMap.get(sapItemCode);
        if (StringUtils.isNotNull(item)) {
            proWorkorder.setProductId(item.getItemId());
            proWorkorder.setProductName(item.getItemName());
            proWorkorder.setProductCode(item.getItemCode());
            proWorkorder.setProductSpc(item.getSpecification());
        }

        // 生产工单名称
        proWorkorder.setWorkorderName(proWorkorder.getProductName() + "[" + proWorkorder.getQuantity() + "]" + proWorkorder.getUnitOfMeasure() + "生产工单");

        // 数据格式转换
        proWorkorder.setQuantity(getNormalData(sapDtoProWorkOrder.getQuantity()));
        proWorkorder.setQuantityProduced(BigDecimal.ZERO);
        proWorkorder.setQuantityChanged(BigDecimal.ZERO);
        proWorkorder.setQuantityScheduled(BigDecimal.ZERO);
        proWorkorder.setQuantityUnqualify(BigDecimal.ZERO);
        proWorkorder.setQuantityQualify(BigDecimal.ZERO);
        proWorkorder.setWorkorderType(WorkorderConst.WORK_ORDER_PRODUCT_TYPE);
        proWorkorder.setStatus(workorder.getStatus());

        // 获取生产版本
        ProProductionSolution productionSolution = proProductionSolutionService.selectByGroupKeyAndGroupCounterAndSapItemCode(groupKey, groupCounter, sapItemCode);
        ExceptionUtil.checkTrueThrowException(ObjectUtil.isEmpty(productionSolution), WorkorderConst.WorkOrderErrorConst.ERROR_5);

        // 获取生产版本数据
        ProProductionSolutionVo proProductionSolutionVo = proProductionSolutionService.selectProProductionSolutionByProductionSolutionId(productionSolution.getProductionSolutionId());
        ProProductionSolutionSpecificationSheet specificationSheet = proProductionSolutionVo.getSpecificationSheet();
        proWorkorder.setDispatchMultiple(DataUtil.getNormalData(specificationSheet.getSendworkMultiple(), String.class));
        proWorkorder.setThickness(getNormalData(specificationSheet.getThick()));
        proWorkorder.setStorageLocation(getNormalData(specificationSheet.getStorePlace(), String.class));
        proWorkorder.setRowNum(getNormalData(specificationSheet.getRowNum(), String.class));
        proWorkorder.setSingleWeight(getNormalData(specificationSheet.getSingleWeight()));

        if (CollectionUtil.isNotEmpty(saleList)) {
            SAPDtoProWorkOrderSoDirective sapDtoProWorkOrderSoDirective = saleList.get(0);
            String salesVoucher = sapDtoProWorkOrderSoDirective.getSalesVoucher();
            String salesVoucherItem = sapDtoProWorkOrderSoDirective.getSalesVoucherItem();
            String clientCode = sapDtoProWorkOrderSoDirective.getClientCode();
            String clientName = sapDtoProWorkOrderSoDirective.getClientName();
            proWorkorder.setClientCode(StringUtils.isEmpty(proWorkorder.getClientCode()) ? clientCode : proWorkorder.getClientCode());
            proWorkorder.setClientName(StringUtils.isEmpty(proWorkorder.getClientName()) ? clientName : proWorkorder.getClientName());
            proWorkorder.setSalesVoucher(salesVoucher);
            proWorkorder.setSalesVoucherItem(salesVoucherItem);

        }


        proWorkorder.setApiFlag(true);
        this.updateProWorkorder(proWorkorder);


        List<ProProductionSolutionProcessVo> solutionProcessVos = proProductionSolutionVo.getProcessList();
        if (CollectionUtil.isNotEmpty(solutionProcessVos)) {
            proWorkOrderProcessService.deleteByWorkorderCode(workorderCode);
            proWorkOrderProcessItemService.deleteByWorkorderCode(workorderCode);
            proWorkOrderProcessToolService.deleteByWorkorderCode(workorderCode);
            for (ProProductionSolutionProcessVo solutionProcessVo : solutionProcessVos) {
                ProWorkOrderProcess proWorkOrderProcess = solutionProcessVo.deepCopyObj(ProWorkOrderProcess.class);
                proWorkOrderProcess.setWorkorderId(workorderId);
                proWorkOrderProcess.setWorkorderCode(workorderCode);
                proWorkOrderProcess.setApiFlag(true);
                String idx = proWorkOrderProcess.getIdx();
                SAPDtoProWorkOrderProcess sapDtoProWorkOrderProcess = processMap.get(idx);
                if (sapDtoProWorkOrderProcess != null) {
                    proWorkOrderProcess.setControlCode(sapDtoProWorkOrderProcess.getControlCode());
                    proWorkOrderProcess.setQuantity(DataUtil.getNormalData(sapDtoProWorkOrderProcess.getQuantity(), BigDecimal.class));
                }

                proWorkOrderProcessService.insertProWorkOrderProcess(proWorkOrderProcess);
                Long workorderProcessId = proWorkOrderProcess.getWorkorderProcessId();

                List<ProWorkOrderBom> proWorkOrderBomList = bomMap.get(idx);
                if (CollectionUtil.isNotEmpty(proWorkOrderBomList)) {
                    for (ProWorkOrderBom proWorkOrderBom : proWorkOrderBomList) {
                        String code = proWorkOrderBom.getSapItemCode();
                        MdItem mdItem = itemMap.get(code);
                        ProWorkOrderProcessItem proWorkOrderProcessItem = new ProWorkOrderProcessItem();
                        proWorkOrderProcessItem.setWorkorderProcessId(workorderProcessId);
                        proWorkOrderProcessItem.setItemId(mdItem.getItemId());
                        proWorkOrderProcessItem.setItemCode(mdItem.getItemCode());
                        proWorkOrderProcessItem.setItemName(mdItem.getItemName());
                        proWorkOrderProcessItem.setSapItemCode(code);
                        proWorkOrderProcessItem.setItemTypeName(mdItem.getItemTypeName());
                        proWorkOrderProcessItem.setProcessName(solutionProcessVo.getProcessName());
                        proWorkOrderProcessItem.setProcessCode(solutionProcessVo.getProcessCode());
                        proWorkOrderProcessItem.setUnitOfMeasure(solutionProcessVo.getUnitOfMeasure());
                        proWorkOrderProcessItem.setQuantity(DataUtil.getNormalData(proWorkOrderBom.getQuantity()));
                        proWorkOrderProcessItem.setRequirementNumber(proWorkOrderBom.getRequirementNumber());
                        proWorkOrderProcessItem.setRequirementProjectNumber(proWorkOrderBom.getRequirementProjectNumber());
                        proWorkOrderProcessItem.setStoreAddr(proWorkOrderBom.getStoreAddr());
                        proWorkOrderProcessItem.setScrapPercentage(DataUtil.getNormalData(proWorkOrderBom.getScrapPercentage()));
                        proWorkOrderProcessItem.setUnitUsage(DataUtil.getNormalData(proWorkOrderBom.getUnitUsage()));
                        proWorkOrderProcessItem.setUnitConvert(solutionProcessVo.getUnitConvert());
                        proWorkOrderProcessItem.setProcessRef(idx);
                        proWorkOrderProcessItem.setIsBackflush(proWorkOrderBom.getIsBackflush());
                        proWorkOrderProcessItem.setApiFlag(true);
                        proWorkOrderProcessItemService.insertProWorkOrderProcessItem(proWorkOrderProcessItem);
                    }
                }

                // 获取质检 工装信息
                List<ProProductionSolutionProcessToolVo> toolList = solutionProcessVo.getToolList();
                toolList = toolList.stream().filter(x -> x.getToolId() != null).collect(Collectors.toList());

                saveProcessTools(toolList, proWorkOrderProcess);
            }
        }

        // 保存so指令
        saveSoDirectives(saleList, proWorkorder);

        // 保存尺码组信息
        saveSoSizes(sizeList, proWorkorder);

        //记录编排规则值
        proWorkOrderArrangeRuleValService.deleteProWorkOrderArrangeRuleVal(proWorkorder.getWorkorderId());
        proWorkOrderArrangeRuleValService.insertProWorkOrderArrangeRuleVal(proWorkorder);
        //记录换型规则值
        proScheduleSetupRuleValService.deleteScheduleSetupRuleVal(proWorkorder.getWorkorderId());
        proScheduleSetupRuleValService.insertProScheduleSetupRuleVal(proWorkorder);
        return null;
    }

    /**
     * 查询生产工单
     *
     * @param workorderId 生产工单主键
     * @return 生产工单
     */
    @Override
    public ProWorkorderVo selectProWorkorderByWorkorderId(Long workorderId) {
        ProWorkorder proWorkorder = proWorkorderMapper.selectWorkorderById(workorderId);
        ExceptionUtil.checkTrueThrowException(proWorkorder == null, "工单id不存在,非法操作");
        List<ProWorkOrderBom> proWorkOrderBomList = proWorkOrderBomMapper.selectBomByWorkorderCode(proWorkorder.getWorkorderCode());
        List<ProWorkOrderProcessVo> proWorkOrderProcessList = proWorkOrderProcessMapper.selectProWorkOrderProcessByWorkOrderId(workorderId);

        String groupCounter = proWorkorder.getGroupCounter();
        String groupKey = proWorkorder.getGroupKey();
        String sapItemCode = proWorkorder.getSapItemCode();
        String epItemCode = proWorkorder.getEpItemCode();
        for (ProWorkOrderProcessVo proWorkOrderProcess : proWorkOrderProcessList) {
            Long workorderProcessId = proWorkOrderProcess.getWorkorderProcessId();

            // 获取外协数据
            QueryWrapper<ProTaskAssistProcess> proTaskAssistProcessQueryWrapper = new QueryWrapper<>();
            proTaskAssistProcessQueryWrapper.eq("workorder_process_id", workorderProcessId);
            proTaskAssistProcessQueryWrapper.eq("delete_state", DataConstans.MARK_NOMAL);
            List<ProTaskAssistProcess> proTaskAssistProcesses = taskAssistProcessMapper.selectListByQw(proTaskAssistProcessQueryWrapper);
//            if (CollectionUtil.isNotEmpty(proTaskAssistProcesses)) {
//                LongSummaryStatistics collect = proTaskAssistProcesses.stream().map(ProTaskAssistProcess::getQuantity).collect(Collectors.summarizingLong(x -> x));
//                proWorkOrderProcess.setAssistQuantity(collect.getSum());
//            }


            if (CollectionUtil.isNotEmpty(proTaskAssistProcesses)) {
                proWorkOrderProcess.setProTaskAssistProcessList(proTaskAssistProcesses);
            }

            // 获取工序明细
            List<ProWorkOrderProcessItem> processItemList = proWorkOrderProcessItemMapper.selectProWorkOrderProcessItemByWorkorderProcessId(workorderProcessId);

            List<Long> itemList = processItemList.stream().map(ProWorkOrderProcessItem::getItemId).filter(Objects::nonNull).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(itemList)) {
                List<MdItem> mdItems = mdItemService.selectListByQw(new QueryWrapper<MdItem>().in("item_id", itemList));
                Map<Long, MdItem> mdItemMap = mdItems.stream().collect(Collectors.toMap(MdItem::getItemId, x -> x));
                List<ProWorkOrderProcessItem> pItemList = processItemList.stream().map(proWorkOrderProcessItem -> {
                    ProWorkOrderProcessItem item = proWorkOrderProcessItem.deepCopyObj();
                    MdItem mdItem = mdItemMap.get(item.getItemId());
                    if (mdItem != null) {
                        item.setItemCode(mdItem.getItemCode());
                        item.setItemName(mdItem.getItemName());
                        item.setItemTypeName(mdItem.getItemTypeName());
                        item.setProcessCode(proWorkOrderProcess.getProcessCode());
                        item.setProcessName(proWorkOrderProcess.getProcessName());
                        return item;
                    } else {
                        return null;
                    }
                }).filter(Objects::nonNull).collect(Collectors.toList());
                proWorkOrderProcess.setProcessItemList(pItemList);
            } else {
                proWorkOrderProcess.setProcessItemList(processItemList);
            }


            // 获取质检
            List<ProWorkOrderProcessQcindex> processQcindexList = proWorkOrderProcessQcindexMapper.selectProWorkOrderProcessQcindexByWorkorderProcessId(workorderProcessId);
            proWorkOrderProcess.setQcindexList(processQcindexList);

            // 获取工装
            List<ProWorkOrderProcessTool> processToolList = proWorkOrderProcessToolMapper.selectProWorkOrderProcessToolByWorkorderProcessId(workorderProcessId);
            proWorkOrderProcess.setToolList(processToolList);

            if (proWorkOrderProcess.getWorkorderId() != null && proWorkOrderProcess.getProcessId() != null) {
                ProTask proTask = proTaskService.selectByArrangeCodeAndProcessId(proWorkorder.getArrangeCode(), proWorkOrderProcess.getProcessId());
                if (proTask != null) {
                    proWorkOrderProcess.setStartTime(proTask.getScheduleStartDate());
                    proWorkOrderProcess.setEndTime(proTask.getScheduleEndDate());
                    proWorkOrderProcess.setWorkunitCode(proTask.getWorkunitCode());
                    proWorkOrderProcess.setWorkunitName(proTask.getWorkunitName());
                }
            }

            ProProductionSolution proProductionSolution = proProductionSolutionService.selectByGroupKeyAndGroupCounterAndSapItemCode(groupKey, groupCounter, sapItemCode);
            if (Objects.nonNull(proProductionSolution)) {
                ProProductionSolutionProcess qa = new ProProductionSolutionProcess();
                qa.setProductionSolutionId(proProductionSolution.getProductionSolutionId());
                qa.setProcessId(proWorkOrderProcess.getProcessId());
                qa.setWorkstationId(proWorkOrderProcess.getWorkstationId());
                List<ProProductionSolutionProcessVo> proProductionSolutionProcessVos = proProductionSolutionProcessService.selectProProductionSolutionProcessList(qa);
                if (CollectionUtil.isNotEmpty(proProductionSolutionProcessVos)) {
                    ProProductionSolutionProcessVo proProductionSolutionProcessVo = proProductionSolutionProcessVos.get(0);
                    ProProductionSolutionProcess proProductionSolutionProcess = proProductionSolutionProcessVo.deepCopyObj(ProProductionSolutionProcess.class);
                    proWorkOrderProcess.setProProductionSolutionProcess(proProductionSolutionProcess);
                }
            }
        }

        // 获取指令
        List<ProWorkOrderSoDirective> proWorkOrderSoDirectiveList = proWorkOrderSoDirectiveMapper.selectProWorkOrderSoDirectiveByWorkorderId(workorderId);

        // 获取size
        List<ProWorkOrderSoSizeItem> sizeList = proWorkOrderSoSizeItemMapper.selectProWorkOrderSoSizeItemByWorkorderId(workorderId);
        for (ProWorkOrderSoSizeItem proWorkOrderSoSizeItem : sizeList) {
            proWorkOrderSoSizeItem.setQuantity(proWorkOrderSoSizeItem.getQuantity().add(proWorkOrderSoSizeItem.getLossNum()));
        }

        ProWorkorderVo proWorkorderVo = proWorkorder.deepCopyObj(ProWorkorderVo.class);
        ProWorkorder workorder = proWorkorderMapper.selectWorkorderById(proWorkorder.getParentId());
        if (workorder != null) {
            proWorkorderVo.setParentCode(workorder.getWorkorderCode());
        }

        MdItem mdItem = mdItemService.selectMdItemById(proWorkorderVo.getProductId());
        if (mdItem != null) {
            proWorkorderVo.setMdItem(mdItem);
        }

        ProProductionSolution productionSolution = proProductionSolutionService.selectByGroupKeyAndGroupCounterAndSapItemCode(groupKey, groupCounter, sapItemCode);

        if (productionSolution != null) {
            ProProductionSolutionSpecificationSheet proProductionSolutionSpecificationSheet = specificationSheetService.selectSpecificationSheetByProductionSolutionId(productionSolution.getProductionSolutionId());
            proWorkorderVo.setProProductionSolution(productionSolution);
            proWorkorderVo.setProductionSolutionCode(productionSolution.getProductionSolutionCode());
            proWorkorderVo.setProProductionSolutionSpecificationSheet(proProductionSolutionSpecificationSheet);
        }
        if (proWorkorder.getWorkorderType().equals("product")) {
            proWorkorderVo.setProductCode(sapItemCode);
        }
        if (proWorkorder.getWorkorderType().equals("prototype")) {
            proWorkorderVo.setProductCode(epItemCode);
        }
        if (proWorkorder.getWorkorderType().equals("complements")) {
            proWorkorderVo.setProductCode(sapItemCode);
        }
        proWorkorderVo.setBomList(proWorkOrderBomList);
        proWorkorderVo.setProcessList(proWorkOrderProcessList);
        proWorkorderVo.setSaleDirectiveList(proWorkOrderSoDirectiveList);
        proWorkorderVo.setSizeList(sizeList);
        return proWorkorderVo;
    }

    @Override
    public ProWorkorder selectWorkorderById(Long workorderId) {
        return proWorkorderMapper.selectWorkorderById(workorderId);
    }


    @Override
    public List<ProWorkorder> selectArrangeListByCode(String workorderCode) {
        return proWorkorderMapper.selectArrangeOrderByCode(workorderCode);
    }

    /**
     * 查询生产工单列表
     *
     * @param proWorkorder 生产工单
     * @return 生产工单
     */
    @Override
    public List<ProWorkorder> selectProWorkorderList(ProWorkorderQuery proWorkorder) {
        return proWorkorderMapper.selectProWorkorderList(proWorkorder);
    }

    @Override
    public List<ProWorkorder> selectListByQw(QueryWrapper<ProWorkorder> query) {
        return proWorkorderMapper.selectListByQw(query);
    }


    @Override
    public List<ProWorkorder> selectProWorkorderByTaskId(ProWorkorder proWorkorder) {
        return proWorkorderMapper.selectProWorkorderByTaskId(proWorkorder);
    }

    @Override
    public boolean checkWorkorderIsExsit(ProWorkorder proWorkorder) {
        QueryWrapper<ProWorkorder> proWorkorderQueryWrapper = new QueryWrapper<>();
        proWorkorderQueryWrapper.eq("workorder_code", proWorkorder.getWorkorderCode());
        List<ProWorkorder> workorders = proWorkorderMapper.selectListByQw(proWorkorderQueryWrapper);
        return CollectionUtil.isEmpty(workorders);
    }

    /**
     * 新增生产工单（包含bom及工序）
     *
     * @param proWorkorderVo 生产工单
     * @return 结果
     */
    @Override
    @Transactional
    public int insertProWorkorderVo(ProWorkorderVo proWorkorderVo) {
        ProWorkorder proWorkorder = proWorkorderVo.deepCopyObj(ProWorkorder.class);

        //新增主表数据
        if (proWorkorder.getParentId() != null) {
            ProWorkorder parent = proWorkorderMapper.selectWorkorderById(proWorkorder.getParentId());
            if (StringUtils.isNotNull(parent)) {
                proWorkorder.setAncestors(parent.getAncestors() + "," + parent.getParentId());
            }
        }
        //生产工单
        if (proWorkorderVo.getWorkorderType().equals("product")) {
            if (StringUtils.isNotEmpty(proWorkorder.getProductCode())) {
                proWorkorder.setSapItemCode(proWorkorder.getProductCode());
            }
        }
        //补料工单
        if (proWorkorderVo.getWorkorderType().equals("complements")) {
            if (StringUtils.isNotEmpty(proWorkorder.getProductCode())) {
                proWorkorder.setSapItemCode(proWorkorder.getProductCode());
            }
        }
        //生产工单
        if (proWorkorderVo.getWorkorderType().equals("prototype")) {
            if (StringUtils.isNotEmpty(proWorkorder.getProductCode())) {
                proWorkorder.setEpItemCode(proWorkorder.getProductCode());
            }
        }

        proWorkorder.setQuantityProduced(BigDecimal.ZERO);
        proWorkorder.setQuantityQualify(BigDecimal.ZERO);
        proWorkorder.setQuantityUnqualify(BigDecimal.ZERO);
        int i = this.insertProWorkorder(proWorkorder);

        //新增生产工单BOM表
        Long workorderId = proWorkorder.getWorkorderId();
        String workorderCode = proWorkorder.getWorkorderCode();
        List<ProWorkOrderBom> bomList = proWorkorderVo.getBomList();
        for (ProWorkOrderBom proWorkOrderBom : bomList) {
            proWorkOrderBom.setBomItemId(null);
            proWorkOrderBom.setWorkorderId(workorderId);
            proWorkOrderBom.setWorkorderCode(workorderCode);
            proWorkOrderBomService.insertProWorkOrderBom(proWorkOrderBom);
        }

        //新增生产工单工序,工序物料表
        List<ProWorkOrderProcessVo> processList = proWorkorderVo.getProcessList();
        int j = 1;
        for (ProWorkOrderProcessVo proWorkOrderProcessVo : processList) {
            // 保存工序
            ProWorkOrderProcess proWorkOrderProcess = proWorkOrderProcessVo.deepCopyObj(ProWorkOrderProcess.class);
            proWorkOrderProcess.setWorkorderProcessId(null);
            proWorkOrderProcess.setWorkorderId(workorderId);
            proWorkOrderProcess.setWorkorderCode(workorderCode);
            proWorkOrderProcess.setIdx(j + "");
            proWorkOrderProcessService.insertProWorkOrderProcess(proWorkOrderProcess);

            Long workorderProcessId = proWorkOrderProcess.getWorkorderProcessId();

            //新增生产工单工序物料表
            List<ProWorkOrderProcessItem> proWorkOrderProcessItemList = proWorkOrderProcessVo.getProcessItemList();
            for (ProWorkOrderProcessItem proWorkOrderProcessItem : proWorkOrderProcessItemList) {
                proWorkOrderProcessItem.setWorkorderProcessItemId(null);
                proWorkOrderProcessItem.setWorkorderProcessId(workorderProcessId);
                proWorkOrderProcessItemService.insertProWorkOrderProcessItem(proWorkOrderProcessItem);
            }

            // 保存工序工装
            List<ProWorkOrderProcessQcindex> processQcindiceList = proWorkOrderProcessVo.getQcindexList();
            if (CollectionUtil.isNotEmpty(processQcindiceList)) {
                for (ProWorkOrderProcessQcindex proWorkOrderProcessQcindex : processQcindiceList) {
                    proWorkOrderProcessQcindex.setId(null);
                    proWorkOrderProcessQcindex.setWorkorderProcessId(workorderProcessId);
                    proWorkOrderProcessQcindex.setWorkOrderId(workorderId);
                    proWorkOrderProcessQcindexService.insertProWorkOrderProcessQcindex(proWorkOrderProcessQcindex);
                }
            }

            // 保存工序质检
            List<ProWorkOrderProcessTool> processToolList = proWorkOrderProcessVo.getToolList();
            if (CollectionUtil.isNotEmpty(processToolList)) {
                for (ProWorkOrderProcessTool proWorkOrderProcessTool : processToolList) {
                    proWorkOrderProcessTool.setWorkorderProcessToolId(null);
                    proWorkOrderProcessTool.setWorkorderProcessId(workorderProcessId);
                    proWorkOrderProcessTool.setWorkOrderId(workorderId);
                    proWorkOrderProcessToolService.insertProWorkOrderProcessTool(proWorkOrderProcessTool);
                }
            }
            j++;
        }

        proWorkOrderArrangeRuleValService.insertProWorkOrderArrangeRuleVal(proWorkorder);
        proScheduleSetupRuleValService.insertProScheduleSetupRuleVal(proWorkorder);
        return i;
    }

    /**
     * 新增生产工单
     *
     * @param proWorkorder 生产工单
     * @return 结果
     */
    @Override
    public int insertProWorkorder(ProWorkorder proWorkorder) {
        if (proWorkorder.getParentId() != null) {
            ProWorkorder parent = proWorkorderMapper.selectWorkorderById(proWorkorder.getParentId());
            if (StringUtils.isNotNull(parent)) {
                proWorkorder.setAncestors(parent.getAncestors() + "," + parent.getParentId());
            }
        }

        proWorkorder.createAction();
        return proWorkorderMapper.insertProWorkorder(proWorkorder);
    }

    /**
     * 修改生产工单
     *
     * @param proWorkorder 生产工单
     * @return 结果
     */
    @Override
    public int updateProWorkorder(ProWorkorder proWorkorder) {
        proWorkorder.updateAction();
        return proWorkorderMapper.updateProWorkorder(proWorkorder);
    }


    /**
     * 批量删除生产工单
     *
     * @param workorderIds 需要删除的生产工单主键
     * @return 结果
     */
    @Override
    public int deleteProWorkorderByWorkorderIds(Long[] workorderIds) {
        return proWorkorderMapper.deleteProWorkorderByWorkorderIds(workorderIds);
    }

    @Override
    public int updateWoStatusByArrangeCode(ProWorkorder proWorkorder) {
        proWorkorder.updateAction();
        return this.proWorkorderMapper.updateWoStatusByArrangeCode(proWorkorder);
    }

    /**
     * 删除生产工单信息
     *
     * @param workorderId 生产工单主键
     * @return 结果
     */
    @Override
    public int deleteProWorkorderByWorkorderId(Long workorderId) {
        return proWorkorderMapper.deleteProWorkorderByWorkorderId(workorderId);
    }

    /**
     * 修改生产工单（附带bom，工序）
     *
     * @param proWorkorderVo 生产工单
     * @return 结果
     */
    @Override
    public int updateProWorkorderWithBomAndProcess(ProWorkorderVo proWorkorderVo) {
        ProWorkorder proWorkorder = proWorkorderVo.deepCopyObj(ProWorkorder.class);
        int i = this.updateProWorkorder(proWorkorder);

        //新增或修改生产工单BOM表（有id则修改，没有则新增）
        Long workorderId = proWorkorder.getWorkorderId();
        List<ProWorkOrderBom> bomList = proWorkorderVo.getBomList();
        if (CollectionUtil.isEmpty(bomList)) {
            //根据工单id删除
            proWorkOrderBomMapper.deleteByWorkorderId(workorderId);
        } else {
            for (ProWorkOrderBom proWorkOrderBom : bomList) {
                if (null == proWorkOrderBom.getBomItemId()) {
                    proWorkOrderBom.setWorkorderId(workorderId);
                    proWorkOrderBomService.insertProWorkOrderBom(proWorkOrderBom);
                } else {
                    proWorkOrderBom.setWorkorderId(workorderId);
                    proWorkOrderBomService.updateProWorkOrderBom(proWorkOrderBom);
                }
            }
        }

        //新增生产工单工序,工序物料表（有id则修改，没有则新增）
        List<ProWorkOrderProcessVo> processList = proWorkorderVo.getProcessList();
        ProWorkOrderProcess proWorkOrderProcess = new ProWorkOrderProcess();
        proWorkOrderProcess.setWorkorderId(workorderId);
        List<ProWorkOrderProcessVo> processListDb = proWorkOrderProcessMapper.selectProWorkOrderProcessList(proWorkOrderProcess);
        if (processList != null) {
            for (ProWorkOrderProcessVo proWorkOrderProcessVo : processList) {
                // 保存工序
                ProWorkOrderProcess tempProcess = proWorkOrderProcessVo.deepCopyObj(ProWorkOrderProcess.class);
                tempProcess.setWorkorderId(workorderId);
                if (tempProcess.getWorkorderProcessId() == null) {
                    proWorkOrderProcessService.insertProWorkOrderProcess(tempProcess);
                } else {
                    proWorkOrderProcessService.updateProWorkOrderProcess(tempProcess);
                }
                Long workorderProcessId = tempProcess.getWorkorderProcessId();
                // 获取工序物料-保存
                if (proWorkOrderProcessVo.getProcessItemList() == null) {
                    proWorkOrderProcessVo.setProcessItemList(new ArrayList<ProWorkOrderProcessItem>());
                }
                List<ProWorkOrderProcessItem> proWorkOrderProcessItemList = proWorkOrderProcessVo.getProcessItemList();
                ProWorkOrderProcessItem proWorkOrderProcessItemQuery = new ProWorkOrderProcessItem();
                proWorkOrderProcessItemQuery.setWorkorderProcessId(workorderProcessId);
                List<ProWorkOrderProcessItem> proWorkOrderProcessItemListDb = proWorkOrderProcessItemMapper.selectProWorkOrderProcessItemList(proWorkOrderProcessItemQuery);
                for (ProWorkOrderProcessItem proWorkOrderProcessItem : proWorkOrderProcessItemList) {
                    proWorkOrderProcessItem.setWorkorderProcessId(workorderProcessId);
                    if (proWorkOrderProcessItem.getWorkorderProcessItemId() == null) {
                        proWorkOrderProcessItemService.insertProWorkOrderProcessItem(proWorkOrderProcessItem);
                    } else {
                        proWorkOrderProcessItemService.updateProWorkOrderProcessItem(proWorkOrderProcessItem);
                    }
                }

                proWorkOrderProcessItemListDb.forEach(v -> {
                    if (!proWorkOrderProcessItemList.stream().filter(v2 -> v.getWorkorderProcessItemId().equals(v2.getWorkorderProcessItemId())).findFirst().isPresent()) {
                        proWorkOrderProcessItemMapper.deleteProWorkOrderProcessItemByWorkorderProcessItemId(v.getWorkorderProcessItemId());
                    }
                });

                //检验项保存、删除
                List<ProWorkOrderProcessQcindex> proWorkOrderProcessQcindexList = proWorkOrderProcessVo.getQcindexList();
                ProWorkOrderProcessQcindex proWorkOrderProcessQcindexQuery = new ProWorkOrderProcessQcindex();
                proWorkOrderProcessQcindexQuery.setWorkorderProcessId(workorderProcessId);
                List<ProWorkOrderProcessQcindex> proWorkOrderProcessQcindexListDb = proWorkOrderProcessQcindexMapper.selectProWorkOrderProcessQcindexList(proWorkOrderProcessQcindexQuery);
                for (ProWorkOrderProcessQcindex proWorkOrderProcessQcindex : proWorkOrderProcessQcindexList) {
                    proWorkOrderProcessQcindex.setWorkOrderId(workorderId);
                    proWorkOrderProcessQcindex.setWorkorderProcessId(workorderProcessId);
                    if (proWorkOrderProcessQcindex.getId() == null) {
                        proWorkOrderProcessQcindexService.insertProWorkOrderProcessQcindex(proWorkOrderProcessQcindex);
                    } else {
                        proWorkOrderProcessQcindexService.updateProWorkOrderProcessQcindex(proWorkOrderProcessQcindex);
                    }
                }
                proWorkOrderProcessQcindexListDb.forEach(v -> {
                    if (!proWorkOrderProcessQcindexList.stream().filter(v2 -> v.getId().equals(v2.getId())).findFirst().isPresent()) {
                        proWorkOrderProcessQcindexMapper.deleteProWorkOrderProcessQcindexById(v.getId());
                    }
                });
                //工装
                List<ProWorkOrderProcessTool> proWorkOrderProcessToolList = proWorkOrderProcessVo.getToolList();
                ProWorkOrderProcessTool proWorkOrderProcessToolQuery = new ProWorkOrderProcessTool();
                proWorkOrderProcessToolQuery.setWorkorderProcessId(workorderProcessId);
                List<ProWorkOrderProcessTool> proWorkOrderProcessToolListDb = proWorkOrderProcessToolMapper.selectProWorkOrderProcessToolList(proWorkOrderProcessToolQuery);
                for (ProWorkOrderProcessTool proWorkOrderProcessTool : proWorkOrderProcessToolList) {
                    proWorkOrderProcessTool.setWorkorderProcessId(workorderProcessId);
                    proWorkOrderProcessTool.setWorkOrderId(workorderId);
                    if (proWorkOrderProcessTool.getWorkorderProcessToolId() == null) {
                        proWorkOrderProcessToolService.insertProWorkOrderProcessTool(proWorkOrderProcessTool);
                    } else {
                        proWorkOrderProcessToolService.updateProWorkOrderProcessTool(proWorkOrderProcessTool);
                    }
                }
                proWorkOrderProcessToolListDb.forEach(v -> {
                    if (!proWorkOrderProcessToolList.stream().filter(v2 -> v.getWorkorderProcessToolId().equals(v2.getWorkorderProcessToolId())).findFirst().isPresent()) {
                        proWorkOrderProcessToolMapper.deleteProWorkOrderProcessToolByWorkorderProcessToolId(v.getWorkorderProcessToolId());
                    }
                });
            }
            processListDb.forEach(v -> {
                if (!processList.stream().filter(v2 -> v.getWorkorderProcessId().equals(v2.getWorkorderProcessId())).findFirst().isPresent()) {
                    proWorkOrderProcessMapper.deleteProWorkOrderProcessByWorkorderProcessId(v.getWorkorderProcessId());
                }
            });
        }
        //记录编排规则值
        proWorkOrderArrangeRuleValService.deleteProWorkOrderArrangeRuleVal(proWorkorder.getWorkorderId());
        proWorkOrderArrangeRuleValService.insertProWorkOrderArrangeRuleVal(proWorkorder);
        //记录换型规则值
        proScheduleSetupRuleValService.deleteScheduleSetupRuleVal(proWorkorder.getWorkorderId());
        proScheduleSetupRuleValService.insertProScheduleSetupRuleVal(proWorkorder);
        return i;
    }

    /**
     * 查询生产工单
     *
     * @param workorderIds 生产工单主键
     * @return 生产工单
     */
    @Override
    public void updateProWorkorderStatus(List<Long> workorderIds, WorkorderStatusEnum workOrderStatusEnum) {
        for (Long id : workorderIds) {
            ProWorkorder proWorkorder = proWorkorderMapper.selectWorkorderById(id);
            proWorkorder.setStatus(workOrderStatusEnum.getValue());
            this.updateProWorkorder(proWorkorder);
        }
    }


    @Override
    public List<ProWorkOrderProcessToolLoseVo> checkToolNum(Long[] workOrderIds) {
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(Arrays.asList(workOrderIds)), "缺少工单id,无法检查刀具");

        List<ProWorkOrderProcessToolLoseVo> rst = new ArrayList<>();
        QueryWrapper<ProWorkorder> proWorkorderQueryWrapper = new QueryWrapper<>();
        proWorkorderQueryWrapper.in("workorder_id", workOrderIds);
        List<ProWorkorder> proWorkorders = proWorkorderMapper.selectListByQw(proWorkorderQueryWrapper);

        ExceptionUtil.checkTrueThrowException(proWorkorders.stream().anyMatch(x -> !WorkorderStatusEnum.PREPARE.getValue().equals(x.getStatus())), "只允许待发布状态操作");

        for (ProWorkorder proWorkorder : proWorkorders) {
            QueryWrapper<ProWorkOrderProcessTool> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("t2.workorder_code", proWorkorder.getWorkorderCode());
            List<ProWorkOrderProcessTool> toolList = proWorkOrderProcessToolMapper.selectListByQw(queryWrapper);

            //判断工装量具是否足够
            //合并相同刀具
            Map<Long, IntSummaryStatistics> processToolMap = toolList.stream().collect(Collectors.groupingBy(ProWorkOrderProcessTool::getToolId, Collectors.summarizingInt(x -> DataUtil.getNormalData(getNormalData(x.getQuantity()).intValue(), 1))));

            if (CollectionUtil.isNotEmpty(processToolMap)) {
                Map<Long, MdItem> itemMap = mdItemMapper.selectBatchIds(processToolMap.keySet()).stream().collect(Collectors.toMap(MdItem::getItemId, s -> s));

                QueryWrapper<TmTool> tmToolQueryWrapper = new QueryWrapper<>();
                tmToolQueryWrapper.in("item_id", processToolMap.keySet());
                tmToolQueryWrapper.notIn("status", TmToolStatusEnum.SCRAP.getStatus());
                Map<Long, IntSummaryStatistics> toolMap = tmToolMapper.selectListByQw(tmToolQueryWrapper).stream().collect(Collectors.groupingBy(TmTool::getItemId, Collectors.summarizingInt(x -> DataUtil.getNormalData(getNormalData(x.getQuantity()).intValue(), 1))));

                processToolMap.forEach((key, value) -> {
                    BigDecimal tmToolSize = DataUtil.getNormalData(toolMap.get(key).getSum(), BigDecimal.class);
                    BigDecimal processNeedSize = new BigDecimal(value.getMax());
                    if (tmToolSize.doubleValue() == 0 || processNeedSize.doubleValue() > tmToolSize.doubleValue()) {
                        rst.add(new ProWorkOrderProcessToolLoseVo(itemMap.get(key), processNeedSize.subtract(tmToolSize), null, Collections.singletonList(proWorkorder.getWorkorderCode())));
                    }
                });
            }

        }


        if (CollectionUtil.isNotEmpty(rst)) {
            StringBuilder buffer = new StringBuilder();
            for (ProWorkOrderProcessToolLoseVo loseVo : rst) {
                String excptionMsg = String.format("工单编码：%s，工装量具：%s，不足数量：%s。", loseVo.getWorkorderCodes(), loseVo.getMdItem().getItemName(), loseVo.getLoseNum());

                if (loseVo.getArrangeCode() != null) {
                    excptionMsg = String.format("编排编码：%s，工单编码：%s，工装量具：%s，不足数量：%s。", loseVo.getArrangeCode(), loseVo.getWorkorderCodes(), loseVo.getMdItem().getItemName(), loseVo.getLoseNum());
                }

                buffer.append(excptionMsg);
            }
            throw new ServiceException(buffer.toString());
        }

        //修改工单状态
        proWorkorderService.updateProWorkorderStatus(Arrays.asList(workOrderIds), WorkorderStatusEnum.PUBLISHED);
        return rst;
    }

    @Override
    public String importWorkOrder(MultipartFile file) throws Exception {
        final InputStream inputStream = file.getInputStream();
        final ExcelReader reader = ExcelUtil.getReader(inputStream);
        List<Map<String, Object>> readAll = reader.readAll();
        reader.setSheet(1);
        List<Map<String, Object>> readAll1 = reader.readAll();
        reader.setSheet(2);
        List<Map<String, Object>> readAll2 = reader.readAll();
        reader.setSheet(3);
        List<Map<String, Object>> readAll3 = reader.readAll();
        for (Map<String, Object> map : readAll) {
            final Long prodId = MapUtil.getLong(map, "产品ID");
            final String util = MapUtil.getStr(map, "单位");
            final BigDecimal quantity = new BigDecimal(MapUtil.getStr(map, "生产数量"));
            final Long clientId = MapUtil.getLong(map, "客户ID");
            final Date date = MapUtil.getDate(map, "需求日期");
            final Long routeId = MapUtil.getLong(map, "工艺路线id");
            final MdItem mdItem = mdItemMapper.selectMdItemById(prodId);
            final ProWorkorder proWorkorder = new ProWorkorder();
            proWorkorder.setProductId(prodId);
            proWorkorder.setProductCode(mdItem.getItemCode());
            proWorkorder.setProductName(mdItem.getItemName());
            final String workorderCode = autoCodeUtil.genSerialCode(UserConstants.WORKORDER_CODE, null);
            proWorkorder.setWorkorderCode(workorderCode);
            proWorkorder.setWorkorderName(workorderCode);
            proWorkorder.setUnitOfMeasure(util);
            proWorkorder.setQuantity(quantity);
            proWorkorder.setClientId(clientId);
            proWorkorder.setRequestDate(date);
            proWorkorderMapper.insertProWorkorder(proWorkorder);
            for (Map<String, Object> map1 : readAll1) {
                final Long itemId = MapUtil.getLong(map1, "物料ID");
                final Long compNum = MapUtil.getLong(map1, "组件数量");
                final String calcUtil = MapUtil.getStr(map1, "计量单位");
                final Long scrapPercent = MapUtil.getLong(map1, "报废百分比");
                final String reGroup = MapUtil.getStr(map1, "替代组");
                final String strategy = MapUtil.getStr(map1, "策略");
                final ProWorkOrderBom proWorkOrderBom = new ProWorkOrderBom();
                proWorkOrderBom.setWorkorderId(proWorkorder.getWorkorderId());
                proWorkOrderBom.setItemId(itemId);
                proWorkOrderBom.setQuantity(BigDecimal.valueOf(compNum));
                proWorkOrderBom.setUnitOfMeasure(calcUtil);
                proWorkOrderBom.setScrapPercentage(BigDecimal.valueOf(scrapPercent));
                proWorkOrderBomMapper.insertProWorkOrderBom(proWorkOrderBom);
            }
            for (Map<String, Object> map2 : readAll2) {
                final Long recordId = MapUtil.getLong(map2, "记录ID");
                final Long workStation = MapUtil.getLong(map2, "工作站");
                final Long times = MapUtil.getLong(map2, "标准工时");
                final Long time = MapUtil.getLong(map2, "准备时间");
                final Long waitTime = MapUtil.getLong(map2, "等待时间");
                final String workSerial = MapUtil.getStr(map2, "关键工序");
                final String check = MapUtil.getStr(map2, "是否检验");
                final ProWorkOrderProcess process = new ProWorkOrderProcess();
                process.setWorkorderId(proWorkorder.getWorkorderId());
                process.setWorkstationId(workStation);
                process.setStdWorkingTime(BigDecimal.valueOf(times));
                process.setKeyFlag(workSerial);
                process.setIsCheck(check);
                proWorkOrderProcessMapper.insertProWorkOrderProcess(process);
                for (Map<String, Object> map3 : readAll3) {
                    final Long pItemId = MapUtil.getLong(map3, "产品物料ID");
                    final String utils = MapUtil.getStr(map3, "单位");
                    final Long ccompNum = MapUtil.getLong(map3, "组件数量");
                    final ProWorkOrderProcessItem proWorkOrderProcessItem = new ProWorkOrderProcessItem();
                    proWorkOrderProcessItem.setWorkorderProcessId(process.getWorkorderProcessId());
                    proWorkOrderProcessItem.setItemId(pItemId);
                    proWorkOrderProcessItem.setUnitOfMeasure(utils);
                    proWorkOrderProcessItem.setQuantity(BigDecimal.valueOf(ccompNum));
                    proWorkOrderProcessItemMapper.insertProWorkOrderProcessItem(proWorkOrderProcessItem);
                }
            }
        }
        return "操作成功";
    }

    @Override
    public void importTemplate(HttpServletResponse response) throws IOException {
        List<String> row1 = Arrays.asList("产品ID", "单位", "生产数量", "客户ID", "需求日期", "工艺路线id");
        List<String> row2 = Arrays.asList("物料ID", "组件数量", "计量单位", "报废百分比", "替代组", "替代优先级", "策略", "使用概率");
        List<String> row3 = Arrays.asList("记录ID", "工作站", "标准工时", "准备时间", "等待时间", "关键工序", "是否检验");
        List<String> row4 = Arrays.asList("产品物料ID", "单位", "组件数量");
        final ExcelWriter writer = ExcelUtil.getWriter(true);
        writer.write(Collections.singleton(row1), true);
        writer.setSheet(1);
        writer.write(Collections.singleton(row2), true);
        writer.setSheet(2);
        writer.write(Collections.singleton(row3), true);
        writer.setSheet(3);
        writer.write(Collections.singleton(row4), true);
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", String.format("attachment;filename=workOrder%d.xlsx", System.currentTimeMillis()));
        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
    }

    @Override
    public Integer countByParentCode(String workorderCode) {
        return proWorkorderMapper.selectProWorkorderByParentCode(workorderCode);
    }

    @Transactional
    @Override
    public void addComplements(ProWorkorderVo proWorkorderVo) {
//        String status = proWorkorderVo.getStatus();
//        ExceptionUtil.checkTruethrowException(
//                !Objects.equals(status, WorkorderStatusEnum.PRODUCING.getValue()) ||
//                        !Objects.equals(status, WorkorderStatusEnum.SCHEDULED.getValue()) ||
//                        !Objects.equals(status, WorkorderStatusEnum.ISSUED.getValue()), "需要是排产以后的状态才能补单");
        ProWorkorder proWorkorder = proWorkorderVo.deepCopyObj(ProWorkorder.class);
        String workorderCode = proWorkorderVo.getWorkorderCode();
        Long parentWorkorderId = proWorkorderVo.getWorkorderId();

        ExceptionUtil.checkTrueThrowException(!this.checkWorkorderIsExsit(proWorkorder), "生产工单编号已存在！");
        proWorkorderVo.setParentId(parentWorkorderId);
        proWorkorderVo.setWorkorderId(null);
        proWorkorderVo.setStatus(WorkorderStatusEnum.PREPARE.getValue());
        this.insertProWorkorderVo(proWorkorderVo);

        QueryWrapper<ProWorkorder> proWorkorderQueryWrapper = new QueryWrapper<>();
        proWorkorderQueryWrapper.eq("workorder_code", workorderCode);
        List<ProWorkorder> proWorkorders = proWorkorderMapper.selectListByQw(proWorkorderQueryWrapper);
        ProWorkorder workorder = proWorkorders.get(0);
        Long workorderId = workorder.getWorkorderId();

        QueryWrapper<ProWorkOrderSoDirective> proWorkOrderSoDirectiveQueryWrapper = new QueryWrapper<>();
        proWorkOrderSoDirectiveQueryWrapper.eq("workorder_id", parentWorkorderId);
        List<ProWorkOrderSoDirective> proWorkOrderSoDirectives = proWorkOrderSoDirectiveMapper.selectListByQw(proWorkOrderSoDirectiveQueryWrapper);
        for (ProWorkOrderSoDirective proWorkOrderSoDirective : proWorkOrderSoDirectives) {
            proWorkOrderSoDirective.setWorkorderSoDirectiveId(null);
            proWorkOrderSoDirective.setWorkorderId(workorderId);
            proWorkOrderSoDirective.setWorkorderCode(workorderCode);
            proWorkOrderSoDirectiveMapper.insertProWorkOrderSoDirective(proWorkOrderSoDirective);
        }

        QueryWrapper<ProWorkOrderSoSizeItem> proWorkOrderSoSizeItemQueryWrapper = new QueryWrapper<>();
        proWorkOrderSoSizeItemQueryWrapper.eq("workorder_id", parentWorkorderId);
        List<ProWorkOrderSoSizeItem> proWorkOrderSoSizeItems = proWorkOrderSoSizeItemMapper.selectListByQw(proWorkOrderSoSizeItemQueryWrapper);
        for (ProWorkOrderSoSizeItem proWorkOrderSoSizeItem : proWorkOrderSoSizeItems) {
            proWorkOrderSoSizeItem.setWorkorderSoSizeItemId(null);
            proWorkOrderSoSizeItem.setWorkorderId(workorderId);
            proWorkOrderSoSizeItem.setWorkorderCode(workorderCode);
            proWorkOrderSoSizeItemMapper.insertProWorkOrderSoSizeItem(proWorkOrderSoSizeItem);
        }


        //  检测刀模版具更新发布
        proWorkorderService.checkToolNum(new Long[]{workorderId});


        ProCombination combination = new ProCombination();
        combination.setWorkorderId(workorderId);
        combination.setWorkorderCode(workorderCode);
        combination.setCombinationSort(1L);
        proCombinationService.batchAddProCombination(Collections.singletonList(combination));


        ProArrange proArrange = new ProArrange();
        proArrange.setWorkorderId(workorderId);
        proArrange.setWorkorderCode(workorderCode);
        proArrange.setArrangeSort(1);
        proArrangeService.batchAddProArrange(Collections.singletonList(proArrange));


//        // 自动生成任务
//        List<ProTask> proTasks = proTaskService.generateTask(Collections.singletonList(proWorkorderVo));

        // 讲对应工站的工作单元关联到 补单工单 自动排产任务
//        Map<Long, ProWorkOrderProcessVo> processMap = proWorkorderVo.getProcessList().stream().collect(Collectors.toMap(ProWorkOrderProcessVo::getProcessId, x -> x));
//
//
//        for (ProTask proTask : proTasks) {
//            Long processId = proTask.getProcessId();
//            ProWorkOrderProcessVo process = processMap.get(processId);
//            ProTaskWorkunit proTaskWorkunit = proTaskWorkunitMapper.selectTaskWorkunitByWoIdAndProId(parentId, processId);
//            if (process == null) {
//                if (proTaskWorkunit == null) {
//                    continue;
//                }
//
//                proTask.setWorkunitId(proTaskWorkunit.getWorkunitId());
//                proTask.setWorkunitCode(proTaskWorkunit.getWorkunitCode());
//                proTask.setWorkunitName(proTaskWorkunit.getWorkunitName());
//                proTask.setArrangeCode(arrangeCode);
//                proTask.setStartTime(proTaskWorkunit.getScheduleStartDate());
//                proTask.setEndTime(proTaskWorkunit.getScheduleEndDate());
//            } else {
//                if (process.getWorkunitCode() == null || process.getWorkunitCode() == "") {
//                    continue;
//                }
//
//                List<MdWorkunit> mdWorkunits = mdWorkunitMapper.selectMdWorkunitByWorkunitCode(process.getWorkunitCode());
//                if (mdWorkunits.size() <= 0) {
//                    continue;
//                }
//
//                MdWorkunit mdWorkunit = mdWorkunits.get(0);
//                proTask.setWorkunitId(mdWorkunit.getWorkunitId());
//                proTask.setWorkunitCode(mdWorkunit.getWorkunitCode());
//                proTask.setWorkunitName(mdWorkunit.getWorkunitName());
//                proTask.setArrangeCode(arrangeCode);
//                proTask.setStartTime(process.getStartTime());
//                proTask.setEndTime(process.getEndTime());
//            }
//
//            proTaskService.copyTask(proTask);
//        }

//        this.updateProWorkorder(new ProWorkorder(workorderId, WorkorderStatusEnum.SCHEDULED.getValue()));
    }


    /**
     * 根据生产工单中的产品生成BOM物料行
     *
     * @param workorderId
     */
    @Override
    public void generateBomLine(Long workorderId) {

        //先根据ID找到对应的产品
        ProWorkorderVo workorder = this.selectProWorkorderByWorkorderId(workorderId);

        //根据产品找到BOM组成
        MdProductBom param = new MdProductBom();
        param.setItemId(workorder.getProductId());
        List<MdProductBom> boms = mdProductBomService.selectMdProductBomList(param);

        //生成BOM数据
        BigDecimal orderQuantitiy = workorder.getQuantity();
        ProWorkOrderBom workorderBom = new ProWorkOrderBom();
        if (CollUtil.isNotEmpty(boms)) {
            for (MdProductBom bom : boms) {
                workorderBom.setWorkorderId(workorderId);
                workorderBom.setItemId(bom.getBomItemId());
                workorderBom.setSapItemCode(bom.getBomItemCode());
                workorderBom.setItemName(bom.getBomItemName());
//                workorderBom.setItemSpc(bom.getBomItemSpec());
//                workorderBom.setItemOrProduct(bom.getItemOrProduct());
                workorderBom.setUnitOfMeasure(bom.getUnitOfMeasure());
                workorderBom.setQuantity(orderQuantitiy.multiply(bom.getQuantity()));
                proWorkOrderBomService.insertProWorkOrderBom(workorderBom);
            }
        }
    }

    // 工单保存刀模版具
    private void saveProcessTools(List<ProProductionSolutionProcessToolVo> toolList, ProWorkOrderProcess proWorkOrderProcess) {
        if (CollectionUtil.isNotEmpty(toolList)) {
            List<Long> toolIds = toolList.stream().map(ProProductionSolutionProcessToolVo::getToolId).collect(Collectors.toList());
            QueryWrapper<MdItem> itemQueryWrapper = new QueryWrapper<>();
            itemQueryWrapper.in(CollectionUtil.isNotEmpty(toolIds), "item_id", toolIds);
            List<MdItem> mdItems = mdItemMapper.selectListByQw(itemQueryWrapper);
            Map<Long, MdItem> itemToolMap = mdItems.stream().collect(Collectors.toMap(MdItem::getItemId, x -> x));

            for (ProProductionSolutionProcessToolVo toolVo : toolList) {
                ProWorkOrderProcessTool proWorkOrderProcessTool = toolVo.deepCopyObj(ProWorkOrderProcessTool.class);
                proWorkOrderProcessTool.setWorkorderProcessId(proWorkOrderProcess.getWorkorderProcessId());
                proWorkOrderProcessTool.setWorkOrderId(proWorkOrderProcess.getWorkorderId());
                MdItem mdItem = itemToolMap.get(proWorkOrderProcessTool.getToolId());
                if (mdItem != null) {
                    proWorkOrderProcessTool.setSapItemCode(mdItem.getSapItemCode());
                    proWorkOrderProcessTool.setItemName(mdItem.getItemName());
                }
                proWorkOrderProcessTool.setApiFlag(true);
                proWorkOrderProcessToolService.insertProWorkOrderProcessTool(proWorkOrderProcessTool);
            }

        }
    }

    private void saveSoSizes(List<SAPDtoProWorkOrderSoSizeItem> sizeList, ProWorkorder proWorkorder) {
        if (CollectionUtil.isNotEmpty(sizeList)) {
            proWorkOrderSoSizeItemService.deleteByWorkorderCode(proWorkorder.getWorkorderCode());
            for (SAPDtoProWorkOrderSoSizeItem sizeItem : sizeList) {
                ProWorkOrderSoSizeItem soSizeItem = sizeItem.deepCopyObj(ProWorkOrderSoSizeItem.class);
                soSizeItem.setWorkorderId(proWorkorder.getWorkorderId());
                soSizeItem.setWorkorderCode(proWorkorder.getWorkorderCode());
                BigDecimal quantity = getNormalData(sizeItem.getQuantity(), BigDecimal.class);
                BigDecimal lossNum = getNormalData(sizeItem.getLossNum(), BigDecimal.class);
                soSizeItem.setQuantity(quantity.add(lossNum));
                soSizeItem.setLossNum(lossNum);
                soSizeItem.setSalesId(getNormalData(sizeItem.getSalesId(), Long.class));
                soSizeItem.setApiFlag(true);
                proWorkOrderSoSizeItemService.insertProWorkOrderSoSizeItem(soSizeItem);
            }
        }
    }


    /**
     * 查询SAP平台流水号
     *
     * @param sapDtoProWorkOrder
     * @return
     */
    @Override
    public Integer getAndUpdateSerialByEpService(SAPDtoProWorkOrder sapDtoProWorkOrder) {
        Integer currentSerial = null;
        //客户编码
        List<SAPDtoProWorkOrderSoDirective> soList = sapDtoProWorkOrder.getSaleList();

        String clientCode = soList.get(0).getClientCode();
//        String clientCode = sapDtoProWorkOrder.getClientCode();
        //物料编号
        String sapItemCode = sapDtoProWorkOrder.getSapItemCode();
        ExceptionUtil.checkTrueThrowException(StringUtils.isEmpty(clientCode) || StringUtils.isEmpty(sapItemCode), "客户编码或者物料编码不存在");

        //工单数量
        BigDecimal quantity = sapDtoProWorkOrder.getQuantity();


        Map<String, Object> map = new HashMap<>();
        map.put("clientNo", DataUtil.removeLeftZeros(clientCode));
        map.put("itemNo", DataUtil.removeLeftZeros(sapItemCode));
        String body = JSON.toJSONString(map);
        //先通过远程调用获取当前流水号
        String epItemSerial = epService.getEpItemSerial(body);
//        String epItemSerial = HttpUtils.sendPost("http://192.168.3.91:12000/api/itemSerial/get", body);
        JSONObject jsonObject = JSON.parseObject(epItemSerial);
        String code = jsonObject.getString("code");
        if (code.equals(String.valueOf(HttpStatus.SUCCESS))) {
            JSONObject data = jsonObject.getJSONObject("data");
            if (data != null) {
                //当前流水码
                currentSerial = data.getInteger("currentSerial");
                //开始序列号=当前流水码+1
                //Integer newStartSerial = currentSerial + 1;
                //重新生成当前流水码,生成规则: 新的当前=获得的当前流水码+工单数量
                Integer newCurrentSerial = currentSerial + quantity.intValue();
                //将新的当前流水码传入EP系统
                Map<String, Object> requestMap = new HashMap<>();
                requestMap.put("clientNo", clientCode);
                requestMap.put("itemNo", sapItemCode);
                requestMap.put("currentSerial", newCurrentSerial);
                String bodys = JSON.toJSONString(requestMap);
                log.info("更新流水码请求报文：{}", bodys);
                String s = epService.updateEpItemSerial(bodys);
                //String s = HttpUtils.sendPost("http://192.168.3.91:12000/api/itemSerial/updCurrent", bodys);
                log.info("更新流水码响应报文：{}", s);
            }
        }
        return currentSerial;
    }

    /**
     * 新工单创建--SAP传入
     *
     * @param sapDtoProWorkOrder
     */
    @Transactional
    @Override
    public String sapCreateObj(SAPDtoProWorkOrder sapDtoProWorkOrder) {
        ExceptionUtil.checkTrueThrowException(!StringUtils.isNotNull(sapDtoProWorkOrder), WorkorderConst.WorkOrderErrorConst.ERROR_1);

        String workorderCode = sapDtoProWorkOrder.getWorkorderCode();
        ProWorkorder workorder = proWorkorderMapper.selectProWorkorderWorderCode(workorderCode);
        ExceptionUtil.checkTrueThrowException(Objects.nonNull(workorder), WorkorderConst.WorkOrderErrorConst.ERROR_6);

        // 封装主数据
        ProWorkorder proWorkorder = sapDtoProWorkOrder.deepCopyObj(ProWorkorder.class);
        proWorkorder.setWorkorderType(WorkorderConst.WORK_ORDER_PRODUCT_TYPE);

        String sapItemCode = proWorkorder.getSapItemCode();
        String groupKey = proWorkorder.getGroupKey();
        String groupCounter = proWorkorder.getGroupCounter();

        // 获取任务清单组键值和组计数器
        ExceptionUtil.checkTrueThrowException(!StringUtils.isNotNull(groupKey) && !StringUtils.isNotNull(groupCounter) && !StringUtils.isNotNull(sapItemCode), WorkorderConst.WorkOrderErrorConst.ERROR_3);
        List<SAPDtoProWorkOrderBom> bomList = sapDtoProWorkOrder.getBomList();

        if (!WorkorderConst.SAP_REBACK01_WORK_ORDER_TYPE_LIST.contains(sapDtoProWorkOrder.getWorkorderType())) {
            ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(bomList), "工单缺少bom集合");
        }

        List<SAPDtoProWorkOrderProcess> processList = sapDtoProWorkOrder.getProcessList();
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(processList), "工单缺少工序集合");

        Set<String> processSortList = processList.stream().map(SAPDtoProWorkOrderProcess::getProcessRef).filter(Objects::nonNull).collect(Collectors.toSet());
        ExceptionUtil.checkTrueThrowException(processSortList.size() < processList.size(), "工序顺序重复," + JSON.toJSONString(processList.stream().map(SAPDtoProWorkOrderProcess::getProcessRef).collect(Collectors.toList())));

        List<SAPDtoProWorkOrderSoSizeItem> sizeList = sapDtoProWorkOrder.getSizeList();
        List<SAPDtoProWorkOrderSoDirective> saleList = sapDtoProWorkOrder.getSaleList();

        //        ExceptionUtil.checkTruethrowException(CollectionUtil.isEmpty(saleList), "工单缺少指令集合");

        Map<String, SAPDtoProWorkOrderProcess> processMap = processList.stream().collect(Collectors.toMap(SAPDtoProWorkOrderProcess::getProcessRef, x -> x));
        Map<String, List<SAPDtoProWorkOrderBom>> bomMap = new HashMap<>();
        Map<String, MdItem> itemMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(bomList)) {
            Set<String> collect = bomList.stream().map(SAPDtoProWorkOrderBom::getSapItemCode).collect(Collectors.toSet());
            itemMap = mdItemMapper.selectListByQw(new QueryWrapper<MdItem>().in("sap_item_code", collect)).stream().collect(Collectors.toMap(MdItem::getSapItemCode, x -> x));
            bomMap = bomList.stream().collect(Collectors.groupingBy(SAPDtoProWorkOrderBom::getProcessRef));
        }

        // 生产工单名称
        proWorkorder.setWorkorderName(proWorkorder.getProductName() + "[" + proWorkorder.getQuantity() + "]" + proWorkorder.getUnitOfMeasure() + "生产工单");

        List<MdItem> mdItems = mdItemMapper.selectListByQw(new QueryWrapper<MdItem>().in("sap_item_code", sapItemCode));
        // 根据SAP编码查询产品信息
        if (CollectionUtil.isNotEmpty(mdItems)) {
            MdItem item = mdItems.get(0);
            proWorkorder.setProductId(item.getItemId());
            proWorkorder.setProductName(item.getItemName());
            proWorkorder.setProductCode(item.getSapItemCode());
            proWorkorder.setProductSpc(item.getSpecification());
        }

        // 数据格式转换
        proWorkorder.setQuantity(getNormalData(sapDtoProWorkOrder.getQuantity()));
        proWorkorder.setQuantityProduced(BigDecimal.ZERO);
        proWorkorder.setQuantityQualify(BigDecimal.ZERO);
        proWorkorder.setQuantityUnqualify(BigDecimal.ZERO);
        proWorkorder.setQuantityChanged(BigDecimal.ZERO);
        proWorkorder.setQuantityScheduled(BigDecimal.ZERO);

        if (CollectionUtil.isNotEmpty(saleList)) {
            SAPDtoProWorkOrderSoDirective sapDtoProWorkOrderSoDirective = saleList.get(0);
            String salesVoucher = sapDtoProWorkOrderSoDirective.getSalesVoucher();
            String salesVoucherItem = sapDtoProWorkOrderSoDirective.getSalesVoucherItem();
            String clientCode = sapDtoProWorkOrderSoDirective.getClientCode();
            String clientName = sapDtoProWorkOrderSoDirective.getClientName();

            proWorkorder.setClientCode(StringUtils.isEmpty(proWorkorder.getClientCode()) ? clientCode : proWorkorder.getClientCode());
            proWorkorder.setClientName(StringUtils.isEmpty(proWorkorder.getClientName()) ? clientName : proWorkorder.getClientName());
            proWorkorder.setSalesVoucher(salesVoucher);
            proWorkorder.setSalesVoucherItem(salesVoucherItem);
        }


        proWorkorder.setStatus(WorkorderStatusEnum.PREPARE.getValue());

        try {
            //请求SAP查询流水号
            if (saleList != null && CollectionUtil.isNotEmpty(saleList)) {
                Integer startSerial = this.getAndUpdateSerialByEpService(sapDtoProWorkOrder);
                Integer endSerial = startSerial + proWorkorder.getQuantity().intValue();
                proWorkorder.setStartSerial(String.valueOf(startSerial));
                proWorkorder.setEndSerial(String.valueOf(endSerial));
            }
        } catch (Exception ignored) {
            log.info("生产工单: " + workorderCode + ", EP没有流水号。");
        }


        proWorkorder.setApiFlag(true);
        this.insertProWorkorder(proWorkorder);
        Long workorderId = proWorkorder.getWorkorderId();

        if (WorkorderConst.SAP_REBACK01_WORK_ORDER_TYPE_LIST.contains(sapDtoProWorkOrder.getWorkorderType())) {
            proWorkorder.setWorkorderType(WorkorderConst.WORK_ORDER_RESTRUCTURING_TYPE);


            Set<String> processNames = processMap.values().stream().filter(Objects::nonNull).map(SAPDtoProWorkOrderProcess::getProcessName).collect(Collectors.toSet());
            Map<String, ProProcess> processNameMap = proProcessMapper.selectListByQw(new QueryWrapper<ProProcess>().in("process_name", processNames)).stream().collect(Collectors.toMap(ProProcess::getProcessName, x -> x));
            ExceptionUtil.checkTrueThrowException(processMap.size() != processNameMap.size(), "返修工单工序未同步");


            for (Map.Entry<String, SAPDtoProWorkOrderProcess> entry : processMap.entrySet()) {
                String idx = entry.getKey();
                SAPDtoProWorkOrderProcess value = entry.getValue();
                ProWorkOrderProcess proWorkOrderProcess = value.deepCopyObj(ProWorkOrderProcess.class);
                proWorkOrderProcess.setApiFlag(true);

                ProProcess proProcess = processNameMap.get(idx);
                proWorkOrderProcessService.insertProWorkOrderProcess(proWorkOrderProcess);
                if (CollectionUtil.isNotEmpty(bomMap)) {
                    List<SAPDtoProWorkOrderBom> sapDtoProWorkOrderBoms = bomMap.get(idx);
                    saveProcessItems(sapDtoProWorkOrderBoms, proProcess, null, proWorkOrderProcess, itemMap);
                }
            }
        } else {

            // 获取生产版本
            ProProductionSolution productionSolution = proProductionSolutionService.selectByGroupKeyAndGroupCounterAndSapItemCode(groupKey, groupCounter, sapItemCode);
            ExceptionUtil.checkTrueThrowException(ObjectUtil.isEmpty(productionSolution), WorkorderConst.WorkOrderErrorConst.ERROR_5);

            // 获取生产版本数据
            ProProductionSolutionVo proProductionSolutionVo = proProductionSolutionService.selectProProductionSolutionByProductionSolutionId(productionSolution.getProductionSolutionId());

            ProProductionSolutionSpecificationSheet specificationSheet = proProductionSolutionVo.getSpecificationSheet();
            ExceptionUtil.checkTrueThrowException(specificationSheet == null, "请检查缺少生产规格书配置");
            proWorkorder.setDispatchMultiple(DataUtil.getNormalData(specificationSheet.getSendworkMultiple(), String.class));
            proWorkorder.setThickness(getNormalData(specificationSheet.getThick()));
            proWorkorder.setStorageLocation(getNormalData(specificationSheet.getStorePlace()));
            proWorkorder.setRowNum(getNormalData(specificationSheet.getRowNum(), String.class));
            proWorkorder.setSingleWeight(getNormalData(specificationSheet.getSingleWeight()));


            // 保存BOM信息
            if (CollectionUtil.isNotEmpty(bomList)) {
                for (SAPDtoProWorkOrderBom bom : bomList) {
                    ProWorkOrderBom proWorkOrderBom = bom.deepCopyObj(ProWorkOrderBom.class);
                    String code = proWorkOrderBom.getSapItemCode();
                    MdItem mdItem = itemMap.get(code);
                    ExceptionUtil.checkTrueThrowException(StringUtils.isNull(mdItem), WorkorderConst.WorkOrderErrorConst.ERROR_2);

                    proWorkOrderBom.setItemId(mdItem.getItemId());
                    proWorkOrderBom.setItemName(mdItem.getItemName());
                    proWorkOrderBom.setSapItemCode(code);

                    proWorkOrderBom.setWorkorderId(workorderId);
                    proWorkOrderBom.setWorkorderCode(workorderCode);
                    proWorkOrderBom.setQuantity(getNormalData(bom.getQuantity(), BigDecimal.class));
                    proWorkOrderBom.setUnitUsage(getNormalData(bom.getUnitUsage()));
                    String isBackFlush = Objects.equals(bom.getIsBackflush(), "X") ? "Y" : "N";
                    proWorkOrderBom.setIsBackflush(isBackFlush);
                    proWorkOrderBom.setApiFlag(true);
                    proWorkOrderBomService.insertProWorkOrderBom(proWorkOrderBom);
                }
            }

            List<ProProductionSolutionProcessVo> solutionProcessVos = proProductionSolutionVo.getProcessList();
            if (CollectionUtil.isNotEmpty(solutionProcessVos)) {
                for (ProProductionSolutionProcessVo solutionProcessVo : solutionProcessVos) {
                    ProWorkOrderProcess proWorkOrderProcess = solutionProcessVo.deepCopyObj(ProWorkOrderProcess.class);
                    proWorkOrderProcess.setWorkorderId(workorderId);
                    proWorkOrderProcess.setWorkorderCode(workorderCode);
                    proWorkOrderProcess.setApiFlag(true);
                    String idx = proWorkOrderProcess.getIdx();
                    SAPDtoProWorkOrderProcess sapDtoProWorkOrderProcess = processMap.get(idx);
                    if (sapDtoProWorkOrderProcess != null) {
                        proWorkOrderProcess.setControlCode(sapDtoProWorkOrderProcess.getControlCode());
                        proWorkOrderProcess.setQuantity(DataUtil.getNormalData(sapDtoProWorkOrderProcess.getQuantity(), BigDecimal.class));
                    }

                    proWorkOrderProcessService.insertProWorkOrderProcess(proWorkOrderProcess);
                    List<SAPDtoProWorkOrderBom> sapDtoProWorkOrderBoms = bomMap.get(idx);
                    saveProcessItems(sapDtoProWorkOrderBoms, null, solutionProcessVo, proWorkOrderProcess, itemMap);

                    // 获取质检 工装信息
                    List<ProProductionSolutionProcessToolVo> toolList = solutionProcessVo.getToolList();
                    toolList = toolList.stream().filter(x -> x.getToolId() != null).collect(Collectors.toList());

                    // 保存工装
                    saveProcessTools(toolList, proWorkOrderProcess);
                }
            }
        }

        // 保存so指令
        saveSoDirectives(saleList, proWorkorder);

        // 保存尺码组信息
        saveSoSizes(sizeList, proWorkorder);

        //记录编排规则值
        proWorkOrderArrangeRuleValService.insertProWorkOrderArrangeRuleVal(proWorkorder);

        //记录换型规则值
        proScheduleSetupRuleValService.insertProScheduleSetupRuleVal(proWorkorder);
        return null;
    }

    private void saveSoDirectives(List<SAPDtoProWorkOrderSoDirective> saleList, ProWorkorder proWorkorder) {
        if (CollectionUtil.isNotEmpty(saleList)) {
            proWorkOrderSoDirectiveService.deleteByWorkorderCode(proWorkorder.getWorkorderCode());

            for (SAPDtoProWorkOrderSoDirective directive : saleList) {
                ProWorkOrderSoDirective proWorkOrderSoDirective = directive.deepCopyObj(ProWorkOrderSoDirective.class);
                proWorkOrderSoDirective.setWorkorderId(proWorkorder.getWorkorderId());
                proWorkOrderSoDirective.setWorkorderCode(proWorkorder.getWorkorderCode());
                BigDecimal quantity = getNormalData(directive.getQuantity(), BigDecimal.class);
                BigDecimal lossNum = getNormalData(directive.getLossNum(), BigDecimal.class);
                proWorkOrderSoDirective.setQuantity(quantity.add(lossNum));
                proWorkOrderSoDirective.setLossNum(lossNum);
                proWorkOrderSoDirective.setApiFlag(true);
                proWorkOrderSoDirectiveService.insertProWorkOrderSoDirective(proWorkOrderSoDirective);
            }
        }
    }


    private void saveProcessItems(List<SAPDtoProWorkOrderBom> sapDtoProWorkOrderBoms, ProProcess proProcess, ProProductionSolutionProcessVo solutionProcessVo, ProWorkOrderProcess proWorkOrderProcess, Map<String, MdItem> itemMap) {
        if (CollectionUtil.isNotEmpty(sapDtoProWorkOrderBoms)) {
            for (SAPDtoProWorkOrderBom bom : sapDtoProWorkOrderBoms) {
                String code = bom.getSapItemCode();
                MdItem mdItem = itemMap.get(code);
                ProWorkOrderProcessItem proWorkOrderProcessItem = new ProWorkOrderProcessItem();
                proWorkOrderProcessItem.setWorkorderProcessId(proWorkOrderProcess.getWorkorderProcessId());
                proWorkOrderProcessItem.setItemId(mdItem.getItemId());
                proWorkOrderProcessItem.setItemCode(mdItem.getItemCode());
                proWorkOrderProcessItem.setItemName(mdItem.getItemName());
                proWorkOrderProcessItem.setSapItemCode(code);
                proWorkOrderProcessItem.setItemTypeName(mdItem.getItemTypeName());
                if (solutionProcessVo != null) {
                    proWorkOrderProcessItem.setProcessName(solutionProcessVo.getProcessName());
                    proWorkOrderProcessItem.setProcessCode(solutionProcessVo.getProcessCode());
                    proWorkOrderProcessItem.setUnitConvert(solutionProcessVo.getUnitConvert());
                }

                if (proProcess != null) {
                    proWorkOrderProcessItem.setProcessName(proProcess.getProcessName());
                    proWorkOrderProcessItem.setProcessCode(proProcess.getProcessCode());
//                    proWorkOrderProcessItem.setUnitConvert(proProcess.getUnitConvert());
                }

                proWorkOrderProcessItem.setUnitOfMeasure(bom.getUnitOfMeasure());
                proWorkOrderProcessItem.setQuantity(DataUtil.getNormalData(bom.getQuantity(), BigDecimal.class));
                proWorkOrderProcessItem.setRequirementNumber(bom.getRequirementNumber());
                proWorkOrderProcessItem.setRequirementProjectNumber(bom.getRequirementProjectNumber());
                proWorkOrderProcessItem.setStoreAddr(bom.getStoreAddr());
                proWorkOrderProcessItem.setScrapPercentage(DataUtil.getNormalData(bom.getScrapPercentage(), BigDecimal.class));
                proWorkOrderProcessItem.setUnitUsage(DataUtil.getNormalData(bom.getUnitUsage()));
                proWorkOrderProcessItem.setProcessRef(proWorkOrderProcess.getIdx());
                proWorkOrderProcessItem.setIsBackflush(Objects.equals(bom.getIsBackflush(), "X") ? "Y" : "N");
                proWorkOrderProcessItem.setApiFlag(true);
                proWorkOrderProcessItemService.insertProWorkOrderProcessItem(proWorkOrderProcessItem);
            }
        }

    }


    /**
     * 新工单创建--SAP传入
     *
     * @param SAPDtoProWorkorder
     */

    @Override
    @Transactional
    public String workorderCreate(EPDtoProWorkOrder SAPDtoProWorkorder) {
        SAPDtoProWorkorder.getWorkorderCode();
//        if (!StringUtils.isNotNull(SAPDtoProWorkorder)) {
//            return 1;
//        }
        ExceptionUtil.checkTrueThrowException(StringUtils.isEmpty(SAPDtoProWorkorder), "传的是空数据");
        // TODO SAP传入工单
        List<EPDtoProWorkOrderBom> bomList = SAPDtoProWorkorder.getBomList();
        // 封装主数据
        ProWorkorder proWorkorder = new ProWorkorder();
        BeanUtils.copyProperties(SAPDtoProWorkorder, proWorkorder);
        // 根据SAP编码查询产品信息
        MdItem item = mdItemMapper.selectMdItemBySapItemCode(proWorkorder.getSapItemCode());
        if (StringUtils.isNotNull(item)) {
            proWorkorder.setProductId(item.getItemId());
            proWorkorder.setProductName(item.getItemName());
            proWorkorder.setProductCode(item.getItemCode());
        }
        // 生产工单名称
        String productName = proWorkorder.getProductName();
        proWorkorder.setWorkorderName(proWorkorder.getProductName() + "[" + proWorkorder.getQuantity() + "]" + proWorkorder.getUnitOfMeasure() + "生产工单");
        // 数据格式转换
        if (StringUtils.isNotNull(SAPDtoProWorkorder.getQuantity())) {
            proWorkorder.setQuantity(SAPDtoProWorkorder.getQuantity());
        }
        if (StringUtils.isNotNull(SAPDtoProWorkorder.getSingleWeight())) {
            proWorkorder.setSingleWeight(SAPDtoProWorkorder.getSingleWeight());
        }
        if (StringUtils.isNotNull(SAPDtoProWorkorder.getThickness())) {
            proWorkorder.setThickness(SAPDtoProWorkorder.getThickness());
        }
        if (StringUtils.isNotNull(SAPDtoProWorkorder.getPackNum())) {
            proWorkorder.setPackNum(SAPDtoProWorkorder.getPackNum());
        }

        // 保存
        if (StringUtils.isNotNull(proWorkorder.getStatus())) {
            if (proWorkorder.getStatus().equals("I0002")) {
                proWorkorder.setStatus("PREPARE");
            }
            proWorkorder.setWorkorderType("product");
        }

        //打样工单需要加的数据
        if (StringUtils.isNotNull(SAPDtoProWorkorder.getEpItem())) {
            if (SAPDtoProWorkorder.getEpItem().equals("ZB02")) {
                proWorkorder.setStatus("PREPARE");
                proWorkorder.setWorkorderType(WorkorderConst.WORK_ORDER_PROTO_TYPE);
                proWorkorder.setProductCode(proWorkorder.getEpItemCode());

            }
        }
        ProProductionSolution proProductionSolutions = proProductionSolutionMapper.selectProProductionSolutionBySapPrototypeMakeCode(SAPDtoProWorkorder.getWorkorderCode());
        ExceptionUtil.checkTrueThrowException(Objects.isNull(proProductionSolutions), "没有匹配到生产版本");
        proWorkorder.setRequestDate(proProductionSolutions.getExpiryDate());
        proWorkorder.setStartDate(DateUtils.getNowDate());
        ProWorkorder proWorkorder1 = proWorkorderMapper.selectProWorkorderWorderCode(SAPDtoProWorkorder.getWorkorderCode());
//        if (Objects.nonNull(proWorkorder1)) {
//            return 6;
//        }
        ExceptionUtil.checkTrueThrowException(Objects.nonNull(proWorkorder1), "数据已经存在不能重复");
        proWorkorder.setCreateBy("EP");
        proWorkorder.setCreateTime(DateUtils.getNowDate());
        proWorkorderMapper.insertProWorkorder(proWorkorder);
        Long workorderId = proWorkorder.getWorkorderId();
        String workorderCode = proWorkorder.getWorkorderCode();


        if (StringUtils.isNotNull(bomList)) {
            for (EPDtoProWorkOrderBom SAPDtoProWorkOrderBom : bomList) {
                ProWorkorder proWorkorder2 = proWorkorderMapper.selectWorkorderById(workorderId);
                ProWorkOrderBom proWorkOrderBom = new ProWorkOrderBom();
                BeanUtils.copyProperties(SAPDtoProWorkOrderBom, proWorkOrderBom);
                proWorkOrderBom.setSapItemCode(SAPDtoProWorkOrderBom.getSapItemCodes());
                MdItem item2 = mdItemMapper.selectMdItemBySapItemCode(proWorkOrderBom.getSapItemCode());
                ExceptionUtil.checkTrueThrowException(StringUtils.isNull(item2), "没有对应的物料信息");
                if (StringUtils.isNotNull(item2)) {
                    proWorkOrderBom.setItemId(item2.getItemId());
                    proWorkOrderBom.setItemName(item2.getItemName());

                    if (StringUtils.isNotNull(SAPDtoProWorkOrderBom.getQuantity())) {
                        proWorkOrderBom.setQuantity(new BigDecimal(SAPDtoProWorkOrderBom.getQuantity()));
                    }
                    if (StringUtils.isNotNull(SAPDtoProWorkOrderBom.getScrapPercentage())) {
                        proWorkOrderBom.setScrapPercentage(new BigDecimal(SAPDtoProWorkOrderBom.getScrapPercentage()));
                    }
                    if (StringUtils.isNotNull(SAPDtoProWorkOrderBom.getUnitUsage())) {
                        proWorkOrderBom.setUnitUsage(SAPDtoProWorkOrderBom.getUnitUsage());
                    }
                    if (StringUtils.isNotNull(SAPDtoProWorkOrderBom.getUnitConvert())) {
                        proWorkOrderBom.setUnitConvert(new BigDecimal(SAPDtoProWorkOrderBom.getUnitConvert()));
                    }
                    proWorkOrderBom.setUnitOfMeasure(item2.getUnitOfMeasure());
                    proWorkOrderBom.setWorkorderId(workorderId);
                    proWorkOrderBom.setWorkorderCode(proWorkorder2.getWorkorderCode());
                    proWorkOrderBom.setCreateBy("EP");
                    proWorkOrderBom.setCreateTime(DateUtils.getNowDate());
                    proWorkOrderBomMapper.insertProWorkOrderBom(proWorkOrderBom);
                }
            }
        }


        //根据ep传来sap打样工单获取生产版本
        ProProductionSolution proProductionSolution = proProductionSolutionMapper.selectProProductionSolutionBySapPrototypeMakeCode(SAPDtoProWorkorder.getWorkorderCode());
        if (StringUtils.isNotNull(SAPDtoProWorkorder.getEpItem())) {

            if (ObjectUtil.isNotEmpty(proProductionSolution)) {
                Long productionSolutionIds = proProductionSolution.getProductionSolutionId();

                // 获取生产版本数据
                ProProductionSolutionVo proProductionSolutionVos = proProductionSolutionService.selectProProductionSolutionByProductionSolutionId(productionSolutionIds);
                List<ProProductionSolutionProcessVo> solutionProcessV = proProductionSolutionVos.getProcessList();
                if (ObjectUtil.isNotEmpty(solutionProcessV)) {
                    for (ProProductionSolutionProcessVo solutionProcessVo : solutionProcessV) {
                        ProWorkOrderProcess proWorkOrderProcess = new ProWorkOrderProcess();
                        BeanUtils.copyProperties(solutionProcessVo, proWorkOrderProcess);
                        proWorkOrderProcess.setWorkorderId(workorderId);
                        proWorkOrderProcess.setWorkorderCode(workorderCode);
                        proWorkOrderProcess.setCreateBy("EP");
                        proWorkOrderProcess.setCreateTime(DateUtils.getNowDate());
                        proWorkOrderProcessMapper.insertProWorkOrderProcess(proWorkOrderProcess);
                        Long workorderProcessId = proWorkOrderProcess.getWorkorderProcessId();

                        List<ProProductionSolutionProcessItem> processItemList = solutionProcessVo.getProcessItemList();

                        // 保存物料
                        if (ObjectUtil.isNotEmpty(processItemList)) {
                            for (ProProductionSolutionProcessItem proProductionSolutionProcessItem : processItemList) {
                                ProWorkOrderProcessItem proWorkOrderProcessItem = new ProWorkOrderProcessItem();
                                BeanUtils.copyProperties(proProductionSolutionProcessItem, proWorkOrderProcessItem);
                                MdItem item3 = mdItemMapper.selectMdItemBySapItemCode(proWorkOrderProcessItem.getSapItemCode());
                                ExceptionUtil.checkTrueThrowException(StringUtils.isNull(item3), "没有匹配到对应的工序物料");
                                if (StringUtils.isNotNull(item3)) {
                                    proWorkOrderProcessItem.setItemId(item3.getItemId());
                                    proWorkOrderProcessItem.setItemCode(item3.getItemCode());
                                    proWorkOrderProcessItem.setItemName(item3.getItemName());
                                    proWorkOrderProcessItem.setWorkorderProcessId(workorderProcessId);
                                    proWorkOrderProcessItem.setCreateBy("EP");
                                    proWorkOrderProcessItem.setCreateTime(DateUtils.getNowDate());
                                    proWorkOrderProcessItemMapper.insertProWorkOrderProcessItem(proWorkOrderProcessItem);
                                }
                            }
                        }

                        // 获取质检 工装信息
                        List<ProProductionSolutionProcessToolVo> toolList = solutionProcessVo.getToolList();
                        // 保存工装
                        if (StringUtils.isNotNull(toolList)) {
                            for (ProProductionSolutionProcessToolVo proProductionSolutionProcessToolVo : toolList) {
                                ProWorkOrderProcessTool proWorkOrderProcessTool = new ProWorkOrderProcessTool();
                                BeanUtils.copyProperties(proProductionSolutionProcessToolVo, proWorkOrderProcessTool);
                                proWorkOrderProcessTool.setWorkorderProcessId(workorderProcessId);
                                proWorkOrderProcessTool.setCreateBy("EP");
                                proWorkOrderProcessTool.setCreateTime(DateUtils.getNowDate());
                                proWorkOrderProcessToolMapper.insertProWorkOrderProcessTool(proWorkOrderProcessTool);
                            }

                        }
                    }
                }
            } else {
                ExceptionUtil.checkTrueThrowException(true, "没有匹配到生产版本");
            }
        }

        return null;
    }

    /**
     * 根据工单生成所有包装标签生成
     */
    @Override
    @Transactional
    public void buildAllPackagePrintInfo(BuildPackageParams2 buildPackageParams2) {
        buildPackageParams2.initPackageValue();
        ProWorkorder workorder = proWorkorderService.selectWorkorderById(buildPackageParams2.getWorkorderId());
        workorder.setUsagePackNum(buildPackageParams2.getPackNum());
        workorder.setUsageEncasementNum(buildPackageParams2.getEncasementNum());
        workorder.setMergePack(0);
        WorkorderPackageResult packageResult = this.buildPackagePrintInfo(buildPackageParams2);
        packageResult.getPackageList().forEach(s -> {
            ProPackagePrintRecord packagePrintRecord = new ProPackagePrintRecord();
            BeanUtil.copyProperties(s, packagePrintRecord);
            ProPackagePrintRecordServiceImpl.initSizeIds(packageResult, s, packagePrintRecord);
            proFdPackagePrintRecordService.insertProPackagePrintRecord(packagePrintRecord);
        });
        this.updateProWorkorder(workorder);
    }

    @Override
    public WorkorderPackageResult buildPackagePrintInfo(BuildPackageParams2 buildPackageParams) {
        ProWorkorder workorder = proWorkorderService.selectWorkorderById(buildPackageParams.getWorkorderId());
        ProWorkOrderSoSizeItem query1 = new ProWorkOrderSoSizeItem();
        query1.setWorkorderId(buildPackageParams.getWorkorderId());
        List<ProWorkOrderSoSizeItem> sizeList = proWorkOrderSoSizeItemService.selectProWorkOrderSoSizeItemList(query1);
        ProWorkOrderSoDirective query2 = new ProWorkOrderSoDirective();
        query2.setWorkorderId(buildPackageParams.getWorkorderId());
        List<ProWorkOrderSoDirective> directiveList = proWorkOrderSoDirectiveService.selectProWorkOrderSoDirectiveList(query2);
        MdItem mdItem = mdItemService.selectMdItemById(workorder.getProductId());
        buildPackageParams.setWorkorderCode(workorder.getWorkorderCode());
        buildPackageParams.setSapItemCode(mdItem.getSapItemCode());
        buildPackageParams.setQuantity(workorder.getQuantity().intValue());
        List<WorkorderPackage> packageList = this.buildPackagePrintInfo(buildPackageParams, directiveList, sizeList);
        WorkorderPackageResult rst = new WorkorderPackageResult();
        rst.setPackageList(packageList);
        rst.setSizeList(sizeList);
        rst.setDirectiveList(directiveList);
        rst.setPackageType(PackageType.NONE);
        if (!sizeList.isEmpty()) {
            rst.setPackageType(PackageType.SIZE);
        } else if (!directiveList.isEmpty()) {
            rst.setPackageType(PackageType.DIRECTIVE);
        }
        return rst;
    }


    private List<WorkorderPackage> buildPackagePrintInfo(BuildPackageParams2 buildPackageParams, List<ProWorkOrderSoDirective> directiveList, List<ProWorkOrderSoSizeItem> sizeList) {
        if (buildPackageParams.getPackNum() == null || buildPackageParams.getPackNum() == 0) {
            buildPackageParams.setPackNum(Integer.MAX_VALUE);
        }
        if (buildPackageParams.getPackNum() != 0 && buildPackageParams.getEncasementNum() != null && buildPackageParams.getEncasementNum() > 0 && buildPackageParams.getPackNum() > buildPackageParams.getEncasementNum()) {
            throw new ServiceException("包装数量不允许大于装箱数");
        }
        List<WorkorderPackage> rst = new ArrayList<WorkorderPackage>();
        if (sizeList != null && !sizeList.isEmpty()) {
            if (directiveList == null || directiveList.isEmpty()) {
                throw new ServiceException("指令数据不存在");
            }
            ProWorkOrderSoDirective directive = directiveList.get(0);
            sizeList = sizeList.stream().sorted(Comparator.comparing(ProWorkOrderSoSizeItem::getWorkorderSoSizeItemId)).collect(Collectors.toList());
            List<PackageBasicData> listData = new ArrayList<PackageBasicData>();
            sizeList.forEach(s -> {
                if (s.getQuantity() == null || s.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                    throw new ServiceException("SIZE派工数量未设置");
                }
                if (s.getLossNum() == null) {
                    s.setLossNum(BigDecimal.ZERO);
                }
                listData.add(new PackageBasicData(s.getWorkorderSoSizeItemId(), s.getQuantity().intValue(), s.getLossNum().intValue(), "Y".equalsIgnoreCase(directive.getLossPack()), buildPackageParams.getPackNum().intValue()));
            });
            List<WorkorderPackage> tempList = ProWorkorderServiceImpl.splitPackage(listData, buildPackageParams.getMergePack(), PackageType.SIZE);
            rst.addAll(tempList);

        } else if (directiveList != null && !directiveList.isEmpty()) {
            List<PackageBasicData> listData = new ArrayList<PackageBasicData>();
            directiveList = directiveList.stream().map(s -> {
                if (org.apache.commons.lang3.StringUtils.isBlank(s.getClientCmd())) {
                    s.setClientCmd("");
                }
                return s;
            }).sorted(Comparator.comparing(ProWorkOrderSoDirective::getClientCmd)).collect(Collectors.toList());
            directiveList.forEach(s -> {
                //包装数量指令存在使用指令的，指令不存在使用界面录入
                listData.add(new PackageBasicData(s.getWorkorderSoDirectiveId(), s.getQuantity().intValue(), s.getLossNum().intValue(), "Y".equalsIgnoreCase(s.getLossPack()), buildPackageParams.getPackNum().intValue()));
            });
            List<WorkorderPackage> tempList = ProWorkorderServiceImpl.splitPackage(listData, buildPackageParams.getMergePack(), PackageType.DIRECTIVE);
            rst.addAll(tempList);
        } else {
            //按工单包装
            List<WorkorderPackage> tempList = ProWorkorderServiceImpl.splitPackage(buildPackageParams.getQuantity(), buildPackageParams.getPackNum().intValue(), 0, false);
            rst.addAll(tempList);
        }

        //生成包装标签二维码，PL开头
        AtomicReference<Integer> index = new AtomicReference<Integer>(1);
        rst.forEach(s -> {
            s.setQrcode(ProWorkorderServiceImpl.buildLabelQrcode("PL", buildPackageParams.getWorkorderCode(), buildPackageParams.getSapItemCode(), s.getPackageNum(), index.get()));
            s.setSheetCount(index.get());
            s.setTotalCount(rst.size());
            index.getAndSet(index.get() + 1);
        });
        if (buildPackageParams.getEncasementNum() != null && buildPackageParams.getEncasementNum() > 0) {
            this.buildBlPackage(buildPackageParams, rst);
        }
        rst.forEach(s -> {
            s.setWorkorderId(buildPackageParams.getWorkorderId());
        });
        return rst;
    }

    //计算装箱数量
    private void buildBlPackage(BuildPackageParams2 buildPackageParams, List<WorkorderPackage> rst) {
        //生成装箱二维码，BL开头
        Integer index2 = 1;
        int tempNum = 0;
        int tempLossNum = 0;
        int plLen = rst.size();//PL数量
        List<WorkorderPackage.QuantityDistribute> distributeList = new ArrayList<WorkorderPackage.QuantityDistribute>();
        List<WorkorderPackage> tempPackageList = new ArrayList<WorkorderPackage>();
        for (int j = 0; j < rst.size(); j++) {
            WorkorderPackage s = rst.get(j);
            int currNum = s.getPackageNum() + s.getLossNum();
            WorkorderPackage encaseLabel = new WorkorderPackage();
            WorkorderPackage.QuantityDistribute currDistribute = null;
            currDistribute = new WorkorderPackage.QuantityDistribute(s.getWorkorderSoDirectiveId(), s.getWorkorderSoSizeItemId(), s.getPackageNum(), s.getLossNum());
            if (tempNum + tempLossNum + currNum == buildPackageParams.getEncasementNum()) {
                if (currDistribute != null) {
                    distributeList.add(currDistribute);
                }
                BeanUtil.copyProperties(s, encaseLabel);
                encaseLabel.setWorkorderSoDirectiveId(null);
                encaseLabel.setWorkorderSoSizeItemId(null);
                encaseLabel.setPackageNum(tempNum + s.getPackageNum());
                encaseLabel.setLossNum(tempLossNum + s.getLossNum());
                encaseLabel.setSheetCount(index2);
                encaseLabel.setDistributes(ProWorkorderServiceImpl.merge(distributeList));
                encaseLabel.setQrcode(ProWorkorderServiceImpl.buildLabelQrcode("BL", buildPackageParams.getWorkorderCode(), buildPackageParams.getSapItemCode(), buildPackageParams.getEncasementNum(), index2));
                tempPackageList.add(s);
                encaseLabel.setPackageList(BeanUtil.copyToList(tempPackageList, WorkorderPackage.class));
                tempPackageList.clear();
                rst.add(j + 1, encaseLabel);
                j++;
                tempNum = 0;
                tempLossNum = 0;
                distributeList = new ArrayList<WorkorderPackage.QuantityDistribute>();
                index2++;
            } else if (tempNum + tempLossNum + currNum > buildPackageParams.getEncasementNum()) {
                BeanUtil.copyProperties(s, encaseLabel);
                encaseLabel.setWorkorderSoDirectiveId(null);
                encaseLabel.setWorkorderSoSizeItemId(null);
                encaseLabel.setPackageNum(tempNum);
                encaseLabel.setLossNum(tempLossNum);
                encaseLabel.setSheetCount(index2);
                encaseLabel.setDistributes(ProWorkorderServiceImpl.merge(distributeList));
                encaseLabel.setQrcode(ProWorkorderServiceImpl.buildLabelQrcode("BL", buildPackageParams.getWorkorderCode(), buildPackageParams.getSapItemCode(), tempNum, index2));
                encaseLabel.setPackageList(BeanUtil.copyToList(tempPackageList, WorkorderPackage.class));
                tempPackageList.clear();
                rst.add(j, encaseLabel);
                j++;
                tempNum = s.getPackageNum();
                tempLossNum = s.getLossNum();
                distributeList = new ArrayList<WorkorderPackage.QuantityDistribute>();
                distributeList.add(currDistribute);
                tempPackageList.add(s);
                index2++;
            } else {
                if (currDistribute != null) {
                    distributeList.add(currDistribute);
                }
                tempPackageList.add(s);
                tempNum += s.getPackageNum();
                tempLossNum += s.getLossNum();
            }
            if (rst.size() == j + 1 && (tempNum + tempLossNum) > 0) {
                encaseLabel = new WorkorderPackage();
                BeanUtil.copyProperties(s, encaseLabel);
                encaseLabel.setWorkorderSoDirectiveId(null);
                encaseLabel.setWorkorderSoSizeItemId(null);
                encaseLabel.setPackageNum(tempNum);
                encaseLabel.setLossNum(tempLossNum);
                encaseLabel.setSheetCount(index2);
                encaseLabel.setDistributes(ProWorkorderServiceImpl.merge(distributeList));
                encaseLabel.setQrcode(ProWorkorderServiceImpl.buildLabelQrcode("BL", buildPackageParams.getWorkorderCode(), buildPackageParams.getSapItemCode(), tempNum, index2));
                encaseLabel.setPackageList(BeanUtil.copyToList(tempPackageList, WorkorderPackage.class));
                tempPackageList.clear();
                rst.add(encaseLabel);
                break;
            }
        }
        //设置总页码与索引页
        Integer tempIndex = rst.size() - plLen;
        int i = 0;
        for (WorkorderPackage s : rst) {
            if (s.getQrcode().startsWith("BL")) {
                s.setTotalCount(tempIndex);
                s.setBlGroup(s.getSheetCount());
                i = s.getSheetCount();
            } else {
                s.setBlGroup(i + 1);
            }
        }
    }

    @Override
    public List<WorkorderPackage> convertSplitData(List<WorkorderPackage> packageList) {
        List<WorkorderPackage> rst = new ArrayList<WorkorderPackage>();
        packageList.forEach(s -> {
            if (s.getDistributes() != null && !s.getDistributes().isEmpty() && s.getPackageNum() > 0) {
                s.getDistributes().forEach(s2 -> {
                    WorkorderPackage temp = new WorkorderPackage();
                    BeanUtil.copyProperties(s, temp);
                    temp.setPackageNum(s2.getPackageNum());
                    temp.setLossNum(s2.getLossNum());
                    temp.setWorkorderSoDirectiveId(s2.getDirectiveId());
                    temp.setWorkorderSoSizeItemId(s2.getSizeId());
                    rst.add(temp);
                });
            } else {
                rst.add(s);
            }
        });
        return rst;
    }

    private int stripping(Long taskWorkunitId, int action) {
        QueryWrapper<ProMaterialRequest> query = new QueryWrapper<>();
        query.eq(taskWorkunitId != null, "p.task_workunit_id", taskWorkunitId);
        List<ProMaterialRequestVo> proMaterialRequestVos = proMaterialRequestService.selectProMaterialRequestLists(query);
        if (proMaterialRequestVos.size() == 0) {
            return 0;
        }

        ProMaterialRequestVo requestVo = proMaterialRequestVos.get(0);
        if (action == 2) {
            ProMaterialRequest proMaterialRequest = requestVo.deepCopyObj(ProMaterialRequest.class);
            proMaterialRequestService.updateProMaterialRequest(proMaterialRequest);
        } else {
            proMaterialRequestService.deleteByTaskWorknuitId(taskWorkunitId);
        }
        String applyNo = requestVo.getApplyNo();

        WmIssueHeader wmIssueHeader = new WmIssueHeader();
//        wmIssueHeader.setApplyNo(applyNo);
        List<WmIssueHeader> wmIssueHeaders = wmIssueHeaderMapper.selectWmIssueHeaderList(wmIssueHeader);
        if (wmIssueHeaders.size() == 0) {
            return 0;
        }

        WmIssueHeader issueHeader = wmIssueHeaders.get(0);
        QueryWrapper<WmIssueLineJoinBean> wmQo = new QueryWrapper<>();
        wmQo.in("t1.issue_id", issueHeader.getIssueId());
        List<WmIssueLineJoinBean> wmIssueLineJoinBeans = wmIssueLineMapper.selectWmIssueLineJoinList(wmQo);
        List<ProMaterialReturn> proMaterialReturns = new ArrayList<>();
        for (WmIssueLineJoinBean issueLine : wmIssueLineJoinBeans) {
            ProMaterialReturn proMaterialReturn = new ProMaterialReturn();
            proMaterialReturn.setItemId(issueLine.getItemId());
            proMaterialReturn.setItemCode(issueLine.getItemCode());
            proMaterialReturn.setItemName(issueLine.getItemName());
            proMaterialReturn.setTaskId(issueHeader.getTaskId());
            proMaterialReturn.setIssueLineId(issueLine.getLineId());
//            proMaterialReturn.setWorkorderId(issueHeader.getWorkorderId());
            proMaterialReturn.setTaskWorkunitId(requestVo.getTaskWorkunitId());
            proMaterialReturn.setBackNum(issueLine.getQuantityIssued());
            proMaterialReturn.setIsQualified(1);
            proMaterialReturn.setBatchNo(issueLine.getBatchCode());
            proMaterialReturn.setPackNo(issueLine.getPackNo());
//            proMaterialReturn.setWorkorderCode(issueHeader.getWorkorderCode());
            proMaterialReturn.setWorkunitCode(requestVo.getWorkunitCode());
            proMaterialReturn.setWorkunitName(requestVo.getWorkunitName());
            proMaterialReturns.add(proMaterialReturn);
        }
        proMaterialReturnService.insertProMaterialReturns(proMaterialReturns);

        return 1;
    }

    @Transactional
    @Override
    public int clossAndDeleteObjV2(ProWorkorder workorder) {
        ProWorkorder proWorkorder1 = new ProWorkorder();
        if (workorder.getApiFlag()) {
            proWorkorder1.setApiFlag(true);
        }
        Long workorderId = workorder.getWorkorderId();
        Set<String> statusSet = new HashSet<>(Arrays.asList(TaskStatusEnum.CANCEL.getStatus(), TaskStatusEnum.CLOSE.getStatus(), TaskStatusEnum.FINISHED.getStatus(), WorkorderStatusEnum.CANCEL.getValue(), WorkorderStatusEnum.CLOSE.getValue(), WorkorderStatusEnum.FINISHED.getValue(), TaskWorkunitStatusEnum.CANCEL.getStatus(), TaskWorkunitStatusEnum.CLOSE.getStatus(), TaskWorkunitStatusEnum.FINISHED.getStatus()));

        QueryWrapper<ProWorkorder> pqw = new QueryWrapper<>();
//        pqw.eq(arrangeCode != null, "t3.arrange_code", arrangeCode);
//        pqw.eq(workorderCode != null, "t3.workorder_code", workorderCode);
        pqw.eq(workorderId != null, "t1.workorder_id", workorderId);
        pqw.notIn("t1.status", statusSet);
        List<ProWorkorder> proWorkorders = proWorkorderMapper.selectListByQw(pqw);
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(proWorkorders), "工单当前状态已关闭或者已完成,不可重复关闭");
        ProWorkorder proWorkorder = proWorkorders.get(0);

        statusSet.remove(TaskWorkunitStatusEnum.FINISHED.getStatus());
        statusSet.remove(TaskStatusEnum.FINISHED.getStatus());
        String workorderCode = proWorkorder.getWorkorderCode();
        String arrangeCode = proWorkorder.getArrangeCode();
        QueryWrapper<ProTask> taskQueryWrapper = new QueryWrapper<>();
        taskQueryWrapper.eq(arrangeCode != null, "t3.arrange_code", arrangeCode);
        taskQueryWrapper.eq(workorderCode != null, "t3.workorder_code", workorderCode);
        taskQueryWrapper.notIn("t1.status", statusSet);
        List<ProTaskVo> proTaskVos = proTaskService.selectProTaskJoinWorkorder(taskQueryWrapper);

        List<ProTaskWorkunit> proTaskWorkunits = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(proTaskVos)) {
            //  查询出所有未关联到工单的排产任务
            // 未分配排产,直接取消工单即可
            Set<Long> collect = proTaskVos.stream().map(ProTaskVo::getTaskId).collect(Collectors.toSet());
            QueryWrapper<ProTaskWorkunit> workunitQueryWrapper = new QueryWrapper<>();
            workunitQueryWrapper.in("ptw.task_id", collect);
            workunitQueryWrapper.notIn("ptw.status", statusSet);
            proTaskWorkunits = proTaskWorkunitService.selectTaskWorkUnitJoinFeedback(workunitQueryWrapper);
        }


        // greaterThan
        // lessThan
        proWorkorder1.setWorkorderId(workorderId);
        proWorkorder1.setWorkorderCode(workorderCode);
        proWorkorder1.setArrangeCode(arrangeCode);
        proWorkorder1.setProTaskWorkunits(proTaskWorkunits);
        proWorkorder1.setTaskVos(proTaskVos);
        return proWorkorderService.closeObj(proWorkorder1);
    }

    @Transactional
    @Override
    public ProWorkorder insertObj(ProWorkorder proWorkorder, ProWorkorderVo workorderVo) {
        if (proWorkorder.getParentId() == null || proWorkorder.getParentId() == 0) {
            proWorkorder.setAncestors("0");
        }

        proWorkorder.setStatus(WorkorderStatusEnum.PREPARE.getValue());
        this.insertProWorkorderVo(workorderVo);
        QueryWrapper<ProWorkorder> proWorkorderQueryWrapper = new QueryWrapper<>();
        proWorkorderQueryWrapper.eq("workorder_code", workorderVo.getWorkorderCode());
        List<ProWorkorder> proWorkorders = proWorkorderMapper.selectListByQw(proWorkorderQueryWrapper);
        ProWorkorder proWorkorderNew = proWorkorders.get(0);
//        Long workorderId = proWorkorderNew.getWorkorderId();
//        proWorkorderService.generateBomLine(workorderId);
//        proWorkorderNew.setCreateBy(getUsername());
        return proWorkorderNew;
    }

}
