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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ximai.common.exception.ServiceException;
import com.ximai.common.utils.MessageUtils;
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.MdFactory;
import com.ximai.mes.md.mapper.MdFactoryMapper;
import com.ximai.mes.md.mapper.MdWorkunitMapper;
import com.ximai.mes.md.service.IMdWorkunitService;
import com.ximai.mes.od.domain.OdSalesOrderDetail;
import com.ximai.mes.od.mapper.OdSalesOrderDetailMapper;
import com.ximai.mes.pro.domain.ProFeedback;
import com.ximai.mes.pro.domain.proWorkOrder.ProWorkorder;
import com.ximai.mes.pro.domain.task.*;
import com.ximai.mes.pro.domain.vo.task.ProTaskWorkunitQuery;
import com.ximai.mes.pro.domain.vo.task.TaskWorkunitOutsourceSplitParam;
import com.ximai.mes.pro.domain.vo.task.TaskWorkunitToOutsourceParam;
import com.ximai.mes.pro.domain.vo.task.TaskWorkunitToSelfMadeParam;
import com.ximai.mes.pro.dto.task.ProTaskWorkunitConvertRecordCreate;
import com.ximai.mes.pro.dto.task.ProTaskWorkunitDto;
import com.ximai.mes.pro.mapper.ProArrangeMapper;
import com.ximai.mes.pro.mapper.ProFeedbackMapper;
import com.ximai.mes.pro.mapper.proWorkOrder.ProWorkorderMapper;
import com.ximai.mes.pro.mapper.task.ProTaskMapper;
import com.ximai.mes.pro.mapper.task.ProTaskWorkunitMapper;
import com.ximai.mes.pro.service.IProAllocationMaterialService;
import com.ximai.mes.pro.service.IProMaterialRequestService;
import com.ximai.mes.pro.service.proWorkOrder.IProWorkorderService;
import com.ximai.mes.pro.service.task.*;
import com.ximai.mes.remote.process.PurchasingRequisitionCreateProcess;
import com.ximai.mes.tm.domain.TmTool;
import com.ximai.mes.tm.domain.TmToolMachines;
import com.ximai.mes.tm.domain.TmToolRequestUseItem;
import com.ximai.mes.tm.mapper.TmToolMachinesMapper;
import com.ximai.mes.tm.mapper.TmToolMapper;
import com.ximai.mes.tm.mapper.TmToolRequestUseItemMapper;
import com.ximai.mes.tm.service.ITmToolRequestService;
import com.ximai.system.mapper.SysUserMapper;
import com.ximai.system.service.ISysDictDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.ximai.mes.constant.WorkorderStatusEnum.CLOSE;

/**
 * 任务工作单元Service业务层处理
 *
 * @author zht
 * @date 2024-01-23
 */
@Service
public class ProTaskWorkunitServiceImpl implements IProTaskWorkunitService {
    @Autowired
    private ProTaskWorkunitMapper proTaskWorkunitMapper;
    @Resource
    private ProFeedbackMapper proFeedbackMapper;
    @Autowired
    private IProTaskService proTaskService;
    @Autowired
    private ProTaskMapper proTaskMapper;
    @Autowired
    private IProTaskWorkunitService proTaskWorkunitService;
    @Resource
    private ProWorkorderMapper proWorkorderMapper;
    @Autowired
    private ISysDictDataService dictDataService;
    @Resource
    private SysUserMapper sysUserMapper;
    @Autowired
    private IProWorkorderService proWorkorderService;
    @Autowired
    private IProTaskWorkorderService proTaskWorkorderService;
    @Autowired
    private TmToolMachinesMapper tmToolMachinesMapper;

    @Autowired
    private TmToolRequestUseItemMapper tmToolRequestUseItemMapper;

    @Autowired
    private TmToolMapper tmToolMapper;
    @Autowired
    private IProTaskWorkunitOpRecordService taskWorkunitOpRecordService;
    @Autowired
    private IProTaskWorkunitConvertRecordService taskWorkunitConvertRecordService;
    @Autowired
    private ITmToolRequestService tmToolRequestService;
    @Autowired
    private IProMaterialRequestService proMaterialRequestService;
    @Autowired
    private MdWorkunitMapper mdWorkunitMapper;
    @Autowired
    private IProAllocationMaterialService proAllocationMaterialService;
    @Autowired
    private MdFactoryMapper mdFactoryMapper;
    @Autowired
    private OdSalesOrderDetailMapper odSalesOrderDetailMapper;
    @Override
    public void updateProTaskWorkunitTimeAndWorkunit(ProTaskWorkunit proTaskWorkunit) {
        proTaskWorkunit.updateAction();
        //记录修改历史
        ProTaskWorkunitOpRecord proTaskWorkunitOpRecord = new ProTaskWorkunitOpRecord();
        ProTaskWorkunit dbTaskWorkunit = this.selectProTaskWorkunitByTaskWorkunitId(proTaskWorkunit.getTaskWorkunitId());
        BeanUtil.copyProperties(proTaskWorkunit, proTaskWorkunitOpRecord);
        proTaskWorkunitOpRecord.setTaskId(dbTaskWorkunit.getTaskId());
        proTaskWorkunitOpRecord.setIdx(dbTaskWorkunit.getIdx());
        proTaskWorkunitOpRecord.setOldWorkunitId(dbTaskWorkunit.getWorkunitId());
        proTaskWorkunitOpRecord.setOldScheduleStartDate(dbTaskWorkunit.getScheduleStartDate());
        proTaskWorkunitOpRecord.setOldScheduleEndDate(dbTaskWorkunit.getScheduleEndDate());
        taskWorkunitOpRecordService.insertProTaskWorkunitOpRecord(proTaskWorkunitOpRecord);
        //修改刀具申领信息
        tmToolRequestService.updateTmToolRequestByTaskWorkunit(proTaskWorkunit);
        //修改物料申领信息
        proMaterialRequestService.updateProMaterialRequestByTaskWorkunit(proTaskWorkunit);
        //修改调拨单
        proAllocationMaterialService.updateProAllocationMaterialByTaskWorkunit(proTaskWorkunit);
        proTaskWorkunitMapper.updateProTaskWorkunit(proTaskWorkunit);
    }


    /**
     * 查询任务工作单元
     *
     * @param taskWorkunitId 任务工作单元主键
     * @return 任务工作单元
     */
    @Override
    public ProTaskWorkunit selectProTaskWorkunitByTaskWorkunitId(Long taskWorkunitId) {
        return proTaskWorkunitMapper.selectProTaskWorkunitByTaskWorkunitId(taskWorkunitId);
    }

    @Override
    public ProTaskWorkunit selectMainObjById(Long taskId) {
        List<ProTaskWorkunit> proTaskWorkunits = proTaskWorkunitMapper.selectListByQw(new QueryWrapper<ProTaskWorkunit>().eq("task_id", taskId));
        Optional<ProTaskWorkunit> first = proTaskWorkunits.stream().filter(x -> Objects.equals(x.getTaskType(), TaskConst.MAIN_TASK)).findFirst();
        ExceptionUtil.checkTrueThrowException(!first.isPresent(), MessageUtils.message("pro.schedule.data.not.exists"));
        return first.get();
    }

    /**
     * 查询任务工作单元列表
     *
     * @param proTaskWorkunit 任务工作单元
     * @return 任务工作单元
     */
    @Override
    public List<ProTaskWorkunit> selectProTaskWorkunitList(ProTaskWorkunit proTaskWorkunit) {
        return proTaskWorkunitMapper.selectProTaskWorkunitList(proTaskWorkunit);
    }


    // 查询已经报工的工序任务
    @Override
    public List<ProTaskWorkunit> queryScheduledTasksBeenReported(ProTaskWorkunit proTaskWorkunit) {
        List<ProTaskWorkunit> proTaskWorkunits = this.selectProTaskWorkunitList(proTaskWorkunit);
        String taskWorkunitIds = proTaskWorkunits.stream().map(x -> x.getTaskWorkunitId().toString()).collect(Collectors.joining(","));
        Map<String, String> feedbackMap =
                proFeedbackMapper.selectListByQw(new QueryWrapper<ProFeedback>().select("task_workunit_id").in("task_workunit_id", taskWorkunitIds)).stream().distinct().collect(Collectors.toMap(x -> x.getTaskWorkunitId().toString(), x -> x.getTaskWorkunitId().toString()));
        return proTaskWorkunits.stream().filter(x -> feedbackMap.get(x.getTaskWorkunitId().toString()) == null).collect(Collectors.toList());
    }


    /**
     * 新增任务工作单元
     *
     * @param proTaskWorkunit 任务工作单元
     * @return 结果
     */
    @Override
    public int insertProTaskWorkunit(ProTaskWorkunit proTaskWorkunit) {
        proTaskWorkunit.createAction();
        proTaskWorkunit.setOutsourced(0);
        return proTaskWorkunitMapper.insertProTaskWorkunit(proTaskWorkunit);
    }

    /**
     * 修改任务工作单元
     *
     * @param proTaskWorkunit 任务工作单元
     * @return 结果
     */
    @Override
    public int updateProTaskWorkunit(ProTaskWorkunit proTaskWorkunit) {
        proTaskWorkunit.updateAction();
        return proTaskWorkunitMapper.updateProTaskWorkunit(proTaskWorkunit);
    }

    @Override
    public void updateProTaskWorkunitState(ProTaskWorkunit proTaskWorkunit, TaskStatusEnum taskStatusEnum) {
        if(taskStatusEnum == TaskStatusEnum.BEGINNING){
            //判断是否设置工单开工
            List<ProWorkorder> orderList = proWorkorderMapper.selectProWorkorderJoinTask(new QueryWrapper<ProWorkorder>().eq("t2.task_id", proTaskWorkunit.getTaskId()));
            for (ProWorkorder proWorkorder : orderList) {
                if (WorkorderStatusEnum.ISSUED.getValue().equals(proWorkorder.getStatus())) {
                    proWorkorder.setStatus(WorkorderStatusEnum.PRODUCING.getValue());
                    proWorkorderService.updateWorkorderState(proWorkorder, WorkorderStatusEnum.PRODUCING);
                }
            }
            //记录实际开始时间
            if(proTaskWorkunit.getActualStartDate()==null){
                proTaskWorkunit.setActualStartDate(Calendar.getInstance().getTime());
            }
        }
        proTaskWorkunit.setStatus(taskStatusEnum.getStatus());
        this.updateProTaskWorkunit(proTaskWorkunit);
    }

    /**
     * 修改任务工作单元
     *
     * @param proTaskWorkunits 任务工作单元
     * @return 结果
     */
    @Override
    public int cancelObj(List<ProTaskWorkunit> proTaskWorkunits) {
        for (ProTaskWorkunit proTaskWorkunit : proTaskWorkunits) {
            proTaskWorkunit.setStatus(TaskStatusEnum.CANCEL.getStatus());
            this.updateProTaskWorkunit(proTaskWorkunit);
        }
        return 1;
    }


    /**
     * 批量删除任务工作单元
     *
     * @param taskWorkunitIds 需要删除的任务工作单元主键
     * @return 结果
     */
    @Override
    public int deleteProTaskWorkunitByTaskWorkunitIds(Long[] taskWorkunitIds) {
        return proTaskWorkunitMapper.deleteProTaskWorkunitByTaskWorkunitIds(taskWorkunitIds);
    }

    /**
     * 删除任务工作单元信息
     *
     * @param taskWorkunitId 任务工作单元主键
     * @return 结果
     */
    @Override
    public int deleteProTaskWorkunitByTaskWorkunitId(Long taskWorkunitId) {
        return proTaskWorkunitMapper.deleteProTaskWorkunitByTaskWorkunitId(taskWorkunitId);
    }

    @Override
    public ProTaskWorkunit selectProTaskWorkunitByTaskId(Long taskId) {
        return proTaskWorkunitMapper.selectProTaskWorkunitByTaskId(taskId);

    }

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

    @Override
    public List<ProTaskWorkunit> selectTaskWorkUnitJoinTask(QueryWrapper<ProTaskWorkunit> query) {
        return proTaskWorkunitMapper.selectTaskWorkUnitJoinTask(query);
    }

    @Override
    public List<ProTaskWorkunitDto> selectTaskWorkUnitDtoJoinTask(QueryWrapper<ProTaskWorkunit> query) {
        return proTaskWorkunitMapper.selectTaskWorkUnitDtoJoinTask(query);
    }

    @Override
    public ProTaskWorkunit queryTaskScheduledForearliest(Long taskId) {
        return proTaskWorkunitMapper.selectTaskScheduledForearliest(taskId);
    }

    @Override
    public ProTaskWorkunit queryTaskScheduledForearliestExec(Long taskId) {
        return proTaskWorkunitMapper.selectTaskScheduledForearliestExec(taskId);
    }

    @Override
    public String updateProTaskWorkunitlife(ProFeedback feedback) {

        String msg = "";

        //已经上架刀模库存扣减寿命
        List<ProTaskWorkunit> proWorkunits = proTaskWorkunitMapper.selectProTaskWorkunitTaskId(feedback.getTaskId());
        if (CollUtil.isEmpty(proWorkunits)) {
            return null;
        }

        TmToolMachines tmToolMachines = new TmToolMachines();
        for (ProTaskWorkunit pro : proWorkunits) {
            if (StringUtils.isNotNull(pro.getWorkunitId())) {
                tmToolMachines.setWorkunitId(pro.getWorkunitId());
                List<TmToolMachines> tmToolMachines1 = tmToolMachinesMapper.selectTmToolMachinesVoList(tmToolMachines);
                for (TmToolMachines tmMachinesRecord : tmToolMachines1) {
                    if (tmMachinesRecord.getIsExistTool() == "1") {
                        TmTool tool = tmToolMapper.selectTmToolByToolId(tmMachinesRecord.getToolId());
                        Long lifeTime = tool.getLifeTime();
                        BigDecimal quantityUnquanlify = feedback.getQuantityQualify();
                        long l = quantityUnquanlify.longValue();
                        tool.setLifeTime(lifeTime - l);
                        tmToolMapper.updateTmTool(tool);
                        if (tool.getNextMaintenPeriod() != null && tool.getLifeTime() != null) {
                            if (tool.getNextMaintenPeriod() >= tool.getLifeTime()) {
                                return msg = tool.getToolName() + "寿命已经上限";
                            }
                        }
                    } else {
                        if (tmMachinesRecord.getType() != null) {
                            if (tmMachinesRecord.getType().equals(TmToolMachineTypeEnum.MOUNT.getType())) {
                                TmToolRequestUseItem tmToolRequestUseItem = tmToolRequestUseItemMapper.selectTmToolRequestUseItemToolRequestUseItemId(tmMachinesRecord.getToolRequestUseItemId());
                                if (tmToolRequestUseItem != null) {
                                    TmTool tool = tmToolMapper.selectTmToolByToolId(tmToolRequestUseItem.getToolId());
                                    Long lifeTime = tool.getLifeTime();
                                    BigDecimal quantityUnquanlify = feedback.getQuantityQualify();
                                    long l = quantityUnquanlify.longValue();
                                    tool.setLifeTime(lifeTime - l);
                                    tmToolMapper.updateTmTool(tool);
                                    if (tool.getNextMaintenPeriod() != null && tool.getLifeTime() != null) {
                                        if (tool.getNextMaintenPeriod() >= tool.getLifeTime()) {
                                            return msg = tool.getToolName() + "寿命已经上限";
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return "";
    }

    @Override
    public void makeProduction(Long[] taskWorkunitIds) {
        Map<Long, ProTask> taskMap = new HashMap<Long, ProTask>();
        List<ProWorkorder> workorderList = new ArrayList<ProWorkorder>();
        List<Long> taskIds = new ArrayList<Long>();
        for (Long id : taskWorkunitIds) {
            ProTaskWorkunit proTaskWorkunit = this.selectProTaskWorkunitByTaskWorkunitId(id);
            proTaskWorkunit.setStatus(TaskStatusEnum.PREPARE.getStatus());
            Long taskId = proTaskWorkunit.getTaskId();
            ProTask proTask = null;
            if (!taskMap.containsKey(taskId)) {
                proTask = proTaskService.selectProTaskByTaskId(taskId);
                taskMap.put(taskId, proTask);
                taskIds.add(taskId);
            }
            this.updateProTaskWorkunit(proTaskWorkunit);
            //生产领料申请单
            proMaterialRequestService.insertProMaterialRequestIssueItem(id, proTask);
        }

        // 生成刀模版具
        List<ProTaskWorkunit> proTaskWorkunits = proTaskWorkunitService.selectListByQw(new QueryWrapper<ProTaskWorkunit>().in("task_workunit_id", Arrays.asList(taskWorkunitIds)));
        tmToolRequestService.addedToolRequestAppForm(proTaskWorkunits);


        //查询关联工单
        QueryWrapper<ProTaskWorkorder> taskWorkorderQuery = new QueryWrapper<ProTaskWorkorder>();
        taskWorkorderQuery.in("task_id", taskIds);
        List<ProTaskWorkorder> taskWorkorderList = proTaskWorkorderService.selectProTaskWorkorder(taskWorkorderQuery);

        //查询任务单关联工单
        for (ProTaskWorkorder taskWorkorder : taskWorkorderList) {
            ProWorkorder workorder = proWorkorderService.selectWorkorderById(taskWorkorder.getWorkorderId());
            workorderList.add(workorder);
        }

        //关联工单修改为下达
        workorderList.forEach(value -> {
            if (value.getStatus().equals(WorkorderStatusEnum.SCHEDULED.getValue())) {
                String arrangeCode = value.getArrangeCode();
                ProWorkorder proWorkorder = new ProWorkorder();
                proWorkorder.setArrangeCode(arrangeCode);
                value.setStatus(WorkorderStatusEnum.ISSUED.getValue());
                proWorkorderService.updateProWorkorder(value);
            }
        });

    }

    @Override
    public List<ProWorkorder> selectWorkorderTaskByQw(ProTaskWorkunitQuery proTaskWorkunit) {
        List<ProWorkorder> proWorkorders = new ArrayList<>();
        if (proTaskWorkunit.getArrangeCode() != null || proTaskWorkunit.getTaskWorkunitId() != null) {
            QueryWrapper<ProTaskWorkunit> proTaskWorkunitQueryWrapper = new QueryWrapper<>();
            proTaskWorkunitQueryWrapper.eq(StringUtils.isNotEmpty(proTaskWorkunit.getTaskWorkunitId()), "ptw.task_workunit_id", proTaskWorkunit.getTaskWorkunitId());
            proTaskWorkunitQueryWrapper.eq(StringUtils.isNotEmpty(proTaskWorkunit.getArrangeCode()), "w.arrange_code", proTaskWorkunit.getArrangeCode());
            proWorkorders = proTaskWorkunitMapper.selectWorkorderTaskByQw(proTaskWorkunitQueryWrapper);
        }

        return proWorkorders;
    }

    @Override
    public List<ProTaskWorkunit> selectTaskWorkUnitJoinFeedback(QueryWrapper<ProTaskWorkunit> proTaskQo) {
        return proTaskWorkunitMapper.selectTaskWorkUnitJoinFeedback(proTaskQo);
    }

    @Override
    public void closeObj(List<ProTaskWorkunit> proTaskWorkunits) {
        if (CollectionUtil.isNotEmpty(proTaskWorkunits)) {
            proTaskWorkunits.forEach(x -> {
                if (x.getQuantity().doubleValue() == 0) {
                    x.setStatus(TaskWorkunitStatusEnum.CLOSE.getStatus());
                }
                this.updateProTaskWorkunit(x);
            });
        }

    }

    @Override
    public List<ProTaskWorkunit> schedulingList(ProTaskWorkunitQuery proTaskWorkunit) {
        QueryWrapper<ProTaskWorkunit> query = new QueryWrapper<>();
        List<String> list1 = Arrays.asList(proTaskWorkunit.getStatusArr());
        //任务编码、工作站名称、产品名称、状态、计划开始、结束时间
        query.in(CollectionUtil.isNotEmpty(list1), "ptw.status", list1);
        query.notIn(CollectionUtil.isNotEmpty(list1), "ptw.status", Collections.singletonList(CLOSE.getValue()));
        query.eq(proTaskWorkunit.getWorkCenterId() != null, "ws.workstation_id", proTaskWorkunit.getWorkCenterId());
        query.eq(proTaskWorkunit.getWorkunitId() != null, "mw.workunit_id", proTaskWorkunit.getWorkunitId());
        query.ne(proTaskWorkunit.getNeWorkunitId() != null, "mw.workunit_id", proTaskWorkunit.getNeWorkunitId());
        query.eq(proTaskWorkunit.getWorkshopId() != null, "ws.workshop_id", proTaskWorkunit.getWorkshopId());
        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getWorkorderCode()), "wo.workorder_code", proTaskWorkunit.getWorkorderCode());
        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getTaskCode()), "t.task_code", proTaskWorkunit.getTaskCode());
        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getWorkunitName()), "mw.workunit_name", proTaskWorkunit.getWorkunitName());
        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getItemName()), "wo.product_name", proTaskWorkunit.getItemName());
        query.gt(StringUtils.isNotEmpty(proTaskWorkunit.getGtQuantity()), "ptw.quantity", proTaskWorkunit.getGtQuantity());
        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getItemCode()), "wo.product_code", proTaskWorkunit.getItemCode());
        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getProcessName()), "t.process_name", proTaskWorkunit.getProcessName());
        query.gt(proTaskWorkunit.getScheduleStartDateFrom() != null, "ptw.schedule_start_date", proTaskWorkunit.getScheduleStartDateFrom());
        query.le(proTaskWorkunit.getScheduleStartDateTo() != null, "ptw.schedule_start_date", proTaskWorkunit.getScheduleStartDateTo());
        query.gt(proTaskWorkunit.getScheduleEndDateFrom() != null, "ptw.schedule_start_date", proTaskWorkunit.getScheduleEndDateFrom());
        query.le(proTaskWorkunit.getScheduleEndDateTo() != null, "ptw.schedule_start_date", proTaskWorkunit.getScheduleEndDateTo());
        query.eq(StringUtils.isNotEmpty(proTaskWorkunit.getArrangeCode()), "t.arrange_code", proTaskWorkunit.getArrangeCode());
        query.eq(proTaskWorkunit.getOutsourced()!=null, "ptw.outsourced", proTaskWorkunit.getOutsourced());
        query.eq(StringUtils.isNotEmpty(proTaskWorkunit.getCustomerProjectNo()), "wo.customer_project_no", proTaskWorkunit.getCustomerProjectNo());
        query.eq(StringUtils.isNotEmpty(proTaskWorkunit.getOrderCode()), "wo.order_code", proTaskWorkunit.getOrderCode());
        query.eq(StringUtils.isNotEmpty(proTaskWorkunit.getTaskBatch()), "SUBSTRING_INDEX(t.task_batch, '-', -1)", proTaskWorkunit.getTaskBatch());

        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getProductCode()), "wo.product_code",
                proTaskWorkunit.getProductCode());
//        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getOrderCode()), "wo.order_code",
//                proTaskWorkunit.getOrderCode());
        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getOrderSerial()), "wo.order_serial",
                proTaskWorkunit.getOrderSerial());
        query.like(StringUtils.isNotEmpty(proTaskWorkunit.getCustomerDrawingNo()), "wo.customer_drawing_no",
                proTaskWorkunit.getCustomerDrawingNo());


        query.gt("ptw.quantity",0);
        query.orderByAsc("schedule_start_date");
        List<ProTaskWorkunit> list = proTaskWorkunitService.selectTaskWorkUnitJoinTask(query);
        return list;
    }

    @Override
    @Transactional
    public void toSelfMade(List<TaskWorkunitToSelfMadeParam> toSelfMadeParamList) {
        toSelfMadeParamList.forEach(toSelfMadeParam->{
            if(toSelfMadeParam.getToSelfMadeQuantity().compareTo(BigDecimal.ZERO)==0){
                throw new ServiceException(MessageUtils.message( "pro.schedule.limit.to.selfMade.min.quantity"));
            }
            ProTaskWorkunit taskWorkunit = this.selectProTaskWorkunitByTaskWorkunitId(toSelfMadeParam.getTaskWorkunitId());
            if(taskWorkunit.getQuantity().compareTo(toSelfMadeParam.getToSelfMadeQuantity())<0){
                throw new ServiceException(MessageUtils.message("pro.schedule.error.to.selfMade.quantity.lack"));
            }
            ProTaskWorkunit newTaskWorkunit = BeanUtil.copyProperties(taskWorkunit, ProTaskWorkunit.class);
            newTaskWorkunit.setQuantity(toSelfMadeParam.getToSelfMadeQuantity());
            BeanUtil.copyProperties(toSelfMadeParam, newTaskWorkunit);
            newTaskWorkunit.setStatus(TaskStatusEnum.PREPARE.getStatus());
            this.insertProTaskWorkunit(newTaskWorkunit);
            //原数量扣减
            taskWorkunit.setQuantity(taskWorkunit.getQuantity().subtract(toSelfMadeParam.getToSelfMadeQuantity()));
            this.updateProTaskWorkunit(taskWorkunit);
            //添加记录
            ProTaskWorkunitConvertRecordCreate record = new ProTaskWorkunitConvertRecordCreate();
            record.setTaskWorkunitId(taskWorkunit.getTaskWorkunitId());
            record.setNewTaskWorkunitId(newTaskWorkunit.getTaskWorkunitId());
            record.setQuantity(toSelfMadeParam.getToSelfMadeQuantity());
            record.setOperateType(IProTaskWorkunitConvertRecordService.TaskWorkunitConvertType.TO_SELF_MADE.getValue());
            taskWorkunitConvertRecordService.insertProTaskWorkunitConvertRecord(record);
        });
    }

    @Override
    @Transactional
    public void outsourceSplit(List<TaskWorkunitOutsourceSplitParam> outsourceSplitParamList) {
        outsourceSplitParamList.forEach(outsourceSplitParam->{
            if(outsourceSplitParam.getSplitQuantity().compareTo(BigDecimal.ZERO)==0){
                throw new ServiceException(MessageUtils.message("pro.schedule.limit.outsource.split.min.quantity"));
            }
            ProTaskWorkunit taskWorkunit = this.selectProTaskWorkunitByTaskWorkunitId(outsourceSplitParam.getTaskWorkunitId());
            if(taskWorkunit.getQuantity().compareTo(outsourceSplitParam.getSplitQuantity())<=0){
                throw new ServiceException(MessageUtils.message("pro.schedule.error.outsource.split.quantity.lack"));
            }
            ProTaskWorkunit newTaskWorkunit = BeanUtil.copyProperties(taskWorkunit, ProTaskWorkunit.class);
            newTaskWorkunit.setQuantity(outsourceSplitParam.getSplitQuantity());
            newTaskWorkunit.setQuantityQualify(BigDecimal.ZERO);
            newTaskWorkunit.setQuantityUnqualify(BigDecimal.ZERO);
            newTaskWorkunit.setQuantityProduced(BigDecimal.ZERO);
            newTaskWorkunit.setQuantityChanged(BigDecimal.ZERO);
            BeanUtil.copyProperties(outsourceSplitParam, newTaskWorkunit);
            this.insertProTaskWorkunit(newTaskWorkunit);
            //原数量扣减
            taskWorkunit.setQuantity(taskWorkunit.getQuantity().subtract(outsourceSplitParam.getSplitQuantity()));
            this.updateProTaskWorkunit(taskWorkunit);
            //添加记录
            ProTaskWorkunitConvertRecordCreate record = new ProTaskWorkunitConvertRecordCreate();
            record.setTaskWorkunitId(taskWorkunit.getTaskWorkunitId());
            record.setNewTaskWorkunitId(newTaskWorkunit.getTaskWorkunitId());
            record.setQuantity(outsourceSplitParam.getSplitQuantity());
            record.setOperateType(IProTaskWorkunitConvertRecordService.TaskWorkunitConvertType.SPLIT.getValue());
            taskWorkunitConvertRecordService.insertProTaskWorkunitConvertRecord(record);
        });
    }

    @Override
    @Transactional
    public void toOutsource(List<TaskWorkunitToOutsourceParam> toOutsourceParamList) {
        toOutsourceParamList.forEach(toOutsourceParam->{
            if(toOutsourceParam.getToOutsourceQuantity().compareTo(BigDecimal.ZERO)==0){
                throw new ServiceException(MessageUtils.message("pro.schedule.limit.to.outsource.min.quantity"));
            }
            ProTaskWorkunit taskWorkunit = this.selectProTaskWorkunitByTaskWorkunitId(toOutsourceParam.getTaskWorkunitId());
            //不可超过未报工数量
            if(taskWorkunit.getQuantity().subtract(taskWorkunit.getQuantityQualify()).compareTo(toOutsourceParam.getToOutsourceQuantity())<0){
                throw new ServiceException(MessageUtils.message("pro.schedule.error.to.outsource.quantity.lack"));
            }
            ProTaskWorkunit newTaskWorkunit = BeanUtil.copyProperties(taskWorkunit, ProTaskWorkunit.class);
            newTaskWorkunit.setWorkunitId(IMdWorkunitService.OUTSOURCE_WORKUNIT_ID);
            newTaskWorkunit.setQuantity(toOutsourceParam.getToOutsourceQuantity());
            newTaskWorkunit.setQuantityQualify(BigDecimal.ZERO);
            newTaskWorkunit.setQuantityUnqualify(BigDecimal.ZERO);
            newTaskWorkunit.setQuantityProduced(BigDecimal.ZERO);
            newTaskWorkunit.setQuantityChanged(BigDecimal.ZERO);
            newTaskWorkunit.setStatus(TaskStatusEnum.PREPARE.getStatus());
            BeanUtil.copyProperties(toOutsourceParam, newTaskWorkunit);
            this.insertProTaskWorkunit(newTaskWorkunit);
            //原数量扣减
            taskWorkunit.setQuantity(taskWorkunit.getQuantity().subtract(toOutsourceParam.getToOutsourceQuantity()));
            this.updateProTaskWorkunit(taskWorkunit);
            //添加记录
            ProTaskWorkunitConvertRecordCreate record = new ProTaskWorkunitConvertRecordCreate();
            record.setTaskWorkunitId(taskWorkunit.getTaskWorkunitId());
            record.setNewTaskWorkunitId(newTaskWorkunit.getTaskWorkunitId());
            record.setQuantity(toOutsourceParam.getToOutsourceQuantity());
            record.setOperateType(IProTaskWorkunitConvertRecordService.TaskWorkunitConvertType.TO_OUTSOURCE.getValue());
            taskWorkunitConvertRecordService.insertProTaskWorkunitConvertRecord(record);
        });
    }

    @Override
    @Transactional
    public void outsourceConfirm(List<Long> taskWorkunitIds) {
        taskWorkunitIds.forEach(id->{
            ProTaskWorkunit taskWorkunit = this.selectProTaskWorkunitByTaskWorkunitId(id);
//            if(taskWorkunit.getVendorId()==null){
//                throw new ServiceException(MessageUtils.message("pro.schedule.error.not.null.vendor"));
//            }
            if(ObjectUtil.equal(taskWorkunit.getOutsourced(), 1)){
                throw new ServiceException(MessageUtils.message("basic.error.repeat.confirm"));
            }
            proTaskWorkunitService.outsourceConfirm(taskWorkunit);
        });
    }

    @MethodExtendedProcesses(config ={
            @MethodExtendedProcess(sysSwitchParam = "erp.purchasing.requisition.create.enable", processClz = PurchasingRequisitionCreateProcess.class,
                    newThread = true, errorCatch = true)
    })
    @Override
    public void outsourceConfirm(ProTaskWorkunit taskWorkunit) {
        taskWorkunit.setOutsourced(1);
        this.updateProTaskWorkunit(taskWorkunit);
        this.updateProTaskWorkunitState(taskWorkunit, TaskStatusEnum.BEGINNING);
    }

    @Override
    public Map<String, Object> printData(List<Long> taskIds) {
        if(taskIds.size() > 0){
            Map<String, Object> printData = new HashMap<>();
            ArrayList valueList = new ArrayList();
            printData.put("reportName","process.xml");
            List<MdFactory> mdFactorys = mdFactoryMapper.selectLikeByName("上海希迈机电");
            if(mdFactorys.size() > 0){
                printData.put("reportName","process-cn.xml");
            }
            printData.put("valueList",valueList);
            List<ProTask> tasks = proTaskMapper.selectByTaskIds(taskIds);
            List<String> taskBatchs = tasks.stream().map(proTask -> proTask.getTaskBatch()).distinct().collect(Collectors.toList());
            int i = 1;
            SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
            for (String taskBatch : taskBatchs){
                List<ProTask> taskBatchTasks = proTaskMapper.selectByTaskBatch(taskBatch);
                String[] sp = taskBatch.split("-");
                if(taskBatchTasks.size() > 0){
                    List<TaskProPrintData> taskProPrintDatas = new ArrayList<>();
                    Map<String,Object> value = new HashMap<>();
                    valueList.add(value);
                    ProWorkorder proWorkorder = proWorkorderMapper.selectProWorkorderWorderCode(taskBatchTasks.get(0).getArrangeCode());
                    TaskProWorkorderPrintData taskProWorkorderPrintData = new TaskProWorkorderPrintData();
                    BeanUtil.copyProperties(proWorkorder,taskProWorkorderPrintData);
                    taskProWorkorderPrintData.setWorkorderType(dictDataService.getDictLabel("mes_workorder_type", taskProWorkorderPrintData.getWorkorderType()));
                    taskProWorkorderPrintData.setTaskBatch(sp[sp.length-1]);
                    value.put("header",taskProWorkorderPrintData);
                    value.put("detail",taskProPrintDatas);
                    Date over = null;
                    if(taskProWorkorderPrintData.getExpectStartDate() != null || taskProWorkorderPrintData.getRequestDate() != null){
                        for (ProTask proTask : taskBatchTasks){
                            TaskProPrintData taskProPrintData = new TaskProPrintData();
                            BeanUtil.copyProperties(proTask,taskProPrintData);
                            String begin = taskProWorkorderPrintData.getExpectStartDate() != null ? simpleDateFormat1.format(taskProWorkorderPrintData.getExpectStartDate()) : "空";
                            String end = taskProWorkorderPrintData.getRequestDate() != null ? simpleDateFormat1.format(taskProWorkorderPrintData.getRequestDate()) : "空";
                            taskProPrintData.setExpectStartDateString(begin);
                            taskProPrintData.setRequestDateString(end);
                            taskProPrintDatas.add(taskProPrintData);
                            if(proTask.getScheduleEndDate() != null){
                                if(over == null || over.getTime() < proTask.getScheduleEndDate().getTime()) {
                                    over = proTask.getScheduleEndDate();
                                }
                            }
                        }
                    }
                    if(over != null){
                        taskProWorkorderPrintData.setRequestDate(over);
                    }
                    taskProWorkorderPrintData.setSize(i++);
                    taskProWorkorderPrintData.setDate(simpleDateFormat1.format(new Date()));
                    taskProWorkorderPrintData.setQuantity(taskBatchTasks.get(0).getQuantity());
                }
            }
            return printData;
        }else{
            return null;
        }
    }

    @Override
    public Map<String, Object> printDataBySpil(Long taskWorkunitId) {
        Map<String, Object> printData = new HashMap<>();
        ArrayList valueList = new ArrayList();
        printData.put("reportName","process.xml");
        List<MdFactory> mdFactorys = mdFactoryMapper.selectLikeByName("上海希迈机电");
        if(mdFactorys.size() > 0){
            printData.put("reportName","process-cn.xml");
        }
        printData.put("valueList",valueList);

        int i = 1;
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
        //for (String taskBatch : taskBatchs){
        List<ProTask> taskBatchTasks = proTaskMapper.selectByTaskWorkunitId(taskWorkunitId);
        String[] sp = taskBatchTasks.get(0).getTaskBatch().split("-");
        if(taskBatchTasks.size() > 0){
            List<TaskProPrintData> taskProPrintDatas = new ArrayList<>();
            Map<String,Object> value = new HashMap<>();
            valueList.add(value);
            ProWorkorder proWorkorder = proWorkorderMapper.selectProWorkorderWorderCode(taskBatchTasks.get(0).getArrangeCode());
            TaskProWorkorderPrintData taskProWorkorderPrintData = new TaskProWorkorderPrintData();
            BeanUtil.copyProperties(proWorkorder,taskProWorkorderPrintData);
            taskProWorkorderPrintData.setWorkorderType(dictDataService.getDictLabel("mes_workorder_type", taskProWorkorderPrintData.getWorkorderType()));
            taskProWorkorderPrintData.setTaskBatch(sp[sp.length-1]);
            value.put("header",taskProWorkorderPrintData);
            value.put("detail",taskProPrintDatas);
            Date over = null;
            if(taskProWorkorderPrintData.getExpectStartDate() != null || taskProWorkorderPrintData.getRequestDate() != null){
                for (ProTask proTask : taskBatchTasks){
                    TaskProPrintData taskProPrintData = new TaskProPrintData();
                    BeanUtil.copyProperties(proTask,taskProPrintData);
                    String begin = taskProWorkorderPrintData.getExpectStartDate() != null ? simpleDateFormat1.format(taskProWorkorderPrintData.getExpectStartDate()) : "空";
                    String end = taskProWorkorderPrintData.getRequestDate() != null ? simpleDateFormat1.format(taskProWorkorderPrintData.getRequestDate()) : "空";
                    taskProPrintData.setExpectStartDateString(begin);
                    taskProPrintData.setRequestDateString(end);
                    taskProPrintDatas.add(taskProPrintData);
                    if(proTask.getScheduleEndDate() != null){
                        if(over == null || over.getTime() < proTask.getScheduleEndDate().getTime()) {
                            over = proTask.getScheduleEndDate();
                        }
                    }
                }
            }
            if(over != null){
                taskProWorkorderPrintData.setRequestDate(over);
            }
            taskProWorkorderPrintData.setSize(i++);
            taskProWorkorderPrintData.setDate(simpleDateFormat1.format(new Date()));
            BigDecimal quantity = taskBatchTasks.stream().filter(proTask -> proTask.getIdx().equals("0010")).map(proTask -> proTask.getQuantity()).reduce(BigDecimal.ZERO,BigDecimal::add);
            taskProWorkorderPrintData.setQuantity(quantity);
            //}
        }
        return printData;
    }
}
