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.ObjectUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.ximai.common.annotation.ApiLog;
import com.ximai.common.constant.UserConstants;
import com.ximai.common.core.domain.entity.SysUser;
import com.ximai.common.enums.BusinessType;
import com.ximai.common.enums.InOutType;
import com.ximai.common.exception.ServiceException;
import com.ximai.common.utils.MessageUtils;
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.aspect.MethodExtendedProcess;
import com.ximai.mes.aspect.MethodExtendedProcesses;
import com.ximai.mes.constant.*;
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.proWorkOrder.*;
import com.ximai.mes.pro.domain.productionSolution.ProProductionSolution;
import com.ximai.mes.pro.domain.productionSolution.ProProductionSolutionProcess;
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.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.IProTaskService;
import com.ximai.mes.pro.service.task.IProTaskWorkunitService;
import com.ximai.mes.remote.ErpService;
import com.ximai.mes.remote.dto.*;
import com.ximai.mes.remote.process.FinishStockInCreateProcess;
import com.ximai.mes.remote.process.WorkorderStateUpdateProcess;
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 io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
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.text.DecimalFormat;
import java.util.*;
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 IProWorkorderService workorderService;

    @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 ProProductionSolutionMapper proProductionSolutionMapper;

    @Autowired
    private IProWorkOrderChangeRecordService proWorkOrderChangeRecordService;

    @Autowired
    private IProProductionSolutionService proProductionSolutionService;


    @Autowired
    private IProProductionSolutionProcessService proProductionSolutionProcessService;

    @Autowired
    private IProProductionSolutionSpecificationSheetService specificationSheetService;

    @Autowired
    private IProWorkOrderSoDirectiveService proWorkOrderSoDirectiveService;

    @Autowired
    private IMdItemService mdItemService;

    @Autowired
    private IProWorkOrderArrangeRuleValService proWorkOrderArrangeRuleValService;

    @Autowired
    private IProScheduleSetupRuleValService proScheduleSetupRuleValService;
    @Autowired
    private ErpService erpService;

    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;
    }


    @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);
            ExceptionUtil.checkTrueThrowException(!workorder.getStatus().equals(WorkorderStatusEnum.PUBLISHED.getValue()), MessageUtils.message("pro.workOrder.status.published.error"));

            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.selectJoinTaskWorkunitByQw(new QueryWrapper<ProWorkorder>().eq("t4.task_workunit_id", proWorkorder.getTaskWorkunitId()));
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(proWorkorders), MessageUtils.message("pro.workOrder.error.not.exist"));
        List<ProWorkorderVo> rst = new ArrayList<>();
        proWorkorders.forEach(workorder -> {
            ProWorkorderVo workorderVo = workorder.deepCopyObj(ProWorkorderVo.class);
            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);
        });
        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);

        // 根据工序创建任务单
        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(MessageUtils.message("md.process.error.not.exist"));
            }
            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.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(), MessageUtils.message("pro.workOrder.error.error4"));

        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());
        proWorkorderService.updateWorkorderState(proWorkorder, WorkorderStatusEnum.CLOSE);
        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;
    }

    /**
     * 查询生产工单
     *
     * @param workorderId 生产工单主键
     * @return 生产工单
     */
    @Override
    public ProWorkorderVo selectProWorkorderByWorkorderId(Long workorderId) {
        ProWorkorder proWorkorder = proWorkorderMapper.selectWorkorderById(workorderId);
        ExceptionUtil.checkTrueThrowException(proWorkorder == null, MessageUtils.message("pro.workOrder.error.not.exist"));
        List<ProWorkOrderBom> proWorkOrderBomList = proWorkOrderBomMapper.selectBomByWorkorderCode(proWorkorder.getWorkorderCode());
        List<ProWorkOrderProcessVo> proWorkOrderProcessList = proWorkOrderProcessMapper.selectProWorkOrderProcessByWorkOrderId(workorderId);
        String epItemCode = proWorkorder.getEpItemCode();
        ProProductionSolutionVo productionSolution = null;
        if(proWorkorder.getProductionSolutionId()!=null){
            productionSolution = proProductionSolutionService.selectProProductionSolutionByProductionSolutionId(proWorkorder.getProductionSolutionId());
            for (ProWorkOrderProcessVo proWorkOrderProcess : proWorkOrderProcessList) {
                Long workorderProcessId = proWorkOrderProcess.getWorkorderProcessId();
                // 获取工序明细
                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());
                    }
                }

                if (Objects.nonNull(productionSolution)) {
                    ProProductionSolutionProcess qa = new ProProductionSolutionProcess();
                    qa.setProductionSolutionId(productionSolution.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);
                    }
                }
            }
        }

        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);
        }

        if (productionSolution != null) {
            ProProductionSolution solution = BeanUtil.copyProperties(productionSolution, ProProductionSolution.class);
            proWorkorderVo.setProProductionSolution(solution);
            proWorkorderVo.setProductionSolutionCode(productionSolution.getProductionSolutionCode());
        }
        if (proWorkorder.getWorkorderType().equals("prototype")) {
            proWorkorderVo.setProductCode(epItemCode);
        }
        proWorkorderVo.setBomList(proWorkOrderBomList);
        proWorkorderVo.setProcessList(proWorkOrderProcessList);
        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());
            }
        }
        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++;
        }

        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.setStatus(WorkorderStatusEnum.PUBLISHED.getValue());
        proWorkorder.createAction();
        proWorkorder.setQuantityProduced(BigDecimal.ZERO);
        proWorkorder.setQuantityQualify(BigDecimal.ZERO);
        proWorkorder.setQuantityUnqualify(BigDecimal.ZERO);
        proWorkorder.setQuantityScheduled(BigDecimal.ZERO);
        proWorkorder.setBatchSerial(1);
        int r = proWorkorderMapper.insertProWorkorder(proWorkorder);
        //未设置生产版本时自动根据产品编号匹配最新生产版本
        if(ObjectUtil.isEmpty(proWorkorder.getProductionSolutionId())){
            ProProductionSolution proProductionSolutionQuery = new ProProductionSolution();
            proProductionSolutionQuery.setItemId(proWorkorder.getProductId());
            PageHelper.startPage(1, 1);
            PageHelper.orderBy("production_solution_code desc");
            List<ProProductionSolution> solutionList = proProductionSolutionService.selectProProductionSolutionList(proProductionSolutionQuery);
            if(solutionList.size()==1){
                QueryWrapper<ProProductionSolutionProcess> solutionProcessQuery = new QueryWrapper<>();
                solutionProcessQuery.eq("production_solution_id", solutionList.get(0).getProductionSolutionId());
                List<ProProductionSolutionProcess> processList = proProductionSolutionProcessService.selectProProductionSolutionProcessList(solutionProcessQuery);
                int i = 1;
                for(ProProductionSolutionProcess solutionProcess : processList){
                    ProWorkOrderProcess proWorkOrderProcess = new ProWorkOrderProcess();
                    proWorkOrderProcess.init(solutionProcess);
                    proWorkOrderProcess.setWorkorderId(proWorkorder.getWorkorderId());
                    proWorkOrderProcess.setWorkorderCode(proWorkorder.getWorkorderCode());
                    //proWorkOrderProcess.setIdx(i + "");
                    proWorkOrderProcessService.insertProWorkOrderProcess(proWorkOrderProcess);
                    i++;
                }
                proWorkorder.setProductionSolutionId(solutionList.get(0).getProductionSolutionId());
                proWorkorder.setProductionSolutionCode(solutionList.get(0).getProductionSolutionCode());
                this.updateProWorkorder(proWorkorder);
            }
        }
        return r;
    }

    /**
     * 修改生产工单
     *
     * @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());
                }
            });
        }
        //记录换型规则值
        proScheduleSetupRuleValService.deleteScheduleSetupRuleVal(proWorkorder.getWorkorderId());
        proScheduleSetupRuleValService.insertProScheduleSetupRuleVal(proWorkorder);
        return i;
    }

    @Override
    public List<ProWorkOrderProcessToolLoseVo> checkToolNum(Long[] workOrderIds) {
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(Arrays.asList(workOrderIds)), MessageUtils.message("pro.tool.error.error27"));

        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())), MessageUtils.message("pro.tool.error.error28"));

        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())));
                    }
                });
            }
            //修改工单状态
            proWorkorderService.updateWorkorderState(proWorkorder, WorkorderStatusEnum.PUBLISHED);
        }


        if (CollectionUtil.isNotEmpty(rst)) {
            StringBuilder buffer = new StringBuilder();
            for (ProWorkOrderProcessToolLoseVo loseVo : rst) {
                String excptionMsg = MessageUtils.message("pro.tool.error.error29", loseVo.getWorkorderCodes(), loseVo.getMdItem().getItemName(), loseVo.getLoseNum());

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

        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) {
        ProWorkorder proWorkorder = proWorkorderVo.deepCopyObj(ProWorkorder.class);
        String workorderCode = proWorkorderVo.getWorkorderCode();
        Long parentWorkorderId = proWorkorderVo.getWorkorderId();

        ExceptionUtil.checkTrueThrowException(!this.checkWorkorderIsExsit(proWorkorder), MessageUtils.message("pro.workOrder.error.workOrderNo.exist"));
        proWorkorderVo.setParentId(parentWorkorderId);
        proWorkorderVo.setWorkorderId(null);
        proWorkorderVo.setStatus(WorkorderStatusEnum.PUBLISHED.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});


    }


    /**
     * 根据生产工单中的产品生成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.setUnitOfMeasure(bom.getUnitOfMeasure());
                workorderBom.setQuantity(orderQuantitiy.multiply(bom.getQuantity()));
                proWorkOrderBomService.insertProWorkOrderBom(workorderBom);
            }
        }
    }


    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.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);
            }
        }

    }

    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();
        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(workorderId != null, "t1.workorder_id", workorderId);
        pqw.notIn("t1.status", statusSet);
        List<ProWorkorder> proWorkorders = proWorkorderMapper.selectListByQw(pqw);
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(proWorkorders), MessageUtils.message("pro.workOrder.error.error5"));
        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, "t2.arrange_code", arrangeCode);
        taskQueryWrapper.eq(workorderCode != null, "t2.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);
        return proWorkorderNew;
    }

    @Override
    public void syncErpData() {
        //更新修改数据
        workorderService.syncEditErpData();
    }

    @Transactional
    @Override
    public void initSyncAddErpData(){
        ProWorkorderErpQuery workorderErpQuery = new ProWorkorderErpQuery();
        //获取最晚创建时间
        Date maxErpCreateTime = proWorkorderMapper.maxErpCreateTime();
        if(maxErpCreateTime==null){
            Calendar curr = Calendar.getInstance();
            curr.set(Calendar.YEAR, 2000);
            maxErpCreateTime = curr.getTime();
        }
        ErpPageParams.Sort sort = new ErpPageParams.Sort(){{
            List<ErpPageParams.Order> orders = new ArrayList<>();
            orders.add(new ErpPageParams.Order("createDate","asc"));
            this.setOrders(orders);
        }};
        QueryWrapper<ProWorkorder> workorderQuery = new QueryWrapper<>();
        workorderQuery.eq("t1.erp_create_time", maxErpCreateTime);
        List<ProWorkorder> existList = proWorkorderMapper.selectListByQw(workorderQuery);
        Map<String, ProWorkorder> existMap = existList.stream().collect(Collectors.toMap(s->s.getWorkorderType()+s.getWorkorderCode(),s->s));
        workorderErpQuery.setSort(sort);
        workorderErpQuery.setGtEqCreateDate(maxErpCreateTime);
        workorderErpQuery.setCurrent(1);
        workorderErpQuery.setVerifyStatus("Y");
        workorderErpQuery.setPageSize(1000);//每次抓取1000行
        List<ProWorkorderErpDto> list = erpService.getWorkorderList(workorderErpQuery).getData();
        QueryWrapper<MdItem> itemQuery = new QueryWrapper<>();
        itemQuery.in("item_code", list.stream().map(s->s.getProductCode()).collect(Collectors.toList()));
        Map<String,MdItem> itemMap = mdItemService.selectListByQw(itemQuery).stream().collect(Collectors.toMap(s->s.getItemCode(), s->s));
        itemQuery.clear();
        List<String> codes = new ArrayList<>();
        list.forEach(s->{
            s.getWorkorderBomList().forEach(s2->{
                codes.add(s2.getItemCode());
            });
        });
        itemQuery.in("item_code", codes);
        Map<String,MdItem> bomItemMap = mdItemService.selectListByQw(itemQuery).stream().collect(Collectors.toMap(s->s.getItemCode(), s->s));

        list.forEach(s->{
            if("Y".equalsIgnoreCase(s.getVerifyStatus()) && !s.getErpStatus().equalsIgnoreCase("Y")){
                if(StringUtils.isNotEmpty(s.getWorkorderCode()) && !existMap.containsKey(s.getWorkorderType()+s.getWorkorderCode())){
                    ProWorkorder insertTemp = BeanUtil.toBean(s, ProWorkorder.class);
                    if(!itemMap.containsKey(insertTemp.getProductCode())){
                        log.error(String.format("未找到工单对应物料基础数据：%s", insertTemp.getProductCode()));
                        return;
                    }
                    insertTemp.setProductId(itemMap.get(insertTemp.getProductCode()).getItemId());
                    this.insertProWorkorder(insertTemp);
                    //保存BOM明细
                    List<ProWorkorderBomErpDto> detailList = s.getWorkorderBomList();
                    detailList.forEach(s2->{
                        ProWorkOrderBom insertDetail = BeanUtil.toBeanIgnoreError(s2, ProWorkOrderBom.class);
                        if(!bomItemMap.containsKey(insertDetail.getItemCode())){
                            log.error(String.format("未找到工单BOM对应物料基础数据：%s", insertDetail.getItemCode()));
                            return;
                        }
                        insertDetail.setItemId(bomItemMap.get(insertDetail.getItemCode()).getItemId());
                        insertDetail.setWorkorderId(insertTemp.getWorkorderId());
                        proWorkOrderBomService.insertProWorkOrderBom(insertDetail);
                    });
                }
            }
        });
        //存在数据续断抓取，直到所有数据更新完成
        if(list.size()==1000){
            this.initSyncAddErpData();
        }
    }


    @Override
    public void syncEditErpData(){
        ProWorkorderErpQuery workorderErpQuery = new ProWorkorderErpQuery();
        ErpPageParams.Sort sort = new ErpPageParams.Sort(){{
            List<ErpPageParams.Order> orders = new ArrayList<>();
            orders.add(new ErpPageParams.Order("createDate","asc"));
            this.setOrders(orders);
        }};
        workorderErpQuery.setSort(sort);
        workorderErpQuery.setNeSyncMark("Y");
        workorderErpQuery.setVerifyStatus("Y");
        workorderErpQuery.setCurrent(1);
        workorderErpQuery.setPageSize(1000);//每次抓取1000行
        List<ProWorkorderErpDto> list = erpService.getWorkorderList(workorderErpQuery).getData();
        Set<String> codes = new HashSet<>();
        list.forEach(s->{
            codes.add(s.getProductCode());
            s.getWorkorderBomList().forEach(s2->{
                codes.add(s2.getItemCode());
            });
        });
        if(list.size()==0){
            return;
        }
        QueryWrapper<MdItem> itemQuery = new QueryWrapper<>();
        itemQuery.in("item_code", codes);
        Map<String,MdItem> itemMap = mdItemService.selectListByQw(itemQuery).stream().collect(Collectors.toMap(s->s.getItemCode(), s->s));
        list.forEach(s->{
            try {
                workorderService.syncEditErpData(s, itemMap);
            }catch (Exception e){
                log.error(String.format("同步工单失败%s", s.getWorkorderCode()), e);
            }
        });
        //存在数据续断抓取，直到所有数据更新完成
        if(list.size()==1000){
            this.syncEditErpData();
        }
    }

    @ApiLog(businessType = BusinessType.SYNC_DATA, inOutType = InOutType.INNER)
    @ApiOperation(value = "工单同步")
    @Transactional
    @Override
    public void syncEditErpData(ProWorkorderErpDto s, Map<String,MdItem> itemMap) {
        QueryWrapper<ProWorkorder> workorderQuery = new QueryWrapper<>();
        workorderQuery.eq("workorder_code",s.getWorkorderCode());
        workorderQuery.eq("workorder_type",s.getWorkorderType());
        List<ProWorkorder> dbList = proWorkorderService.selectListByQw(workorderQuery);
        Long workorderId = null;
        if(dbList.size()==0){
            if("Y".equalsIgnoreCase(s.getVerifyStatus())){
                if(StringUtils.isNotEmpty(s.getWorkorderCode())){
                    ProWorkorder insertTemp = BeanUtil.toBean(s, ProWorkorder.class);
                    if(itemMap.containsKey(s.getProductCode())){
                        MdItem mdItem = itemMap.get(s.getProductCode());
                        insertTemp.setProductId(mdItem.getItemId());
                    }
                    this.insertProWorkorder(insertTemp);
                    workorderId = insertTemp.getWorkorderId();
                }
            }
        }else{
            //已存在工单，主表仅更新数量字段，
            // 数量增加直接修改，
            ProWorkorder dbWorkorder = dbList.get(0);
            if(!dbWorkorder.getQuantity().equals(s.getQuantity())){
                if(s.getQuantity().compareTo(dbWorkorder.getQuantity())>0){
                    dbWorkorder.setQuantity(s.getQuantity());
                    this.updateProWorkorder(dbWorkorder);
                    // 数量减小时，判断减少数量 < 未排产数量时才进行更改
                }else if(dbWorkorder.getQuantity().subtract(s.getQuantity())
                        .compareTo(dbWorkorder.getQuantity().subtract(dbWorkorder.getQuantityScheduled()))<0){
                    dbWorkorder.setQuantity(s.getQuantity());
                    this.updateProWorkorder(dbWorkorder);
                }
            }
            workorderId = dbList.get(0).getWorkorderId();
        }
        if(ObjectUtil.isEmpty(workorderId)){
            return;
        }
        //保存BOM明细
        List<ProWorkorderBomErpDto> detailList = s.getWorkorderBomList();
        ProWorkOrderBom workOrderBomQuery = new ProWorkOrderBom();
        workOrderBomQuery.setWorkorderId(workorderId);
        List<ProWorkOrderBom> dbBomList = proWorkOrderBomService.selectProWorkOrderBomList(workOrderBomQuery);
        detailList.forEach(s2->{
            java.util.Optional<ProWorkOrderBom> workOrderBom = dbBomList.stream().filter(temp->temp.getItemCode().equals(s2.getItemCode())).findFirst();
            if(workOrderBom.isPresent()) {
                ProWorkOrderBom dbWorkOrderBom =  workOrderBom.get();
                BeanUtil.copyProperties(s2, dbWorkOrderBom);
                proWorkOrderBomService.updateProWorkOrderBom(dbWorkOrderBom);
            }else{
                ProWorkOrderBom insertDetail = BeanUtil.toBeanIgnoreError(s2, ProWorkOrderBom.class);
                insertDetail.setWorkorderId(workOrderBomQuery.getWorkorderId());
                if(itemMap.containsKey(s2.getItemCode())){
                    MdItem mdItem = itemMap.get(s2.getItemCode());
                    insertDetail.setItemId(mdItem.getItemId());
                }
                proWorkOrderBomService.insertProWorkOrderBom(insertDetail);
            }
        });
        //判断删除关联BOM
        dbBomList.forEach(s2->{
            if(detailList.stream().noneMatch(temp->temp.getItemCode().equals(s2.getItemCode()))){
                proWorkOrderBomService.deleteProWorkOrderBomByBomItemId(s2.getBomItemId());
            }
        });
        ProWorkorderSyncMarkUpdate syncMarkUpdate = new ProWorkorderSyncMarkUpdate();
        syncMarkUpdate.setWorkorderType(s.getWorkorderType());
        syncMarkUpdate.setWorkorderCode(s.getWorkorderCode());
        ErpResponseResult<Object> rst = erpService.workorderSyncMark(syncMarkUpdate);
        if(!rst.isSuccess()){
            log.error(String.format("回写工单同步状态失败:%s，%s", s.getWorkorderCode(), rst.getErrorMessage()));
            throw new ServiceException(rst.getErrorMessage());
        }
    }

    @Override
    public int updateWorkProcess(ProWorkorderVo proWorkorderVo) {
        ProWorkorder proWorkorder = proWorkorderMapper.selectWorkorderById(proWorkorderVo.getWorkorderId());
        ExceptionUtil.checkTrueThrowException(proWorkorder == null, MessageUtils.message("pro.workOrder.error.not.exist"));
        ExceptionUtil.checkTrueThrowException(proWorkorder.getStatus().equals(WorkorderStatusEnum.PUBLISHED.getValue()), MessageUtils.message("pro.workOrder.status.published.error"));
        List<ProWorkOrderProcessVo> processList = proWorkorderVo.getProcessList();
        if (processList != null) {
            for (ProWorkOrderProcessVo proWorkOrderProcessVo : processList) {
                // 保存工序
                ProWorkOrderProcess tempProcess = proWorkOrderProcessVo.deepCopyObj(ProWorkOrderProcess.class);
                tempProcess.setWorkorderId(proWorkorderVo.getWorkorderId());
                if (tempProcess.getWorkorderProcessId() == null) {
                    proWorkOrderProcessService.insertProWorkOrderProcess(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(proWorkorderVo.getWorkorderId());
                    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(proWorkorderVo.getWorkorderId());
                    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());
                    }
                });
            }
            proWorkOrderProcessMapper.deleteProWorkOrderProcessByWorkorderId(proWorkorderVo.getWorkorderId());
        }
        return proWorkorderMapper.updateProductionSolution(proWorkorderVo.getProductionSolutionId(),proWorkorderVo.getProductionSolutionCode(),proWorkorderVo.getProductionSolutionName(),proWorkorderVo.getWorkorderId());
    }

    @MethodExtendedProcesses(config ={
            @MethodExtendedProcess(sysSwitchParam = "erp.finish.stockin.create.enable", processClz = FinishStockInCreateProcess.class,
                    newThread = true, errorCatch = true)
    })
    @Override
    public void reportUpdateProWorkorder(ProWorkorder workorder, BigDecimal qualifyQuantity, BigDecimal unQualifyQuantity) {
        workorder.setQuantityQualify(workorder.getQuantityQualify().add(qualifyQuantity));
        workorder.setQuantityUnqualify(workorder.getQuantityUnqualify().add(unQualifyQuantity));
        workorder.setQuantityProduced(DataUtil.getNormalData(workorder.getQuantityProduced()).add(qualifyQuantity));
        if(workorder.getQuantityProduced().compareTo(workorder.getQuantity())>=0){
            proWorkorderService.updateWorkorderState(workorder, WorkorderStatusEnum.FINISHED);
        }
        proWorkorderService.updateProWorkorder(workorder);
    }

    @MethodExtendedProcesses(config ={
            @MethodExtendedProcess(sysSwitchParam = "erp.workorder.state.update", processClz = WorkorderStateUpdateProcess.class,
                    newThread = true, errorCatch = true)
    })
    @Override
    public void updateWorkorderState(ProWorkorder workorder, WorkorderStatusEnum workorderStatusEnum){
        workorder.setStatus(workorderStatusEnum.getValue());
        proWorkorderService.updateProWorkorder(workorder);
    }
}
