package com.yeejoin.amos.boot.module.jyjc.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdcardUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.controller.BaseController;
import com.yeejoin.amos.boot.biz.common.dao.mapper.DataDictionaryMapper;
import com.yeejoin.amos.boot.biz.common.dto.DataDictionaryDto;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.enums.LicenceStateEnum;
import com.yeejoin.amos.boot.biz.common.excel.ExcelUtil;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.boot.module.common.api.dto.AttachmentDto;
import com.yeejoin.amos.boot.module.common.api.dto.BaseEnterpriseCertDto;
import com.yeejoin.amos.boot.module.common.api.dto.TzsUserPermissionDto;
import com.yeejoin.amos.boot.module.common.api.entity.BaseEnterpriseCert;
import com.yeejoin.amos.boot.module.common.biz.service.impl.BaseEnterpriseCertServiceImpl;
import com.yeejoin.amos.boot.module.jg.api.enums.WorkFlowStatusEnum;
import com.yeejoin.amos.boot.module.jyjc.api.common.BizCommonConstant;
import com.yeejoin.amos.boot.module.jyjc.api.dto.InspectionCompanyPublicityDto;
import com.yeejoin.amos.boot.module.jyjc.api.entity.JyjcInspectionHistory;
import com.yeejoin.amos.boot.module.jyjc.api.entity.JyjcOpeningApplication;
import com.yeejoin.amos.boot.module.jyjc.api.enums.*;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcOpeningApplicationMapper;
import com.yeejoin.amos.boot.module.jyjc.api.model.*;
import com.yeejoin.amos.boot.module.jyjc.api.service.IJyjcOpeningApplicationService;
import com.yeejoin.amos.boot.module.jyjc.api.vo.JyjcOpeningApplicationVo;
import com.yeejoin.amos.boot.module.jyjc.biz.config.BaseException;
import com.yeejoin.amos.boot.module.jyjc.biz.message.factoty.OpenAppMsgFactory;
import com.yeejoin.amos.boot.module.jyjc.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jyjc.biz.service.TaskModelServiceImpl;
import com.yeejoin.amos.boot.module.ymt.api.dto.TzBaseEnterpriseInfoDto;
import com.yeejoin.amos.boot.module.ymt.api.entity.BaseUnitLicence;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzBaseEnterpriseInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzBaseUnitLicence;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzsUserInfo;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.BaseUnitLicenceMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzBaseEnterpriseInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzsUserInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.vo.TzsUserInfoVo;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
import com.yeejoin.amos.feign.systemctl.model.TaskV2Model;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowBatchDTO;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowStartDTO;
import com.yeejoin.amos.feign.workflow.model.ProcessTaskDTO;
import com.yeejoin.amos.feign.workflow.model.TaskResultDTO;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2023-12-13
 */
@Service
@Slf4j
public class JyjcOpeningApplicationServiceImpl extends BaseService<JyjcOpeningApplicationModel, JyjcOpeningApplication, JyjcOpeningApplicationMapper> implements IJyjcOpeningApplicationService {

    private final static String INDUSTRY_SUPERVISOR_DICT_TYPE = "HYZGBM";
    /**
     * 人员级别字典KEY
     */
    private final static String RYJB_JYJC_DICT_KEY = "RYJB_JYJC";
    /**
     * 所有人员资质检验检测项目key
     */
    private final static String ZZXM_JYJC_DICT_KEY = "ZZXM_JYJC_ALL";
    private static Map<String, DictionarieValueModel> permissionLevelMap;
    private static List<DictionarieValueModel> permissionItemList;
    @Autowired
    JyjcOpeningApplicationMapper jyjcOpeningApplicationMapper;
    @Autowired
    BaseUnitLicenceMapper baseUnitLicenceMapper;
    @Autowired
    CommonServiceImpl commonService;
    @Autowired
    CmWorkflowServiceImpl cmWorkflowService;
    @Autowired
    TaskModelServiceImpl taskModelService;
    @Autowired
    DataDictionaryMapper dataDictionaryMapper;
    @Autowired
    RedissonClient redissonClient;
    @Autowired
    private TzsServiceFeignClient tzsServiceFeignClient;
    @Value("${process-definition-key.jyjc.openapplication:}")
    private String processDefinitionKey;
    @Value("${jy.user-post:66151}")
    private String jyUserPost;

    @Value("${jc.user-post:66152}")
    private String jcUserPost;

    @Value("${jyjc.charge.user-post:6667}")
    private String chargeUserPost;

    @Autowired
    private TzBaseEnterpriseInfoMapper enterpriseInfoMapper;
    @Autowired
    private TzsUserInfoMapper userInfoMapper;
    @Autowired
    private RuleCommonServiceImpl ruleCommonService;
    @Autowired
    private TzBaseEnterpriseInfoMapper tzBaseEnterpriseInfoMapper;
    @Autowired
    private BaseEnterpriseCertServiceImpl enterpriseCertService;

    @Resource
    private JyjcInspectionHistoryServiceImpl inspectionHistoryService;

    @Resource
    private SnowflakeIdUtil sequence;

    @Resource
    private  OpenAppMsgFactory  openAppMsgFactory;

    /**
     * 编辑、工作台暂存逻辑
     *
     * @param model 对象
     * @return JyjcOpeningApplicationModel
     */
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    @GlobalTransactional(rollbackFor = Exception.class)
    public JyjcOpeningApplicationModel saveOrUpdate(JyjcOpeningApplicationModel model, String unitCode) {
        if (model.getSequenceNbr() != null) {
            // 编辑逻辑
            model.setOriDetectionRegion(model.getDetectionRegion());
            // 存json
            commonService.saveOrUpdateHistory(model.getOpenBizType(), JSONObject.parseObject(JSONObject.toJSONString(model)), model.getSequenceNbr());
            return this.updateWithModel(model);
        } else {
            // 工作台暂存（新增）逻辑
            // 1.创建开通申请
            List<String> codes = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.JY.getCode(), 1).getResult();
            model.setApplicationSeq(codes.get(0));
            CompanyBo companyBo = commonService.getReginParamsOfCurrentUser().getCompany();
            model.setUnitCode(unitCode);
            model.setUnitCodeName(companyBo.getCompanyName());
            model.setCreateUserId(RequestContext.getExeUserId());
            model.setStatus(WorkFlowStatusEnum.OPENING_APPLICATION_SUBMIT.getPass());
            model.setDockingUnitCode(this.getAppId(unitCode));
            // 编辑逻辑
            model.setOriDetectionRegion(model.getDetectionRegion());
            this.createWithModel(model);
            // 2.创建待办
            createDraftTask(model);
            // 3.存json
            commonService.saveOrUpdateHistory(model.getOpenBizType(), JSONObject.parseObject(JSONObject.toJSONString(model)), model.getSequenceNbr());
        }
        return this.updateWithModel(model);
    }

    private String getAppId(String unitCode) {
        TzBaseEnterpriseInfo baseEnterpriseInfo = tzBaseEnterpriseInfoMapper.selectOne(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().eq(TzBaseEnterpriseInfo::getUseCode, unitCode).select(BaseEntity::getSequenceNbr, TzBaseEnterpriseInfo::getAppId));
        return baseEnterpriseInfo.getAppId();
    }

    /**
     * 提交、保存并提交逻辑
     *
     * @param model       对象
     * @param companyCode
     * @return JyjcOpeningApplicationModel
     */
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    @GlobalTransactional(rollbackFor = Exception.class)
    public JyjcOpeningApplicationModel submitApplication(JyjcOpeningApplicationModel model, String companyCode) {
        String instanceId = model.getWorkflowProstanceId();
        this.setDefaultFieldValue(model, companyCode);
        if (StringUtils.isBlank(instanceId)) {
            // 未开启过工作流则进行开启 startProcess
            ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
            ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
            ArrayList<ActWorkflowStartDTO> list = new ArrayList<>();
            dto.setProcessDefinitionKey(processDefinitionKey);
            dto.setBusinessKey("1");
            dto.setCompleteFirstTask(Boolean.TRUE);
            // 接受机构
            list.add(dto);
            actWorkflowBatchDTO.setProcess(list);
            List<ProcessTaskDTO> processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
            List<WorkflowResultDto> resultDto = taskModelService.buildWorkFlowInfo(processTaskDTOS);
            WorkflowResultDto workflowResultDto = resultDto.get(0);
            if (!org.springframework.util.ObjectUtils.isEmpty(workflowResultDto.getNextTaskCode())) {
                model.setStatus(WorkFlowStatusEnum.getMessage(workflowResultDto.getNextTaskCode()).getPass());
            }
            model.setPromoter(RequestContext.getExeUserId());
            model.setWorkflowProstanceId(workflowResultDto.getInstanceId());
            model.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
            model.setNextTaskId(workflowResultDto.getNextTaskId());
            model.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            model.setDockingUnitCode(this.getAppId(companyCode));
            // 首次提交时删除暂存的待办
            this.deleteDraftTask(model);
            saveModel(model);
            // 创建代办
            buildTask(model, workflowResultDto);
            // 缓存流程数据
            commonService.saveExecuteFlowData2Redis(workflowResultDto.getInstanceId(), this.buildInstanceRuntimeData(model));
            // 存json
            commonService.saveOrUpdateHistory(model.getOpenBizType(), JSONObject.parseObject(JSONObject.toJSONString(model)), model.getSequenceNbr());
            return model;
        } else {
            // 首次提交时删除暂存的待办
            this.deleteDraftTask(model);
            // 存在流程，执行
            executeOneStep(model, "0");
            model.setDockingUnitCode(this.getAppId(companyCode));
            saveModel(model);
            // 存json
            commonService.saveOrUpdateHistory(model.getOpenBizType(), JSONObject.parseObject(JSONObject.toJSONString(model)), model.getSequenceNbr());
            return model;
        }
    }

    private void deleteDraftTask(JyjcOpeningApplicationModel model) {
        if (model.getSequenceNbr() != null) {
            taskModelService.deleteTaskModel(model.getSequenceNbr() + "");
        }
    }

    private void setDefaultFieldValue(JyjcOpeningApplicationModel model, String companyCode) {
        CompanyBo companyBo = commonService.getReginParamsOfCurrentUser().getCompany();
        model.setApplyTime(new Date());
        model.setUnitCode(companyCode);
        model.setUnitCodeName(companyBo.getCompanyName());
        if (model.getSequenceNbr() == null) {
            model.setCreateUserId(RequestContext.getExeUserId());
            List<String> codes = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.JY.getCode(), 1).getResult();
            model.setApplicationSeq(codes.get(0));
        }
    }

    private JyjcOpeningApplicationModel saveModel(JyjcOpeningApplicationModel model) {
        if (model.getSequenceNbr() == null) {
            model.setOriDetectionRegion(model.getDetectionRegion());
            return this.createWithModel(model);
        } else {
            model.setOriDetectionRegion(model.getDetectionRegion());
            return this.updateWithModel(model);
        }
    }

    private void createDraftTask(JyjcOpeningApplicationModel model) {
        ArrayList<TaskModelDto> list = new ArrayList<>();
        TaskModelDto dto = new TaskModelDto();
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(model, taskMessageDto);
        // 数据参数
        dto.setModel(taskMessageDto);
        // 摘要
        dto.setTaskContent(String.format("检验检测业务开通办理，【申请单号：%s】", model.getApplicationSeq()));
        // 申请单号
        dto.setTaskCode(model.getApplicationSeq());
        // 业务类型
        dto.setTaskType(BusinessTypeEnum.JY_OPENING_APPLICATION.getCode());
        // 业务主键
        dto.setRelationId(String.valueOf(model.getSequenceNbr()));
        dto.setNextExecuteUser("");
        list.add(dto);
        taskModelService.buildTaskModel(list);
    }

    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public JyjcOpeningApplicationModel resubmit(JyjcOpeningApplicationModel model) {
        model.setStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode() + "");
        model = this.updateWithModel(model);
        executedFlow(MapBuilder.<String, Object>create()
                .put("op", "0")
                .put("instanceId", model.getWorkflowProstanceId())
                .put("comments", "")
                .put("nextTaskId", model.getNextTaskId())
                .build());
        return model;
    }


    /**
     * 完成的时候作废其他已完成的申请单-除去本次开通
     *
     * @param unitCode    unitCode
     * @param sequenceNbr sequenceNbr
     * @param openBizType 按照单位及开通业务类型进进行作废
     */
    private void doDiscard(String unitCode, Long sequenceNbr, String openBizType) {
        if (!(openBizType.equals(OpenBizTypeEnumV2.SYDW.getCode()) || openBizType.equals(OpenBizTypeEnumV2.AGW.getCode()))) {
            JyjcInspectionHistory history = inspectionHistoryService.getBySSeq(sequenceNbr);
            JSONObject hisData = history.getHistoryData();
            Set<String> agencyTypeLast = hisData.getJSONArray(BizCommonConstant.UNIT_LICENCE_KEY).toJavaList(BaseEnterpriseCertDto.class).stream().map(BaseEnterpriseCertDto::getAgencyType).collect(Collectors.toSet());
            List<Long> ids = this.lambdaQuery().select(JyjcOpeningApplication::getSequenceNbr)
                    .eq(JyjcOpeningApplication::getUnitCode, unitCode)
                    .eq(JyjcOpeningApplication::getOpenBizType, openBizType)
                    .ne(JyjcOpeningApplication::getSequenceNbr, sequenceNbr)
                    .eq(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_FINISHED.getName())
                    .list().stream().map(JyjcOpeningApplication::getSequenceNbr).collect(Collectors.toList());
            if (ValidationUtil.isEmpty(ids) || agencyTypeLast.isEmpty()) {
                return;
            }
            // 历史已经开通的同单位类型+同机构类别的单据集合
            Set<Long> filterIds = new HashSet<>();
            // 将历史同单位类型+同机构类别的开通申请作废掉
            for (Long id : ids) {
                JyjcInspectionHistory historyOpened = inspectionHistoryService.getBySSeq(id);
                if(historyOpened != null){
                    JSONObject hisDataOpened = historyOpened.getHistoryData();
                    List<BaseEnterpriseCertDto> certOpened = hisDataOpened.getJSONArray(BizCommonConstant.UNIT_LICENCE_KEY).toJavaList(BaseEnterpriseCertDto.class);
                    boolean matchHisOpened = certOpened.stream().anyMatch(c -> agencyTypeLast.contains(c.getAgencyType()));
                    if (matchHisOpened) {
                        filterIds.add(id);
                    }
                }
            }
            if (!filterIds.isEmpty()) {
                LambdaUpdateWrapper<JyjcOpeningApplication> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_DISCARD.getName())
                        .set(JyjcOpeningApplication::getRemark, "新开通申请生效，原有开通申请自动作废")
                        .in(org.typroject.tyboot.core.rdbms.orm.entity.BaseEntity::getSequenceNbr, ids);
                this.update(updateWrapper);
            }
        } else {
            // 使用单位和安改维按照开通类型进行作废, 非自己且单位code且业务类型且已完成
            LambdaUpdateWrapper<JyjcOpeningApplication> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_DISCARD.getName())
                    .set(JyjcOpeningApplication::getRemark, "新开通申请生效，原有开通申请自动作废")
                    .ne(org.typroject.tyboot.core.rdbms.orm.entity.BaseEntity::getSequenceNbr, sequenceNbr)
                    .eq(JyjcOpeningApplication::getUnitCode, unitCode)
                    .eq(JyjcOpeningApplication::getOpenBizType, openBizType)
                    .eq(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_FINISHED.getName());
            this.update(updateWrapper);
        }
    }

    public Boolean doDiscard(Long sequenceNbr, String remark) {
        if (sequenceNbr == null) {
            throw new BadRequest("sequenceNbr不能为空！");
        }
        JyjcOpeningApplication jyjcOpeningApplication = jyjcOpeningApplicationMapper.selectById(sequenceNbr);
        if (jyjcOpeningApplication == null) {
            return false;
        }
        if (!String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getName()).equals(jyjcOpeningApplication.getStatus())) {
            throw new BadRequest("只有已完成的申请单才可以作废！");
        }
        JyjcInspectionHistory history = inspectionHistoryService.getBySSeq(jyjcOpeningApplication.getSequenceNbr());
        JSONObject hisData = history.getHistoryData();
        List<BaseEnterpriseCertDto> certDtos = hisData.getJSONArray(BizCommonConstant.UNIT_LICENCE_KEY).toJavaList(BaseEnterpriseCertDto.class);
        // 逻辑删除之前审批完成的证书、资质信息
        this.deleteHisCert(certDtos, jyjcOpeningApplication);
        // 单据修改为作废状态
        UpdateWrapper<JyjcOpeningApplication> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .set("status", FlowStatusEnum.TO_BE_DISCARD.getName())
                .set("remark", remark)
                .eq("SEQUENCE_NBR", sequenceNbr);
        return this.update(updateWrapper);
    }

    public void doDiscardAndOverdueLicense(Long sequenceNbr, String remark) {
        JyjcOpeningApplication jyjcOpeningApplication = jyjcOpeningApplicationMapper.selectById(sequenceNbr);
        if (!String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getName()).equals(jyjcOpeningApplication.getStatus())) {
            return;
        }
        if (!(jyjcOpeningApplication.getOpenBizType().equals(OpenBizTypeEnumV2.SYDW.getCode()) || jyjcOpeningApplication.getOpenBizType().equals(OpenBizTypeEnumV2.AGW.getCode()))) {
            JyjcInspectionHistory history = inspectionHistoryService.getBySSeq(jyjcOpeningApplication.getSequenceNbr());
            JSONObject hisData = history.getHistoryData();
            List<BaseEnterpriseCertDto> certDtos = hisData.getJSONArray(BizCommonConstant.UNIT_LICENCE_KEY).toJavaList(BaseEnterpriseCertDto.class);
            // 修改资质及证为超期状态
            this.overdueLicense(certDtos, jyjcOpeningApplication);
            // 单据修改为作废状态
            UpdateWrapper<JyjcOpeningApplication> updateWrapper = new UpdateWrapper<>();
            updateWrapper
                    .set("status", FlowStatusEnum.TO_BE_DISCARD.getName())
                    .set("remark", remark)
                    .eq("SEQUENCE_NBR", sequenceNbr);
            this.update(updateWrapper);
        } else {
            LambdaUpdateWrapper<JyjcOpeningApplication> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_DISCARD.getName())
                    .set(JyjcOpeningApplication::getRemark, remark)
                    .eq(org.typroject.tyboot.core.rdbms.orm.entity.BaseEntity::getSequenceNbr, sequenceNbr);
            this.update(updateWrapper);
        }
    }

    private void overdueLicense(List<BaseEnterpriseCertDto> certDtos, JyjcOpeningApplication jyjcOpeningApplication) {
        certDtos.forEach(certDto -> {
            List<Long> allergists = getCertFromHisData(jyjcOpeningApplication, certDto);
            if (!allergists.isEmpty()) {
                baseUnitLicenceMapper.update(null, new LambdaUpdateWrapper<BaseUnitLicence>().in(BaseUnitLicence::getEnterpriseCertSeq, allergists).set(BaseUnitLicence::getLicenceState, LicenceStateEnum.overdue.getValue()));
                enterpriseCertService.update(new LambdaUpdateWrapper<BaseEnterpriseCert>().in(BaseEntity::getSequenceNbr, allergists).set(BaseEnterpriseCert::getCertState, LicenceStateEnum.overdue.getValue()));
            }
        });
    }

    private List<Long> getCertFromHisData(JyjcOpeningApplication jyjcOpeningApplication, BaseEnterpriseCertDto certDto) {
        return enterpriseCertService.list(new LambdaQueryWrapper<BaseEnterpriseCert>()
                        .eq(BaseEnterpriseCert::getUnitCode, jyjcOpeningApplication.getUnitCode())
                        .eq(BaseEnterpriseCert::getUnitType, Optional.ofNullable(OpenBizTypeEnumV2.getOneByCode(jyjcOpeningApplication.getOpenBizType())).map(OpenBizTypeEnumV2::getUnitType).orElse(null))
                        .eq(BaseEnterpriseCert::getCertTypeCode, certDto.getCertTypeCode())
                        .eq(BaseEnterpriseCert::getAgencyType, certDto.getAgencyType())
                        .eq(BaseEntity::getIsDelete, false))
                .stream().map(BaseEnterpriseCert::getSequenceNbr).collect(Collectors.toList());
    }


    /**
     * 列表查询 示例
     */
    public List<JyjcOpeningApplicationModel> queryForJyjcOpeningApplicationList() {
        return this.queryForList("", false);
    }

    public Page<JyjcOpeningApplicationModel> queryForJyjcOpeningApplicationPage(Page<JyjcOpeningApplication> page, JyjcOpeningApplicationRequestDto dto, String client) {
        ReginParams reginParams = commonService.getReginParamsOfCurrentUser();
        String companyLevel = CommonServiceImpl.getCompanyLevel(reginParams.getCompany());
        String currentUserId = RequestContext.getExeUserId();
        String level = reginParams.getCompany().getLevel();
        if (BaseController.COMPANY_TYPE_COMPANY.equals(level)) {
            dto.setType("enterprise");
            // 按照登录人身份过滤开通单据，如检验机构身份登录只能看到检验开通的单据
            dto.setOpenBizTypeIdentify(OpenBizTypeEnumV2.getOneByUnitType(reginParams.getCompany().getCompanyType()).getCode());
            dto.setUnitCode(CommonServiceImpl.getUnitCode(reginParams.getCompany()));
        } else {
            dto.setType("supervision");
        }
        dto.setType("jgLook".equals(client) ? null : dto.getType());
        String orgCode = "jgLook".equals(client) ? reginParams.getCompany().getOrgCode() : null;
        String applyStartTime = "";
        String applyEndTime = "";
        if (ObjectUtils.isNotEmpty(dto.getApplyTime())) {
            String date = dto.getApplyTime();
            applyStartTime = date + " 00:00:00";
            applyEndTime = date + " 23:59:59";
        }
        Page<JyjcOpeningApplicationModel> result = jyjcOpeningApplicationMapper.selectJyjcOpeningApplicationList(page, dto, applyStartTime, currentUserId, applyEndTime,orgCode);
        for (JyjcOpeningApplicationModel openingApplicationModel : result.getRecords()) {
            openingApplicationModel.setIdentityType(dto.getType());
            openingApplicationModel.setOpenBizTypeName(this.getOpenBizTypeName(openingApplicationModel.getOpenBizType()));
            openingApplicationModel.setUnitCode(this.desensitizeIdCard(openingApplicationModel.getUnitCode()));
            openingApplicationModel.setCompanyLevel(companyLevel);
        }
        return result;
    }

    private String desensitizeIdCard(String unitCode) {
        // 身份证时进行脱敏处理
        if (IdcardUtil.isValidCard(unitCode)) {
            return DesensitizedUtil.idCardNum(unitCode, 3, 4);
        }
        return unitCode;
    }


    private String getOpenBizTypeName(String openBizType) {
        return Optional.ofNullable(OpenBizTypeEnumV2.getOneByCode(openBizType))
                .map(OpenBizTypeEnumV2::getDescription)
                .orElse("");
    }


    /**
     * 开通详情
     *
     * @param sequenceNbr 主键，开始时为空，详情时非空
     * @param company     登录人的公司信息
     * @return 开通申请详情
     */
    public JyjcOpeningApplicationModel queryDetail(Long sequenceNbr, CompanyBo company) {
        // 公司类型前端区分监管还是企业端
        String companyLevel = CommonServiceImpl.getCompanyLevel(company);
        // todo 不带证件类型的单位编码
        String unitCode;
        JyjcOpeningApplicationModel jyjcOpeningApplicationModel;
        if (null != sequenceNbr) {
            jyjcOpeningApplicationModel = this.queryBySeq(sequenceNbr);
            unitCode = jyjcOpeningApplicationModel.getUnitCode();
            JyjcInspectionHistory jyjcInspectionHistory = inspectionHistoryService.getBySSeq(jyjcOpeningApplicationModel.getSequenceNbr());
            JSONObject hisData = jyjcInspectionHistory.getHistoryData();
            if (jyjcOpeningApplicationModel.getStatus().equals(FlowStatusEnum.TO_BE_DISCARD.getName()) ||
                    jyjcOpeningApplicationModel.getStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName())) { // 审批完成、已作废时显示历史数据
                hisData.put("status", jyjcOpeningApplicationModel.getStatus());
                BeanUtil.copyProperties(hisData, jyjcOpeningApplicationModel);
            } else {                                                                                           // 流程中实时数据显示人、企业基本信息
                setJYJCUserList(unitCode, jyjcOpeningApplicationModel);
                // 企业基本信息
                setBaseEnterpriseInfo(unitCode, jyjcOpeningApplicationModel);
            }
            jyjcOpeningApplicationModel.setEquipVeriCert(hisData.getJSONArray("equipVeriCert"));
            jyjcOpeningApplicationModel.setArchivesCert(hisData.getJSONArray("archivesCert"));
            jyjcOpeningApplicationModel.setInstrumentCert(hisData.getJSONArray("instrumentCert"));
            jyjcOpeningApplicationModel.setQuaSystemCert(hisData.getJSONArray("quaSystemCert"));
            // 证书资质信息-按照json显示
            jyjcOpeningApplicationModel.setBaseUnitLicences(hisData.getJSONArray("baseUnitLicences").toJavaList(BaseEnterpriseCertDto.class));
        } else {
            jyjcOpeningApplicationModel = new JyjcOpeningApplicationModel();
            jyjcOpeningApplicationModel.setOpenBizType(this.getOpenBizTypeByIdentity(company.getCompanyType()));
            unitCode = CommonServiceImpl.getUnitCode(company);
            jyjcOpeningApplicationModel.setUnitCodeName(company.getCompanyName());
            jyjcOpeningApplicationModel.setUnitCode(unitCode);
            // 证书资质信息
            setBaseUnitLicences2(unitCode, jyjcOpeningApplicationModel, company.getCompanyType());
            // 企业基本信息
            setBaseEnterpriseInfo(unitCode, jyjcOpeningApplicationModel);
        }
        jyjcOpeningApplicationModel.setCompanyLevel(companyLevel);
        return jyjcOpeningApplicationModel;
    }



    private String getOpenBizTypeByIdentity(String unitType) {
        OpenBizTypeEnumV2 bizTypeEnumV2 = OpenBizTypeEnumV2.getOneByUnitType(unitType);
        if (bizTypeEnumV2 == null) {
            throw new BadRequest("非法的的单位类型！");
        }
        return bizTypeEnumV2.getCode();
    }

    private void setBaseEnterpriseInfo(String unitCode, JyjcOpeningApplicationModel jyjcOpeningApplicationModel) {
        LambdaQueryWrapper<TzBaseEnterpriseInfo> enterpriseInfoQueryWrapper = new LambdaQueryWrapper<>();
        // todo 注意useUnitCode不带证件类型, useCode带证件类型
        enterpriseInfoQueryWrapper.eq(TzBaseEnterpriseInfo::getUseUnitCode, unitCode);
        TzBaseEnterpriseInfo baseEnterpriseInfo = enterpriseInfoMapper.selectOne(enterpriseInfoQueryWrapper);
        // 获取企业资质
        if (baseEnterpriseInfo != null) {
            jyjcOpeningApplicationModel.setUseContact(baseEnterpriseInfo.getUseContact());
            jyjcOpeningApplicationModel.setContactPhone(baseEnterpriseInfo.getContactPhone());
            jyjcOpeningApplicationModel.setUnitAddress(this.buildFullAddress(baseEnterpriseInfo));
            if (StringUtils.isNotBlank(baseEnterpriseInfo.getIndustrySupervisor())) {
                DataDictionary dict = dataDictionaryMapper.getByCode(baseEnterpriseInfo.getIndustrySupervisor(), INDUSTRY_SUPERVISOR_DICT_TYPE);
                if (dict != null) {
                    jyjcOpeningApplicationModel.setIndustrySupervisor(dict.getName());
                } else {
                    jyjcOpeningApplicationModel.setIndustrySupervisor(baseEnterpriseInfo.getIndustrySupervisor());
                }
            }
            jyjcOpeningApplicationModel.setGeographic(JyjcGeographicModel.builder().latitude(baseEnterpriseInfo.getLatitude()).longitude(baseEnterpriseInfo.getLongitude()).build());
            jyjcOpeningApplicationModel.setLongitude(baseEnterpriseInfo.getLongitude());
            jyjcOpeningApplicationModel.setLatitude(baseEnterpriseInfo.getLatitude());
            jyjcOpeningApplicationModel.setDataSources(baseEnterpriseInfo.getDataSources());
            jyjcOpeningApplicationModel.setOfficeRegion(this.caseRegionCode2Name(baseEnterpriseInfo.getOfficeRegion()));
            jyjcOpeningApplicationModel.setOfficeAddress(baseEnterpriseInfo.getOfficeAddress());
            if (ObjectUtils.isNotEmpty(baseEnterpriseInfo.getUnitBusinessLicense())) {
                jyjcOpeningApplicationModel.setUnitBusinessLicense(JSONArray.parseArray(baseEnterpriseInfo.getUnitBusinessLicense(), AttachmentDto.class));
            }
        }
    }

    private String buildFullAddress(TzBaseEnterpriseInfo baseEnterpriseInfo) {
        if (StringUtils.isEmpty(baseEnterpriseInfo.getAddress())) {
            return trimNull(baseEnterpriseInfo.getProvince()) + trimNull(baseEnterpriseInfo.getCity()) + trimNull(baseEnterpriseInfo.getDistrict()) + trimNull(baseEnterpriseInfo.getStreet()) + trimNull(baseEnterpriseInfo.getCommunity());
        }
        if (baseEnterpriseInfo.getAddress().contains("省") || baseEnterpriseInfo.getAddress().contains("市") || baseEnterpriseInfo.getAddress().contains("自治区")) {
            return baseEnterpriseInfo.getAddress();
        }
        return trimNull(baseEnterpriseInfo.getProvince()) + trimNull(baseEnterpriseInfo.getCity()) + trimNull(baseEnterpriseInfo.getDistrict()) + trimNull(baseEnterpriseInfo.getStreet()) + trimNull(baseEnterpriseInfo.getCommunity()) + trimNull(baseEnterpriseInfo.getAddress());
    }

    private String trimNull(String str) {
        return str == null ? "" : str.trim();
    }

    private String caseRegionCode2Name(String officeRegion) {
        StringBuilder fullName = new StringBuilder();
        if (StringUtils.isNotBlank(officeRegion)) {
            for (String regionCode : officeRegion.split("#")) {
                fullName.append(commonService.getRegionName(regionCode));
            }
        }
        return fullName.toString();
    }


    private void setBaseUnitLicences2(String unitCode, JyjcOpeningApplicationModel jyjcOpeningApplicationModel, String unitType) {
        jyjcOpeningApplicationModel.setBaseUnitLicences(new ArrayList<>());
    }

    private List<DataDictionaryDto> getBuildItemCode(Long sequenceNbr) {
        List<BaseUnitLicence> baseUnitLicences = baseUnitLicenceMapper.selectList(new LambdaQueryWrapper<BaseUnitLicence>()
                .eq(BaseUnitLicence::getEnterpriseCertSeq, sequenceNbr)
                .select(BaseUnitLicence::getItemCode,
                        BaseEntity::getSequenceNbr,
                        BaseUnitLicence::getItemCode,
                        BaseUnitLicence::getItemCodeName,
                        BaseUnitLicence::getDictSeq));
        return baseUnitLicences.stream().map(l -> {
            DataDictionaryDto dto = new DataDictionaryDto();
            dto.setCode(l.getItemCode());
            dto.setName(l.getItemCodeName());
            dto.setSequenceNbr(l.getDictSeq());
            return dto;
        }).collect(Collectors.toList());
    }


    private void setJYJCUserList(String unitCode, JyjcOpeningApplicationModel jyjcOpeningApplicationModel) {
        LambdaQueryWrapper<TzsUserInfo> userInfoQueryWrapper = new LambdaQueryWrapper<>();
        userInfoQueryWrapper.eq(TzsUserInfo::getUnitCode, unitCode);
        userInfoQueryWrapper.eq(BaseEntity::getIsDelete, false);
        commonService.castPersonType2Post(userInfoQueryWrapper, "jy,jc,charge");
        List<TzsUserInfo> userInfos = userInfoMapper.selectList(userInfoQueryWrapper);
        if (!ValidationUtil.isEmpty(userInfos)) {
            List<TzsUserInfoVo> tzsUserInfoVos = userInfos.stream().map(userInfo -> {
                TzsUserInfoVo vo = new TzsUserInfoVo();
                BeanUtils.copyProperties(userInfo, vo, "identification", "profile", "permissionItem", "appointDoc", "permissionData", "appointDoc");
                if (!ObjectUtils.isEmpty(userInfo.getPost())) {
                    vo.setPost(JSON.parseArray(userInfo.getPost()));
                }
                return vo;
            }).collect(Collectors.toList());
            jyjcOpeningApplicationModel.setJyjcUserInfos(tzsUserInfoVos.stream().filter(u -> u.getPost().contains(jyUserPost) || u.getPost().contains(jcUserPost)).collect(Collectors.toList()));
            jyjcOpeningApplicationModel.setChargeUserInfos(tzsUserInfoVos.stream().filter(u -> u.getPost().contains(chargeUserPost)).collect(Collectors.toList()));
        }
    }

    public List<TzsUserInfoVo> getUserListByUnitCodeAndPost(String unitCode, String personType) {
        List<TzsUserInfo> userInfos = getUserList(unitCode, personType);
        String appKey = RequestContext.getAppKey();
        String product = RequestContext.getProduct();
        String token = RequestContext.getToken();
        return userInfos.parallelStream().map(userInfo -> {
            TzsUserInfoVo vo = new TzsUserInfoVo();
            BeanUtils.copyProperties(userInfo, vo, "identification", "profile", "permissionItem", "appointDoc", "permissionData");
            vo.setSequenceNbr(userInfo.getSequenceNbr());
            RequestContext.setAppKey(appKey);
            RequestContext.setProduct(product);
            RequestContext.setToken(token);
            this.setPermissionInfo(vo, userInfo, personType);
            if (!ObjectUtils.isEmpty(userInfo.getNewPost())) {
                vo.setPost(JSON.parseArray(userInfo.getNewPost()));
            }
            if (!ObjectUtils.isEmpty(userInfo.getAppointDoc())) {
                vo.setAppointDoc(JSON.parseArray(userInfo.getAppointDoc()));
            }
            return vo;
        }).collect(Collectors.toList());
    }

    public Map<String, List<TzsUserInfoVo>> getUserListByUnitCodeAndPostV2(String unitCode, String personType) {
        Map<String, List<TzsUserInfoVo>> result = new HashMap<>();
        List<TzsUserInfo> userInfos = getUserList(unitCode, personType);
        List<TzsUserInfoVo> tzsUserInfoVos = userInfos.stream().map(userInfo -> {
            TzsUserInfoVo vo = new TzsUserInfoVo();
            BeanUtils.copyProperties(userInfo, vo, "identification", "profile", "permissionItem", "appointDoc", "permissionData", "appointDoc");
            vo.setSequenceNbr(userInfo.getSequenceNbr());
            if (!ObjectUtils.isEmpty(userInfo.getPost())) {
                vo.setPost(JSON.parseArray(userInfo.getPost()));
            }
            return vo;
        }).collect(Collectors.toList());
        result.put(BizCommonConstant.JYJC_USER_LIST_KEY, tzsUserInfoVos.stream().filter(u -> u.getPost().contains(jyUserPost) || u.getPost().contains(jcUserPost)).collect(Collectors.toList()));
        result.put(BizCommonConstant.CHAGRE_USER_LIST_KEY, tzsUserInfoVos.stream().filter(u -> u.getPost().contains(chargeUserPost)).collect(Collectors.toList()));
        return result;
    }

    private List<TzsUserInfo> getUserList(String unitCode, String personType) {
        LambdaQueryWrapper<TzsUserInfo> userInfoQueryWrapper = new LambdaQueryWrapper<>();
        userInfoQueryWrapper.eq(TzsUserInfo::getUnitCode, unitCode);
        commonService.castPersonType2Post(userInfoQueryWrapper, personType);
        userInfoQueryWrapper.eq(BaseEntity::getIsDelete, false);
        userInfoQueryWrapper.orderByDesc(TzsUserInfo::getRecDate);
        return userInfoMapper.selectList(userInfoQueryWrapper);
    }


    private void setPermissionInfo(TzsUserInfoVo vo, TzsUserInfo userInfo, String personType) {
        String post = "6615";
        if (personType.equals(OpenBizTypeEnum.JY.getCode())) {
            post = jyUserPost;
        }
        if (personType.equals(OpenBizTypeEnum.JC.getCode())) {
            post = jcUserPost;
        }
        // 查询资质的人,
        List<TzsUserPermissionDto> permissionDtos = userInfoMapper.queryPermissionByUserSeq(userInfo.getSequenceNbr(), this.buildPermissionKey(post));
        // 注意检验资质、检测资质，每人只有一行数据, 一个人一个证
        if (!permissionDtos.isEmpty()) {
            TzsUserPermissionDto userPermissionDto = permissionDtos.get(0);
            // 不会出现为null, 程序健壮处理
            if (userPermissionDto.getPermissionItem() != null && userPermissionDto.getPermissionLevel() != null) {
                vo.setPermissionItem(JSONArray.parseArray(userPermissionDto.getPermissionItem()));
                vo.setPermissionItemName(this.castItemCode2Name(vo.getPermissionItem()));
                vo.setPermissionLevelName(this.getDictNameByCode(userPermissionDto.getPermissionLevel()));
            }
        }
    }

    private String buildPermissionKey(String post) {
        return String.format("%s%s", "permissionData", post);
    }

    private String castItemCode2Name(JSONArray permissionItem) {
        if (permissionItemList == null) {
            FeignClientResult<List<DictionarieValueModel>> itemDicts = Systemctl.dictionarieClient.dictValues(ZZXM_JYJC_DICT_KEY);
            permissionItemList = itemDicts.getResult();
        }
        return permissionItemList.stream().filter(i -> permissionItem.contains(i.getDictDataKey())).map(this::buildItemWithCode).collect(Collectors.joining(","));
    }

    private String buildItemWithCode(DictionarieValueModel d) {
        return String.format("%s[%s]", d.getDictDataValue(), d.getDictDataKey());
    }

    private String getDictNameByCode(String permissionLevel) {
        if (StringUtils.isEmpty(permissionLevel)) {
            return "";
        }
        if (permissionLevelMap == null) {
            FeignClientResult<List<DictionarieValueModel>> levelDicts = Systemctl.dictionarieClient.dictValues(RYJB_JYJC_DICT_KEY);
            permissionLevelMap = levelDicts.getResult().stream().collect(Collectors.toMap(DictionarieValueModel::getDictDataKey, Function.identity(), (k1, k2) -> k2));
        }
        return Optional.ofNullable(permissionLevelMap.get(permissionLevel).getDictDataValue()).orElse("");
    }


    /**
     * 接收/驳回通知检验单
     */
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void executedFlow(Map<String, Object> params) {
        String instanceId = params.get("instanceId").toString();
        String nextTaskId = params.get("nextTaskId").toString();
        String lockKey = CommonServiceImpl.buildJcExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForExecuteFlow(nextTaskId, instanceId);
            Long sequenceNbr = Long.parseLong(params.get("sequenceNbr") + "");
            String op = params.get("op").toString();
            JyjcOpeningApplication jyjcOpeningApplication = jyjcOpeningApplicationMapper.selectById(sequenceNbr);
            //组装信息
            TaskResultDTO dto = new TaskResultDTO();
            dto.setResultCode("approvalStatus");
            dto.setTaskId(jyjcOpeningApplication.getNextTaskId());
            dto.setComment(params.get("comments").toString());
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", op);
            if (WorkFlowStatusEnum.OPENING_APPLICATION_SUBMIT.getReject().equals(jyjcOpeningApplication.getStatus()) || WorkFlowStatusEnum.OPENING_APPLICATION_SUBMIT.getRollBack().equals(jyjcOpeningApplication.getStatus())) {
                map.put("approvalStatus", "提交");
            }
            dto.setVariable(map);
            ProcessTaskDTO complete = new ProcessTaskDTO();
            if ("0".equals(op)) {
                complete = cmWorkflowService.complete(jyjcOpeningApplication.getNextTaskId(), dto);
            } else {
                complete = cmWorkflowService.reject(jyjcOpeningApplication.getNextTaskId(), dto);
            }
            ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
            processTaskDTOS.add(complete);
            List<WorkflowResultDto> resultDto = taskModelService.buildWorkFlowInfo(processTaskDTOS);
            WorkflowResultDto workflowResultDto = resultDto.get(0);
            String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
            if (!org.springframework.util.ObjectUtils.isEmpty(workflowResultDto.getNextTaskCode())) {
                taskCode = workflowResultDto.getNextTaskCode();
            }
            if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
                if ("0".equals(op)) {
                    // 通过操作
                    List<String> detectionRegion = (List<String>) params.get("detectionRegion");
                    jyjcOpeningApplication.setDetectionRegion(detectionRegion);
                    jyjcOpeningApplication.setStatus(WorkFlowStatusEnum.getMessage(workflowResultDto.getNextTaskCode()).getPass());
                    jyjcOpeningApplication.setExpiryDate(DateUtil.parseDate(params.get("expiryDate").toString()));
                    jyjcOpeningApplication.setAgencyClassify(params.get("agencyClassify").toString());
                    jyjcOpeningApplication.setPromoter(RequestContext.getExeUserId());
                    jyjcOpeningApplication.setResultType(Optional.ofNullable(params.get("resultType")).map(Object::toString).orElse(""));
                    this.sendMsg2User(jyjcOpeningApplication);
                    // 更新json
                    commonService.saveOrUpdateHistory(jyjcOpeningApplication.getOpenBizType(), JSONObject.parseObject(JSONObject.toJSONString(params)), jyjcOpeningApplication.getSequenceNbr());
                } else {
                    // 驳回操作, 驳回时不更新json数据
                    jyjcOpeningApplication.setStatus(WorkFlowStatusEnum.getMessage(workflowResultDto.getNextTaskCode()).getReject());
                    jyjcOpeningApplication.setPromoter("");
                    this.sendMsg2User(jyjcOpeningApplication);
                    // 驳回到发起单位时，恢复原始的开通区域，清空机构分类、核准项目
                    this.restoreApplicationData(jyjcOpeningApplication, params);
                }
                jyjcOpeningApplication.setNextTaskId(workflowResultDto.getNextTaskId());
                jyjcOpeningApplication.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                // 更新代办
                updateTask(jyjcOpeningApplication, workflowResultDto, op);
            } else {
                // 流程结束
                jyjcOpeningApplication.setStatus(taskCode);
                //更新办理日期
                jyjcOpeningApplication.setAcceptDate(new Date());
                // 更新代办
                HashMap<String, Object> taskParams = new HashMap<>();
                taskParams.put("relationId", jyjcOpeningApplication.getWorkflowProstanceId());
                taskParams.put("flowStatus", commonService.getDictionaryCodeByName(jyjcOpeningApplication.getStatus()));
                taskParams.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                taskParams.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                taskParams.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                taskParams.put("model", jyjcOpeningApplication);
                taskModelService.updateTaskModel(taskParams);
                List<String> detectionRegion = (List<String>) params.get("detectionRegion");
                jyjcOpeningApplication.setDetectionRegion(detectionRegion);
                jyjcOpeningApplication.setPromoter("");
                jyjcOpeningApplication.setNextTaskId("");
                jyjcOpeningApplication.setNextExecuteUserIds("");
                jyjcOpeningApplication.setExpiryDate(DateUtil.parseDate(params.get("expiryDate").toString()));
                jyjcOpeningApplication.setAgencyClassify(params.get("agencyClassify").toString());
                jyjcOpeningApplication.setResultType(Optional.ofNullable(params.get("resultType")).map(Object::toString).orElse(""));
                // 更新json
                commonService.saveOrUpdateHistory(jyjcOpeningApplication.getOpenBizType(), JSONObject.parseObject(JSONObject.toJSONString(params)), jyjcOpeningApplication.getSequenceNbr());
                // 将审批通过的资质信息写入到企业资质表
                this.saveLicenseData2Company(jyjcOpeningApplication);
            }
            jyjcOpeningApplicationMapper.updateById(jyjcOpeningApplication);
            // 已完成 作废逻辑
            if (FlowStatusEnum.TO_BE_FINISHED.getName().equals(jyjcOpeningApplication.getStatus())) {
                doDiscard(jyjcOpeningApplication.getUnitCode(), jyjcOpeningApplication.getSequenceNbr(), jyjcOpeningApplication.getOpenBizType());
            }
            // 更新流程中的流程数据
            commonService.saveExecuteFlowData2Redis(jyjcOpeningApplication.getWorkflowProstanceId(), this.buildInstanceRuntimeData(jyjcOpeningApplication));
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    private void restoreApplicationData(JyjcOpeningApplication jyjcOpeningApplication, Map<String, Object> params) {
        // 资料校对受理已退回时恢复数据到原始数据
        if (jyjcOpeningApplication.getStatus().equals(WorkFlowStatusEnum.OPENING_APPLICATION_SUBMIT.getReject())) {
            jyjcOpeningApplication.setDetectionRegion(jyjcOpeningApplication.getOriDetectionRegion());
            jyjcOpeningApplication.setAgencyClassify(null);
            jyjcOpeningApplication.setExpiryDate(null);
            JSONObject data = new JSONObject(params);
            List<BaseEnterpriseCertDto> certDtos = data.getJSONArray(BizCommonConstant.UNIT_LICENCE_KEY).toJavaList(BaseEnterpriseCertDto.class);
            certDtos.forEach(c -> {
                c.setItemCodes(new ArrayList<>());
            });
            data.put(BizCommonConstant.UNIT_LICENCE_KEY, certDtos);
            // 更新json
            commonService.saveOrUpdateHistory(jyjcOpeningApplication.getOpenBizType(), data, jyjcOpeningApplication.getSequenceNbr());
        }
    }

    private void sendMsg2User(JyjcOpeningApplication jyjcOpeningApplication) {
        String createUserId = jyjcOpeningApplication.getCreateUserId();
        String relationId = jyjcOpeningApplication.getSequenceNbr() + "";
        String companyType = this.OpenBizType2CompanyType(jyjcOpeningApplication.getOpenBizType());
        openAppMsgFactory.getOpenAppMsgHandler(jyjcOpeningApplication.getStatus()).handle(createUserId, relationId, companyType);
    }

    private String OpenBizType2CompanyType(String openBizType) {
        return Optional.ofNullable(OpenBizTypeEnumV2.getOneByCode(openBizType)).map(OpenBizTypeEnumV2::getUnitType).orElse(null);
    }

    private void saveLicenseData2Company(JyjcOpeningApplication jyjcOpeningApplication) {
        JyjcInspectionHistory history = inspectionHistoryService.getBySSeq(jyjcOpeningApplication.getSequenceNbr());
        JSONObject hisData = history.getHistoryData();
        List<BaseEnterpriseCertDto> certDtos = hisData.getJSONArray(BizCommonConstant.UNIT_LICENCE_KEY).toJavaList(BaseEnterpriseCertDto.class);
        // 单位类型+证书类型+机构类别唯一，删除之前已有的
        this.deleteHisCert(certDtos, jyjcOpeningApplication);
        List<BaseEnterpriseCert> certs = new ArrayList<>();
        List<BaseUnitLicence> licences = new ArrayList<>();
        certDtos.forEach(e -> {
            BaseEnterpriseCert cert = new BaseEnterpriseCert();
            BeanUtils.copyProperties(e, cert);
            cert.setUnitType(Optional.ofNullable(OpenBizTypeEnumV2.getOneByCode(jyjcOpeningApplication.getOpenBizType())).map(OpenBizTypeEnumV2::getUnitType).orElse(null));
            cert.setQualificationCertificateAttachment(e.getQualificationCertificateAttachment().toJSONString());
            cert.setUnitCode(jyjcOpeningApplication.getUnitCode());
            cert.setSequenceNbr(sequence.nextId());
            cert.setRecUserId(RequestContext.getExeUserId());
            cert.setRecDate(new Date());
            cert.setCertState(LicenceStateEnum.enabled.getValue());
            Optional.ofNullable(e.getItemCodes())
                    .orElseGet(Collections::emptyList)
                    .stream()
                    .filter(Objects::nonNull).forEach(item -> {
                        BaseUnitLicence licence = new BaseUnitLicence();
                        BeanUtils.copyProperties(e, licence);
                        licence.setSequenceNbr(sequence.nextId());
                        licence.setQualificationCertificateAttachment(cert.getQualificationCertificateAttachment());
                        licence.setItemCode(item.getCode());
                        licence.setItemCodeName(item.getName());
                        licence.setDictSeq(item.getSequenceNbr());
                        licence.setRecDate(new Date());
                        licence.setRecUserId(RequestContext.getExeUserId());
                        licence.setLicenceState(LicenceStateEnum.enabled.getValue());
                        // 改成联想输入，直接存名称，approvedOrganName, approvedOrgan不再需要
                        // licence.setApprovedOrgan(commonService.getDictName(Collections.singletonList("DJJG"), licence.getApprovedOrganCode()));
                        licence.setAgencyTypeName(commonService.getDictName(Arrays.asList("1233-1", "1233-2"), licence.getAgencyType()));
                        licence.setUnitCode(jyjcOpeningApplication.getUnitCode());
                        licence.setUnitName(jyjcOpeningApplication.getUnitCodeName());
                        licence.setLicenceType( LicenceTypeEnum.JY_JC.getCode());
                        licence.setEnterpriseCertSeq(cert.getSequenceNbr().toString());
                        licences.add(licence);
                    });
            certs.add(cert);
        });
        // 保存证书
        if (!certs.isEmpty()) {
            enterpriseCertService.saveOrUpdateBatch(certs);
        }
        // 保存资质
        if (!licences.isEmpty()) {
            licences.parallelStream().forEach(licence -> {
                baseUnitLicenceMapper.insert(licence);
            });
        }
    }

    private void deleteHisCert(List<BaseEnterpriseCertDto> certDtos, JyjcOpeningApplication jyjcOpeningApplication) {
        certDtos.forEach(certDto -> {
            List<Long> allCertSeqs = getCertFromHisData(jyjcOpeningApplication, certDto);
            if (!allCertSeqs.isEmpty()) {
                // 逻辑删除
                baseUnitLicenceMapper.update(null, new LambdaUpdateWrapper<BaseUnitLicence>()
                        .in(BaseUnitLicence::getEnterpriseCertSeq, allCertSeqs)
                        .set(BaseEntity::getIsDelete, true)
                        .set(BaseEntity::getRecDate, new Date())
                        .set(BaseEntity::getRecUserId, RequestContext.getExeUserId()));
                // 逻辑删除
                enterpriseCertService.update(new LambdaUpdateWrapper<BaseEnterpriseCert>()
                        .in(BaseEntity::getSequenceNbr, allCertSeqs)
                        .set(BaseEntity::getIsDelete, true)
                        .set(BaseEntity::getRecDate, new Date())
                        .set(BaseEntity::getRecUserId, RequestContext.getExeUserId()));
            }
        });
    }

    private void executeOneStep(JyjcOpeningApplicationModel openingApplication, String operate) {
        String instanceId = openingApplication.getWorkflowProstanceId();
        String nextTaskId = openingApplication.getNextTaskId();
        String lockKey = CommonServiceImpl.buildJcExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForExecuteFlow(nextTaskId, instanceId);
            // 组装信息执行工作流
            TaskResultDTO dto = new TaskResultDTO();
            dto.setResultCode("approvalStatus");
            dto.setTaskId(nextTaskId);
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", "提交");
            dto.setVariable(map);
            ProcessTaskDTO complete = cmWorkflowService.complete(nextTaskId, dto);
            ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
            processTaskDTOS.add(complete);
            List<WorkflowResultDto> resultDto = taskModelService.buildWorkFlowInfo(processTaskDTOS);
            WorkflowResultDto workflowResultDto = resultDto.get(0);
            if ("0".equals(operate)) {
                // 通过操作
                openingApplication.setStatus(WorkFlowStatusEnum.getMessage(workflowResultDto.getNextTaskCode()).getPass());
            } else {
                // 驳回操作
                openingApplication.setStatus(WorkFlowStatusEnum.getMessage(workflowResultDto.getNextTaskCode()).getReject());
                openingApplication.setPromoter("");
            }
            // 更新业务信息
            openingApplication.setPromoter(RequestContext.getExeUserId());
            openingApplication.setNextTaskId(workflowResultDto.getNextTaskId());
            openingApplication.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            // 更新代办
            JyjcOpeningApplication jyjcOpeningApplicationEntry = new JyjcOpeningApplication();
            BeanUtil.copyProperties(openingApplication, jyjcOpeningApplicationEntry);
            updateTask(jyjcOpeningApplicationEntry, workflowResultDto, operate);
            // 更新流程中的流程数据
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jyjcOpeningApplicationEntry));
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }


    /**
     * 撤回流程办理单
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public JyjcOpeningApplication rollBackFlow(String sequenceNbr, String instanceId, String nextTaskId) {
        String lockKey = CommonServiceImpl.buildJcExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForRevocationFlow(nextTaskId, instanceId);
            JyjcOpeningApplication jyjcOpeningApplication = jyjcOpeningApplicationMapper.selectById(sequenceNbr);
            //撤回流程
            ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(jyjcOpeningApplication.getWorkflowProstanceId());
            ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
            processTaskDTOS.add(processTaskDTO);
            List<WorkflowResultDto> resultDto = taskModelService.buildWorkFlowInfo(processTaskDTOS);
            String taskCode = "";
            if (!org.springframework.util.ObjectUtils.isEmpty(resultDto) && !org.springframework.util.ObjectUtils.isEmpty(resultDto.get(0))) {
                taskCode = resultDto.get(0).getNextTaskCode();
                jyjcOpeningApplication.setNextTaskId(resultDto.get(0).getNextTaskId());
                jyjcOpeningApplication.setNextExecuteUserIds(resultDto.get(0).getNextExecutorUserIds());
                jyjcOpeningApplication.setNextExecuteIds(resultDto.get(0).getNextExecutorRoleIds());
            }
            if (StringUtils.isNotEmpty(taskCode)) {
                jyjcOpeningApplication.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getRollBack());
            }
            jyjcOpeningApplication.setPromoter("");
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(jyjcOpeningApplication));
            jsonObject.put("nextTaskId", jyjcOpeningApplication.getNextTaskId());
            jsonObject.put("nextExecuteUser", jyjcOpeningApplication.getNextExecuteIds());
            jsonObject.put("taskType", BusinessTypeEnum.JY_OPENING_APPLICATION.getCode());
            jsonObject.put("flowStatus", commonService.getDictionaryCodeByName(jyjcOpeningApplication.getStatus()));
            jsonObject.put("flowStatusLabel", jyjcOpeningApplication.getStatus());
            this.sendMsg2User(jyjcOpeningApplication);
            // 撤回到发起单位时，数据恢复到原始提交状态
            this.restoreApplicationData(jyjcOpeningApplication);
            // 撤回删除代办
            taskModelService.rollbackTask(jyjcOpeningApplication.getWorkflowProstanceId(), jsonObject);
            // 更新数据
            jyjcOpeningApplicationMapper.updateById(jyjcOpeningApplication);
            // 缓存下一个任务id,再任务进行时，用来校验数据，不再进行数据库查询
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jyjcOpeningApplication));
            return jyjcOpeningApplication;
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return null;
    }

    private void restoreApplicationData(JyjcOpeningApplication jyjcOpeningApplication) {
        if (jyjcOpeningApplication.getStatus().equals(WorkFlowStatusEnum.OPENING_APPLICATION_SUBMIT.getRollBack())) {
            jyjcOpeningApplication.setDetectionRegion(jyjcOpeningApplication.getOriDetectionRegion());
            jyjcOpeningApplication.setAgencyClassify(null);
            jyjcOpeningApplication.setExpiryDate(null);
            JyjcInspectionHistory history = inspectionHistoryService.getBySSeq(jyjcOpeningApplication.getSequenceNbr());
            JSONObject hisData = history.getHistoryData();
            List<BaseEnterpriseCertDto> certDtos = hisData.getJSONArray(BizCommonConstant.UNIT_LICENCE_KEY).toJavaList(BaseEnterpriseCertDto.class);
            certDtos.forEach(c -> c.setItemCodes(new ArrayList<>()));
            hisData.put(BizCommonConstant.UNIT_LICENCE_KEY, certDtos);
            // 更新json
            commonService.saveOrUpdateHistory(jyjcOpeningApplication.getOpenBizType(), hisData, jyjcOpeningApplication.getSequenceNbr());
        }
    }


    private InstanceRuntimeData buildInstanceRuntimeData(JyjcOpeningApplicationModel jyjcOpeningApplication) {
        return InstanceRuntimeData.builder()
                .nextExecuteUserIds(jyjcOpeningApplication.getNextExecuteUserIds())
                .promoter(jyjcOpeningApplication.getPromoter())
                .nextTaskId(jyjcOpeningApplication.getNextTaskId())
                .build();
    }

    private InstanceRuntimeData buildInstanceRuntimeData(JyjcOpeningApplication jyjcOpeningApplication) {
        return InstanceRuntimeData.builder()
                .nextExecuteUserIds(jyjcOpeningApplication.getNextExecuteUserIds())
                .promoter(jyjcOpeningApplication.getPromoter())
                .nextTaskId(jyjcOpeningApplication.getNextTaskId())
                .build();
    }


    public List<Map<String, Object>> selectForFlowStatusList() {
        return Arrays.stream(FlowStatusEnum.values()).map(this::mapPointTypeToMap).collect(Collectors.toList());
    }

    private Map<String, Object> mapPointTypeToMap(FlowStatusEnum e) {
        Map<String, Object> record = new HashMap<>();
        record.put("key", e.getCode());
        record.put("label", e.getName());
        return record;
    }

    public Boolean deleteBatchByIds(List<Long> ids) {
        List<JyjcOpeningApplication> jyjcOpeningApplicationList = jyjcOpeningApplicationMapper.selectList(new QueryWrapper<JyjcOpeningApplication>()
                .in("sequence_nbr"));
        List<String> status = Arrays.asList(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()), String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()));
        jyjcOpeningApplicationList = jyjcOpeningApplicationList.stream().filter(jyjcOpeningApplication -> status.contains(jyjcOpeningApplication.getStatus())).collect(Collectors.toList());
        if (jyjcOpeningApplicationList.isEmpty()) {
            throw new BadRequest("除撤回跟驳回的流程之外其余流程不可删除，请核对数据后重新提交！");
        }
        deleteBatchByIds(ids);
        return true;
    }

    public List<TzBaseEnterpriseInfoDto> getInspectionUnitList() {
        List<TzBaseEnterpriseInfoDto> tzBaseEnterpriseInfos = enterpriseInfoMapper.getInspectionUnitList(null);
        if (ValidationUtil.isEmpty(tzBaseEnterpriseInfos)) {
            return Collections.EMPTY_LIST;
        }
        List<String> unitCodes = this.lambdaQuery().select(JyjcOpeningApplication::getUnitCode).list().stream().map(JyjcOpeningApplication::getUnitCode).collect(Collectors.toList());
        // 根据开通机构过滤
        return tzBaseEnterpriseInfos.stream().filter(o -> StringUtils.isNotBlank(o.getUseCode()) && unitCodes.contains(o.getUseCode())).collect(Collectors.toList());
    }

    public List<Long> selectOverdueData() {
        return jyjcOpeningApplicationMapper.selectOverdueData();

    }


    private void buildTask(JyjcOpeningApplicationModel model, WorkflowResultDto workflowResultDto) {
        ReginParams reginParams = commonService.getReginParamsOfCurrentUser();
        // 代办消息
        ArrayList<TaskModelDto> list = new ArrayList<>();
        TaskModelDto dto = new TaskModelDto();
        dto.setTaskType(BusinessTypeEnum.JY_OPENING_APPLICATION.getCode());
        dto.setTaskTypeLabel(BizTypeEnum.BUSINESS_OPEN.getName());
        dto.setFlowCreateDate(model.getRecDate());
        dto.setTaskName(workflowResultDto.getNextTaskName());
        dto.setTaskCode(workflowResultDto.getNextTaskCode());
        dto.setTaskContent(String.format("检验检测业务开通办理，【申请单号：%s】", model.getApplicationSeq()));
        dto.setRelationId(workflowResultDto.getInstanceId());
        dto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        dto.setTaskStatus(commonService.getDictionaryCodeByName(model.getStatus()));
        dto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
        dto.setFlowStatus(commonService.getDictionaryCodeByName(model.getStatus()));
        dto.setFlowStatusLabel(model.getStatus());
        dto.setStartUserId(reginParams.getUserModel().getUserId());
        dto.setStartUser(reginParams.getUserModel().getRealName());
        dto.setStartUserCompanyName(reginParams.getCompany().getCompanyName());
        dto.setStartDate(new Date());
        model.setWorkflowProstanceId(workflowResultDto.getInstanceId());
        model.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
        JyjcOpeningApplicationModel urlParms = new JyjcOpeningApplicationModel();
        BeanUtil.copyProperties(model, urlParms, "unitCode", "unitAddress", "unitCodeName", "detectionRegion", "detectionRegionName", "applicationSeq", "resultType", "expiryDate", "acceptDate", "remark", "applyTime", "baseUnitLicences", "userInfos", "useContact", "contactPhone", "industrySupervisor", "longitude", "latitude", "geographic", "unitBusinessLicense");
        dto.setModel(urlParms);
        dto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
        this.setPageTypeByFlowStatus(dto.getFlowStatus(), dto);
        list.add(dto);
        taskModelService.buildTaskModel(list);
    }

    private void setPageTypeByFlowStatus(Integer flowStatus, TaskModelDto dto) {
//        if(flowStatus == 167264){
        dto.setPageType("edit");
//        } else {
//            dto.setPageType("look");
//        }
    }

    private void updateTask(JyjcOpeningApplication model, WorkflowResultDto workflowResultDto, String operate) {
        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        if (!org.springframework.util.ObjectUtils.isEmpty(workflowResultDto.getNextTaskCode())) {
            taskCode = workflowResultDto.getNextTaskCode();
        }
        // 更新代办状态
        HashMap<String, Object> params = new HashMap<>();
        params.put("relationId", model.getWorkflowProstanceId());
        params.put("flowStatus", commonService.getDictionaryCodeByName(model.getStatus()));
        params.put("flowStatusLabel", model.getStatus());
        params.put("taskStatus", commonService.getDictionaryCodeByName(model.getStatus()));
        params.put("taskStatusLabel", model.getStatus());
        TaskV2Model taskV2Model = taskModelService.updateTaskModel(params);
        // 创建新的代办
        if (!ObjectUtils.isEmpty(taskV2Model)) {
            TaskModelDto taskModelDto = new TaskModelDto();
            BeanUtils.copyProperties(taskV2Model, taskModelDto);
            JyjcOpeningApplication urlParms = new JyjcOpeningApplication();
            BeanUtil.copyProperties(model, urlParms, "unitCode", "unitAddress", "unitCodeName", "detectionRegion", "detectionRegionName", "applicationSeq", "resultType", "expiryDate", "acceptDate", "remark", "applyTime", "baseUnitLicences", "userInfos", "useContact", "contactPhone", "industrySupervisor", "longitude", "latitude", "geographic", "unitBusinessLicense");
            taskModelDto.setModel(urlParms);
            taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
            taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
            taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
            taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
            // 退回到发起单位或者在资料校队节点时，可编辑
//            if (WorkFlowStatusEnum.OPENING_APPLICATION_SUBMIT.getCode().equals(taskCode) && "1".equals(operate) || WorkFlowStatusEnum.OPENING_APPLICATION_RECEIVE.getCode().equals(taskCode)) {
            taskModelDto.setPageType("edit");
//            }
            taskModelService.buildTaskModel(Collections.singletonList(taskModelDto));
        } else {
            JyjcOpeningApplicationModel applicationModel = new JyjcOpeningApplicationModel();
            BeanUtil.copyProperties(model, applicationModel);
            buildTask(applicationModel, workflowResultDto);
        }
    }

    @Override
    public List<TzBaseEnterpriseInfoDto> getUnitListByRecord(String record) {
        return this.getInspectionUnitList(new ArrayList<>(), true, record, OpenBizTypeEnum.JC.getCode());
    }

    private List<TzBaseEnterpriseInfoDto> getInspectionUnitList(List<TzBaseUnitLicence> unitLicenceList, Boolean isMatchArea, String record, String openBizType) {
        // 是否进行属地过滤
        String areaCode = isMatchArea ? ruleCommonService.getArea(record) : "";
        // 所有符合单位的code
        Set<String> unitCodes = unitLicenceList.stream().map(TzBaseUnitLicence::getUnitCode).collect(Collectors.toSet());
        List<TzBaseEnterpriseInfoDto> matchEnterpriseInfos = new ArrayList<>();
        // 按照资质 + areaCode，进行设备单位的筛选
        if (!unitCodes.isEmpty()) {
            matchEnterpriseInfos = tzBaseEnterpriseInfoMapper.getInspectionUnitListByCode(new ArrayList<>(unitCodes), areaCode, openBizType);
        }
        if (matchEnterpriseInfos.isEmpty()) {
            log.info("按照资质、区域未匹配到对应的单位、按照地市未匹配到单位，将返回全部单位");
            return tzBaseEnterpriseInfoMapper.getInspectionUnitListByCode(null, null, openBizType);
        }
        return matchEnterpriseInfos;
    }

    /**
     * 缓存当前正在流程中的实例的流程数据
     */
    public void initFlowData2Redis() {
        LambdaQueryWrapper<JyjcOpeningApplication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ne(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_FINISHED.getCode());
        queryWrapper.ne(JyjcOpeningApplication::getStatus, FlowStatusEnum.TO_BE_DISCARD.getCode());
        queryWrapper.isNotNull(JyjcOpeningApplication::getWorkflowProstanceId);
        queryWrapper.select(JyjcOpeningApplication::getWorkflowProstanceId, JyjcOpeningApplication::getNextTaskId, JyjcOpeningApplication::getPromoter, JyjcOpeningApplication::getNextExecuteUserIds);
        List<JyjcOpeningApplication> openingApplicationListInFlowing = this.list(queryWrapper);
        openingApplicationListInFlowing.forEach(inspectionApplication -> {
            commonService.saveExecuteFlowData2Redis(inspectionApplication.getWorkflowProstanceId(), this.buildInstanceRuntimeData(inspectionApplication));
        });
    }

    public List<InspectionCompanyPublicityDto> queryInspectionOrgListForBiz() {
        // 查询所有已经业务开通的检验检测机构，已机构为维度进行证的合并处理
        List<InspectionCompanyPublicityDto> inspectionCompanyPublicityDtos = this.getBaseMapper().queryInspectionOrgListForBiz();
        // 枚举转换
        inspectionCompanyPublicityDtos.forEach(c -> {
            c.setDetectionRegion(this.castRegionCode2Name(c.getDetectionRegion()));
            c.setApprovalInfo(this.breakNewLineForApprovalInfo(c.getApprovalInfo()));
            c.setOpenBizType(this.getOpenBizTypeName(c.getOpenBizType()));
        });
        return inspectionCompanyPublicityDtos;
    }

    private String castRegionCode2Name(String detectionRegion) {
        return "";
    }

    private String breakNewLineForApprovalInfo(String approvalInfo) {
        String[] approvalArray = approvalInfo.split("#");
        StringBuilder stringBuilder = new StringBuilder();
        return "";
    }


    public void exportData(HttpServletResponse response, List<String> ids) {
        List<JyjcOpeningApplicationVo> exportData = jyjcOpeningApplicationMapper.queryJyjcOpeningApplicationListByIds(ids);
        for (JyjcOpeningApplicationVo data : exportData) {
            data.setOpenBizType(this.getOpenBizTypeName(data.getOpenBizType()));
        }
        ExcelUtil.createTemplate(response, "检验检测开通列表数据", "检验检测开通列表", exportData, JyjcOpeningApplicationVo.class, null, false);
    }


    public String getAppIdBySeq(Long seq) {
        JyjcOpeningApplication openingApplication = this.getOne(new LambdaQueryWrapper<JyjcOpeningApplication>().eq(org.typroject.tyboot.core.rdbms.orm.entity.BaseEntity::getSequenceNbr, seq).select(org.typroject.tyboot.core.rdbms.orm.entity.BaseEntity::getSequenceNbr, JyjcOpeningApplication::getDockingUnitCode));
        return openingApplication.getDockingUnitCode();
    }

}