package com.qmth.sop.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.sop.business.activiti.service.ActivitiService;
import com.qmth.sop.business.bean.dto.DataPermissionDto;
import com.qmth.sop.business.bean.dto.OrgUserNameDto;
import com.qmth.sop.business.bean.params.*;
import com.qmth.sop.business.bean.result.*;
import com.qmth.sop.business.entity.*;
import com.qmth.sop.business.mapper.TBSopInfoMapper;
import com.qmth.sop.business.service.*;
import com.qmth.sop.common.contant.SystemConstant;
import com.qmth.sop.common.enums.*;
import com.qmth.sop.common.util.GsonUtil;
import com.qmth.sop.common.util.JacksonUtil;
import com.qmth.sop.common.util.ServletUtil;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * sop表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2023-08-01
 */
@Service
public class TBSopInfoServiceImpl extends ServiceImpl<TBSopInfoMapper, TBSopInfo> implements TBSopInfoService {

    private final static Logger log = LoggerFactory.getLogger(TBSopInfoServiceImpl.class);

    @Resource
    TBSopInfoMapper tbSopInfoMapper;

    @Resource
    ActivitiService activitiService;

    @Resource
    TFCustomFlowEntityService tfCustomFlowEntityService;

    @Resource
    TaskService taskService;

    @Resource
    TBSopInfoDetailService tbSopInfoDetailService;

    @Resource
    TBSopInfoService tbSopInfoService;

    @Resource
    TBCrmService tbCrmService;

    @Resource
    TFCustomFlowService tfCustomFlowService;

    @Resource
    TSJobRemindService tsJobRemindService;

    @Resource
    TFFlowApproveService tfFlowApproveService;

    @Resource
    SysUserService sysUserService;

    @Value("${db.name}")
    String databaseName;

    @Resource
    TBDeviceInOutService tbDeviceInOutService;

    @Resource
    TFFlowLogService tfFlowLogService;

    @Resource
    SysUserRoleService sysUserRoleService;

    @Resource
    TBServiceService tbServiceService;

    @Resource
    TBSopPlanDateLogService tbSopPlanDateLogService;

    @Resource
    TBDeviceDeliveryService tbDeviceDeliveryService;

    @Resource
    TBUserArchivesService tbUserArchivesService;

    /**
     * 查询动态sop表名是否存在
     *
     * @param db
     * @param tableName
     * @return
     */
    @Override
    public int selectSopDynamicExist(String db, String tableName) {
        return this.baseMapper.selectSopDynamicExist(db, tableName);
    }

    /**
     * 保存动态sop信息
     *
     * @param tfCustomFlow
     * @param code
     * @param flowId
     * @param flowTaskResult
     * @return
     */
    @Override
    @Transactional
    public Boolean saveDynamicSop(TFCustomFlow tfCustomFlow, String code, Long flowId, FlowTaskResult flowTaskResult) {
        String tableName = tfCustomFlow.getType().getTableName() + "_" + tfCustomFlow.getVersion();
        List<FlowFormWidgetResult> flowFormWidgetResultList = flowTaskResult.getFormProperty();
        Map<String, String> formFieldMap = new HashMap<>(flowFormWidgetResultList.size());
        for (FlowFormWidgetResult f : flowFormWidgetResultList) {
            if (f.getCode() != WidgetCodeEnum.FORM_GROUP_TITLE && f.getCode() != WidgetCodeEnum.ONLY_TITLE
                    && f.getCode() != WidgetCodeEnum.BUTTON && f.getCode() != WidgetCodeEnum.IMG
                    && f.getCode() != WidgetCodeEnum.LABEL && f.getCode() != WidgetCodeEnum.SIGN
                    && f.getCode() != WidgetCodeEnum.OTHER) {
                if (f.getInputType() != WidgetInputTypeEnum.ARRAY) {
                    if (Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {
                        JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                        String value = jsonObject.getString(SystemConstant.VALUE);
                        formFieldMap.put(f.getFormId(), value);
                    }
                } else {
                    if (Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {
                        JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                        JSONArray jsonArray = jsonObject.getJSONArray(SystemConstant.VALUE);
                        StringJoiner stringJoiner = new StringJoiner(",");
                        for (int i = 0; i < jsonArray.size(); i++) {
                            stringJoiner.add(jsonArray.getString(i));
                        }
                        formFieldMap.put(f.getFormId(), stringJoiner.toString());
                    }
                }
            }
        }
        //首先查询动态表里是否有当前表单的数据，没有插入，有则更新
        int count = this.selectDynamicSop(tableName, tfCustomFlow.getFlowDeploymentId(), flowId);
        if (count == 0) {//插入操作
            //查询所有列
            List<Map<String, String>> dynamicFieldList = this.baseMapper.selectDynamicSopAll(databaseName, tableName);
            Map<String, Object> map = new LinkedHashMap<>();
            if (!CollectionUtils.isEmpty(dynamicFieldList)) {
                StringJoiner stringJoinerFieldName = new StringJoiner(",");
                StringJoiner stringJoinerFieldValue = new StringJoiner(",");
                for (Map<String, String> m : dynamicFieldList) {
                    for (Map.Entry<String, String> entry : m.entrySet()) {
                        switch (entry.getValue()) {
                        case SystemConstant.TYPE:
                            map.put(entry.getValue(), tfCustomFlow.getType());
                            break;
                        case SystemConstant.FLOW_DEPLOYMENT_ID_FIELD:
                            map.put(entry.getValue(), tfCustomFlow.getFlowDeploymentId());
                            break;
                        case SystemConstant.VERSION:
                            map.put(entry.getValue(), tfCustomFlow.getVersion());
                            break;
                        case SystemConstant.CODE:
                            map.put(entry.getValue(), code);
                            break;
                        case SystemConstant.FLOW_ID:
                            map.put(entry.getValue(), flowId);
                            break;
                        default:
                            if (formFieldMap.containsKey(entry.getValue())) {
                                map.put(entry.getValue(), formFieldMap.get(entry.getValue()));
                            } else {
                                map.put(entry.getValue(), null);
                            }
                            break;
                        }
                    }
                }
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    stringJoinerFieldName.add(entry.getKey());
                    stringJoinerFieldValue.add(
                            Objects.nonNull(entry.getValue()) ? "'" + entry.getValue().toString() + "'" : null);
                }
                tbSopInfoMapper.saveDynamicSop(tableName, stringJoinerFieldName.toString(),
                        stringJoinerFieldValue.toString());
            }
        } else {//否则更新
            if (!CollectionUtils.isEmpty(formFieldMap)) {
                StringJoiner stringJoinerFieldValue = new StringJoiner(",");
                for (Map.Entry<String, String> entry : formFieldMap.entrySet()) {
                    stringJoinerFieldValue.add(entry.getKey() + "='" + entry.getValue() + "'");
                }
                tbSopInfoMapper.updateDynamicSop(tableName, tfCustomFlow.getFlowDeploymentId(), flowId,
                        stringJoinerFieldValue.toString());
            }
        }
        return true;
    }

    /**
     * 查询动态sop数据
     *
     * @param tableName
     * @param flowDeploymentId
     * @param flowId
     * @return
     */
    @Override
    public int selectDynamicSop(String tableName, String flowDeploymentId, Long flowId) {
        return this.baseMapper.selectDynamicSop(tableName, flowDeploymentId, flowId);
    }

    /**
     * sop发布信息
     *
     * @param sopPublishParam
     * @return
     * @throws InterruptedException
     */
    @Override
    @Transactional
    public Boolean sopPublish(SopPublishParam sopPublishParam) throws InterruptedException {
        Optional.ofNullable(sopPublishParam.getCrmNo())
                .orElseThrow(() -> ExceptionResultEnum.PARAMS_ERROR.exception("crm编号不能为空"));
        if (sopPublishParam.getApprove() != FlowApprovePassEnum.DRAFT) {
            throw ExceptionResultEnum.PARAMS_ERROR.exception("sop发布只能为草稿");
        }
        return tbSopInfoService.sopApplyOrPublish(sopPublishParam.getSopNo(), sopPublishParam.getCrmNo(),
                sopPublishParam.getFlowDeploymentId(), sopPublishParam.getApprove(),
                sopPublishParam.getFormProperties());
    }

    /**
     * sop申请信息
     *
     * @param sopApplyParam
     * @return
     */
    @Override
    @Transactional
    public Boolean sopApply(SopApplyParam sopApplyParam) throws InterruptedException {
        Optional.ofNullable(sopApplyParam.getCrmNo())
                .orElseThrow(() -> ExceptionResultEnum.PARAMS_ERROR.exception("crm编号不能为空"));
        if (sopApplyParam.getApprove() != FlowApprovePassEnum.START
                && sopApplyParam.getApprove() != FlowApprovePassEnum.DRAFT) {
            throw ExceptionResultEnum.PARAMS_ERROR.exception("sop申请只能为提交或草稿");
        }
        return tbSopInfoService.sopApplyOrPublish(sopApplyParam.getSopNo(), sopApplyParam.getCrmNo(),
                sopApplyParam.getFlowDeploymentId(), sopApplyParam.getApprove(), sopApplyParam.getFormProperties());
    }

    /**
     * sop填报信息
     *
     * @param flowApproveParam
     * @return
     */
    @Override
    @Transactional
    public Boolean sopApprove(FlowApproveParam flowApproveParam) throws InterruptedException {
        Optional.ofNullable(flowApproveParam.getTaskId())
                .orElseThrow(() -> ExceptionResultEnum.FLOW_TASK_ID_IS_NULL.exception());
        if (flowApproveParam.getApprove() != FlowApprovePassEnum.PASS
                && flowApproveParam.getApprove() != FlowApprovePassEnum.REJECT
                && flowApproveParam.getApprove() != FlowApprovePassEnum.DRAFT
                && flowApproveParam.getApprove() != FlowApprovePassEnum.START) {
            throw ExceptionResultEnum.PARAMS_ERROR.exception("sop填报只能为通过或驳回或草稿或提交");
        }
        Optional.ofNullable(flowApproveParam.getFormProperties())
                .orElseThrow(() -> ExceptionResultEnum.FLOW_FORM_PROPERTIES_IS_NULL.exception());
        if (flowApproveParam.getApprove() == FlowApprovePassEnum.REJECT && Objects.isNull(
                flowApproveParam.getSetup())) {
            throw ExceptionResultEnum.FLOW_REJECT_SETUP_IS_NULL.exception();
        }
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Task task = taskService.createTaskQuery().taskId(String.valueOf(flowApproveParam.getTaskId())).singleResult();
        Optional.ofNullable(task).orElseThrow(() -> ExceptionResultEnum.FLOW_TASK_NO_DATA.exception());

        List<String> taskApproveUserList = activitiService.getTaskApprove(task);
        if (flowApproveParam.getApprove() != FlowApprovePassEnum.DRAFT && !CollectionUtils.isEmpty(taskApproveUserList)
                && !taskApproveUserList.contains(sysUser.getId().toString())) {
            throw ExceptionResultEnum.FLOW_SOP_DATA_NOT_ME.exception();
        }

        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(
                new QueryWrapper<TFCustomFlowEntity>().lambda()
                        .eq(TFCustomFlowEntity::getFlowId, Long.parseLong(task.getProcessInstanceId())));
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.FLOW_ENTITY_NO_DATA.exception());

        TFCustomFlow tfCustomFlow = tfCustomFlowService.getById(tfCustomFlowEntity.gettFCustomFlowId());
        Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.FLOW_CUSTOM_NO_DATA.exception());

        if (tfCustomFlow.getType() != TFCustomTypeEnum.OFFICE_SOP_FLOW
                && tfCustomFlow.getType() != TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW) {
            throw ExceptionResultEnum.ERROR.exception("sop流程类型错误");
        }

        TBSopInfo tbSopInfo = this.getOne(
                new QueryWrapper<TBSopInfo>().lambda().eq(TBSopInfo::getSopNo, tfCustomFlowEntity.getCode()));
        Optional.ofNullable(tbSopInfo).orElseThrow(() -> ExceptionResultEnum.SOP_INFO_NO_DATA.exception());

        TBSopInfoDetail tbSopInfoDetail = tbSopInfoDetailService.getOne(
                new QueryWrapper<TBSopInfoDetail>().lambda().eq(TBSopInfoDetail::getSopInfoId, tbSopInfo.getId()));
        Optional.ofNullable(tbSopInfoDetail).orElseThrow(() -> ExceptionResultEnum.SOP_DETAIL_INFO_NO_DATA.exception());

        //更新表单信息
        FlowTaskResult flowTaskResult = JSONObject.parseObject(flowApproveParam.getFormProperties(),
                FlowTaskResult.class);
        Long engineerUserId = null;
        if (flowTaskResult.getSetup().intValue() == 1) {
            Long regionUserId = null;
            String assistantEngineerUserIds = null;
            Map<String, Object> map = this.getApproveUserIds(flowTaskResult);
            regionUserId = (Long) map.get(SystemConstant.REGION_USER_ID);
            engineerUserId = (Long) map.get(SystemConstant.ENGINEER_USER_ID);
            assistantEngineerUserIds = (String) map.get(SystemConstant.ASSISTANT_ENGINEER_USER_ID);

            tbSopInfoDetail.updateUserIdInfo(regionUserId, engineerUserId, assistantEngineerUserIds);
            tbSopInfoDetailService.updateById(tbSopInfoDetail);
        } else {
            engineerUserId = Long.parseLong(taskApproveUserList.get(0));
        }
        if (flowApproveParam.getApprove() == FlowApprovePassEnum.PASS
                || flowApproveParam.getApprove() == FlowApprovePassEnum.START) {
            List<String> approveUserIds = this.getNextApproveUserIds(tfCustomFlow.getType(), flowTaskResult,
                    tbSopInfoDetail, Long.parseLong(task.getProcessInstanceId()));
            flowApproveParam.setApproveUserIds(approveUserIds);
        }

        if (flowTaskResult.getSetup().intValue() == 3) {//内审时要set全部值
            FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
            FlowTaskResult currFlowTaskResult = GsonUtil.fromJson(
                    GsonUtil.toJson(flowResult.getSetupMap().get(flowTaskResult.getTaskKey())), FlowTaskResult.class);
            List<FlowFormWidgetResult> flowFormWidgetResultList = currFlowTaskResult.getFormProperty();
            Map<String, FlowFormWidgetResult> flowTaskResultMap = flowTaskResult.getFormProperty().stream().collect(
                    Collectors.toMap(FlowFormWidgetResult::getFormId, Function.identity(), (dto1, dto2) -> dto1));
            for (FlowFormWidgetResult f : flowFormWidgetResultList) {
                if (flowTaskResultMap.containsKey(f.getFormId())) {
                    f.setValue(flowTaskResultMap.get(f.getFormId()).getValue());
                }
            }
            flowTaskResult.setFormProperty(flowFormWidgetResultList);
            flowApproveParam.setFormProperties(JacksonUtil.parseJson(flowTaskResult));
        }

        CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectBySopNoOrCrmNo(tfCustomFlowEntity.getCode(),
                tfCustomFlowEntity.getCrmNo());
        Optional.ofNullable(crmProjectResult).orElseThrow(() -> ExceptionResultEnum.CRM_NO_NO_DATA.exception());

        Map<String, Object> map = activitiService.taskApprove(flowApproveParam);
        if (flowApproveParam.getApprove() != FlowApprovePassEnum.DRAFT) {
            map.put(SystemConstant.CRM_INFO, crmProjectResult);
            map.put(SystemConstant.SOP_ID, tbSopInfo.getId());
            map.put(SystemConstant.SOURCE, "sopApprove");
            tbSopInfoService.saveJobRemind(map);
        }
        TFFlowApprove tfFlowApprove = (TFFlowApprove) map.get(SystemConstant.FLOW_APPROVE);
        tbSopInfo.setStatus(
                tfFlowApprove.getSetup().intValue() == 1 && tfFlowApprove.getStatus() == FlowStatusEnum.DRAFT ?
                        SopStatusEnum.DRAFT :
                        SopStatusEnum.START);
        tbSopInfo.updateInfo(sysUser.getId());
        tbSopInfoService.updateById(tbSopInfo);

        //如果下一步审批是大区经理内审并且区域协调人和大区经理为同一人时，后台自动审批
        tbSopInfoService.sopSystemApprove(tfCustomFlow, tfCustomFlowEntity, tfFlowApprove, tbSopInfoDetail,
                flowApproveParam.getCrmNo());
        return true;
    }

    /**
     * sop管理列表
     *
     * @param sopInfoListParam
     * @return
     */
    @Override
    public IPage<Map> list(SopInfoListParam sopInfoListParam) {
        if (sopInfoListParam.getType() != TFCustomTypeEnum.OFFICE_SOP_FLOW
                && sopInfoListParam.getType() != TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW) {
            throw ExceptionResultEnum.ERROR.exception("流程类型只能为教务处或研究生");
        }
        TFCustomFlow maxTfCustomFlow = tfCustomFlowService.findMaxVersion(null, null, sopInfoListParam.getType());
        Optional.ofNullable(maxTfCustomFlow).orElseThrow(() -> ExceptionResultEnum.FLOW_CUSTOM_NO_DATA.exception());
        sopInfoListParam.setVersion(maxTfCustomFlow.getVersion());
        String tableName = sopInfoListParam.getType().getTableName() + "_" + sopInfoListParam.getVersion();
        String fieldName = null, fieldValue = null, fieldOrder = null;
        StringJoiner stringJoinerView = new StringJoiner(",");
        StringJoiner stringJoinerCondition = new StringJoiner("");
        StringJoiner stringJoinerOrder = new StringJoiner("");

        //显示字段
        if (!CollectionUtils.isEmpty(sopInfoListParam.getFormWidgetMetadataViewList())) {
            for (FormWidgetMetadataParam f : sopInfoListParam.getFormWidgetMetadataViewList()) {
                stringJoinerView.add(f.getFieldId());
            }
            fieldName = stringJoinerView.toString();
        }
        //筛选字段
        if (!CollectionUtils.isEmpty(sopInfoListParam.getFormWidgetMetadataConditionList())) {
            LinkedMultiValueMap<String, FormWidgetMetadataParam> formWidgetMetadataParamLinkedMultiValueMap = new LinkedMultiValueMap<>(
                    sopInfoListParam.getFormWidgetMetadataConditionList().size());
            for (FormWidgetMetadataParam f : sopInfoListParam.getFormWidgetMetadataConditionList()) {
                if (Objects.nonNull(f.getOperator())) {
                    //加入固定字段转换
                    if (SystemConstant.SOP_TRANSFORM_MAP.containsKey(f.getFieldId())) {
                        if (Objects.equals(f.getFieldId().toLowerCase(), "status")) {
                            JSONArray jsonArray = JSONArray.parseArray(f.getFieldValue());
                            if (Objects.nonNull(jsonArray) && jsonArray.size() > 0) {
                                StringJoiner stringJoiner = new StringJoiner("").add("(");
                                f.setOperator(f.getOperator() == FormWidgetMetadataOperator.EQ ?
                                        FormWidgetMetadataOperator.IN :
                                        FormWidgetMetadataOperator.NOT_IN);
                                for (int i = 0; i < jsonArray.size(); i++) {
                                    if (Objects.equals(jsonArray.getString(i), FlowStatusEnum.AUDITING.name())) {
                                        stringJoiner.add(
                                                "'" + FlowStatusEnum.START.name() + "','" + FlowStatusEnum.DRAFT.name()
                                                        + "','" + FlowStatusEnum.AUDITING.name() + "','"
                                                        + FlowStatusEnum.REJECT.name() + "','"
                                                        + FlowStatusEnum.CANCEL.name() + "',");
                                    } else if (Objects.equals(jsonArray.getString(i), FlowStatusEnum.FINISH.name())) {
                                        stringJoiner.add("'" + FlowStatusEnum.FINISH.name() + "',");
                                    }
                                }
                                String s = stringJoiner.toString().substring(0, stringJoiner.length() - 1) + ")";
                                f.setFieldValue(s);
                            }
                        }
                        String fieldId = SystemConstant.SOP_TRANSFORM_MAP.get(f.getFieldId());
                        f.setFieldId(fieldId);
                        formWidgetMetadataParamLinkedMultiValueMap.add(fieldId, f);
                    } else {
                        formWidgetMetadataParamLinkedMultiValueMap.add(f.getFieldId(), f);
                    }
                }
            }
            for (Map.Entry<String, List<FormWidgetMetadataParam>> entry : formWidgetMetadataParamLinkedMultiValueMap.entrySet()) {
                List<FormWidgetMetadataParam> formWidgetMetadataParamList = entry.getValue();
                if (Objects.isNull(sopInfoListParam.getFormWidgetMetadataOperation())) {
                    sopInfoListParam.setFormWidgetMetadataOperation(FormWidgetMetadataOperation.AND);
                }
                if (formWidgetMetadataParamList.size() > 1) {
                    StringJoiner conditionJoin = new StringJoiner("").add(
                            sopInfoListParam.getFormWidgetMetadataOperation().getCode()).add(" ( ");
                    for (int y = 0; y < formWidgetMetadataParamList.size(); y++) {
                        FormWidgetMetadataParam f = formWidgetMetadataParamList.get(y);
                        if (f.getOperator() == FormWidgetMetadataOperator.LIKE) {
                            conditionJoin.add(f.getFieldId()).add(f.getOperator().getCode()).add("('%','")
                                    .add(f.getFieldValue()).add("','%')");
                        } else if (f.getOperator() == FormWidgetMetadataOperator.IN
                                || f.getOperator() == FormWidgetMetadataOperator.NOT_IN) {
                            conditionJoin.add(f.getFieldId()).add(f.getOperator().getCode()).add(f.getFieldValue());
                        } else {
                            conditionJoin.add(f.getFieldId()).add(f.getOperator().getCode()).add("'")
                                    .add(f.getFieldValue()).add("'");
                        }
                        if (y < formWidgetMetadataParamList.size() - 1) {
                            conditionJoin.add(FormWidgetMetadataOperation.OR.getCode());
                        }
                    }
                    conditionJoin.add(" ) ");
                    stringJoinerCondition.add(conditionJoin.toString()).add("\r\n");
                } else {
                    for (FormWidgetMetadataParam f : formWidgetMetadataParamList) {
                        if (f.getOperator() == FormWidgetMetadataOperator.LIKE) {
                            stringJoinerCondition.add(sopInfoListParam.getFormWidgetMetadataOperation().getCode())
                                    .add(f.getFieldId()).add(f.getOperator().getCode()).add("('%','")
                                    .add(f.getFieldValue()).add("','%')").add("\r\n");
                        } else if (f.getOperator() == FormWidgetMetadataOperator.IN
                                || f.getOperator() == FormWidgetMetadataOperator.NOT_IN) {
                            stringJoinerCondition.add(sopInfoListParam.getFormWidgetMetadataOperation().getCode())
                                    .add(f.getFieldId()).add(f.getOperator().getCode()).add(f.getFieldValue())
                                    .add("\r\n");
                        } else {
                            stringJoinerCondition.add(sopInfoListParam.getFormWidgetMetadataOperation().getCode())
                                    .add(f.getFieldId()).add(f.getOperator().getCode()).add("'").add(f.getFieldValue())
                                    .add("'").add("\r\n");
                        }
                    }
                }
            }
        }
        fieldValue = !Objects.equals(stringJoinerCondition.toString().trim(), "") ?
                stringJoinerCondition.toString().trim() :
                null;

        //排序字段
        if (!CollectionUtils.isEmpty(sopInfoListParam.getFormWidgetMetadataOrderList())) {
            for (FormWidgetMetadataParam f : sopInfoListParam.getFormWidgetMetadataOrderList()) {
                stringJoinerOrder.add(f.getFieldId()).add(f.getOrder().getCode()).add(",");
            }
            fieldOrder = stringJoinerOrder.toString();
            fieldOrder = fieldOrder.substring(0, fieldOrder.length() - 1);
        }

        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        DataPermissionDto dpr = sysUserService.buildUserDataPermission(requestUser.getId());
        IPage<Map> list = this.baseMapper.list(
                new Page<>(sopInfoListParam.getPageNumber(), sopInfoListParam.getPageSize()),
                Objects.nonNull(sopInfoListParam.getType()) ? sopInfoListParam.getType().name() : null,
                sopInfoListParam.getServiceId(), tableName, fieldName, fieldValue, dpr, fieldOrder);
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        for (Map m : list.getRecords()) {
            String regionUserId = (String) m.get("region_user_id_1");
            String engineerUserId = (String) m.get("engineer_user_id_1");
            String assistantEngineerUserId = (String) m.get("assistant_engineer_user_id_1");
            List<Long> userIdList = new ArrayList<>(3);
            Map<Long, String> map = new HashMap<>(3);
            Map<Long, String> assistantEngineerMap = new HashMap<>();//助理工程师map
            if (Objects.nonNull(regionUserId)) {
                userIdList.add(Long.parseLong(regionUserId));
                map.put(Long.parseLong(regionUserId), "region_user_id_1");
            }
            if (Objects.nonNull(engineerUserId)) {
                userIdList.add(Long.parseLong(engineerUserId));
                map.put(Long.parseLong(engineerUserId), "engineer_user_id_1");
            }
            if (Objects.nonNull(assistantEngineerUserId)) {
                if (assistantEngineerUserId.contains(SystemConstant.LIST_JOIN_SPLIT)) {
                    String[] strs = assistantEngineerUserId.split(",");
                    for (int i = 0; i < strs.length; i++) {
                        userIdList.add(Long.parseLong(strs[i]));
                        assistantEngineerMap.put(Long.parseLong(strs[i]), "assistant_engineer_user_id_1");
                    }
                } else {
                    userIdList.add(Long.parseLong(assistantEngineerUserId));
                    assistantEngineerMap.put(Long.parseLong(assistantEngineerUserId), "assistant_engineer_user_id_1");
                }
            }
            if (!CollectionUtils.isEmpty(userIdList)) {
                List<OrgUserNameDto> orgUserNameDtoList = sysUserService.findOrgUserName(userIdList);
                StringJoiner stringJoiner = new StringJoiner(SystemConstant.LIST_JOIN_SPLIT);
                for (OrgUserNameDto s : orgUserNameDtoList) {
                    if (map.containsKey(s.getId())) {
                        m.put(map.get(s.getId()), s.getOrgUserName());
                    }
                    if (assistantEngineerMap.containsKey(s.getId())) {
                        stringJoiner.add(s.getOrgUserName());
                    }
                }
                if (!CollectionUtils.isEmpty(assistantEngineerMap)) {
                    m.put("assistant_engineer_user_id_1", stringJoiner.toString());
                }
            }

            String flowId = (String) m.get("flowId");
            TFFlowLog tfFlowLog = tfFlowLogService.findByLastFlowLog(Long.parseLong(flowId));
            if (Objects.nonNull(tfFlowLog) && Objects.nonNull(tfFlowLog.getPendApproveId())) {
                List<String> userList = Arrays.asList(
                        tfFlowLog.getPendApproveId().split(SystemConstant.LIST_JOIN_SPLIT));
                List<OrgUserNameDto> orgUserNameDtoList = sysUserService.findOrgUserName(
                        userList.stream().map(s -> Long.parseLong(s)).collect(Collectors.toList()));
                List<String> userName = orgUserNameDtoList.stream().map(s -> s.getOrgUserName())
                        .collect(Collectors.toList());
                m.put("pendApproveName", StringUtils.join(userName, SystemConstant.LIST_JOIN_SPLIT));
            } else {
                m.put("pendApproveName", "--");
            }

            String taskIds = (String) m.get("taskId");
            if (Objects.nonNull(taskIds) && taskIds.contains(",")) {
                String[] taskStrs = taskIds.split(",");
                boolean match = false;
                for (int i = 0; i < taskStrs.length; i++) {
                    Task task = taskService.createTaskQuery().taskId(taskStrs[i]).singleResult();
                    if (task.getAssignee().equals(sysUser.getId().toString())) {
                        m.put("taskId", task.getId());
                        match = true;
                        m.put("myself", true);
                        break;
                    }
                }
                if (!match) {
                    m.put("taskId", taskStrs[0]);
                    m.put("myself", false);
                }
            } else if (Objects.nonNull(taskIds)) {
                Task task = taskService.createTaskQuery().taskId(taskIds).singleResult();
                if (Objects.nonNull(task.getAssignee()) && task.getAssignee().equals(sysUser.getId().toString())) {
                    m.put("myself", true);
                } else {
                    m.put("myself", false);
                    List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(task.getId());
                    if (!CollectionUtils.isEmpty(identityLinkList)) {
                        for (IdentityLink i : identityLinkList) {
                            if (i.getUserId().equals(sysUser.getId().toString())) {
                                m.put("myself", true);
                                break;
                            }
                        }
                    }
                }
            } else {
                m.put("myself", false);
            }
        }
        return list;
    }

    /**
     * sop自动审批
     *
     * @param tfCustomFlow
     * @param tfCustomFlowEntity
     * @param tfFlowApprove
     * @param tbSopInfoDetail
     * @param crmNo
     * @throws InterruptedException
     */
    @Override
    @Transactional
    public void sopSystemApprove(TFCustomFlow tfCustomFlow, TFCustomFlowEntity tfCustomFlowEntity,
            TFFlowApprove tfFlowApprove, TBSopInfoDetail tbSopInfoDetail, String crmNo) throws InterruptedException {
        //如果下一步审批是内审并且区域协调人和大区经理为同一人时，后台自动审批
        if (tfFlowApprove.getStatus() != FlowStatusEnum.FINISH && tfFlowApprove.getStatus() != FlowStatusEnum.END
                && tfFlowApprove.getStatus() == FlowStatusEnum.AUDITING && tfFlowApprove.getSetup().intValue() == 3
                && tbSopInfoDetail.getLeadId().longValue() == tbSopInfoDetail.getRegionUserId().longValue()) {
            Task taskNew = taskService.createTaskQuery().processInstanceId(String.valueOf(tfFlowApprove.getFlowId()))
                    .taskAssignee(String.valueOf(tbSopInfoDetail.getLeadId())).singleResult();
            Optional.ofNullable(taskNew).orElseThrow(() -> ExceptionResultEnum.FLOW_TASK_NO_DATA.exception());

            FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
            LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
            FlowTaskResult nextFlowTaskResult = null;
            for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
                if (entry.getValue().getSetup().intValue() == 3) {
                    nextFlowTaskResult = entry.getValue();
                    break;
                }
            }

            if (Objects.nonNull(nextFlowTaskResult)) {
                List<FlowFormWidgetResult> flowFormWidgetResultList = nextFlowTaskResult.getFormProperty();
                for (FlowFormWidgetResult f : flowFormWidgetResultList) {
                    if (f.getFormId().contains(SystemConstant.APPROVE_RADIO_REGION)) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("value", "1");
                        f.setValue(jsonObject.toString());
                    } else if (f.getFormId().contains(SystemConstant.APPROVE_REMARK_REGION)) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("value", SystemConstant.SYSTEM_AUTO_APPROVE);
                        f.setValue(jsonObject.toString());
                    } else if (f.getFormId().contains(SystemConstant.SIGN_REGION)) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("value", "https://sop-file.qmth.com.cn/logo/logo.png");
                        f.setValue(jsonObject.toString());
                    }
                }
            }
            activitiService.taskApprove(new FlowApproveParam(Long.parseLong(taskNew.getId()), FlowApprovePassEnum.PASS,
                    this.getNextApproveUserIds(tfCustomFlow.getType(), nextFlowTaskResult, tbSopInfoDetail,
                            tfCustomFlowEntity.getFlowId()), crmNo, SystemConstant.SYSTEM_AUTO_APPROVE,
                    JacksonUtil.parseJson(nextFlowTaskResult)));
        }
    }

    /**
     * 获取下一级审批人
     *
     * @param type
     * @param flowTaskResult
     * @param tbSopInfoDetail
     * @param flowId
     * @return
     */
    public List<String> getNextApproveUserIds(TFCustomTypeEnum type, FlowTaskResult flowTaskResult,
            TBSopInfoDetail tbSopInfoDetail, Long flowId) {
        List<String> approveUserIds = null;
        if (type == TFCustomTypeEnum.OFFICE_SOP_FLOW) {//教务处sop流程待审核人
            if (flowTaskResult.getSetup().intValue() == 1) {
                approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getRegionUserId()));
            } else if (flowTaskResult.getSetup().intValue() == 2) {
                approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getLeadId()),
                        String.valueOf(tbSopInfoDetail.getEngineerUserId()));
            } else if (flowTaskResult.getSetup().intValue() == 3) {
                List<Task> taskList = taskService.createTaskQuery().processInstanceId(String.valueOf(flowId)).list();
                if (!CollectionUtils.isEmpty(taskList) && taskList.size() == 1) {
                    approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getLeadId()));
                } else {
                    approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getLeadId()),
                            String.valueOf(tbSopInfoDetail.getEngineerUserId()));
                }
            } else {
                if (flowTaskResult.getSetup().intValue() >= 8 && tbSopInfoDetail.getAfterRegionToEnginess()) {
                    approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getRegionUserId()));
                } else {
                    approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getEngineerUserId()));
                }
            }
        } else if (type == TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW) {//研究生sop流程待审核人
            if (flowTaskResult.getSetup().intValue() == 1) {
                approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getRegionUserId()));
            } else if (flowTaskResult.getSetup().intValue() == 2) {
                approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getLeadId()),
                        String.valueOf(tbSopInfoDetail.getEngineerUserId()));
            } else if (flowTaskResult.getSetup().intValue() == 3) {
                List<Task> taskList = taskService.createTaskQuery().processInstanceId(String.valueOf(flowId)).list();
                if (!CollectionUtils.isEmpty(taskList) && taskList.size() == 1) {
                    approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getLeadId()));
                } else {
                    approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getLeadId()),
                            String.valueOf(tbSopInfoDetail.getEngineerUserId()));
                }
            } else {
                approveUserIds = Arrays.asList(String.valueOf(tbSopInfoDetail.getEngineerUserId()));
            }
        }
        return approveUserIds;
    }

    /**
     * 获取审批人
     *
     * @param flowTaskResult
     * @return
     */
    public Map<String, Object> getApproveUserIds(FlowTaskResult flowTaskResult) {
        Map<String, Object> map = new HashMap<>();
        Long regionUserId = null, engineerUserId = null;
        String assistantEngineerUserIds = null;
        List<FlowFormWidgetResult> formProperty = flowTaskResult.getFormProperty();
        for (FlowFormWidgetResult f : formProperty) {
            if (f.getFormId().contains(SystemConstant.REGION_USER_ID) && Objects.nonNull(f.getValue()) && !f.getValue()
                    .contains("null")) {
                JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                String value = jsonObject.getString(SystemConstant.VALUE);
                regionUserId = Long.parseLong(value);
            } else if (f.getFormId().contains(SystemConstant.ASSISTANT_ENGINEER_USER_ID) && Objects.nonNull(
                    f.getValue()) && !f.getValue().contains("null")) {
                JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                JSONArray jsonArray = jsonObject.getJSONArray(SystemConstant.VALUE);
                StringJoiner stringJoiner = new StringJoiner(",");
                for (int i = 0; i < jsonArray.size(); i++) {
                    stringJoiner.add(jsonArray.getString(i));
                }
                assistantEngineerUserIds = stringJoiner.toString();
            } else if ((f.getFormId().contains(SystemConstant.ENGINEER_USER_ID) && Objects.nonNull(f.getValue()))
                    && !f.getValue().contains("null")) {
                JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                String value = jsonObject.getString(SystemConstant.VALUE);
                engineerUserId = Long.parseLong(value);
            }
            if (Objects.nonNull(regionUserId) && Objects.nonNull(engineerUserId) && Objects.nonNull(
                    assistantEngineerUserIds)) {
                break;
            }
        }
        Optional.ofNullable(regionUserId).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("区域协调人不能为空"));
        Optional.ofNullable(engineerUserId).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("实施工程师不能为空"));
        map.put(SystemConstant.REGION_USER_ID, regionUserId);
        map.put(SystemConstant.ENGINEER_USER_ID, engineerUserId);
        map.put(SystemConstant.ASSISTANT_ENGINEER_USER_ID, assistantEngineerUserIds);
        return map;
    }

    /**
     * sop申请或发布
     *
     * @param sopNo
     * @param crmNo
     * @param flowDeploymentId
     * @param approve
     * @param formProperties
     * @return
     * @throws InterruptedException
     */
    @Override
    @Transactional
    public Boolean sopApplyOrPublish(String sopNo, String crmNo, String flowDeploymentId, FlowApprovePassEnum approve,
            String formProperties) throws InterruptedException {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectBySopNoOrCrmNo(sopNo, crmNo);
        Optional.ofNullable(crmProjectResult).orElseThrow(() -> ExceptionResultEnum.CRM_NO_NO_DATA.exception());
        Optional.ofNullable(crmProjectResult.getRegionManagerId())
                .orElseThrow(() -> ExceptionResultEnum.ERROR.exception("该派单号[" + crmNo + "]未设置大区经理"));

        TBService tbService = tbServiceService.getById(crmProjectResult.getServiceUnitId());
        Optional.ofNullable(tbService).orElseThrow(() -> ExceptionResultEnum.SERVICE_NO_DATA.exception());
        Optional.ofNullable(tbService.getStatus()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("服务单元状态为空"));

        if (Objects.isNull(tbService.getEnable()) || !tbService.getEnable()) {
            throw ExceptionResultEnum.ERROR.exception("服务单元已作废");
        }
        if (tbService.getStatus() != ServiceStatusEnum.PUBLISH) {
            throw ExceptionResultEnum.ERROR.exception("只有发布状态的服务单元才能新增sop");
        }

        TFCustomFlow tfCustomFlow = null;
        TBSopInfoDetail tbSopInfoDetail = null;
        List<String> approveUserIds = new ArrayList<>();
        if (approve == FlowApprovePassEnum.DRAFT) {
            approveUserIds.add(String.valueOf(crmProjectResult.getRegionManagerId()));
        } else if (approve == FlowApprovePassEnum.START) {
            Optional.ofNullable(formProperties)
                    .orElseThrow(() -> ExceptionResultEnum.FLOW_FORM_PROPERTIES_IS_NULL.exception());

            tfCustomFlow = tfCustomFlowService.getOne(
                    new QueryWrapper<TFCustomFlow>().lambda().eq(TFCustomFlow::getFlowDeploymentId, flowDeploymentId));
            Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.FLOW_CUSTOM_NO_DATA.exception());
            TFCustomFlow maxTfCustomFlow = tfCustomFlowService.findMaxVersion(null, null, tfCustomFlow.getType());
            Optional.ofNullable(maxTfCustomFlow).orElseThrow(() -> ExceptionResultEnum.FLOW_CUSTOM_NO_DATA.exception());
            if (maxTfCustomFlow.getVersion().intValue() != tfCustomFlow.getVersion().intValue()) {//说明版本发生变化
                BeanUtils.copyProperties(maxTfCustomFlow, tfCustomFlow);
            }

            if (tfCustomFlow.getType() != TFCustomTypeEnum.OFFICE_SOP_FLOW
                    && tfCustomFlow.getType() != TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW) {
                throw ExceptionResultEnum.ERROR.exception("sop流程类型错误");
            }

            FlowTaskResult flowTaskResult = JSONObject.parseObject(formProperties, FlowTaskResult.class);
            Map<String, Object> map = this.getApproveUserIds(flowTaskResult);
            Long regionUserId = (Long) map.get(SystemConstant.REGION_USER_ID);
            Long engineerUserId = (Long) map.get(SystemConstant.ENGINEER_USER_ID);
            String assistantEngineerUserIds = (String) map.get(SystemConstant.ASSISTANT_ENGINEER_USER_ID);
            tbSopInfoDetail = new TBSopInfoDetail(crmProjectResult.getRegionManagerId(), regionUserId, engineerUserId,
                    assistantEngineerUserIds);
            approveUserIds = this.getNextApproveUserIds(tfCustomFlow.getType(), flowTaskResult, tbSopInfoDetail, null);
        }

        Map<String, Object> map = activitiService.taskApprove(
                new FlowApproveParam(flowDeploymentId, approve, approveUserIds, crmNo, formProperties));
        if (approve != FlowApprovePassEnum.DRAFT) {
            map.put(SystemConstant.CRM_INFO, crmProjectResult);
            map.put(SystemConstant.SOP_ID, null);
            map.put(SystemConstant.SOURCE, "sopApplyOrPublish");
            tbSopInfoService.saveJobRemind(map);
        }

        tfCustomFlow = Objects.isNull(tfCustomFlow) ? (TFCustomFlow) map.get(SystemConstant.FLOW_CUSTOM) : tfCustomFlow;
        TFCustomFlowEntity tfCustomFlowEntity = (TFCustomFlowEntity) map.get(SystemConstant.FLOW_ENTITY);

        TBSopInfo tbSopInfo = new TBSopInfo(crmNo, tfCustomFlowEntity.getCode(), crmProjectResult.getServiceUnitId(),
                crmProjectResult.getCustomId(), crmProjectResult.getProductId(), tfCustomFlow.getType(),
                SopStatusEnum.valueOf(approve.name()), sysUser.getId());
        if (Objects.isNull(tbSopInfoDetail)) {
            tbSopInfoDetail = new TBSopInfoDetail(tbSopInfo.getId(), crmProjectResult.getRegionManagerId());
        } else {
            tbSopInfoDetail.setSopInfoId(tbSopInfo.getId());
        }
        tbSopInfoDetailService.save(tbSopInfoDetail);
        TBSopPlanDateLog tbSopPlanDateLog = tbSopPlanDateLogService.getOne(new QueryWrapper<TBSopPlanDateLog>().lambda()
                .eq(TBSopPlanDateLog::getFlowId, tfCustomFlowEntity.getFlowId())
                .orderByDesc(TBSopPlanDateLog::getCreateTime).last(" limit 1 "));
        if (Objects.nonNull(tbSopPlanDateLog)) {
            tbSopPlanDateLog.setSopId(tbSopInfo.getId());
            tbSopPlanDateLogService.updateById(tbSopPlanDateLog);
        }

        tfCustomFlowEntity.setObjId(tbSopInfo.getId());
        tfCustomFlowEntityService.updateById(tfCustomFlowEntity);
        tbCrmService.updateCrmStatus(crmNo, CrmStatusEnum.PUBLISH);
        return tbSopInfoService.save(tbSopInfo);
    }

    /**
     * 保存提醒/延时任务
     *
     * @param map
     */
    @Override
    @Transactional
    public void saveJobRemind(Map<String, Object> map) throws InterruptedException {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        TFCustomFlow tfCustomFlow = (TFCustomFlow) map.get(SystemConstant.FLOW_CUSTOM);
        Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.FLOW_CUSTOM_NO_DATA.exception());

        TFCustomFlowEntity tfCustomFlowEntity = (TFCustomFlowEntity) map.get(SystemConstant.FLOW_ENTITY);
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.FLOW_ENTITY_NO_DATA.exception());

        TFFlowApprove tfFlowApprove = (TFFlowApprove) map.get(SystemConstant.FLOW_APPROVE);
        Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_NO_DATA.exception());

        TFFlowLog tfFlowLog = (TFFlowLog) map.get(SystemConstant.FLOW_APPROVE_LOG);
        Optional.ofNullable(tfFlowLog).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_LOG_NO_DATA.exception());

        Long sopId = (Long) map.get(SystemConstant.SOP_ID);
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceId(String.valueOf(tfCustomFlowEntity.getFlowId())).list();
        if (!CollectionUtils.isEmpty(taskList) && (tfFlowApprove.getStatus() != FlowStatusEnum.DRAFT
                && tfFlowApprove.getStatus() != FlowStatusEnum.FINISH
                && tfFlowApprove.getStatus() != FlowStatusEnum.END)) {
            Long processLimitedTime = null;
            String execField = null;
            if (tfCustomFlow.getType() == TFCustomTypeEnum.OFFICE_SOP_FLOW) {//教务处sop
                if (tfFlowApprove.getSetup().intValue() == 2) {//项目关键信息
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 1);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.PROJECT_KEY_INFO_DATE.getKey());
                    execField = ProcessLimitedEnum.PROJECT_KEY_INFO_DATE.getKey();
                    tbSopInfoService.saveSopPlanDate(flowTaskResult, sopId, tfCustomFlowEntity.getFlowId(),
                            sysUser.getId());
                } else if (tfFlowApprove.getSetup().intValue() == 3) {//内审
                    processLimitedTime = tfFlowApprove.getUpdateTime();
                    execField = ProcessLimitedEnum.APPROVE_RADIO.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 5) {//扫描准备
                    String source = (String) map.get(SystemConstant.SOURCE);
                    if (Objects.nonNull(source) && !Objects.equals(source, "save")) {
                        tbSopInfoService.sopDeviceInOutSave(map, 4);
                    }
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.SCAN_START_TIME.getKey());
                    execField = ProcessLimitedEnum.SCAN_START_TIME.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 7) {//校验收尾
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.SCAN_END_TIME.getKey());
                    execField = ProcessLimitedEnum.SCAN_END_TIME.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 8) {//设备入库登记
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 1);
                    String source = (String) map.get(SystemConstant.SOURCE);
                    //审批过程中，如果外包服务范围为"仅扫描"，则释放实施工程师资源，后续有区域协调人兼任
                    if (Objects.nonNull(source) && Objects.equals(source, "sopApprove")) {
                        List<FlowFormWidgetResult> formProperty = flowTaskResult.getFormProperty();
                        Long engineerUserId = null;
                        for (FlowFormWidgetResult f : formProperty) {
                            if (f.getFormId().contains(SystemConstant.THIRD_SERVICE_REGION_CB) && Objects.nonNull(
                                    f.getValue()) && !f.getValue().contains("null")) {
                                JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                                String value = jsonObject.getString(SystemConstant.VALUE);
                                if (Objects.nonNull(value) && Objects.nonNull(sopId) && value.equals("SCAN")) {
                                    TBSopInfoDetail tbSopInfoDetail = tbSopInfoDetailService.getOne(
                                            new QueryWrapper<TBSopInfoDetail>().lambda()
                                                    .eq(TBSopInfoDetail::getSopInfoId, sopId));
                                    engineerUserId = tbSopInfoDetail.getEngineerUserId();
                                    tbSopInfoDetail.setAfterRegionToEnginess(true);
                                    tbSopInfoDetailService.updateById(tbSopInfoDetail);
                                    break;
                                }
                            }
                        }
                        if (Objects.nonNull(engineerUserId)) {
                            List<Map<String, Object>> sopPassageMap = this.findSopPassage(null);
                            if (!CollectionUtils.isEmpty(sopPassageMap)) {
                                for (Map m : sopPassageMap) {
                                    String engineerUserStr =
                                            Objects.nonNull(m) && Objects.nonNull(m.get("engineerUserIds")) ?
                                                    m.get("engineerUserIds").toString() :
                                                    null;
                                    if (Objects.nonNull(engineerUserStr)) {
                                        String[] strs = engineerUserStr.split(",");
                                        Set<String> set = new HashSet<>(Arrays.asList(strs));
                                        if (!set.contains(engineerUserId)) {
                                            TBUserArchives tbUserArchives = tbUserArchivesService.findByUserId(
                                                    engineerUserId);
                                            if (Objects.nonNull(tbUserArchives)) {
                                                tbUserArchives.setStatus(UserArchivesStatusEnum.FREE);
                                                tbUserArchives.updateInfo(sysUser.getId());
                                                tbUserArchivesService.updateById(tbUserArchives);
                                            }
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.SERVICE_FINISH_PLAN_DATE.getKey());
                    execField = ProcessLimitedEnum.SERVICE_FINISH_PLAN_DATE.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 9) {//评卷准备
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.MARK_START_TIME.getKey());
                    execField = ProcessLimitedEnum.MARK_START_TIME.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 10) {//评卷收尾
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.MARK_END_TIME.getKey());
                    execField = ProcessLimitedEnum.MARK_END_TIME.getKey();
                }
            } else if (tfCustomFlow.getType() == TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW) {//研究生sop
                if (tfFlowApprove.getSetup().intValue() == 2) {//项目关键信息
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 1);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.PROJECT_KEY_INFO_DATE.getKey());
                    execField = ProcessLimitedEnum.PROJECT_KEY_INFO_DATE.getKey();
                    tbSopInfoService.saveSopPlanDate(flowTaskResult, sopId, tfCustomFlowEntity.getFlowId(),
                            sysUser.getId());
                } else if (tfFlowApprove.getSetup().intValue() == 3) {//内审
                    processLimitedTime = tfFlowApprove.getUpdateTime();
                    execField = ProcessLimitedEnum.APPROVE_RADIO.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 5) {//现场环境测试/环境部署时间
                    String source = (String) map.get(SystemConstant.SOURCE);
                    if (Objects.nonNull(source) && !Objects.equals(source, "save")) {
                        tbSopInfoService.sopDeviceInOutSave(map, 4);
                    }
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.ENV_DEPLOYMENT_TIME.getKey());
                    execField = ProcessLimitedEnum.ENV_DEPLOYMENT_TIME.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 6) {//扫描准备
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.SCAN_START_TIME.getKey());
                    execField = ProcessLimitedEnum.SCAN_START_TIME.getKey();

                    //现场环境测试后，设备发货管理里的设备通过序列号匹配更新为签收
                    FlowTaskResult flowTaskResultDeviceOut = this.getFormProperties(tfCustomFlowEntity, 4);
                    tbDeviceDeliveryService.updateStatusBySop(flowTaskResultDeviceOut, DeviceDeliveryStatusEnum.RECEIVE,
                            sysUser.getId());
                } else if (tfFlowApprove.getSetup().intValue() == 7) {//校验收尾
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.SCAN_END_TIME.getKey());
                    execField = ProcessLimitedEnum.SCAN_END_TIME.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 8) {//评卷准备
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.MARK_START_TIME.getKey());
                    execField = ProcessLimitedEnum.MARK_START_TIME.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 9) {//成绩复核
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 2);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.MARK_END_TIME.getKey());
                    execField = ProcessLimitedEnum.MARK_END_TIME.getKey();
                } else if (tfFlowApprove.getSetup().intValue() == 11) {//设备入库登记
                    FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 1);
                    processLimitedTime = this.getProcessLimitedTime(flowTaskResult,
                            ProcessLimitedEnum.SERVICE_FINISH_PLAN_DATE.getKey());
                    execField = ProcessLimitedEnum.SERVICE_FINISH_PLAN_DATE.getKey();
                }
            }
            if (Objects.nonNull(execField)) {
                for (Task task : taskList) {
                    tsJobRemindService.updateJobRemind(Long.parseLong(task.getId()));
                    List<TSJobRemind> tsJobRemindList = new ArrayList<>();
                    if (Objects.nonNull(task.getAssignee())) {
                        tsJobRemindList.add(new TSJobRemind(JobQuartzTypeEnum.FLOW, tfCustomFlowEntity.getCode(),
                                Long.parseLong(task.getId()), tfCustomFlow.getType().getTitle() + ";" + task.getName(),
                                JobTypeEnum.BEFORE, Long.parseLong(task.getAssignee()), tfFlowLog.getApproveOperation(),
                                processLimitedTime, execField, sysUser.getId(), tfCustomFlowEntity.getCrmNo()));
                        tsJobRemindList.add(new TSJobRemind(JobQuartzTypeEnum.FLOW, tfCustomFlowEntity.getCode(),
                                Long.parseLong(task.getId()), tfCustomFlow.getType().getTitle() + ";" + task.getName(),
                                JobTypeEnum.AFTER, Long.parseLong(task.getAssignee()), tfFlowLog.getApproveOperation(),
                                processLimitedTime, execField, sysUser.getId(), tfCustomFlowEntity.getCrmNo()));
                    } else {
                        List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(task.getId());
                        if (!CollectionUtils.isEmpty(identityLinkList)) {
                            for (IdentityLink i : identityLinkList) {
                                tsJobRemindList.add(
                                        new TSJobRemind(JobQuartzTypeEnum.FLOW, tfCustomFlowEntity.getCode(),
                                                Long.parseLong(i.getTaskId()),
                                                tfCustomFlow.getType().getTitle() + ";" + task.getName(),
                                                JobTypeEnum.BEFORE, Long.parseLong(i.getUserId()),
                                                tfFlowLog.getApproveOperation(), processLimitedTime, execField,
                                                sysUser.getId(), tfCustomFlowEntity.getCrmNo()));
                                tsJobRemindList.add(
                                        new TSJobRemind(JobQuartzTypeEnum.FLOW, tfCustomFlowEntity.getCode(),
                                                Long.parseLong(i.getTaskId()),
                                                tfCustomFlow.getType().getTitle() + ";" + task.getName(),
                                                JobTypeEnum.AFTER, Long.parseLong(i.getUserId()),
                                                tfFlowLog.getApproveOperation(), processLimitedTime, execField,
                                                sysUser.getId(), tfCustomFlowEntity.getCrmNo()));
                            }
                        }
                    }
                    tsJobRemindService.saveJobRemind(tsJobRemindList);
                }
            }
        } else if (tfFlowApprove.getStatus() == FlowStatusEnum.FINISH) {
            if (tfCustomFlow.getType() == TFCustomTypeEnum.OFFICE_SOP_FLOW) {//教务处sop
                tbSopInfoService.sopDeviceInOutSave(map, 10);
            } else if (tfCustomFlow.getType() == TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW) {//研究生sop
                tbSopInfoService.sopDeviceInOutSave(map, 11);
            }
        }
    }

    /**
     * sop保存设备信息
     *
     * @param map
     * @param setup
     * @throws InterruptedException
     */
    @Override
    @Transactional
    public void sopDeviceInOutSave(Map<String, Object> map, Integer setup) throws InterruptedException {
        TFCustomFlowEntity tfCustomFlowEntity = (TFCustomFlowEntity) map.get(SystemConstant.FLOW_ENTITY);
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.FLOW_ENTITY_NO_DATA.exception());

        FlowTaskResult flowTaskResultDeviceTable = this.getFormProperties(tfCustomFlowEntity, setup);
        if (Objects.nonNull(flowTaskResultDeviceTable)) {
            CrmProjectResult crmProjectResult = (CrmProjectResult) map.get(SystemConstant.CRM_INFO);
            List<FlowFormWidgetResult> flowFormWidgetResultList = flowTaskResultDeviceTable.getFormProperty();
            List<DeviceInOutForm> deviceInOutFormList = new ArrayList<>();
            InOutTypeEnum type = null;
            Long deviceInOutTime = null;
            for (FlowFormWidgetResult f : flowFormWidgetResultList) {
                if (f.getFormId().contains(SystemConstant.DEVICE_OUT_TIME) || f.getFormId()
                        .contains(SystemConstant.DEVICE_IN_TIME)) {
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    String value = jsonObject.getString(SystemConstant.VALUE);
                    deviceInOutTime = Long.parseLong(value);
                    type = f.getFormId().contains(SystemConstant.DEVICE_OUT_TIME) ?
                            InOutTypeEnum.OUT :
                            InOutTypeEnum.IN;
                } else if (f.getFormId().contains(SystemConstant.DEVICE_OUT_TABLE) || f.getFormId()
                        .contains(SystemConstant.DEVICE_IN_TABLE)) {
                    if (Objects.isNull(type)) {
                        type = f.getFormId().contains(SystemConstant.DEVICE_OUT_TABLE) ?
                                InOutTypeEnum.OUT :
                                InOutTypeEnum.IN;
                    }
                    JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                    JSONArray jsonArray = jsonObject.getJSONArray(SystemConstant.VALUE);
                    for (int i = 0; i < jsonArray.size(); i++) {
                        deviceInOutFormList.add(
                                GsonUtil.fromJson(GsonUtil.toJson(jsonArray.getJSONObject(i)), DeviceInOutForm.class));
                    }
                }
            }
            tbDeviceInOutService.deviceInOutSubmit(
                    new DeviceInOutSubmitParam(crmProjectResult.getServiceUnitId(), tfCustomFlowEntity.getCrmNo(),
                            tfCustomFlowEntity.getCode(), deviceInOutTime, type, true, deviceInOutFormList));
        }
    }

    /**
     * sop编辑
     *
     * @param id
     * @return
     */
    @Override
    public FlowResult sopEdit(Long id) throws InterruptedException {
        Optional.ofNullable(id).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("sopId不能为空"));
        TBSopInfo tbSopInfo = this.getById(id);
        Optional.ofNullable(tbSopInfo).orElseThrow(() -> ExceptionResultEnum.SOP_INFO_NO_DATA.exception());

        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(
                new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getCode, tbSopInfo.getSopNo()));
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.FLOW_ENTITY_NO_DATA.exception());

        TFFlowApprove tfFlowApprove = tfFlowApproveService.getOne(new QueryWrapper<TFFlowApprove>().lambda()
                .eq(TFFlowApprove::getFlowId, tfCustomFlowEntity.getFlowId()));
        Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_NO_DATA.exception());

        FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
        FlowResult flowResultNew = new FlowResult();
        BeanUtils.copyProperties(flowResult, flowResultNew);
        LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
        LinkedHashMap<String, FlowTaskResult> setupMapNew = new LinkedHashMap<>(setupMap.size());
        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
            if (entry.getValue().getSetup().intValue() > 0) {
                if (entry.getValue().getSetup().intValue() == 1 || entry.getValue().getSetup().intValue() == 3) {
                    for (FlowFormWidgetResult f : entry.getValue().getFormProperty()) {
                        f.setReadable(true);
                        f.setWritable(false);
                    }
                }
                if (tfFlowApprove.getSetup().intValue() != 0 && tfFlowApprove.getSetup().intValue() < entry.getValue()
                        .getSetup().intValue()) {
                    break;
                } else if (entry.getValue().getSetup().intValue() != tfFlowApprove.getSetup().intValue()) {
                    setupMapNew.put(entry.getKey(), entry.getValue());
                }
            }
        }
        flowResultNew.setSetupMap(setupMapNew);

        CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectBySopNoOrCrmNo(tfCustomFlowEntity.getCode(),
                tfCustomFlowEntity.getCrmNo());
        Optional.ofNullable(crmProjectResult).orElseThrow(() -> ExceptionResultEnum.CRM_NO_NO_DATA.exception());

        flowResultNew.setCrmInfo(crmProjectResult);
        return flowResultNew;
    }

    /**
     * sop保存
     *
     * @param sopSaveParam
     * @return
     */
    @Override
    @Transactional
    public Boolean sopSave(SopSaveParam sopSaveParam) throws InterruptedException {
        TBSopInfo tbSopInfo = this.getById(sopSaveParam.getId());
        Optional.ofNullable(tbSopInfo).orElseThrow(() -> ExceptionResultEnum.SOP_INFO_NO_DATA.exception());

        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.getOne(
                new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getCode, tbSopInfo.getSopNo()));
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.FLOW_ENTITY_NO_DATA.exception());

        TFFlowApprove tfFlowApprove = tfFlowApproveService.getOne(new QueryWrapper<TFFlowApprove>().lambda()
                .eq(TFFlowApprove::getFlowId, tfCustomFlowEntity.getFlowId()));
        Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_NO_DATA.exception());

        TFCustomFlow tfCustomFlow = tfCustomFlowService.getById(tfCustomFlowEntity.gettFCustomFlowId());
        Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.FLOW_CUSTOM_NO_DATA.exception());

        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        FlowResult flowResultParam = JSONObject.parseObject(sopSaveParam.getFormProperties(), FlowResult.class);
        LinkedHashMap<String, FlowTaskResult> setupParamMap = flowResultParam.getSetupMap();
        for (Map.Entry<String, FlowTaskResult> entry : setupParamMap.entrySet()) {
            if (entry.getValue().getSetup() != 0) {//更新动态表单字段和处理时限
                tbSopInfoService.saveDynamicSop(tfCustomFlow, tfCustomFlowEntity.getCode(),
                        tfCustomFlowEntity.getFlowId(), entry.getValue());
            }
        }
        FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
        LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
            if (Objects.nonNull(setupParamMap.get(entry.getKey()))) {
                setupMap.put(entry.getKey(), setupParamMap.get(entry.getKey()));
            }
        }
        flowResult.setSetupMap(setupMap);
        tfCustomFlowEntity.updateInfo(sysUser.getId());
        tfCustomFlowEntity.setFlowProcessVar(JacksonUtil.parseJson(flowResult));
        if (tfFlowApprove.getStatus() != FlowStatusEnum.FINISH && tfFlowApprove.getStatus() != FlowStatusEnum.END) {
            Map<String, Object> map = new HashMap<>();
            CrmProjectResult crmProjectResult = tbCrmService.findCrmProjectBySopNoOrCrmNo(tfCustomFlowEntity.getCode(),
                    tfCustomFlowEntity.getCrmNo());
            Optional.ofNullable(crmProjectResult).orElseThrow(() -> ExceptionResultEnum.CRM_NO_NO_DATA.exception());

            TFFlowLog tfFlowLog = tfFlowLogService.getOne(
                    new QueryWrapper<TFFlowLog>().lambda().eq(TFFlowLog::getFlowId, tfCustomFlowEntity.getFlowId())
                            .last(" order by create_time limit 1 "));
            Optional.ofNullable(tfFlowLog).orElseThrow(() -> ExceptionResultEnum.FLOW_APPROVE_LOG_NO_DATA.exception());

            map.put(SystemConstant.FLOW_CUSTOM, tfCustomFlow);
            map.put(SystemConstant.FLOW_ENTITY, tfCustomFlowEntity);
            map.put(SystemConstant.FLOW_APPROVE, tfFlowApprove);
            map.put(SystemConstant.FLOW_APPROVE_LOG, tfFlowLog);
            map.put(SystemConstant.CRM_INFO, crmProjectResult);
            map.put(SystemConstant.SOP_ID, tbSopInfo.getId());
            map.put(SystemConstant.SOURCE, "save");
            tbSopInfoService.saveJobRemind(map);

            if (tfCustomFlow.getType() == TFCustomTypeEnum.OFFICE_SOP_FLOW
                    && tfFlowApprove.getSetup().intValue() >= 4) {
                tbSopInfoService.sopDeviceInOutSave(map, 4);
            } else if (tfCustomFlow.getType() == TFCustomTypeEnum.CLOUD_MARK_SOP_FLOW
                    && tfFlowApprove.getSetup().intValue() >= 4) {
                tbSopInfoService.sopDeviceInOutSave(map, 4);
                if (tfFlowApprove.getSetup().intValue() > 5) {
                    FlowTaskResult flowTaskResultDeviceOut = this.getFormProperties(tfCustomFlowEntity, 4);
                    tbDeviceDeliveryService.updateStatusBySop(flowTaskResultDeviceOut, DeviceDeliveryStatusEnum.RECEIVE,
                            sysUser.getId());
                }
            }

            FlowTaskResult flowTaskResult = this.getFormProperties(tfCustomFlowEntity, 1);
            tbSopInfoService.saveSopPlanDate(flowTaskResult, tbSopInfo.getId(), tfCustomFlowEntity.getFlowId(),
                    sysUser.getId());
        }
        return tfCustomFlowEntityService.updateById(tfCustomFlowEntity);
    }

    @Override
    public List<SysUser> userList(Long id) {
        return this.baseMapper.userList(id);
    }

    /**
     * 根据服务单元查找在途的区域协调人、实施工程师、助理工程师
     *
     * @param serviceId
     * @return
     */
    @Override
    public List<Map<String, Object>> findSopPassage(Long serviceId) {
        return this.baseMapper.findSopPassage(serviceId);
    }

    /**
     * 获取表单内容
     *
     * @param tfCustomFlowEntity
     * @param setup
     * @return
     */
    @Override
    public FlowTaskResult getFormProperties(TFCustomFlowEntity tfCustomFlowEntity, Integer setup) {
        FlowResult flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
        LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
        FlowTaskResult flowTaskResult = null;
        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
            if (entry.getValue().getSetup().intValue() == setup.intValue()) {
                flowTaskResult = entry.getValue();
                break;
            }
        }
        return flowTaskResult;
    }

    /**
     * 获取处理时限时间
     *
     * @param flowTaskResult
     * @param fieldId
     * @return
     */
    public Long getProcessLimitedTime(FlowTaskResult flowTaskResult, String fieldId) {
        Long processLimitedTime = null;
        List<FlowFormWidgetResult> formProperty = flowTaskResult.getFormProperty();
        for (FlowFormWidgetResult f : formProperty) {
            if (f.getFormId().contains(fieldId) && Objects.nonNull(f.getValue()) && !f.getValue().contains("null")) {
                JSONObject jsonObject = JSONObject.parseObject(f.getValue());
                String value = jsonObject.getString(SystemConstant.VALUE);
                processLimitedTime = Long.parseLong(value);
                break;
            }
        }
        if (!fieldId.contains(ProcessLimitedEnum.SERVICE_FINISH_PLAN_BEGIN_DATE.getKey())) {
            Optional.ofNullable(processLimitedTime).orElseThrow(() -> ExceptionResultEnum.ERROR.exception(
                    ProcessLimitedEnum.convertKeyToEnum(fieldId).getTitle() + "处理时限时间为空"));
        }
        return processLimitedTime;
    }

    /**
     * 更新sop计划进场开始时间和结束时间
     *
     * @param flowTaskResult
     * @param sopId
     * @param flowId
     * @param userId
     */
    @Override
    @Transactional
    public void saveSopPlanDate(FlowTaskResult flowTaskResult, Long sopId, Long flowId, Long userId) {
        Long serviceFinishPlanBeginDate = this.getProcessLimitedTime(flowTaskResult,
                ProcessLimitedEnum.SERVICE_FINISH_PLAN_BEGIN_DATE.getKey());
        Long serviceFinishPlanEndDate = this.getProcessLimitedTime(flowTaskResult,
                ProcessLimitedEnum.SERVICE_FINISH_PLAN_DATE.getKey());
        if (Objects.nonNull(serviceFinishPlanBeginDate)) {
            TBSopPlanDateLog tbSopPlanDateLog = tbSopPlanDateLogService.getOne(
                    new QueryWrapper<TBSopPlanDateLog>().lambda().eq(TBSopPlanDateLog::getFlowId, flowId)
                            .orderByDesc(TBSopPlanDateLog::getCreateTime).last(" limit 1 "));
            if (Objects.isNull(tbSopPlanDateLog)) {
                tbSopPlanDateLog = new TBSopPlanDateLog(sopId, flowId, serviceFinishPlanBeginDate,
                        serviceFinishPlanEndDate, userId);
                tbSopPlanDateLogService.save(tbSopPlanDateLog);
            } else {
                TBSopPlanDateLog tbSopPlanDateLogNew = new TBSopPlanDateLog();
                BeanUtils.copyProperties(tbSopPlanDateLog, tbSopPlanDateLogNew);
                tbSopPlanDateLogNew.setBeginTime(serviceFinishPlanBeginDate);
                tbSopPlanDateLogNew.setEndTime(serviceFinishPlanEndDate);
                if (!tbSopPlanDateLogNew.equals(tbSopPlanDateLog)) {
                    tbSopPlanDateLogNew.updateInfo(userId);
                    tbSopPlanDateLogService.save(tbSopPlanDateLogNew);
                }
            }
        }
    }

    /**
     * 根据crmNo查询在途的sop信息
     *
     * @param crmNo
     * @return
     */
    @Override
    public List<String> findFlowPassageByCrmNo(String crmNo, Long requestUserId) {
        Optional.ofNullable(crmNo).orElseThrow(() -> ExceptionResultEnum.CRM_NO_NO_DATA.exception());
        SysUser sysUser = sysUserService.getById(requestUserId);
        List<SysRole> sysRoleList = sysUserRoleService.listRoleByUserId(sysUser.getId());
        RoleTypeEnum roleTypeEnum = null;
        if (!CollectionUtils.isEmpty(sysRoleList)) {
            for (SysRole sysRole : sysRoleList) {
                if (sysRole.getType() == RoleTypeEnum.EFFECT_ENGINEER) {
                    roleTypeEnum = sysRole.getType();
                    break;
                } else if (sysRole.getType() == RoleTypeEnum.ASSISTANT_ENGINEER) {
                    roleTypeEnum = sysRole.getType();
                }
            }
        }
        return this.baseMapper.findFlowPassageByCrmNo(crmNo, sysUser.getId(),
                Objects.nonNull(roleTypeEnum) ? roleTypeEnum.name() : null);
    }

    /**
     * 根据serviceId和userId查询所有sop信息
     *
     * @param serviceId
     * @param userId
     * @return
     */
    @Override
    public List<SopInfoResult> findFlowByServiceId(Long serviceId, Long userId) {
        Optional.ofNullable(userId).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("用户id不能为空"));
        List<SysRole> sysRoleList = sysUserRoleService.listRoleByUserId(userId);
        RoleTypeEnum roleTypeEnum = null;
        if (!CollectionUtils.isEmpty(sysRoleList)) {
            for (SysRole sysRole : sysRoleList) {
                if (sysRole.getType() == RoleTypeEnum.EFFECT_ENGINEER) {
                    roleTypeEnum = sysRole.getType();
                    break;
                } else if (sysRole.getType() == RoleTypeEnum.ASSISTANT_ENGINEER) {
                    roleTypeEnum = sysRole.getType();
                }
            }
        }
        return this.baseMapper.findFlowByServiceId(serviceId, userId,
                Objects.nonNull(roleTypeEnum) ? roleTypeEnum.name() : null);
    }
}
