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

import cn.hutool.core.bean.BeanUtil;
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.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.util.StringUtil;
import com.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.annotation.ResultFieldMapping;
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.dao.mapper.DataDictionaryMapper;
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.entity.TzsBaseEntity;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.boot.module.common.api.dao.ESEquipmentCategory;
import com.yeejoin.amos.boot.module.common.api.dto.ESEquipmentCategoryDto;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.*;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CompanyTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.PipelineEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgInstallationNoticeEqMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgInstallationNoticeMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgRegistrationHistoryMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IJgInstallationNoticeService;
import com.yeejoin.amos.boot.module.jg.api.vo.SortVo;
import com.yeejoin.amos.boot.module.jg.api.vo.tableDataExportVo.InstallationVo;
import com.yeejoin.amos.boot.module.jg.biz.config.LocalBadRequest;
import com.yeejoin.amos.boot.module.jg.biz.context.EquipUsedCheckStrategyContext;
import com.yeejoin.amos.boot.module.jg.biz.context.FlowingEquipRedisContext;
import com.yeejoin.amos.boot.module.jg.biz.event.CancellationEvent;
import com.yeejoin.amos.boot.module.jg.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.ICmWorkflowService;
import com.yeejoin.amos.boot.module.jg.biz.service.ICompensateFlowDataOfRedis;
import com.yeejoin.amos.boot.module.jg.biz.service.IIdxBizJgConstructionInfoService;
import com.yeejoin.amos.boot.module.jg.biz.service.IIdxBizJgUseInfoService;
import com.yeejoin.amos.boot.module.jg.biz.utils.CodeUtil;
import com.yeejoin.amos.boot.module.jg.biz.utils.ImageUtils;
import com.yeejoin.amos.boot.module.jg.biz.utils.WordTemplateUtils;
import com.yeejoin.amos.boot.module.ymt.api.entity.*;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquCodeTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquimentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.*;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
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.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import io.seata.tm.api.GlobalTransactionContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
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.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
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 org.typroject.tyboot.core.restful.utils.ResponseModel;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.alibaba.fastjson.JSON.parseArray;

/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2023-12-12
 */
@Service
@Slf4j
public class JgInstallationNoticeServiceImpl extends BaseService<JgInstallationNoticeDto, JgInstallationNotice, JgInstallationNoticeMapper> implements IJgInstallationNoticeService, ICompensateFlowDataOfRedis<JgInstallationNotice> {

    private static final String SUBMIT_TYPE_FLOW = "1";
    private static final String PROCESS_DEFINITION_KEY = "installationNotificationNew";
    private static final String PROCESS_INSTALL_NOTICE_KEY = "installNotice";

    private static final String TABLE_PAGE_ID = "1734141426742095873";
    public static final String CONSTRUCTION_TYPE = "SGLX";
    public static final String CONSTRUCTION_TYPE_NAME = "安装";
    public static final String EXPORT_SUMMARY_TABLE = "exportSummaryTable";
    @Autowired
    JgInstallationNoticeEqMapper jgInstallationNoticeEqMapper;
    @Autowired
    JgInstallationNoticeEqServiceImpl jgInstallationNoticeEqService;
    @Autowired
    IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Autowired
    IdxBizJgRegisterInfoMapper tzsJgRegistrationInfoMapper;
    @Autowired
    OtherInfoMapper tzsJgOtherInfoMapper;
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    IdxBizJgSupervisionInfoMapper idxBizJgSupervisionInfoMapper;
    @Autowired
    SupervisoryCodeInfoMapper supervisoryCodeInfoMapper;
    @Autowired
    IIdxBizJgConstructionInfoService constructionInfoService;
    @Autowired
    IIdxBizJgUseInfoService useInfoService;
    @Autowired
    IdxBizJgUseInfoMapper idxBizJgUseInfoMapper;
    @Value(value = "${tzs.domain:http://sxtzsb.sxsei.com}")
    String TZSDOMAIN;
    @Autowired
    CodeUtil codeUtil;
    @Autowired
    JgCertificateChangeRecordServiceImpl certificateChangeRecordService;
    @Autowired
    JgCertificateChangeRecordEqServiceImpl certificateChangeRecordEqService;
    @Autowired
    private SnowflakeIdUtil sequence;
    @Autowired
    private JgInstallationNoticeMapper jgInstallationNoticeMapper;
    @Autowired
    private ProduceInfoMapper produceInfoMapper;
    @Autowired
    private DataDictionaryMapper dataDictionaryMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private TzBaseUnitLicenceMapper baseUnitLicenceMapper;
    @Autowired
    private ICmWorkflowService iCmWorkflowService;
    @Autowired
    private CommonServiceImpl commonService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private IdxBizJgConstructionInfoMapper constructionInfoMapper;
    @Autowired
    private ESEquipmentCategory esEquipmentCategory;
    @Autowired
    private JgResumeInfoServiceImpl jgResumeInfoService;
    @Autowired
    private TzBaseEnterpriseInfoMapper tzBaseEnterpriseInfoMapper;
    @Autowired
    private JgRegistrationHistoryMapper jgRegistrationHistoryMapper;
    @Autowired
    private IdxBizJgFactoryInfoServiceImpl idxBizJgFactoryInfoService;
    @Autowired
    private IdxBizJgProjectContraptionServiceImpl projectContraptionService;

    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private IdxBizJgProjectConstructionMapper projectConstructionMapper;
    @Autowired
    private IdxBizJgProjectContraptionMapper projectContraptionMapper;
    @Autowired
    EventPublisher eventPublisher;
    @Autowired
    private JgUseRegistrationServiceImpl jgUseRegistrationService;

    /**
     * 安装改造维修单位吱资质类型：1234-安改维、1236-制造单位
     */
    @Value("${company.type.notice:1234,1236}")
    private String companyType;

    /**
     * 根据sequenceNbr查询
     *
     * @param sequenceNbr 主键
     * @return 安装告知
     */
    @Override
    @ResultFieldMapping({
            @ResultFieldMapping.ResultFieldMap(sourceField = "installationInfo.useUnitCreditCode", targetField = "installationInfo.useUnitSeq", serviceClass = CommonServiceImpl.class, queryMethod = "queryUnitInfoByCreditCode"),
            @ResultFieldMapping.ResultFieldMap(sourceField = "installationInfo.propertyUnitName", targetField = "installationInfo.propertyUnitSeq", serviceClass = CommonServiceImpl.class, queryMethod = "queryUnitInfoByCreditCode")
    })
    public Map<String, Map<String, Object>> queryBySequenceNbr(Long sequenceNbr, CompanyBo company) {
        // 安装告知信息
        JgInstallationNotice notice = jgInstallationNoticeMapper.selectById(sequenceNbr);
        if (Objects.isNull(notice)) {
            return null;
        }
        // 流程数据补偿 防止redis缓存数据存在与数据库不一致问题
        this.doCompensate(notice);
        Map<String, Object> installationInfo = BeanUtil.beanToMap(notice, false, true);

        installationInfo.put("province", notice.getProvince() + "_" + notice.getProvinceName());
        installationInfo.put("city", notice.getCity() + "_" + notice.getCityName());
        installationInfo.put("county", notice.getCounty() + "_" + notice.getCountyName());
        // 处理安装负责人-详情
        if (!ObjectUtils.isEmpty(installationInfo.get("installLeaderName"))) {
            installationInfo.put("installLeaderName", installationInfo.get("installLeaderName"));
        }
        // 处理设备类型
        if (!ObjectUtils.isEmpty(installationInfo.get("equCategoryCode"))) {
            installationInfo.put("EQU_CATEGORY_CODE", installationInfo.get("equCategoryCode"));
        }
        // 处理设备筛选默认值
        installationInfo.put("QUERY_TYPE", "AZ");
        installationInfo.put("IS_INTO_MANAGEMENT", "false");
        installationInfo.put("isIntoManagement", "false");
        // 处理图片
        if (!ValidationUtil.isEmpty(installationInfo.get("proxyStatementAttachment"))) {
            installationInfo.put("proxyStatementAttachmentList", JSONObject.parseArray(installationInfo.get("proxyStatementAttachment").toString()));
        }
        if (!ValidationUtil.isEmpty(installationInfo.get("installContractAttachment"))) {
            installationInfo.put("installContractAttachmentList", JSONObject.parseArray(installationInfo.get("installContractAttachment").toString()));
        }
        if (!ValidationUtil.isEmpty(installationInfo.get("otherAccessories"))) {
            installationInfo.put("otherAccessoriesList", JSONObject.parseArray(installationInfo.get("otherAccessories").toString()));
        }
        TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(
                new QueryWrapper<TzBaseEnterpriseInfo>()
                        .eq("use_unit_code", notice.getUseUnitCreditCode())
        );

        if (useCodeResult != null) {
            String result = notice.getUseUnitCreditCode() + "_" + notice.getUseUnitName() +
                    ("个人主体".equals(useCodeResult.getUnitType())
                            ? "_" + notice.getUseUnitCreditCode().substring(notice.getUseUnitCreditCode().length() - 4)
                            : "");
            installationInfo.put("useUnitCreditCode", result);
        }
        //installationInfo.put("useUnitCreditCode", notice.getUseUnitCreditCode() + "_" + notice.getUseUnitName());

        installationInfo.put("receiveOrgCreditCode", notice.getReceiveOrgCreditCode() + "_" + notice.getReceiveOrgName());
        installationInfo.put("installLeaderId", notice.getInstallLeaderId() + "_" + notice.getInstallLeaderName());
        if (!ValidationUtil.isEmpty(notice.getInspectUnitId()) && !ValidationUtil.isEmpty(notice.getInspectUnitName())) {
            installationInfo.put("inspectUnitId", notice.getInspectUnitId() + "_" + notice.getInspectUnitName());
        }
        if (!ValidationUtil.isEmpty(notice.getFactoryUseSiteStreet()) && !ValidationUtil.isEmpty(notice.getStreetName())) {
            installationInfo.put("factoryUseSiteStreet", notice.getFactoryUseSiteStreet() + "_" + notice.getStreetName());
        }
        if (!ValidationUtil.isEmpty(notice.getOrgBranchCode()) && !ValidationUtil.isEmpty(notice.getOrgBranchName())) {
            installationInfo.put("orgBranchCode", notice.getOrgBranchCode() + "_" + notice.getOrgBranchName());
        }

        if (!ValidationUtil.isEmpty(notice.getPropertyUnitCreditCode()) && !ValidationUtil.isEmpty(notice.getPropertyUnitName())) {
            //installationInfo.put("propertyUnitName", notice.getPropertyUnitCreditCode() + "_" + notice.getPropertyUnitName());
            TzBaseEnterpriseInfo useCodeResult1 = tzBaseEnterpriseInfoMapper.selectOne(
                    new QueryWrapper<TzBaseEnterpriseInfo>()
                            .eq("use_unit_code", notice.getPropertyUnitCreditCode())
            );
            if (useCodeResult1 != null) {
                installationInfo.put("propertyUnitName", notice.getPropertyUnitCreditCode() + "_" + notice.getPropertyUnitName() +
                        ("个人主体".equals(useCodeResult1.getUnitType())
                                ? "_" + notice.getPropertyUnitCreditCode().substring(notice.getPropertyUnitCreditCode().length() - 4)
                                : ""));
            }
        }

        String[] fields = {"productPhoto", "designDoc", "designStandard", "factoryStandard",
                "productQualityYieldProve", "insUseMaintainExplain", "inspectReport",
                "proxyStatementAttachment", "installContractAttachment", "otherAccessories"};
        // 设备信息
//        List<Map<String, Object>> equipmentInfos = jgInstallationNoticeMapper.queryEquipInformation(sequenceNbr);
        for (String s : fields) {
            if (installationInfo.containsKey(s)) {
                installationInfo.put(s, ObjectUtils.isEmpty(installationInfo.get(s)) ? new JSONArray() : parseArray(installationInfo.get(s).toString()));
            }
        }
        String[] jsonObjFields = {"startLatitudeLongitude", "endLatitudeLongitude"};
        for (String s : jsonObjFields) {
            if (installationInfo.containsKey(s)) {
                installationInfo.put(s, ObjectUtils.isEmpty(installationInfo.get(s)) ? null : JSON.parseObject(installationInfo.get(s).toString()));
            }
        }
        String companyLevel = CommonServiceImpl.getCompanyType(company);
        if (Integer.parseInt(notice.getNoticeStatus()) >= FlowStatusEnum.TO_BE_FINISHED.getCode()) {
            // 完成及作废时显示历史数据
            JSONObject hisData = commonService.queryHistoryData(notice.getSequenceNbr());
            // 兼容老数据
            if (hisData == null) {
                // todo companyLevel赋值这个不能少，控制前端页面的字段(安装负责人）显示隐藏
                Map<String, Object> detail = setNewEquipData(companyLevel, installationInfo);
                this.fillingEquCategoryNameForHisData(detail, notice);
                new FillingEditPermForCurrentUser(new JSONObject(detail), company).getData();;
                return new HashMap<String, Map<String, Object>>() {{
                    this.put("installationInfo", detail);
                }};
            } else {
                hisData.putAll(installationInfo);
                CommonServiceImpl.formatTime2StrDateForEquip(hisData);
                this.fillingEquCategoryNameForHisData(hisData, notice);
                new FillingEditPermForCurrentUser(hisData, company).getData();
                // todo 这个不能少 控制前端页面的字段(安装负责人）显示隐藏
                hisData.put("companyLevel", companyLevel);
                return new HashMap<String, Map<String, Object>>() {{
                    this.put("installationInfo", hisData);
                }};
            }
        } else {
            // 显示最新的设备信息
            // todo companyLevel赋值这个不能少，控制前端页面的字段(安装负责人）显示隐藏
            Map<String, Object> detail = setNewEquipData(companyLevel, installationInfo);
            detail.put("startLatitudeLongitude", JSON.parseObject(notice.getStartLatitudeLongitude()));
            detail.put("endLatitudeLongitude", JSON.parseObject(notice.getEndLatitudeLongitude()));
            new FillingEditPermForCurrentUser(new JSONObject(detail), company).getData();
            return new HashMap<String, Map<String, Object>>() {{
                this.put("installationInfo", detail);
            }};
        }
    }

    /**
     * 历史数据填充设备种类、设备类别、设备品种
     * @param detail  返回json
     * @param notice  当前单据
     */
    private void fillingEquCategoryNameForHisData(Map<String, Object> detail, JgInstallationNotice notice) {
        if(!StringUtils.isEmpty(notice.getProjectContraptionId())){
            LambdaQueryWrapper<IdxBizJgProjectContraption> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BaseEntity::getSequenceNbr, notice.getProjectContraptionId());
            queryWrapper.select(IdxBizJgProjectContraption::getEquListName,IdxBizJgProjectContraption::getEquCategoryName,IdxBizJgProjectContraption::getEquDefineName,BaseEntity::getSequenceNbr);
            IdxBizJgProjectContraption projectContraption = projectContraptionService.getBaseMapper().selectOne(queryWrapper);
            if(projectContraption != null){
                detail.put("equListName", projectContraption.getEquListName());
                detail.put("equCategoryName", projectContraption.getEquCategoryName());
                detail.put("equDefineName", projectContraption.getEquDefineName());
            }
        }
    }

    private List<Map<String, Object>> getEquipListMaps(Iterable<ESEquipmentCategoryDto> equips) {
        List<Map<String, Object>> arrayList = new ArrayList<>();
        equips.forEach(equip -> {
            Map<String, Object> objectHashMap = new HashMap<>();
            BeanUtil.beanToMap(equip, objectHashMap, false, false);
            objectHashMap.put("record", equip.getSEQUENCE_NBR());
            objectHashMap.put("ADDRESS", concatDetailAddress(equip));
            arrayList.add(objectHashMap);
        });
        return arrayList;
    }

    private String concatDetailAddress(ESEquipmentCategoryDto esEquipmentCategoryDto) {
        // 省、市、区
        String usePlace = esEquipmentCategoryDto.getUSE_PLACE();
        // 详细地址
        String address = esEquipmentCategoryDto.getADDRESS();
        return String.format("%s%s", usePlace, address);
    }


    private Map<String, Object> setNewEquipData(String companyLevel, Map<String, Object> installationInfo) {
        List<Map<String, Object>> equipListMaps = Lists.newArrayList();
        String equCategory = (String) installationInfo.get("equCategoryCode");
        LambdaQueryWrapper<JgInstallationNoticeEq> lambda = new QueryWrapper<JgInstallationNoticeEq>().lambda();
        lambda.eq(JgInstallationNoticeEq::getEquipTransferId, installationInfo.get("sequenceNbr"));
        List<JgInstallationNoticeEq> jgInstallationNoticeEqs = jgInstallationNoticeEqMapper.selectList(lambda);
        if (!ValidationUtil.isEmpty(jgInstallationNoticeEqs)) {
            // 压力管道从工程装置表查询设备信息
            if (PipelineEnum.INDUSTRIAL_PIPELINE.getCode().equals(equCategory) || PipelineEnum.LONG_DISTANCE_PIPELINE.getCode().equals(equCategory) || PipelineEnum.COMMON_PIPELINE.getCode().equals(equCategory)) {
                String projectContraptionId = (String) installationInfo.get("projectContraptionId");
                IdxBizJgProjectContraption projectContraption = projectContraptionService.getById(projectContraptionId);
                installationInfo.put("pipelineLength", projectContraption.getPipelineLength());
                installationInfo.put("projectContraptionNo", projectContraption.getProjectContraptionNo());
                installationInfo.put("projectContraption", projectContraption.getProjectContraption());
                installationInfo.put("equListName", projectContraption.getEquListName());
                installationInfo.put("equCategoryName", projectContraption.getEquCategoryName());
                installationInfo.put("equDefineName", projectContraption.getEquDefineName());
                equipListMaps = projectContraptionService.getBaseMapper().selectEquipList(projectContraptionId);
                equipListMaps.forEach(item ->
                        item.put("deviceLevel", Optional.ofNullable(dataDictionaryMapper.selectById(String.valueOf(item.get("deviceLevel"))))
                                .map(DataDictionary::getName)
                                .orElse("")));
            } else {
                List<String> ids = jgInstallationNoticeEqs.stream().map(JgInstallationNoticeEq::getEquId).collect(Collectors.toList());
                Iterable<ESEquipmentCategoryDto> equips = esEquipmentCategory.findAllById(ids);
                equipListMaps = getEquipListMaps(equips);
            }
        }

//        Map<String, Object> detail = equipmentInfos.get(0);
//        Map<String, Object> equInfo = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(detail.get("equId").toString());
//        equInfo.put("useUnitCreditCodeUse", equInfo.getOrDefault("useUnitCreditCode", ""));
//        equInfo.put("useUnitNameUse", equInfo.getOrDefault("useUnitName", ""));
//        equInfo.put("productPhoto", JSON.parse(String.valueOf(detail.get("productPhoto"))));
//        equInfo.put("factoryStandard", JSON.parse(String.valueOf(detail.get("factoryStandard"))));
//        equInfo.put("productQualityYieldProve", JSON.parse(String.valueOf(detail.get("productQualityYieldProve"))));
//        equInfo.put("insUseMaintainExplain", JSON.parse(String.valueOf(detail.get("insUseMaintainExplain"))));
//        equInfo.put("inspectReport", JSON.parse(String.valueOf(detail.get("inspectReport"))));
//        equInfo.put("designStandard", JSON.parse(String.valueOf(detail.get("designStandard"))));
//        equInfo.put("designDoc", JSON.parse(String.valueOf(detail.get("designDoc"))));
//        equInfo.put("otherAccessoriesList", JSON.parse(String.valueOf(detail.get("otherAccessories"))));
//        BeanUtil.copyProperties(equInfo, detail);
//        BeanUtil.copyProperties(installationInfo, detail, "equList", "supervisoryCode", "factoryNum", "equRegisterCode");
        installationInfo.put("companyLevel", companyLevel);
        installationInfo.put("deviceList", equipListMaps);
//        // 处理图片
//        if (!ValidationUtil.isEmpty(installationInfo.get("proxyStatementAttachment"))) {
//            installationInfo.put("proxyStatementAttachmentList", installationInfo.get("proxyStatementAttachment"));
//        }
//        if (!ValidationUtil.isEmpty(installationInfo.get("installContractAttachment"))) {
//            installationInfo.put("installContractAttachmentList", installationInfo.get("installContractAttachment"));
//        }
//        if (!ValidationUtil.isEmpty(installationInfo.get("otherAccessories"))) {
//            installationInfo.put("otherAccessoriesList", installationInfo.get("otherAccessories"));
//        }
        return installationInfo;
    }

    /**
     * 更新安装告知
     *
     * @param noticeDto 安装告知
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public JgInstallationNoticeDto updateInstallationNotice(String submitType, JgInstallationNoticeDto noticeDto, String op) {
        if (Objects.isNull(noticeDto) || StringUtils.isEmpty(submitType)) {
            throw new IllegalArgumentException("参数不能为空");
        }
        try {
            // 字段转换
            this.convertField(noticeDto);
            JgInstallationNotice notice = this.getById(noticeDto.getSequenceNbr());
            this.checkRepeatUsed(submitType, notice);
            if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                if (!StringUtils.hasText(noticeDto.getInstanceId())) {
                    // 发起流程
                    ProcessTaskDTO processTaskDTO = new ProcessTaskDTO();
                    WorkflowResultDto workflowResultDto = new WorkflowResultDto();
                    // 如果没有实例ID，说明是启动并执行一步
                    // 直接调用工作流 启动并执行API  -  可以拿到两个节点的信息，用于填充业务字段
                    ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                    List<ActWorkflowStartDTO> list = new ArrayList<>();
                    ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                    dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
                    dto.setBusinessKey(noticeDto.getSequenceNbr().toString());
                    dto.setCompleteFirstTask(Boolean.TRUE);
                    // 下一节点执行人单位（下节点接收机构code）
                    dto.setNextExecuteUserCompanyCode(notice.getReceiveOrgCreditCode());
                    list.add(dto);
                    actWorkflowBatchDTO.setProcess(list);
                    processTaskDTO = iCmWorkflowService.startBatch(actWorkflowBatchDTO).get(0);
                    // 提取节点等信息
                    workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
                    BeanUtils.copyProperties(noticeDto, notice);
                    notice.setStartLatitudeLongitude(JSON.toJSONString(noticeDto.getStartLatitudeLongitude()));
                    notice.setEndLatitudeLongitude(JSON.toJSONString(noticeDto.getEndLatitudeLongitude()));
                    if (!ObjectUtils.isEmpty(notice.getInstanceStatus())) {
                        notice.setInstanceStatus(notice.getInstanceStatus() + "," + workflowResultDto.getNextExecutorRoleIds());
                    } else {
                        notice.setInstanceStatus(workflowResultDto.getNextExecutorRoleIds());
                    }
                    notice.setPromoter(RequestContext.getExeUserId());
                    notice.setNextExecuteIds(String.join(",", workflowResultDto.getNextExecutorRoleIds()));
                    notice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    notice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
                    notice.setNextTaskId(workflowResultDto.getNextTaskId());
                    notice.setInstanceId(workflowResultDto.getInstanceId());
                    this.updateById(notice);
                    // 如果为保存并提交，则创建代办
                    buildTask(Collections.singletonList(notice), Collections.singletonList(workflowResultDto), Boolean.TRUE);
                } else {
                    ProcessTaskDTO processTaskDTO = new ProcessTaskDTO();
                    WorkflowResultDto workflowResultDto = new WorkflowResultDto();
                    // 只调用执行API，返回下个节点信息，用于填充业务字段
                    // 组装信息
                    TaskResultDTO dto = new TaskResultDTO();
                    dto.setResultCode("approvalStatus");
                    dto.setTaskId(notice.getNextTaskId());
                    HashMap<String, Object> commMap = new HashMap<>();
                    if (notice.getNoticeStatus().equals("6614") || notice.getNoticeStatus().equals("6615")) {
                        commMap.put("approvalStatus", "提交");
                    } else {
                        commMap.put("approvalStatus", op);
                    }
                    dto.setVariable(commMap);
                    // 下一节点执行人单位（下节点接收机构code）
                    dto.setNextExecuteUserCompanyCode(notice.getReceiveOrgCreditCode());
                    processTaskDTO = iCmWorkflowService.completeOrReject(notice.getNextTaskId(), dto, op);
                    // 提取节点等信息
                    workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
                    BeanUtils.copyProperties(noticeDto, notice);
                    notice.setStartLatitudeLongitude(JSON.toJSONString(noticeDto.getStartLatitudeLongitude()));
                    notice.setEndLatitudeLongitude(JSON.toJSONString(noticeDto.getEndLatitudeLongitude()));
                    if (!ObjectUtils.isEmpty(notice.getInstanceStatus())) {
                        notice.setInstanceStatus(notice.getInstanceStatus() + "," + workflowResultDto.getNextExecutorRoleIds());
                    } else {
                        notice.setInstanceStatus(workflowResultDto.getNextExecutorRoleIds());
                    }
                    notice.setPromoter(RequestContext.getExeUserId());
                    notice.setNextExecuteIds(String.join(",", workflowResultDto.getNextExecutorRoleIds()));
                    notice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    notice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
                    notice.setNextTaskId(workflowResultDto.getNextTaskId());
                    this.updateById(notice);
                    // 上个代办改为已办
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("taskStatus", FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    map.put("taskStatusLabel", FlowStatusEnum.TO_BE_PROCESSED.getName());
                    map.put("relationId", notice.getInstanceId());
                    map.put("flowStatus", FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    map.put("flowStatusLabel", FlowStatusEnum.TO_BE_PROCESSED.getName());
                    TaskV2Model taskV2Model = commonService.updateTaskModel(map);
                    if (ObjectUtils.isEmpty(taskV2Model)) {
                        // 如果为保存并提交，则创建代办
                        buildTask(Collections.singletonList(notice), Collections.singletonList(workflowResultDto), Boolean.FALSE);
                    } else {
                        TaskModelDto taskModelDto = new TaskModelDto();
                        BeanUtils.copyProperties(taskV2Model, taskModelDto);
                        // 创建新的代办
                        taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                        taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                        taskModelDto.setFlowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
                        taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                        taskModelDto.setFlowCode(notice.getNextTaskId());
                        taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                        TaskMessageDto taskMessageDto = new TaskMessageDto();
                        BeanUtils.copyProperties(notice, taskMessageDto);
                        taskModelDto.setModel(taskMessageDto);
                        commonService.buildTaskModel(Collections.singletonList(taskModelDto));
                    }
                }
                commonService.saveExecuteFlowData2Redis(notice.getInstanceId(), this.buildInstanceRuntimeData(notice));
            } else {
                JgInstallationNotice bean = new JgInstallationNotice();
                BeanUtils.copyProperties(noticeDto, bean);
                this.updateById(bean);
            }
            // 更新关联设备信息
            LambdaQueryWrapper<JgInstallationNoticeEq> lambda = new QueryWrapper<JgInstallationNoticeEq>().lambda();
            lambda.eq(JgInstallationNoticeEq::getEquipTransferId, noticeDto.getSequenceNbr());
            jgInstallationNoticeEqMapper.delete(lambda);
            List<Map<String, Object>> deviceList = noticeDto.getDeviceList();
            if(!CollectionUtils.isEmpty(deviceList)){
                ArrayList<JgInstallationNoticeEq> jgInstallationNoticeEqs = new ArrayList<>();
                deviceList.forEach(item -> {
                    JgInstallationNoticeEq jgInstallationNoticeEq = new JgInstallationNoticeEq();
                    jgInstallationNoticeEq.setEquId(!ValidationUtil.isEmpty(item.get("SEQUENCE_NBR")) ? String.valueOf(item.get("SEQUENCE_NBR")) : String.valueOf(item.get("record")));
                    jgInstallationNoticeEq.setEquCategoryCode(!ValidationUtil.isEmpty(item.get("EQU_CATEGORY_CODE")) ? String.valueOf(item.get("EQU_CATEGORY_CODE")) : String.valueOf(item.get("equCategory")));
                    jgInstallationNoticeEq.setEquListCode(!ValidationUtil.isEmpty(item.get("EQU_LIST_CODE")) ? String.valueOf(item.get("EQU_LIST_CODE")) : String.valueOf(item.get("equList")));
                    jgInstallationNoticeEq.setEquipTransferId(noticeDto.getSequenceNbr().toString());
                    jgInstallationNoticeEqs.add(jgInstallationNoticeEq);
                });
                jgInstallationNoticeEqMapper.insertBatchSomeColumn(jgInstallationNoticeEqs);
            }
            return noticeDto;
        } catch (BadRequest | LocalBadRequest e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw new BadRequest("保存失败！");
        } finally {
            FlowingEquipRedisContext.clean();
        }
    }

    private void checkRepeatUsed(String submitType, JgInstallationNotice jgInstallationNotice) {
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            // 流程中校验
            LambdaQueryWrapper<JgInstallationNoticeEq> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JgInstallationNoticeEq::getEquipTransferId, jgInstallationNotice.getSequenceNbr());
            List<JgInstallationNoticeEq> jgInstallationNoticeEqs = jgInstallationNoticeEqMapper.selectList(queryWrapper);
            for (JgInstallationNoticeEq jgInstallationNoticeEq : jgInstallationNoticeEqs) {
                EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_INSTALL_NOTICE_KEY).equipRepeatUsedCheck(jgInstallationNoticeEq.getEquId(), jgInstallationNotice.getInstallUnitCreditCode());
            }
        }
    }


    /**
     * 分页查询
     *
     * @param page   分页对象
     * @param model  查询参数
     * @param type   类型：enterprise-企业端、supervision-监管端
     * @param client 类型：jgAudit-监管审核;jgLook-监管查看
     * @return 安装告知列表
     */
    @Override
    public Page<Map<String, Object>> queryForJgInstallationNoticePage(Page<JgInstallationNotice> page,
                                                                      JgInstallationNoticeDto model,
                                                                      String type,
                                                                      String sort,
                                                                      ReginParams reginParams, String client) {

        String companyCode = reginParams.getCompany().getCompanyCode();
        SortVo sortMap = commonService.sortFieldConversion(sort);
        model.setTransferToUserIds(reginParams.getUserModel().getUserId());
        String orgCode = reginParams.getCompany().getOrgCode();
        Page<Map<String, Object>> noticePage = jgInstallationNoticeMapper.queryForPage(page, model, type, sortMap, companyCode, orgCode, client);
        List<Map<String, Object>> mappedRecords = noticePage.getRecords().stream().peek(notice -> {
            Optional<Long> noticeStatusOpt = Optional.ofNullable((String) notice.get("noticeStatus")).map(Long::valueOf);
            noticeStatusOpt.ifPresent(status -> {
                String noticeStatusDesc = FlowStatusEnum.getNameByType(status);
                notice.put("noticeStatusDesc", noticeStatusDesc);
            });
        }).collect(Collectors.toList());
        noticePage.setRecords(mappedRecords);
        return noticePage;
    }

    /**
     * 批量删除
     *
     * @param sequenceNbrs 主键
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteForBatch(Long[] sequenceNbrs) {
        if (Objects.isNull(sequenceNbrs) || sequenceNbrs.length == 0) {
            return false;
        }
        for (Long sequenceNbr : sequenceNbrs) {
            // 删除待办 + 中止流程
            JgInstallationNotice jgInstallationNotice = this.baseMapper.selectById(sequenceNbr);
            commonService.deleteTaskModel(String.valueOf(sequenceNbr), jgInstallationNotice.getInstanceId());
            // 删除业务单
            jgInstallationNotice.setIsDelete(true);
            this.getBaseMapper().deleteById(sequenceNbr);
            // 删除对应equ
            jgInstallationNoticeEqMapper.delete(new LambdaUpdateWrapper<JgInstallationNoticeEq>()
                    .eq(JgInstallationNoticeEq::getEquipTransferId, sequenceNbr));
            // 删除单子对应历史表数据
            jgRegistrationHistoryMapper.delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getCurrentDocumentId, jgInstallationNotice.getSequenceNbr()));
        }
        return Boolean.TRUE;
    }

    /**
     * 打印安装告知单
     *
     * @param sequenceNbr 主键
     * @return pdf文件路径
     */
    @Override
    public void generateInstallationNoticeReport(Long sequenceNbr, HttpServletResponse response) {
        if (Objects.isNull(sequenceNbr)) {
            throw new IllegalArgumentException("参数不能为空");
        }
        JgInstallationNotice jgInstallationNotice = this.getById(sequenceNbr);
        List<JgInstallationNoticeEq> equList = jgInstallationNoticeEqService.lambdaQuery().eq(JgInstallationNoticeEq::getEquipTransferId, jgInstallationNotice.getSequenceNbr()).list();
        HashMap<String, Object> map = new HashMap<>();
        ArrayList<Map<String, Object>> maps = new ArrayList<>();
        // 管道按照装置打一份告知书
        if ("8000".equals(jgInstallationNotice.getEquListCode()) && !equList.isEmpty()) {
            List<Map<String, Object>> informationList = jgInstallationNoticeMapper.queryEquipInformation(equList.get(0).getSequenceNbr());
            if (CollectionUtils.isEmpty(informationList)) {
                throw new IllegalArgumentException("安装告知单不存在");
            }
            Map<String, Object> placeholders = fullFillTemplateObj(informationList, BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName().substring(0, 2));
            maps.add(placeholders);
        } else {
            equList.forEach(equ -> {
                List<Map<String, Object>> informationList = jgInstallationNoticeMapper.queryEquipInformation(equ.getSequenceNbr());
                if (CollectionUtils.isEmpty(informationList)) {
                    throw new IllegalArgumentException("安装告知单不存在");
                }
                Map<String, Object> placeholders = fullFillTemplateObj(informationList, BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName().substring(0, 2));
                maps.add(placeholders);
            });
        }
        JSONObject tagJson = Optional.ofNullable(jgInstallationNotice.getCertificatePrintTag())
                .map(JSONObject::parseObject)
                .orElse(new JSONObject());
        tagJson.put(EXPORT_SUMMARY_TABLE, 2);
        jgInstallationNotice.setCertificatePrintTag(JSONObject.toJSONString(tagJson));
        jgInstallationNoticeMapper.updateById(jgInstallationNotice);
        String tempFileName = "安装告知单_" + System.currentTimeMillis() + "_temp";
//        String url = WordTemplateUtils.templateToPdf(tempFileName, "installation-notification-report.ftl", placeholders);
//
//        // 更新到数据库
//        jgInstallationNotice.setNoticeReportUrl(url);
//        this.updateById(jgInstallationNotice);
        map.put("equipBasicInfoList", maps);
        //将安装告知单和汇总表压缩到zip中 如果是压力/长输/公用管道的情况需要压缩包
        String category = jgInstallationNotice.getEquCategoryCode();
        if ("8300".equals(category) || "8200".equals(category) || "8100".equals(category)) {
            //获取告知单信息
            byte[] templateToPdfData = WordTemplateUtils.getTemplateToPdfData(tempFileName, "installation-notification-report.ftl", map);
            //获取管道和气瓶的基本信息汇总表
            List<CompletableFuture<byte[]>> exportSummaryBasicInfoData = jgUseRegistrationService.getExportSummaryBasicInfoData(Collections.singletonList(Long.valueOf(sequenceNbr)), jgInstallationNotice.getEquCategoryCode(), "安装告知", Boolean.TRUE, null);
            toZipFileByData(response, exportSummaryBasicInfoData, templateToPdfData, jgInstallationNotice.getApplyNo());
        }else {
            WordTemplateUtils.templateToPdfDownload(tempFileName, "installation-notification-report.ftl", map, response);
        }
    }

    /**
     * 将数据全部压缩成zip
     * @param response
     * @param exportSummaryBasicInfoData
     * @param templateToPdfData
     * @param applyNo
     */
    private void toZipFileByData(HttpServletResponse response, List<CompletableFuture<byte[]>> exportSummaryBasicInfoData, byte[] templateToPdfData, String applyNo) {
        String filePrefix ="压力管道基本信息汇总表_";
        String customFileName="压力管道告知单_设备基本信息汇总表_" + applyNo + ".zip";
        // 打包zip
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
             ZipOutputStream zip = new ZipOutputStream(outputStream)) {

            for (int i = 0; i < exportSummaryBasicInfoData.size(); i++) {
                try {
                    zip.putNextEntry(new ZipEntry(filePrefix + "第" + (i + 1) + "页" + ".pdf"));
                    IOUtils.write(exportSummaryBasicInfoData.get(i).join(), zip);
                    zip.closeEntry(); // 每个条目结束后关闭
                } catch (IOException e) {
                    log.error("打包zip失败：" + e.getMessage());
                    throw new BadRequest("打包zip失败");
                }
            }
            //添加安装告知单到zip中
            try {
                String tempFileName = "安装告知单_" + System.currentTimeMillis() + "_temp";
                zip.putNextEntry(new ZipEntry(tempFileName + ".pdf"));
                IOUtils.write(templateToPdfData, zip);
                zip.closeEntry();
            } catch (IOException e) {
                log.error("打包zip失败：" + e.getMessage());
                throw new BadRequest("打包zip失败");
            }
            // 所有条目写入完成后关闭 ZipOutputStream
            zip.finish();
            // 设置响应头并将压缩文件写入 HttpServletResponse
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/zip");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(customFileName, "UTF-8"));
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            IOUtils.write(outputStream.toByteArray(), response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException("导出异常：", e);
        }
    }

    public Map<String, Object> fullFillTemplateObj(List<Map<String, Object>> informationList, String businessType) {
        Map<String, Object> informObj = informationList.get(0);
        String sequenceNbr = String.valueOf(informObj.get("sequenceNbr"));
        String useCode = String.valueOf(informObj.get("installUnitCreditCode"));
        LambdaQueryWrapper<TzBaseUnitLicence> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TzBaseUnitLicence::getUnitCode, useCode);
        // 资质支持多个显示and (certTypeCode = 'xx1' or certTypeCode = 'xx2')
        wrapper.and(w-> {
            String[] certTypeCodes = companyType.split(",");
            for(String certTypeCode: certTypeCodes){
                w.or().eq(TzBaseUnitLicence::getCertTypeCode, certTypeCode);
            }
        });
        wrapper.orderByDesc(TzBaseUnitLicence::getExpiryDate);
        wrapper.orderByDesc(TzBaseUnitLicence::getRecDate);
        // 去重显示3个
        wrapper.groupBy(TzBaseUnitLicence::getCertNo,TzBaseUnitLicence::getExpiryDate);
        wrapper.select(TzBaseUnitLicence::getCertNo,TzBaseUnitLicence::getExpiryDate);
        wrapper.last(" LIMIT 3");
        List<TzBaseUnitLicence> list = baseUnitLicenceMapper.selectList(wrapper);

        ArrayList<String> installLicenseNoList = new ArrayList<>();
        ArrayList<String> installLicenseExpirationDateList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(tzBaseUnitLicence -> {
                // 因模板许可证编号配置最多支持三个，再多样式混乱，目前返回三个
                if (installLicenseNoList.size() < 3) {
                    installLicenseNoList.add(tzBaseUnitLicence.getCertNo());
                    installLicenseExpirationDateList.add(DateUtils.convertDateToString(tzBaseUnitLicence.getExpiryDate(), DateUtils.DATE_PATTERN));
                }
            });
        }

        Function<String, String> getValue = key -> informObj.getOrDefault(key, "").toString();

        // 组装模板变量
        Map<String, Object> placeholders = new HashMap<>();
        placeholders.put("doMain", TZSDOMAIN);
        placeholders.put("equList", getValue.apply("equList"));
        placeholders.put("installUnitName", getValue.apply("installUnitName"));
        placeholders.put("informNumber", getValue.apply("informNumber"));
        placeholders.put("equipCode", getValue.apply("equRegisterCode"));
        placeholders.put("produceUnitName", getValue.apply("produceUnitName"));
        placeholders.put("produceLicenseNum", getValue.apply("produceLicenseNum"));
        placeholders.put("installUnitAddress", getValue.apply("installUnitAddress")); // 施工单位地址
        placeholders.put("installStartDate", getValue.apply("installStartDate"));
        placeholders.put("installType", businessType); // 施工类别
        placeholders.put("installLeaderName", getValue.apply("installLeaderName"));
        placeholders.put("installLeaderPhone", getValue.apply("installLeaderPhone"));
        placeholders.put("fullAddress", getValue.apply("equipProvinceName") + getValue.apply("equipCityName") + getValue.apply("equipCountyName") + getValue.apply("equipStreetName") + getValue.apply("equipAddress"));
        placeholders.put("useUnitName", getValue.apply("useUnitName"));
        placeholders.put("useUnitLeaderName", getValue.apply("safetyManager"));
        placeholders.put("useUnitLeaderPhone", getValue.apply("safetyManagerPhone"));
        placeholders.put("useUnitLeaderAddress", getValue.apply("useUnitLeaderAddress"));
        if ("压力管道".equals(getValue.apply("equList"))) {
            JgRegistrationHistory history = jgRegistrationHistoryMapper.selectOne(new LambdaQueryWrapper<JgRegistrationHistory>().eq(JgRegistrationHistory::getCurrentDocumentId, sequenceNbr));
            JSONObject historyJson = JSON.parseObject(history.getChangeData());
            List<Map<String, Object>> deviceList = (List<Map<String, Object>>) historyJson.get("deviceList");
            List<Object> equipTypeList = deviceList.stream().limit(3).map(item -> item.get("pipelineNumber") + "(" + item.get("nominalDiameter") + "/" + item.get("wallThickness") + "/" + item.get("pipeLength") + ")").collect(Collectors.toList());
            List<Object> factoryNumList = deviceList.stream().limit(3).map(item -> item.get("pipelineNumber")).collect(Collectors.toList());
            placeholders.put("equipTypeList", equipTypeList);
            placeholders.put("produceCodeList", factoryNumList);
            placeholders.put("productName", Optional.ofNullable(historyJson.get("projectContraption")).orElse(historyJson.get("PROJECT_CONTRAPTION")));
        } else {
            placeholders.put("equipType", getValue.apply("equType"));
            placeholders.put("produceCode", getValue.apply("factoryNum"));
            placeholders.put("productName", getValue.apply("productName"));
        }


        // 安装单位许可信息
        placeholders.put("installLicenseNoList", installLicenseNoList);
        placeholders.put("installLicenseExpirationDateList", installLicenseExpirationDateList);

        // 生成二维码
        String qrCode = ImageUtils.generateQRCode(getValue.apply("informNumber"), 300, 300);
        placeholders.put("qrCode", qrCode);
        return placeholders;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public List<JgInstallationNotice> saveNotice(String submitType, JSONObject jgInstallationNoticeDtoMap, ReginParams reginParams) {
        try {
            JgInstallationNoticeDto model = JSON.parseObject(jgInstallationNoticeDtoMap.get(TABLE_PAGE_ID).toString(), JgInstallationNoticeDto.class);
            // 字段转换
            this.convertField(model);

            // 获取告知设备列表
            List<Map<String, Object>> deviceList = model.getDeviceList();
            if (CollectionUtils.isEmpty(deviceList)) {
                throw new BadRequest("设备列表为空");
            }
            // 提交时对设备状态进行校验（处理并发问题，一个未被使用的设备同时被多个使用这打开，同时提交发起申请） todo 回滚异常未写
            if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                this.repeatUsedEquipCheck(deviceList, reginParams.getCompany().getCompanyCode());
            }
            // 获取告知单号
            ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.AZGZ.getCode(), 1);
            if (!ObjectUtils.isEmpty(listResponseModel) && listResponseModel.getStatus() != HttpStatus.OK.value()) {
                log.error("告知单获取失败: {}", listResponseModel.getMessage());
                throw new BadRequest("告知单生成失败！");
            }
            List<String> applyNoList = listResponseModel.getResult();
            if (CollectionUtils.isEmpty(applyNoList)) {
                log.error("告知单返回为空");
                throw new BadRequest("告知单生成失败！");
            }

            // 启动工作流并返回信息
            List<WorkflowResultDto> workflowResultList = workFlowInfo(submitType, deviceList, model.getReceiveOrgCreditCode());

            List<JgInstallationNotice> list = new ArrayList<>();
            List<JgInstallationNoticeEq> equipList = new ArrayList<>();
            // 业务数据组装等
            businessData(submitType, reginParams, model, deviceList, applyNoList, list, equipList, workflowResultList);

            jgInstallationNoticeMapper.insertBatchSomeColumn(list);
            // 如果为保存并提交，则创建代办
            if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                buildTask(list, workflowResultList, Boolean.TRUE);
            } else {
                // 暂存任务
                buildTaskDraft(list);
            }
            List<JgInstallationNoticeEq> jgRelationEquipList = equipList.stream().map(jgRelationEquip -> {
                List<JgInstallationNotice> collect = list.stream().filter(jgInstallationNotice -> jgRelationEquip.getEquipTransferId().equals(jgInstallationNotice.getApplyNo())).collect(Collectors.toList());
                Long sequenceNbr = collect.get(0).getSequenceNbr();
                return jgRelationEquip.setEquipTransferId(String.valueOf(sequenceNbr));
            }).collect(Collectors.toList());
            jgInstallationNoticeEqMapper.insertBatchSomeColumn(jgRelationEquipList);
            this.updateRedisBatch(list);
            return list;
        } catch (BadRequest | LocalBadRequest e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw new BadRequest("保存失败！");
        } finally {
            FlowingEquipRedisContext.clean();
        }
    }

    private void rollBackForDelRedisData() {
        FlowingEquipRedisContext.getContext().forEach(e -> {
            EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_INSTALL_NOTICE_KEY).delDataForCheckWithKey(e.getData(), e.getRedisKey());
        });
    }

    private void repeatUsedEquipCheck(List<Map<String, Object>> equipList, String companyCode) {
        equipList.forEach(equipMap -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_INSTALL_NOTICE_KEY).equipRepeatUsedCheck(!ValidationUtil.isEmpty(equipMap.get("SEQUENCE_NBR")) ? String.valueOf(equipMap.get("SEQUENCE_NBR")) : String.valueOf(equipMap.get("record")), companyCode));
    }

    private void updateRedisBatch(List<JgInstallationNotice> jgInstallationNotices) {
        jgInstallationNotices.stream().filter(n -> StringUtil.isNotEmpty(n.getInstanceId())).forEach(jgInstallationNotice -> {
            commonService.saveExecuteFlowData2Redis(jgInstallationNotice.getInstanceId(), this.buildInstanceRuntimeData(jgInstallationNotice));
        });
    }

    /**
     * 暂存任务生成待办
     *
     * @param list 业务信息
     */
    private void buildTaskDraft(List<JgInstallationNotice> list) {
        List<TaskModelDto> modelDtos = new ArrayList<>();
        list.forEach(obj -> {
            TaskModelDto dto = new TaskModelDto();
            // 行数据
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtils.copyProperties(obj, taskMessageDto);
            dto.setModel(taskMessageDto);
            // 摘要 按原有规则组装
            dto.setTaskContent(String.format("来自%s的业务办理，【申请单号：%s】", obj.getEquList(), obj.getApplyNo()));
            // 申请单号
            dto.setTaskCode(obj.getApplyNo());
            // 业务类型枚举code值
            dto.setTaskType(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getCode());
            ////业务主键
            dto.setRelationId(obj.getSequenceNbr() + "");
            modelDtos.add(dto);
        });
        commonService.buildTaskModel(modelDtos);
    }

    private void buildTask(List<JgInstallationNotice> list, List<WorkflowResultDto> workflowResultList, Boolean isDeleteDraft) {
        List<TaskModelDto> taskModelDtoList = new ArrayList<>();
        WorkflowResultDto workflowResultDto = workflowResultList.get(0);
        list.forEach(item -> {
            TaskModelDto taskModelDto = new TaskModelDto();
            taskModelDto.setFlowCreateDate(item.getCreateDate());
            taskModelDto.setTaskName(workflowResultDto.getNextTaskName()); // 工作流API返回
            taskModelDto.setTaskCode(item.getApplyNo());
            taskModelDto.setTaskType(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getCode());
            taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName());
            taskModelDto.setRelationId(item.getInstanceId());
            taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds()); // 工作流API返回
            taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
            taskModelDto.setFlowStatus(commonService.getDictionaryCodeByName(FlowStatusEnum.TO_BE_PROCESSED.getName())); // 流程状态枚举
            taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
            taskModelDto.setFlowCode(item.getNextTaskId());
            taskModelDto.setStartUserId(item.getCreateUserId());
            taskModelDto.setStartUser(item.getCreateUserName());
            taskModelDto.setStartUserCompanyName(item.getCreateUserCompanyName()); // 任务发起人所在单位
            taskModelDto.setStartDate(item.getCreateDate());
            taskModelDto.setNextExecuteUser(item.getNextExecuteIds());
            taskModelDto.setTaskContent(String.format("来自%s的业务办理，【申请单号：%s】", item.getEquList(), item.getApplyNo()));
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtils.copyProperties(item, taskMessageDto);
            taskModelDto.setModel(taskMessageDto);
            taskModelDtoList.add(taskModelDto);
            if (isDeleteDraft) {
                // 删除暂存时生成的待办
                commonService.deleteTasksByRelationId(item.getSequenceNbr() + "");
            }
        });
        commonService.buildTaskModel(taskModelDtoList);
    }

    private void businessData(String submitType, ReginParams reginParams, JgInstallationNoticeDto model, List<Map<String, Object>> deviceList, List<String> applyNoList, List<JgInstallationNotice> list, List<JgInstallationNoticeEq> equipList, List<WorkflowResultDto> workflowResultList) {
        CompanyBo companyBo = commonService.getOneCompany(model.getReceiveOrgCreditCode());
        JgInstallationNotice dto = new JgInstallationNotice();
        BeanUtils.copyProperties(model, dto);
//            int i = deviceList.indexOf(obj);
        dto.setStartLatitudeLongitude(JSON.toJSONString(model.getStartLatitudeLongitude()));
        dto.setEndLatitudeLongitude(JSON.toJSONString(model.getEndLatitudeLongitude()));
        String applyNo = applyNoList.get(0);
        dto.setApplyNo(applyNo);
        dto.setNoticeDate(new Date());
        // 统计使用
        dto.setReceiveCompanyOrgCode(companyBo.getOrgCode());
        dto.setEquList(Optional.ofNullable(deviceList.get(0).get("EQU_LIST")).map(String::valueOf).orElse(String.valueOf(deviceList.get(0).get("equListName"))));
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            dto.setNextExecuteIds(workflowResultList.get(0).getNextExecutorRoleIds());
            dto.setNextExecuteUserIds(workflowResultList.get(0).getNextExecutorUserIds());
            dto.setInstanceStatus(workflowResultList.get(0).getNextExecutorRoleIds() + "," + workflowResultList.get(0).getExecutorRoleIds());
            dto.setPromoter(reginParams.getUserModel().getUserId());
            dto.setNextTaskId(workflowResultList.get(0).getNextTaskId());
        } else {
            dto.setNextExecuteUserIds(reginParams.getUserModel().getUserId());
        }
        dto.setInstallUnitName(reginParams.getCompany().getCompanyName());
        dto.setInstallUnitCreditCode(reginParams.getCompany().getCompanyCode());
        dto.setEntrustingUnitName(dto.getUseUnitName());
        dto.setCreateUserCompanyName(reginParams.getCompany().getCompanyName());

        if (!CollectionUtils.isEmpty(workflowResultList)) {
            dto.setInstanceId(workflowResultList.get(0).getInstanceId());
            dto.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
        } else {
            dto.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_SUBMITTED.getCode()));
        }
        dto.setCreateUserName(reginParams.getUserModel().getRealName());
        dto.setCreateUserId(reginParams.getUserModel().getUserId());
        list.add(dto);
        deviceList.forEach(obj -> {
            JgInstallationNoticeEq jgRelationEquip = new JgInstallationNoticeEq();
            jgRelationEquip.setEquId(!ValidationUtil.isEmpty(obj.get("SEQUENCE_NBR")) ? String.valueOf(obj.get("SEQUENCE_NBR")) : String.valueOf(obj.get("record")));
            jgRelationEquip.setEquCategoryCode(!ValidationUtil.isEmpty(obj.get("EQU_CATEGORY_CODE")) ? String.valueOf(obj.get("EQU_CATEGORY_CODE")) : String.valueOf(obj.get("equCategory")));
            jgRelationEquip.setEquListCode(!ValidationUtil.isEmpty(obj.get("EQU_LIST_CODE")) ? String.valueOf(obj.get("EQU_LIST_CODE")) : String.valueOf(obj.get("equList")));
            jgRelationEquip.setEquipTransferId(applyNo);
            equipList.add(jgRelationEquip);
        });

    }

    /**
     * 工作流启动并执行
     *
     * @param submitType 是否提交
     * @param deviceList 设备信息
     * @return 工作流返回相关数据
     */
    private List<WorkflowResultDto> workFlowInfo(String submitType, List<Map<String, Object>> deviceList, String receiveOrgCreditCode) {
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
            List<ActWorkflowStartDTO> list = new ArrayList<>();
//            deviceList.forEach(item -> {
            ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
            dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
//                dto.setBusinessKey(item.get("SEQUENCE_NBR").toString());
            dto.setCompleteFirstTask(Boolean.TRUE);
            dto.setNextExecuteUserCompanyCode(receiveOrgCreditCode);
            list.add(dto);
//            });
            actWorkflowBatchDTO.setProcess(list);
            List<ProcessTaskDTO> processTaskDTOS = iCmWorkflowService.startBatch(actWorkflowBatchDTO);
            // 组装工作流返回的数据
            return commonService.buildWorkFlowInfo(processTaskDTOS);
        }
        return new ArrayList<>();
    }


    private void convertField(JgInstallationNoticeDto model) {
        // 处理图片
        if (!ValidationUtil.isEmpty(model.getProxyStatementAttachmentList())) {
            model.setProxyStatementAttachment(JSON.toJSONString(model.getProxyStatementAttachmentList()));
        } else {
            model.setProxyStatementAttachment("");
        }
        if (!ValidationUtil.isEmpty(model.getInstallContractAttachmentList())) {
            model.setInstallContractAttachment(JSON.toJSONString(model.getInstallContractAttachmentList()));
        } else {
            model.setInstallContractAttachment("");
        }
        if (!ValidationUtil.isEmpty(model.getOtherAccessoriesList())) {
            model.setOtherAccessories(JSON.toJSONString(model.getOtherAccessoriesList()));
        } else {
            model.setOtherAccessories("");
        }

        // 分割省市区字段
        String province = model.getProvince();
        if (!ObjectUtils.isEmpty(province)) {
            String[] provinceList = province.split("_");
            if (provinceList.length > 1) {
                model.setProvince(provinceList[0]);
                model.setProvinceName(provinceList[1]);
            }
        }

        String city = model.getCity();
        if (!ObjectUtils.isEmpty(city)) {
            String[] cityList = city.split("_");
            if (cityList.length > 1) {
                model.setCity(cityList[0]);
                model.setCityName(cityList[1]);
            }
        }

        String propertyUnitName = model.getPropertyUnitName();
        if (!ObjectUtils.isEmpty(propertyUnitName)) {
            String[] split = propertyUnitName.split("_");
            if (split.length > 1) {
                model.setPropertyUnitCreditCode(split[0]);
                model.setPropertyUnitName(split[1]);
            }
        }


        String county = model.getCounty();
        if (!ObjectUtils.isEmpty(county)) {
            String[] countyList = county.split("_");
            if (countyList.length > 1) {
                model.setCounty(countyList[0]);
                model.setCountyName(countyList[1]);
            }
        }

        String factoryUseSiteStreet = model.getFactoryUseSiteStreet();
        if (!ObjectUtils.isEmpty(factoryUseSiteStreet)) {
            String[] factoryUseSiteStreetList = factoryUseSiteStreet.split("_");
            if (factoryUseSiteStreetList.length > 1) {
                model.setFactoryUseSiteStreet(factoryUseSiteStreetList[0]);
                model.setStreetName(factoryUseSiteStreetList[1]);
            }
        }

        String branchCodeString = model.getOrgBranchCode();
        if (!ObjectUtils.isEmpty(branchCodeString)) {
            String[] branchCodeStringList = branchCodeString.split("_");
            if (branchCodeStringList.length > 1) {
                model.setOrgBranchCode(branchCodeStringList[0]);
                model.setOrgBranchName(branchCodeStringList[1]);
            }
        }

        // 分割单位
        String useUnitId = model.getUseUnitCreditCode();
        if (!ObjectUtils.isEmpty(useUnitId)) {
            String[] useUnitList = useUnitId.split("_");
            if (useUnitList.length > 1) {
                model.setUseUnitCreditCode(useUnitList[0]);
                model.setUseUnitName(useUnitList[1]);
            }
        }

        String receiveOrgId = model.getReceiveOrgCreditCode();
        if (!ObjectUtils.isEmpty(receiveOrgId)) {
            String[] receiveOrgIdList = receiveOrgId.split("_");
            if (receiveOrgIdList.length > 1) {
                model.setReceiveOrgCreditCode(receiveOrgIdList[0]);
                model.setReceiveOrgName(receiveOrgIdList[1]);
            }
        }

        String inspectUnitId = model.getInspectUnitId();
        if (!ObjectUtils.isEmpty(inspectUnitId)) {
            String[] inspectUnitIdList = inspectUnitId.split("_");
            if (inspectUnitIdList.length > 1) {
                model.setInspectUnitId(inspectUnitIdList[0]);
                model.setInspectUnitName(inspectUnitIdList[1]);
            }
        }

        String installLeaderId = model.getInstallLeaderId();
        if (!ObjectUtils.isEmpty(installLeaderId)) {
            String[] leaderList = installLeaderId.split("_");
            if (leaderList.length > 1) {
                model.setInstallLeaderId(leaderList[0]);
                model.setInstallLeaderName(leaderList[1]);
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void cancel(JgInstallationNoticeDto noticeDto) {
        String instanceId = noticeDto.getInstanceId();
        String nextTaskId = noticeDto.getNextTaskId();
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForRevocationFlow(nextTaskId, instanceId);
            JgInstallationNotice jgInstallationNotice = this.baseMapper.selectById(noticeDto.getSequenceNbr());
            ProcessTaskDTO processTaskDTO = iCmWorkflowService.rollBack(jgInstallationNotice.getInstanceId());
            // 提取节点等信息
            WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
            jgInstallationNotice.setPromoter("");
            jgInstallationNotice.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
            jgInstallationNotice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            jgInstallationNotice.setNoticeStatus(String.valueOf(FlowStatusEnum.ROLLBACK.getCode()));
            jgInstallationNotice.setNextTaskId(workflowResultDto.getNextTaskId());
            this.updateById(jgInstallationNotice);
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtils.copyProperties(jgInstallationNotice, taskMessageDto);
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(taskMessageDto));
            jsonObject.put("taskType", BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getCode());
            jsonObject.put("nextExecuteUser", jgInstallationNotice.getNextExecuteIds());
            jsonObject.put("flowStatusLabel", FlowStatusEnum.ROLLBACK.getName());
            jsonObject.put("flowStatus", FlowStatusEnum.ROLLBACK.getCode());
            jsonObject.put("nextTaskId", jgInstallationNotice.getNextTaskId());
            commonService.rollbackTask(jgInstallationNotice.getInstanceId(), jsonObject);
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgInstallationNotice));
            this.delRepeatUseEquipData(jgInstallationNotice);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 删除 redis校验重复引用设备的数据
     *
     * @param jgInstallationNotice 安装告知entry
     */
    private void delRepeatUseEquipData(JgInstallationNotice jgInstallationNotice) {
        List<String> ids = getEquList(jgInstallationNotice);
        EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_INSTALL_NOTICE_KEY).delDataForCheckEquipRepeatUsed(ids, jgInstallationNotice.getInstallUnitCreditCode());
    }

    private List<String> getEquList(JgInstallationNotice jgInstallationNotice) {
        LambdaQueryWrapper<JgInstallationNoticeEq> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JgInstallationNoticeEq::getEquipTransferId, jgInstallationNotice.getSequenceNbr());
        List<JgInstallationNoticeEq> jgInstallationNoticeEqs = jgInstallationNoticeEqMapper.selectList(queryWrapper);
        return jgInstallationNoticeEqs.stream().map(JgInstallationNoticeEq::getEquId).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 6000000)
    public void accept(JgInstallationNoticeDto dto, String op) {
        String xid = GlobalTransactionContext.getCurrentOrCreate().getXid();
        log.info(xid);
        RootContext.bind(xid);
        String instanceId = dto.getInstanceId();
        String nextTaskId = dto.getNextTaskId();
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForExecuteFlow(nextTaskId, instanceId);

            JgInstallationNotice jgInstallationNotice = this.getById(dto.getSequenceNbr());
            jgInstallationNotice.setProcessAdvice(dto.getProcessAdvice());
            // 组装设备注册代码
            String ym = null;
            try {
                ym = DateUtils.dateFormat(new Date(), DateUtils.DATE_PATTERN_MM);
            } catch (ParseException e) {
                log.error("日期转换失败：{}", e);
            }
            // 执行工作流并返回组装好的工作流信息
            WorkflowResultDto workflowResultDto = getWorkflowResultDto(op, jgInstallationNotice);
            jgInstallationNotice.setPromoter(RequestContext.getExeUserId());
            jgInstallationNotice.setNextTaskId(workflowResultDto.getNextTaskId());
            TaskV2Model taskV2Model = new TaskV2Model();
            if ("0".equals(op)) {
                if (StringUtils.isEmpty(workflowResultDto.getNextExecutorRoleIds())) { // 审批通过
                    LambdaQueryWrapper<JgInstallationNoticeEq> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(JgInstallationNoticeEq::getEquipTransferId, dto.getSequenceNbr());
                    List<JgInstallationNoticeEq> jgRelationEquips = jgInstallationNoticeEqMapper.selectList(queryWrapper);

                    jgInstallationNotice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode()));
                    // 上个代办改为已办
                    HashMap<String, Object> taskMap = new HashMap<>();
                    taskMap.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                    taskMap.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                    taskMap.put("relationId", jgInstallationNotice.getInstanceId());
                    taskMap.put("flowStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                    taskMap.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());

                    TaskMessageDto taskMessageDto = new TaskMessageDto();
                    BeanUtils.copyProperties(jgInstallationNotice, taskMessageDto);
                    taskMap.put("model", taskMessageDto);
                    TaskV2Model taskV2Model1 = commonService.updateTaskModel(taskMap);
                    String finalYm = ym;
                    // 工程装置id
                    String projectContraptionId = jgInstallationNotice.getProjectContraptionId();
                    String equCategoryCode = jgInstallationNotice.getEquCategoryCode();
                    if (PipelineEnum.INDUSTRIAL_PIPELINE.getCode().equals(equCategoryCode)|| PipelineEnum.LONG_DISTANCE_PIPELINE.getCode().equals(equCategoryCode) || PipelineEnum.COMMON_PIPELINE.getCode().equals(equCategoryCode)) {
                        // 处理工业管道审批后业务数据保存
                        this.savePipelineData(jgInstallationNotice, jgRelationEquips, finalYm, dto, taskV2Model1);
                        jgResumeInfoService.saveBatchResume(
                                Lists.newArrayList(JgResumeInfoDto.builder()
                                        .applyNo(jgInstallationNotice.getApplyNo())
                                        .businessType(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName())
                                        .businessId(String.valueOf(jgInstallationNotice.getSequenceNbr()))
                                        .equId(String.valueOf(jgInstallationNotice.getProjectContraptionId()))
                                        .approvalUnit(jgInstallationNotice.getReceiveOrgName())
                                        .approvalUnitCode(jgInstallationNotice.getReceiveOrgCreditCode())
                                        .status("正常")
                                        .routePath(taskV2Model1.getRoutePath())
                                        .build()));
                    } else {
                        jgRelationEquips.forEach(jgRelationEquip -> {
                            LambdaQueryWrapper<OtherInfo> queryWrapper1 = new LambdaQueryWrapper<>();
                            queryWrapper1.eq(OtherInfo::getRecord, jgRelationEquip.getEquId());
                            OtherInfo tzsJgOtherInfo = tzsJgOtherInfoMapper.selectOne(queryWrapper1);
                            IdxBizJgRegisterInfo idxBizJgRegisterInfo = getIdxBizJgRegisterInfo(jgRelationEquip);
                            String equCode = Optional.ofNullable(idxBizJgRegisterInfo.getEquDefine())
                                    .orElse(idxBizJgRegisterInfo.getEquCategory());
                            String registrationCode = equCode + jgInstallationNotice.getReceiveOrgCreditCode() + finalYm;
                            ResponseModel<String> responseModel = tzsServiceFeignClient.deviceRegistrationCode(registrationCode);
                            String deviceRegistrationCode = responseModel.getResult();
                            Map<String, Object> map = new HashMap<>();
                            map.put("cityCode", jgInstallationNotice.getCity());
                            map.put("countyCode", jgInstallationNotice.getCounty());
                            map.put("equCategory", idxBizJgRegisterInfo.getEquCategory());
                            map.put("isXiXian", jgInstallationNotice.getIsXixian() == null ? "null" : jgInstallationNotice.getIsXixian().equals("0") ? "null" : "1");
                            Map<String, Object> mapCode;
                            ResponseModel<Map<String, Object>> code = tzsServiceFeignClient.createCode(map);
                            mapCode = code.getResult();
                            supervisoryCodeInfoMapper.updateStatusBySuperviseCode(mapCode.get("superviseCode").toString());
                            jgInstallationNotice.setHandleDate(new Date());
                            //jgInstallationNotice.setInformNumber(deviceRegistrationCode);
                            jgRelationEquip.setInformNumber(deviceRegistrationCode);
                            jgInstallationNotice.setSupervisoryCode(mapCode.get("superviseCode").toString());
                            jgInstallationNotice.setPromoter("");

                            Map<String, Object> map1 = new HashMap<>();
                            // 更新其他业务表
                            if (!ValidationUtil.isEmpty(mapCode.get("code96333"))) {
                                tzsJgOtherInfo.setCode96333(mapCode.get("code96333").toString());
                                map1.put("CODE96333", tzsJgOtherInfo.getCode96333());
                            }
                            tzsJgOtherInfo.setSupervisoryCode(mapCode.get("superviseCode").toString());
                            tzsJgOtherInfoMapper.updateById(tzsJgOtherInfo);
                            // 更新设备监管部门信息
                            LambdaQueryWrapper<IdxBizJgSupervisionInfo> eq = new QueryWrapper<IdxBizJgSupervisionInfo>().lambda()
                                    .eq(IdxBizJgSupervisionInfo::getRecord, jgRelationEquip.getEquId());
                            IdxBizJgSupervisionInfo idxBizJgSupervisionInfo = idxBizJgSupervisionInfoMapper.selectOne(eq);
                            if (!ObjectUtils.isEmpty(jgInstallationNotice.getOrgBranchCode()) && !ObjectUtils.isEmpty(jgInstallationNotice.getOrgBranchName())) {
                                HashMap<String, Object> parentMessage = (HashMap<String, Object>) Privilege.companyClient.queryByOrgcode(jgInstallationNotice.getOrgBranchCode()).getResult();
                                // 目前平台返回key为compnay(存在拼写错误)
                                CompanyModel parentModel = JSON.parseObject(JSON.toJSONString(parentMessage.get("compnay")), CompanyModel.class);
                                idxBizJgSupervisionInfo.setOrgBranchCode(parentModel.getOrgCode());
                                idxBizJgSupervisionInfo.setOrgBranchName(parentModel.getCompanyName());
                                idxBizJgSupervisionInfo.setCompanyOrgBranchCode(parentModel.getCompanyCode());
                                idxBizJgSupervisionInfoMapper.updateById(idxBizJgSupervisionInfo);
                            }

                            // 生成设备代码及更新历史表的的设备代码字段
                            this.justGenerateEquCode(idxBizJgRegisterInfo, jgInstallationNotice.getReceiveOrgCreditCode(), jgInstallationNotice);
                            tzsJgRegistrationInfoMapper.updateById(idxBizJgRegisterInfo);
                            // 更新es
                            updateEquipEs(jgInstallationNotice, tzsJgOtherInfo, idxBizJgRegisterInfo, idxBizJgSupervisionInfo, map1, dto);
                            // 记录施工信息表
                            createConstruction2Db(jgInstallationNotice, jgRelationEquip);

                            // 更新使用信息
                            updateJgUseInfo(jgInstallationNotice, jgRelationEquip);
                            // 生成证记录表主键
                            long certChangeSeq = sequence.nextId();
                            // 生成jg证书变更记录
                            genJgCertificateChangeRecord(jgInstallationNotice, certChangeSeq, registrationCode, idxBizJgRegisterInfo.getEquCategory(), taskV2Model1);
                            // 查询设备制造信息
                            LambdaQueryWrapper<IdxBizJgFactoryInfo> factoryInfoWrapper = new LambdaQueryWrapper<>();
                            factoryInfoWrapper.eq(IdxBizJgFactoryInfo::getRecord, jgRelationEquip.getEquId());
                            IdxBizJgFactoryInfo idxBizJgFactoryInfo = idxBizJgFactoryInfoService.getOne(factoryInfoWrapper);

                            // 生成tzs_jg_certificate_change_record_eq记录
                            JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
                            changeRecordEq.setChangeRecordId(String.valueOf(certChangeSeq));//登记证记录主键
                            changeRecordEq.setEquId(jgRelationEquip.getEquId());//设备主键
                            changeRecordEq.setProductCode(idxBizJgFactoryInfo.getFactoryNum());
                            certificateChangeRecordEqService.save(changeRecordEq);
                        });
                        jgResumeInfoService.saveBatchResume(
                                jgRelationEquips.stream()
                                        .map(v -> JgResumeInfoDto.builder()
                                                .applyNo(jgInstallationNotice.getApplyNo())
                                                .businessType(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName())
                                                .businessId(String.valueOf(jgInstallationNotice.getSequenceNbr()))
                                                .equId(String.valueOf(v.getEquId()))
                                                .approvalUnit(jgInstallationNotice.getReceiveOrgName())
                                                .approvalUnitCode(jgInstallationNotice.getReceiveOrgCreditCode())
                                                .status("正常")
                                                .routePath(taskV2Model1.getRoutePath())
                                                .build())
                                        .collect(Collectors.toList())
                        );
                    }
                    // 更新关联设备表
                    jgInstallationNoticeEqService.updateBatchById(jgRelationEquips);

                } else {
                    jgInstallationNotice.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
                    jgInstallationNotice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    if (!ObjectUtils.isEmpty(jgInstallationNotice.getInstanceStatus())) {
                        jgInstallationNotice.setInstanceStatus(jgInstallationNotice.getInstanceStatus() + "," + workflowResultDto.getNextExecutorRoleIds());
                    } else {
                        jgInstallationNotice.setInstanceStatus(workflowResultDto.getNextExecutorRoleIds());
                    }
                    jgInstallationNotice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getCode()));
                    // 上个代办改为已办
                    HashMap<String, Object> taskMap = new HashMap<>();
                    taskMap.put("taskStatus", FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    taskMap.put("taskStatusLabel", FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskMap.put("flowStatus", FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    taskMap.put("flowStatusLabel", FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskMap.put("relationId", jgInstallationNotice.getInstanceId());
                    taskV2Model = commonService.updateTaskModel(taskMap);
                    TaskModelDto taskModelDto = new TaskModelDto();
                    BeanUtils.copyProperties(taskV2Model, taskModelDto);
                    // 创建新的代办
                    taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                    taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    taskModelDto.setFlowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
                    taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                    TaskMessageDto taskMessageDto = new TaskMessageDto();
                    BeanUtils.copyProperties(jgInstallationNotice, taskMessageDto);
                    taskModelDto.setModel(taskMessageDto);
                    commonService.buildTaskModel(Collections.singletonList(taskModelDto));
                }
            } else {
                jgInstallationNotice.setPromoter("");
                jgInstallationNotice.setNoticeStatus(String.valueOf(FlowStatusEnum.REJECTED.getCode()));
                // 上个代办改为已办
                HashMap<String, Object> taskMap = new HashMap<>();
                taskMap.put("taskStatus", jgInstallationNotice.getNoticeStatus());
                taskMap.put("taskStatusLabel", FlowStatusEnum.REJECTED.getName());
                taskMap.put("relationId", jgInstallationNotice.getInstanceId());
                taskMap.put("flowStatus", FlowStatusEnum.REJECTED.getCode());
                taskMap.put("flowStatusLabel", FlowStatusEnum.REJECTED.getName());
                taskV2Model = commonService.updateTaskModel(taskMap);
                TaskModelDto taskModelDto = new TaskModelDto();
                BeanUtils.copyProperties(taskV2Model, taskModelDto);
                // 创建新的代办
                taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                taskModelDto.setFlowStatus(FlowStatusEnum.REJECTED.getCode());
                taskModelDto.setFlowStatusLabel(FlowStatusEnum.REJECTED.getName());
                taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
                taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                taskModelDto.setPageType("edit");
                TaskMessageDto taskMessageDto = new TaskMessageDto();
                BeanUtils.copyProperties(jgInstallationNotice, taskMessageDto);
                taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                taskModelDto.setModel(taskMessageDto);
                commonService.buildTaskModel(Collections.singletonList(taskModelDto));
                this.delRepeatUseEquipData(jgInstallationNotice);
            }
            jgInstallationNotice.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            jgInstallationNotice.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
            this.updateById(jgInstallationNotice);
            this.saveHisDataBeforeUpdate(jgInstallationNotice);
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgInstallationNotice));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    private IdxBizJgRegisterInfo getIdxBizJgRegisterInfo(JgInstallationNoticeEq jgRelationEquip) {
        LambdaQueryWrapper<IdxBizJgRegisterInfo> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(IdxBizJgRegisterInfo::getRecord, jgRelationEquip.getEquId());
        return tzsJgRegistrationInfoMapper.selectOne(queryWrapper2);
    }
    private IdxBizJgRegisterInfo getIdxBizJgRegisterInfo2(JgInstallationNoticeEq jgRelationEquip) {
        LambdaQueryWrapper<IdxBizJgRegisterInfo> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(IdxBizJgRegisterInfo::getRecord, jgRelationEquip.getEquId());
        queryWrapper2.select(TzsBaseEntity::getSequenceNbr,IdxBizJgRegisterInfo::getRecord, IdxBizJgRegisterInfo::getEquCodeType);
        return tzsJgRegistrationInfoMapper.selectOne(queryWrapper2);
    }

    private void genJgCertificateChangeRecord(JgInstallationNotice jgInstallationNotice, Long sequenceNbr, String registrationCode, String equCategory, TaskV2Model taskV2Model1) {
        // 生成一条tzs_jg_certificate_change_record记录
        JgCertificateChangeRecord jgCertificateChangeRecord = new JgCertificateChangeRecord();
        jgCertificateChangeRecord.setApplyNo(jgInstallationNotice.getApplyNo());
        jgCertificateChangeRecord.setReceiveOrgName(jgInstallationNotice.getReceiveOrgName());
        jgCertificateChangeRecord.setAuditPassDate(new Date());
        jgCertificateChangeRecord.setRegType(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName());
        jgCertificateChangeRecord.setRegDate(jgInstallationNotice.getInstallStartDate());
        jgCertificateChangeRecord.setChangeContent(this.buildRecordContent(jgInstallationNotice));//变更内容
        jgCertificateChangeRecord.setUseRegistrationCode(registrationCode);//使用登记编号
        jgCertificateChangeRecord.setReceiveCompanyCode(jgInstallationNotice.getReceiveCompanyOrgCode());//接收机构公司代码
        jgCertificateChangeRecord.setCertificateNo("");//登记证书唯一码
        jgCertificateChangeRecord.setUseUnitCreditCode(jgInstallationNotice.getUseUnitCreditCode());//使用单位统一信用代码
        jgCertificateChangeRecord.setUseUnitName(jgInstallationNotice.getUseUnitName());//使用单位名称
        jgCertificateChangeRecord.setEquCategory(equCategory);//设备类别编码
        jgCertificateChangeRecord.setCreateDate(new Date());
        jgCertificateChangeRecord.setRoutePath(taskV2Model1.getRoutePath());
        jgCertificateChangeRecord.setCreateUserId(jgInstallationNotice.getCreateUserId());
        jgCertificateChangeRecord.setSequenceNbr(sequenceNbr);
        certificateChangeRecordService.save(jgCertificateChangeRecord);
    }

    private void createConstruction2Db(JgInstallationNotice jgInstallationNotice, JgInstallationNoticeEq jgRelationEquip) {
        IdxBizJgConstructionInfo idxBizJgConstructionInfo = new IdxBizJgConstructionInfo();
        idxBizJgConstructionInfo.setUscUnitCreditCode(jgInstallationNotice.getInstallUnitCreditCode());
        idxBizJgConstructionInfo.setUscUnitName(jgInstallationNotice.getInstallUnitName());
        idxBizJgConstructionInfo.setUscDate(jgInstallationNotice.getInstallStartDate());
        idxBizJgConstructionInfo.setRecord(jgRelationEquip.getEquId());
        idxBizJgConstructionInfo.setRecDate(new Date());
        idxBizJgConstructionInfo.setRecUserId(RequestContext.getExeUserId());
        idxBizJgConstructionInfo.setNoticeId(jgInstallationNotice.getSequenceNbr() + "");
        // 获取施工类型id
        LambdaQueryWrapper<DataDictionary> lambda = new LambdaQueryWrapper<>();
        lambda.eq(DataDictionary::getType, CONSTRUCTION_TYPE);
        lambda.eq(DataDictionary::getName, CONSTRUCTION_TYPE_NAME);
        List<DataDictionary> dataDictionaries = dataDictionaryMapper.selectList(lambda);
        if (!CollectionUtils.isEmpty(dataDictionaries)) {
            idxBizJgConstructionInfo.setConstructionType(String.valueOf(dataDictionaries.get(0).getSequenceNbr()));
        }
        constructionInfoService.save(idxBizJgConstructionInfo);
    }

    private void updateEquipEs(JgInstallationNotice jgInstallationNotice, OtherInfo tzsJgOtherInfo,
                               IdxBizJgRegisterInfo tzsJgRegistrationInfo, IdxBizJgSupervisionInfo idxBizJgSupervisionInfo,
                               Map<String, Object> map1, JgInstallationNoticeDto dto) {
        Map<String, Map<String, Object>> objMap = new HashMap<>();
        map1.put("EQU_CODE", tzsJgRegistrationInfo.getEquCode());
        map1.put("ORG_BRANCH_CODE", idxBizJgSupervisionInfo.getOrgBranchCode());
        map1.put("ORG_BRANCH_NAME", idxBizJgSupervisionInfo.getOrgBranchName());
        map1.put("SUPERVISORY_CODE", tzsJgOtherInfo.getSupervisoryCode());
        map1.put("USE_UNIT_CREDIT_CODE", jgInstallationNotice.getUseUnitCreditCode());
        map1.put("USE_UNIT_NAME", jgInstallationNotice.getUseUnitName());
        map1.put("IS_INTO_MANAGEMENT", true);
        map1.put("STATUS", "已认领");
        map1.put("USE_PLACE_CODE", dto.getProvince().split("_")[0] + "#" + dto.getCity().split("_")[0] + "#" + dto.getCounty().split("_")[0] + "#" + dto.getFactoryUseSiteStreet().split("_")[0]);
        map1.put("USC_UNIT_CREDIT_CODE", jgInstallationNotice.getInstallUnitCreditCode());
        map1.put("USC_UNIT_NAME", jgInstallationNotice.getInstallUnitName());
        map1.put("USE_PLACE", String.format("%s/%s/%s/%s", jgInstallationNotice.getProvinceName(), jgInstallationNotice.getCityName(), jgInstallationNotice.getCountyName(), jgInstallationNotice.getStreetName()));
        map1.put("ADDRESS", jgInstallationNotice.getAddress());
        objMap.put(tzsJgOtherInfo.getRecord(), map1);
        tzsServiceFeignClient.commonUpdateEsDataByIds(objMap);
    }

    private String buildRecordContent(JgInstallationNotice obj) {
        FeignClientResult<AgencyUserModel> agencyUserModelFeignClientResult = Privilege.agencyUserClient.queryByUserId(obj.getCreateUserId());
        //张三办理了【单位变更】 ，单号【DWBG202407050001】，办理日期2024-07-05
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");

        return  obj.getUseUnitName()+"的"+agencyUserModelFeignClientResult.getResult().getRealName() + "办理了【" + BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName() + "】，单号【"
                + obj.getApplyNo() + "】，申请日期" + simpleDateFormat.format(obj.getCreateDate());
    }

    /**
     * 系统类型的code 自动生成设备代码
     *
     * @param registerInfo       注册信息
     * @param receiveCompanyCode 接收机构行政区划代码
     */
    private void justGenerateEquCode(IdxBizJgRegisterInfo registerInfo, String receiveCompanyCode, JgInstallationNotice jgInstallationNotice) {
        if (EquCodeTypeEnum.SYSTEM_GENERATED.getCode().equals(registerInfo.getEquCodeType())) {
            // 更新注册信息表的设备代码字段
            String equCode = this.getEquCode(registerInfo, receiveCompanyCode);
            registerInfo.setEquCode(equCode);
            //updateHisDataEquCode(registerInfo, jgInstallationNotice, equCode);
        }
    }

    private void updateHisDataEquCode(IdxBizJgRegisterInfo registerInfo, JgInstallationNotice jgInstallationNotice, String equCode) {
        JSONObject his = commonService.queryHistoryData(jgInstallationNotice.getSequenceNbr());
        his.put("equCode", equCode);
        commonService.saveOrUpdateHistory(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName(), new JSONObject(his), registerInfo.getRecord(), jgInstallationNotice.getSequenceNbr().toString());
    }

    public JSONObject getHisData(JgInstallationNotice jgInstallationNotice){
        return commonService.queryHistoryData(jgInstallationNotice.getSequenceNbr());
    }

    private String getEquCode(IdxBizJgRegisterInfo registerInfo, String receiveCompanyCode) {
        ProduceInfo produceInfo = produceInfoMapper.selectOne(new LambdaQueryWrapper<ProduceInfo>().eq(AbstractEquipBaseEntity::getRecord, registerInfo.getRecord()));
        CodeGenerateDto codeGenerateDto = new CodeGenerateDto();
        codeGenerateDto.setEquList(registerInfo.getEquList());
        codeGenerateDto.setEquCategory(registerInfo.getEquCategory());
        codeGenerateDto.setEquDefine(registerInfo.getEquDefine());
        codeGenerateDto.setProduceDate(produceInfo.getProduceDate());
        codeGenerateDto.setReceiveCompanyCode(receiveCompanyCode);
        return codeUtil.generateEquipmentCode(codeGenerateDto);
    }

    private void updateJgUseInfo(JgInstallationNotice jgInstallationNotice, JgInstallationNoticeEq jgRelationEquip) {
        LambdaUpdateWrapper<IdxBizJgUseInfo> lambda = new LambdaUpdateWrapper<>();
        lambda.eq(IdxBizJgUseInfo::getRecord, jgRelationEquip.getEquId());
        IdxBizJgUseInfo idxBizJgUseInfo = new IdxBizJgUseInfo();
        idxBizJgUseInfo.setUseUnitCreditCode(jgInstallationNotice.getUseUnitCreditCode());
        idxBizJgUseInfo.setUseUnitName(jgInstallationNotice.getUseUnitName());
        idxBizJgUseInfo.setProvince(jgInstallationNotice.getProvince());
        idxBizJgUseInfo.setProvinceName(jgInstallationNotice.getProvinceName());
        idxBizJgUseInfo.setCity(jgInstallationNotice.getCity());
        idxBizJgUseInfo.setCityName(jgInstallationNotice.getCityName());
        idxBizJgUseInfo.setCounty(jgInstallationNotice.getCounty());
        idxBizJgUseInfo.setCountyName(jgInstallationNotice.getCountyName());
        idxBizJgUseInfo.setFactoryUseSiteStreet(jgInstallationNotice.getFactoryUseSiteStreet());
        idxBizJgUseInfo.setStreetName(jgInstallationNotice.getStreetName());
        idxBizJgUseInfo.setAddress(jgInstallationNotice.getAddress());
        idxBizJgUseInfo.setIsNotXiXian(jgInstallationNotice.getIsXixian());
        if ("8100".equals(jgInstallationNotice.getEquCategoryCode()) || "8200".equals(jgInstallationNotice.getEquCategoryCode())) {
            idxBizJgUseInfo.setEquState(String.valueOf(EquimentEnum.ZAIYONG.getCode()));
        }
        idxBizJgUseInfo.setEstateUnitCreditCode(jgInstallationNotice.getPropertyUnitCreditCode());
        idxBizJgUseInfo.setEstateUnitName(jgInstallationNotice.getPropertyUnitName());
        idxBizJgUseInfo.setIsIntoManagement(Boolean.TRUE);
        idxBizJgUseInfoMapper.update(idxBizJgUseInfo, lambda);
    }

    public void saveHisDataBeforeUpdate(JgInstallationNotice jgInstallationNotice) {
        LambdaQueryWrapper<JgInstallationNoticeEq> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JgInstallationNoticeEq::getEquipTransferId, jgInstallationNotice.getSequenceNbr());
        List<JgInstallationNoticeEq> jgInstallationNoticeEqs = jgInstallationNoticeEqMapper.selectList(queryWrapper);
        List<String> ids = jgInstallationNoticeEqs.stream().map(JgInstallationNoticeEq::getEquId).collect(Collectors.toList());
        List<Map<String, Object>> equipListMaps;
        String equCategoryCode = jgInstallationNotice.getEquCategoryCode();
        Map<String, Object> installationInfo = BeanUtil.beanToMap(jgInstallationNotice, false, true);
        // 压力管道从工程装置表查询设备信息
        if (PipelineEnum.INDUSTRIAL_PIPELINE.getCode().equals(equCategoryCode)|| PipelineEnum.LONG_DISTANCE_PIPELINE.getCode().equals(equCategoryCode) || PipelineEnum.COMMON_PIPELINE.getCode().equals(equCategoryCode)) {
            String projectContraptionId = jgInstallationNotice.getProjectContraptionId();
            IdxBizJgProjectContraption projectContraption = projectContraptionService.getById(projectContraptionId);
            if (!ValidationUtil.isEmpty(projectContraption)) {
                installationInfo.put("pipelineLength", projectContraption.getPipelineLength());
                installationInfo.put("projectContraptionNo", projectContraption.getProjectContraptionNo());
                installationInfo.put("projectContraption", projectContraption.getProjectContraption());
                // 装置安装告知冗余的装置名称
                LambdaUpdateWrapper<JgInstallationNotice> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(BaseEntity::getSequenceNbr,  jgInstallationNotice.getSequenceNbr());
                updateWrapper.set(JgInstallationNotice::getProjectContraption, projectContraption.getProjectContraption());
                this.update(updateWrapper);
            }
            equipListMaps = jgInstallationNoticeMapper.getPipelineEquInfoByRecords(ids);
        } else {
            Iterable<ESEquipmentCategoryDto> equips = esEquipmentCategory.findAllById(ids);
            equipListMaps = getEquipListMaps(equips);
        }

        installationInfo.put("deviceList", equipListMaps);
        commonService.saveOrUpdateHistory(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName(), new JSONObject(installationInfo), null, jgInstallationNotice.getSequenceNbr().toString());
    }


    private void saveHisDataBeforeUpdate(JgInstallationNotice jgInstallationNotice, String equId) {
        Map<String, Object> map = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(equId);
        commonService.saveOrUpdateHistory(BusinessTypeEnum.JG_INSTALLATION_NOTIFICATION.getName(), new JSONObject(map), equId, jgInstallationNotice.getSequenceNbr().toString());
    }

    public InstanceRuntimeData buildInstanceRuntimeData(JgInstallationNotice jgInstallationNotice) {
        return InstanceRuntimeData.builder()
                .nextExecuteUserIds(jgInstallationNotice.getNextExecuteUserIds())
                .promoter(jgInstallationNotice.getPromoter())
                .nextTaskId(jgInstallationNotice.getNextTaskId())
                .build();
    }


    /**
     * 执行工作流并返回组装好的工作流信息
     *
     * @param op               是否通过
     * @param jgTransferNotice 业务信息  opinion 备注信息
     * @return 返回组装好的工作流信息
     */
    private WorkflowResultDto getWorkflowResultDto(String op, JgInstallationNotice jgTransferNotice) {
        ProcessTaskDTO processTaskDTO = new ProcessTaskDTO();
        WorkflowResultDto workflowResultDto = new WorkflowResultDto();
        // 只调用执行API，返回下个节点信息，用于填充业务字段
        // 组装信息
        TaskResultDTO workDto = new TaskResultDTO();
        workDto.setResultCode("approvalStatus");
        workDto.setTaskId(jgTransferNotice.getNextTaskId());
        HashMap<String, Object> commMap = new HashMap<>();
        if (jgTransferNotice.getNoticeStatus().equals("6614") || jgTransferNotice.getNoticeStatus().equals("6615")) {
            commMap.put("approvalStatus", "提交");
        } else {
            commMap.put("approvalStatus", op);
        }
        commMap.put("approvalStatus", op);
        workDto.setVariable(commMap);
        workDto.setComment(jgTransferNotice.getProcessAdvice());
        workDto.setNextExecuteUserCompanyCode("1".equals(op) ? jgTransferNotice.getInstallUnitCreditCode() : jgTransferNotice.getReceiveOrgCreditCode());
        processTaskDTO = iCmWorkflowService.completeOrReject(jgTransferNotice.getNextTaskId(), workDto, op);
        // 提取节点等信息
        workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
        return workflowResultDto;
    }


    @Override
    public Map<String, Object> getCompanyType() {
        Map<String, Object> result = new HashMap<>();
        result.put("companyType", "");
        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        if (reginParams == null) {
            return null;
        }
        CompanyBo currentCompany = reginParams.getCompany();
        result.put("companyName", currentCompany.getCompanyName());
        result.put("orgCode", currentCompany.getOrgCode());
        result.put("creditCode", currentCompany.getCompanyCode().contains("_") ? currentCompany.getCompanyCode().split("_")[1] : currentCompany.getCompanyCode());
        // 单位级别
        String companyLevel = CompanyTypeEnum.decideCompanyLevel(currentCompany.getCompanyType());
        // 单位类型
        String companyType = CompanyTypeEnum.decideCompanyCode(currentCompany.getCompanyType());
        String companyTypeName = CompanyTypeEnum.decideCompanyType(currentCompany.getCompanyType());
        if (!ValidationUtil.isEmpty(companyLevel)) {
            result.put("companyLevel", companyLevel);
            if (companyLevel.contains(",")) {
                result.put("companyLevel", "testAdmin");
            }
        }
        if (!ValidationUtil.isEmpty(companyType)) {
            result.put("companyType", companyType);
        }
        if (!ValidationUtil.isEmpty(companyTypeName)) {
            result.put("companyTypeName", companyTypeName);
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public JgInstallationNotice cancelApplication(Long sequenceNbr, String cancelReason) {
        // 1.更新为已作废
        JgInstallationNotice installationNotice = this.getById(sequenceNbr);
        String oldNoticeStatus = installationNotice.getNoticeStatus();
        installationNotice.setNoticeStatus(String.valueOf(FlowStatusEnum.TO_BE_DISCARD.getCode()));
        installationNotice.setCancelReason(cancelReason);
        installationNotice.setCancelDate(new Date());
        installationNotice.setCancelUserId(RequestContext.getExeUserId());
        installationNotice.setNextExecuteUserIds(null);
        installationNotice.setPromoter(null);
        this.updateById(installationNotice);
        // 2.更新关联的业务
        this.processElseDataByStatus(Objects.requireNonNull(FlowStatusEnum.getEumByCode(Integer.parseInt(oldNoticeStatus))), installationNotice);
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                eventPublisher.publish(new CancellationEvent(this, getEquList(installationNotice)));
            }
        });
        return installationNotice;
    }


    private void processElseDataByStatus(FlowStatusEnum oldNoticeStatus, JgInstallationNotice installationNotice) {
        switch (oldNoticeStatus) {
            case TO_BE_SUBMITTED: // 待提交
                // 1.写入历史表
                this.saveHisDataBeforeUpdate(installationNotice);
                // 2.删除暂存时生成的待办
                commonService.deleteTasksByRelationId(installationNotice.getSequenceNbr() + "");
                break;
            case TO_BE_FINISHED: // 已完成
                // 1.删除之前完成时同步到一码通的施工信息
                this.deleteConstructionInfo(installationNotice);
                // 2.删除与设备的关系，设备可再次发起安装告知
                this.clearUseInfoOfEquip(installationNotice);
                // 3.清空redis 缓存的流程中及已完成安装告知的设备
                this.delRepeatUseEquipData(installationNotice);
                break;
            default:
                // 流程中（驳回、撤回等）
                // 1.待办任务更新为已完成
                this.finishedTask(installationNotice);
                // 2.终止流程-工作流报错暂时注释掉
                iCmWorkflowService.stopProcess(installationNotice.getInstanceId(), installationNotice.getCancelReason());
                // 3.写入历史表
                this.saveHisDataBeforeUpdate(installationNotice);
                // 4.清空redis（缓存的流程中及已完成安装告知的设备）
                this.delRepeatUseEquipData(installationNotice);
        }
    }

    private void finishedTask(JgInstallationNotice jgInstallationNotice) {
        HashMap<String, Object> taskMap = new HashMap<>();
        taskMap.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
        taskMap.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
        taskMap.put("flowStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
        taskMap.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
        taskMap.put("relationId", jgInstallationNotice.getInstanceId());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        jgInstallationNotice.setProxyStatementAttachment(null);
        jgInstallationNotice.setInstallContractAttachment(null);
        BeanUtils.copyProperties(jgInstallationNotice, taskMessageDto);
        taskMap.put("model", taskMessageDto);
        commonService.updateTaskModel(taskMap);
    }

    private void deleteConstructionInfo(JgInstallationNotice installationNotice) {
        constructionInfoMapper.delete(new LambdaQueryWrapper<IdxBizJgConstructionInfo>().eq(IdxBizJgConstructionInfo::getNoticeId, installationNotice.getSequenceNbr()));
        String equCategoryCode = installationNotice.getEquCategoryCode();
        // 如果设备类型是工业管道，则还需删除工程装置施工信息
        if (PipelineEnum.INDUSTRIAL_PIPELINE.getCode().equals(equCategoryCode)|| PipelineEnum.LONG_DISTANCE_PIPELINE.getCode().equals(equCategoryCode) || PipelineEnum.COMMON_PIPELINE.getCode().equals(equCategoryCode)) {
            LambdaQueryWrapper<IdxBizJgProjectConstruction> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(IdxBizJgProjectConstruction::getNoticeId, installationNotice.getSequenceNbr());
            projectConstructionMapper.delete(queryWrapper);
        }
    }

    private void clearUseInfoOfEquip(JgInstallationNotice installationNotice) {
        LambdaQueryWrapper<JgInstallationNoticeEq> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JgInstallationNoticeEq::getEquipTransferId, installationNotice.getSequenceNbr());
        queryWrapper.select(JgInstallationNoticeEq::getEquipTransferId, BaseEntity::getSequenceNbr,JgInstallationNoticeEq::getEquId);
        List<JgInstallationNoticeEq> jgInstallationNoticeEqs = jgInstallationNoticeEqMapper.selectList(queryWrapper);
        jgInstallationNoticeEqs.forEach(jgRelationEquip -> {
            // 1.use_info      回退
            this.rollBackUseInfo(jgRelationEquip);
            // 2.释放96333码为 未使用状态
            this.release96333Code(jgRelationEquip);
            // 3.other_info    回退
            this.rollBackOtherInfo(jgRelationEquip);
            // 4.supervise_info回退
            this.rollBackSuperviseInfo(jgRelationEquip);
            // 5.设备代码       回退
            IdxBizJgRegisterInfo idxBizJgRegisterInfo = getIdxBizJgRegisterInfo2(jgRelationEquip);
            this.rollBackRegisterInfo(jgRelationEquip, idxBizJgRegisterInfo);
            // 6.es           回退
            this.rollBackEsInfo(jgRelationEquip, idxBizJgRegisterInfo);
        });
        // 如果是工业管道，则回滚工程装置表信息
        String equCategoryCode = installationNotice.getEquCategoryCode();
        if (PipelineEnum.INDUSTRIAL_PIPELINE.getCode().equals(equCategoryCode)|| PipelineEnum.LONG_DISTANCE_PIPELINE.getCode().equals(equCategoryCode) || PipelineEnum.COMMON_PIPELINE.getCode().equals(equCategoryCode)) {
            this.rollBackProjectContraptionInfo(installationNotice);
        }
        //删除设备履历信息
        Set<String> equipTransferIds = jgInstallationNoticeEqs.stream()
                .map(JgInstallationNoticeEq::getEquipTransferId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        if (!equipTransferIds.isEmpty()) {
            jgResumeInfoService.deleteBatchByBusinessId(equipTransferIds);
        }
    }

    /**
     * 回滚工程装置表信息
     * @param installationNotice installationNotice
     */
    private void rollBackProjectContraptionInfo(JgInstallationNotice installationNotice) {
        LambdaUpdateWrapper<IdxBizJgProjectContraption> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(IdxBizJgProjectContraption::getSequenceNbr, installationNotice.getProjectContraptionId()); // 设置更新条件
        // 强制更新字段为 NULL
        updateWrapper.set(IdxBizJgProjectContraption::getUseUnitCreditCode, null);
        updateWrapper.set(IdxBizJgProjectContraption::getUseUnitName, null);
        updateWrapper.set(IdxBizJgProjectContraption::getOrgCode, null);
        updateWrapper.set(IdxBizJgProjectContraption::getOrgName, null);
        updateWrapper.set(IdxBizJgProjectContraption::getUseRegistrationCode, null);
        updateWrapper.set(IdxBizJgProjectContraption::getSupervisoryCode, null);
        updateWrapper.set(IdxBizJgProjectContraption::getEquCode, null);
        updateWrapper.set(IdxBizJgProjectContraption::getIsIntoManagement, false);
        projectContraptionMapper.update(null, updateWrapper);
    }

    /**
     * 释放96333码为未使用状态
     * @param jgRelationEquip jgRelationEquip
     */
    private void release96333Code(JgInstallationNoticeEq jgRelationEquip) {
        Optional.ofNullable(jgRelationEquip)
                .map(JgInstallationNoticeEq::getEquId)
                .map(equId -> tzsJgOtherInfoMapper.selectOne(
                        new LambdaQueryWrapper<OtherInfo>()
                                .eq(OtherInfo::getRecord, equId)
                                .select(OtherInfo::getSupervisoryCode)
                ))
                .map(OtherInfo::getSupervisoryCode)
                .ifPresent(code -> supervisoryCodeInfoMapper.updateStatus(Collections.singletonList(code)));
    }

    private void rollBackEsInfo(JgInstallationNoticeEq jgRelationEquip, IdxBizJgRegisterInfo idxBizJgRegisterInfo) {
        Optional<ESEquipmentCategoryDto> optional = esEquipmentCategory.findById(jgRelationEquip.getEquId());
        if (optional.isPresent()) {
            ESEquipmentCategoryDto esEquipmentCategoryDto = optional.get();
            esEquipmentCategoryDto.setUSE_UNIT_CREDIT_CODE(null);
            esEquipmentCategoryDto.setUSE_UNIT_NAME(null);
            esEquipmentCategoryDto.setORG_BRANCH_CODE(null);
            esEquipmentCategoryDto.setORG_BRANCH_NAME(null);
            esEquipmentCategoryDto.setSUPERVISORY_CODE(null);
            esEquipmentCategoryDto.setCODE96333(null);
            esEquipmentCategoryDto.setUSE_PLACE(null);
            esEquipmentCategoryDto.setUSE_PLACE_CODE(null);
            esEquipmentCategoryDto.setADDRESS(null);
            if (EquCodeTypeEnum.SYSTEM_GENERATED.getCode().equals(idxBizJgRegisterInfo.getEquCodeType())){
                esEquipmentCategoryDto.setEQU_CODE(null);
            }
            esEquipmentCategory.save(esEquipmentCategoryDto);
        }
    }

    private void rollBackRegisterInfo(JgInstallationNoticeEq jgRelationEquip, IdxBizJgRegisterInfo idxBizJgRegisterInfo) {
        if (EquCodeTypeEnum.SYSTEM_GENERATED.getCode().equals(idxBizJgRegisterInfo.getEquCodeType())) {
            // 如果设备代码是系统自动生成，回退注册信息表的设备代码字段
            LambdaUpdateWrapper<IdxBizJgRegisterInfo> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(IdxBizJgRegisterInfo::getRecord, jgRelationEquip.getEquId());
            updateWrapper.set(IdxBizJgRegisterInfo::getEquCode, null);
            tzsJgRegistrationInfoMapper.update(null,updateWrapper);
        }
    }

    private void rollBackSuperviseInfo(JgInstallationNoticeEq jgRelationEquip) {
        LambdaUpdateWrapper<IdxBizJgSupervisionInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(IdxBizJgSupervisionInfo::getRecord, jgRelationEquip.getEquId());
        updateWrapper.set(IdxBizJgSupervisionInfo::getOrgBranchCode, null);
        updateWrapper.set(IdxBizJgSupervisionInfo::getOrgBranchName, null);
        updateWrapper.set(IdxBizJgSupervisionInfo::getCompanyOrgBranchCode, null);
        idxBizJgSupervisionInfoMapper.update(null, updateWrapper);
    }

    private void rollBackOtherInfo(JgInstallationNoticeEq jgRelationEquip) {
        LambdaUpdateWrapper<OtherInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(AbstractEquipBaseEntity::getRecord,jgRelationEquip.getEquId());
        updateWrapper.set(OtherInfo::getCode96333, null);
        updateWrapper.set(OtherInfo::getSupervisoryCode,  null);
        tzsJgOtherInfoMapper.update(null, updateWrapper);
    }

    private void rollBackUseInfo(JgInstallationNoticeEq jgRelationEquip) {
        LambdaUpdateWrapper<IdxBizJgUseInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(IdxBizJgUseInfo::getRecord, jgRelationEquip.getEquId()); // 设置更新条件
        // 强制更新字段为 NULL
        updateWrapper.set(IdxBizJgUseInfo::getUseUnitCreditCode, null);
        updateWrapper.set(IdxBizJgUseInfo::getUseUnitName, null);
        updateWrapper.set(IdxBizJgUseInfo::getProvince, null);
        updateWrapper.set(IdxBizJgUseInfo::getProvinceName, null);
        updateWrapper.set(IdxBizJgUseInfo::getCity, null);
        updateWrapper.set(IdxBizJgUseInfo::getCityName, null);
        updateWrapper.set(IdxBizJgUseInfo::getCounty, null);
        updateWrapper.set(IdxBizJgUseInfo::getCountyName, null);
        updateWrapper.set(IdxBizJgUseInfo::getFactoryUseSiteStreet, null);
        updateWrapper.set(IdxBizJgUseInfo::getStreetName, null);
        updateWrapper.set(IdxBizJgUseInfo::getIsNotXiXian, null);
        updateWrapper.set(IdxBizJgUseInfo::getEstateUnitCreditCode, null);
        updateWrapper.set(IdxBizJgUseInfo::getEstateUnitName, null);
        updateWrapper.set(IdxBizJgUseInfo::getAddress, null);
        useInfoService.update(updateWrapper);
    }


    /**
     * 查询工程装置下的所有未做安装告知、不在安装告知流程、安装告知作废的设备
     *
     * @param projectContraptionSeq 工程装置seq
     * @return 设备列表
     */
    @Override
    public Object getDeviceListByProjectContraption(String projectContraptionSeq) {
        IdxBizJgProjectContraption projectContraption = projectContraptionService.getById(projectContraptionSeq);
        if (ValidationUtil.isEmpty(projectContraption)) {
            return null;
        }
        List<Map<String, Object>> deviceList = projectContraptionService.getBaseMapper().selectEquipList(projectContraptionSeq);
        deviceList.forEach(device -> {
            String deviceLevel = String.valueOf(device.get("deviceLevel"));
            device.put("deviceLevel", dataDictionaryMapper.selectById(deviceLevel).getName());
            device.put("sequenceNbr", projectContraptionSeq);
            device.put("equListName", projectContraption.getEquListName());
        });
        JSONObject result = new JSONObject();
        result.fluentPut("deviceList", deviceList)
                .fluentPut("projectContraption", projectContraption.getProjectContraption())
                .fluentPut("projectContraptionNo", projectContraption.getProjectContraptionNo())
                .fluentPut("pipelineLength", BigDecimal.valueOf(projectContraption.getPipelineLength())
                        .setScale(2, RoundingMode.HALF_UP)
                        .doubleValue())
                .fluentPut("projectContraptionId", projectContraptionSeq);
        if (!ValidationUtil.isEmpty(projectContraption.getCity())) {
            result.fluentPut("city", projectContraption.getCity() + "_" + projectContraption.getCityName());
        }
        if (!ValidationUtil.isEmpty(projectContraption.getCounty())) {
            result.fluentPut("county", projectContraption.getCounty() + "_" + projectContraption.getCountyName());
        }
        if (!ValidationUtil.isEmpty(projectContraption.getStreet())) {
            result.fluentPut("factoryUseSiteStreet", projectContraption.getStreet() + "_" + projectContraption.getStreetName());
        }
        if (!ValidationUtil.isEmpty(projectContraption.getAddress())) {
            result.fluentPut("address", projectContraption.getAddress());
        }
        result.put("equListName", projectContraption.getEquListName());
        result.put("equCategoryName", projectContraption.getEquCategoryName());
        result.put("equDefineName", projectContraption.getEquDefineName());
        return result;
    }

    @Override
    public boolean beforeCheck(JgInstallationNotice notice) {
        return notice.getInstanceId() != null && !notice.getNoticeStatus().equals(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getCode())) &&!notice.getNoticeStatus().equals(String.valueOf(FlowStatusEnum.TO_BE_DISCARD.getCode()));
    }

    @Override
    public void compensate(JgInstallationNotice notice) {
        commonService.saveExecuteFlowData2Redis(notice.getInstanceId(), this.buildInstanceRuntimeData(notice));
    }


    /**
     * 列表数据查询
     * @param ids
     * @return
     */
    public List<InstallationVo> queryInstallationInIds(List<String> ids) {
        List<InstallationVo> installationVos = jgInstallationNoticeMapper.queryInstallationInIds(ids);
        return installationVos.stream().peek(notice -> {
            Optional<String> noticeStatusOpt = Optional.ofNullable(notice.getNoticeStatus());
            noticeStatusOpt.ifPresent(status -> notice.setNoticeStatus(FlowStatusEnum.getNameByType(Long.valueOf(status))));
        }).collect(Collectors.toList());
    }

    private void savePipelineData(JgInstallationNotice jgInstallationNotice, List<JgInstallationNoticeEq> noticeRelationEquips, String finalYm, JgInstallationNoticeDto dto, TaskV2Model taskV2Model1) {
        IdxBizJgProjectContraption projectContraption = projectContraptionService.getById(jgInstallationNotice.getProjectContraptionId());
        // 生成监管码
        Map<String, Object> createCodeMap = new HashMap<>();
        createCodeMap.put("cityCode", jgInstallationNotice.getCity());
        createCodeMap.put("countyCode", jgInstallationNotice.getCounty());
        createCodeMap.put("equCategory", jgInstallationNotice.getEquCategoryCode());
        createCodeMap.put("isXiXian", jgInstallationNotice.getIsXixian() == null ? "null" : jgInstallationNotice.getIsXixian().equals("0") ? "null" : "1");
        ResponseModel<Map<String, Object>> resultModel = tzsServiceFeignClient.createCode(createCodeMap);
        String superviseCode = resultModel.getResult().get("superviseCode").toString();
        supervisoryCodeInfoMapper.updateStatusBySuperviseCode(superviseCode);

        // 生成告知单编号
        String noticeCode = Optional.ofNullable(projectContraption.getEquDefine())
                .orElse(projectContraption.getEquCategory());
        String registrationCode = noticeCode + jgInstallationNotice.getReceiveOrgCreditCode() + finalYm;
        ResponseModel<String> responseModel = tzsServiceFeignClient.deviceRegistrationCode(registrationCode);
        String deviceRegistrationCode = responseModel.getResult();

        // 更新所属监管部门信息
        String orgBranchCode = "";
        String orgBranchName = "";
        String companyCode = "";
        if (!ObjectUtils.isEmpty(jgInstallationNotice.getOrgBranchCode()) && !ObjectUtils.isEmpty(jgInstallationNotice.getOrgBranchName())) {
            HashMap<String, Object> parentMessage = (HashMap<String, Object>) Privilege.companyClient.queryByOrgcode(jgInstallationNotice.getOrgBranchCode()).getResult();
            // 目前平台返回key为compnay(存在拼写错误)
            CompanyModel parentModel = JSON.parseObject(JSON.toJSONString(parentMessage.get("compnay")), CompanyModel.class);
            orgBranchCode = parentModel.getOrgCode();
            orgBranchName = parentModel.getCompanyName();
            companyCode = parentModel.getCompanyCode();
        }

        // 生成设备代码
        String equCode = generateEquCode(projectContraption.getEquList(), projectContraption.getEquCategory(), projectContraption.getEquDefine(), new Date(), jgInstallationNotice.getReceiveOrgCreditCode());

        // 更新工程装置信息
        projectContraption.setEquCode(equCode);
        projectContraption.setSupervisoryCode(superviseCode);
        projectContraption.setOrgCode(orgBranchCode);
        projectContraption.setOrgName(orgBranchName);
        projectContraption.setIsIntoManagement(true);
        projectContraption.setUscUnitCreditCode(jgInstallationNotice.getInstallUnitCreditCode());
        projectContraption.setUscUnitName(jgInstallationNotice.getInstallUnitName());
        projectContraption.setUseUnitName(jgInstallationNotice.getUseUnitName());
        projectContraption.setUseUnitCreditCode(jgInstallationNotice.getUseUnitCreditCode());
        projectContraption.setStartLatitudeLongitude(jgInstallationNotice.getStartLatitudeLongitude());
        projectContraption.setEndLatitudeLongitude(jgInstallationNotice.getEndLatitudeLongitude());
        projectContraption.setProvinceName(jgInstallationNotice.getProvinceName());
        projectContraption.setCityName(jgInstallationNotice.getCityName());
        projectContraption.setCountyName(jgInstallationNotice.getCountyName());
        projectContraption.setStreetName(jgInstallationNotice.getStreetName());
        projectContraption.setProvince(jgInstallationNotice.getProvince());
        projectContraption.setCity(jgInstallationNotice.getCity());
        projectContraption.setCounty(jgInstallationNotice.getCounty());
        projectContraption.setStreet(jgInstallationNotice.getFactoryUseSiteStreet());
        projectContraption.setAddress(jgInstallationNotice.getAddress());
        projectContraptionService.updateById(projectContraption);

        // 更新安装告知业务表信息
        jgInstallationNotice.setHandleDate(new Date());
        jgInstallationNotice.setSupervisoryCode(superviseCode);
        jgInstallationNotice.setPromoter("");

        // 生成证记录表主键
        long certChangeSeq = sequence.nextId();
        // 生成jg证书变更记录
        genJgCertificateChangeRecord(jgInstallationNotice, certChangeSeq, registrationCode, projectContraption.getEquCategory(), taskV2Model1);

        // 生成tzs_jg_certificate_change_record_eq记录
        JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
        changeRecordEq.setChangeRecordId(String.valueOf(certChangeSeq));//登记证记录主键
        changeRecordEq.setEquId(String.valueOf(projectContraption.getSequenceNbr()));//工程装置主键
        certificateChangeRecordEqService.save(changeRecordEq);

        // 更新工程装置下设备信息
        String finalOrgBranchCode = orgBranchCode;
        String finalOrgBranchName = orgBranchName;
        String finalCompanyCode = companyCode;
        noticeRelationEquips.forEach(installationNoticeEq -> {
            LambdaQueryWrapper<OtherInfo> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(OtherInfo::getRecord, installationNoticeEq.getEquId());
            OtherInfo tzsJgOtherInfo = tzsJgOtherInfoMapper.selectOne(queryWrapper1);
            IdxBizJgRegisterInfo idxBizJgRegisterInfo = getIdxBizJgRegisterInfo(installationNoticeEq);

            installationNoticeEq.setInformNumber(deviceRegistrationCode);

            // 更新其他业务表
            tzsJgOtherInfo.setSupervisoryCode(superviseCode); // 工程装置下的管道设备共享监管码
            tzsJgOtherInfoMapper.updateById(tzsJgOtherInfo);

            // 更新设备监管部门信息
            LambdaQueryWrapper<IdxBizJgSupervisionInfo> eq = new QueryWrapper<IdxBizJgSupervisionInfo>().lambda()
                    .eq(IdxBizJgSupervisionInfo::getRecord, installationNoticeEq.getEquId());
            IdxBizJgSupervisionInfo idxBizJgSupervisionInfo = idxBizJgSupervisionInfoMapper.selectOne(eq);
            idxBizJgSupervisionInfo.setOrgBranchCode(finalOrgBranchCode);
            idxBizJgSupervisionInfo.setOrgBranchName(finalOrgBranchName);
            idxBizJgSupervisionInfo.setCompanyOrgBranchCode(finalCompanyCode);
            idxBizJgSupervisionInfoMapper.updateById(idxBizJgSupervisionInfo);

            // 和工程装置共享设备代码
            idxBizJgRegisterInfo.setEquCode(equCode);
            tzsJgRegistrationInfoMapper.updateById(idxBizJgRegisterInfo);

            // 更新es
            updateEquipEs(jgInstallationNotice, tzsJgOtherInfo, idxBizJgRegisterInfo, idxBizJgSupervisionInfo, new HashMap<>(), dto);

            // 记录管道施工信息表
            createConstruction2Db(jgInstallationNotice, installationNoticeEq);

            // 更新使用信息
            updateJgUseInfo(jgInstallationNotice, installationNoticeEq);
        });

        // 记录工程装置施工信息表
        createProjectConstruction2Db(jgInstallationNotice, projectContraption, deviceRegistrationCode, noticeRelationEquips);
    }

    public String generateEquCode(String equListCode, String equCategoryCode, String equDefineCode, Date now, String receiveCompanyCode) {
        CodeGenerateDto codeGenerateDto = new CodeGenerateDto();
        codeGenerateDto.setEquList(equListCode);
        codeGenerateDto.setEquCategory(equCategoryCode);
        codeGenerateDto.setEquDefine(equDefineCode);
        codeGenerateDto.setProduceDate(now);
        codeGenerateDto.setReceiveCompanyCode(receiveCompanyCode);
        return codeUtil.generateEquipmentCode(codeGenerateDto);
    }

    private void createProjectConstruction2Db(JgInstallationNotice jgInstallationNotice, IdxBizJgProjectContraption projectContraption, String deviceRegistrationCode, List<JgInstallationNoticeEq> noticeRelationEquips) {
        IdxBizJgProjectConstruction idxBizJgProjectConstruction = new IdxBizJgProjectConstruction();
        idxBizJgProjectConstruction.setUscUnitCreditCode(jgInstallationNotice.getInstallUnitCreditCode());
        idxBizJgProjectConstruction.setUscUnitName(jgInstallationNotice.getInstallUnitName());
        idxBizJgProjectConstruction.setUscDate(jgInstallationNotice.getInstallStartDate());
        idxBizJgProjectConstruction.setRecord(String.valueOf(projectContraption.getSequenceNbr()));
        idxBizJgProjectConstruction.setSequenceCode(String.valueOf(projectContraption.getSequenceNbr()));
        idxBizJgProjectConstruction.setNoticeId(String.valueOf(jgInstallationNotice.getSequenceNbr()));
        idxBizJgProjectConstruction.setInformCode(deviceRegistrationCode);
        idxBizJgProjectConstruction.setConstructionLeaderId(jgInstallationNotice.getInstallLeaderId());
        idxBizJgProjectConstruction.setConstructionLeaderName(jgInstallationNotice.getInstallLeaderName());
        idxBizJgProjectConstruction.setConstructionLeaderPhone(jgInstallationNotice.getInstallLeaderPhone());
        idxBizJgProjectConstruction.setAddress(jgInstallationNotice.getAddress());
        idxBizJgProjectConstruction.setProvinceName(jgInstallationNotice.getProvinceName());
        idxBizJgProjectConstruction.setCityName(jgInstallationNotice.getCityName());
        idxBizJgProjectConstruction.setCountyName(jgInstallationNotice.getCountyName());
        idxBizJgProjectConstruction.setStreetName(jgInstallationNotice.getStreetName());
        idxBizJgProjectConstruction.setIsXixian(jgInstallationNotice.getIsXixian());
        idxBizJgProjectConstruction.setProjectContraptionId(String.valueOf(projectContraption.getSequenceNbr()));
        idxBizJgProjectConstruction.setEquipRecords(noticeRelationEquips.stream().map(JgInstallationNoticeEq::getEquId).collect(Collectors.joining(",")));
        idxBizJgProjectConstruction.setConstructionContractAttachment(jgInstallationNotice.getInstallContractAttachment());
        idxBizJgProjectConstruction.setProxyStatementAttachment(jgInstallationNotice.getProxyStatementAttachment());
        idxBizJgProjectConstruction.setConstructionOtherAccessories(jgInstallationNotice.getOtherAccessories());
        idxBizJgProjectConstruction.setRecDate(new Date());
        idxBizJgProjectConstruction.setRecUserId(RequestContext.getExeUserId());
        // 获取施工类型id
        LambdaQueryWrapper<DataDictionary> lambda = new LambdaQueryWrapper<>();
        lambda.eq(DataDictionary::getType, CONSTRUCTION_TYPE);
        lambda.eq(DataDictionary::getName, CONSTRUCTION_TYPE_NAME);
        List<DataDictionary> dataDictionaries = dataDictionaryMapper.selectList(lambda);
        if (!CollectionUtils.isEmpty(dataDictionaries)) {
            idxBizJgProjectConstruction.setConstructionType(String.valueOf(dataDictionaries.get(0).getSequenceNbr()));
        }
        projectConstructionMapper.insert(idxBizJgProjectConstruction);
    }
}