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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapBuilder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
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.WorkFlowStatusEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.*;
import com.yeejoin.amos.boot.module.jg.api.service.IJgChangeRegistrationReformService;
import com.yeejoin.amos.boot.module.jg.api.vo.SortVo;
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.edit.permission.FillingEditPermForCurrentUser;
import com.yeejoin.amos.boot.module.jg.biz.edit.process.biz.changeRegistrationReform.ChangeRegisterReformBackupManager;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.*;
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.EquipmentClassifityEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgRegisterInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgTechParamsElevatorMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.InspectionDetectionInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.OtherInfoMapper;
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.systemctl.model.TaskV2Model;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowBatchDTO;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowStartDTO;
import com.yeejoin.amos.feign.workflow.model.ProcessTaskDTO;
import com.yeejoin.amos.feign.workflow.model.TaskResultDTO;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
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.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.yeejoin.amos.boot.module.jg.biz.service.impl.JgUseRegistrationServiceImpl.getAuditPassedDate;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

/**
 * 改造变更登记服务实现类
 *
 * @author system_generator
 * @date 2023-12-20
 */
@Service
@Slf4j
public class JgChangeRegistrationReformServiceImpl extends BaseService<JgChangeRegistrationReformDto, JgChangeRegistrationReform, JgChangeRegistrationReformMapper> implements IJgChangeRegistrationReformService,ICompensateFlowDataOfRedis<JgChangeRegistrationReform> {
    /**
     * 安改维单位名称
     */
    public static final String USC_UNIT_NAME = "USC_UNIT_NAME";
    /**
     * 安改维单位统一信用代码
     */
    public static final String USC_UNIT_CREDIT_CODE = "USC_UNIT_CREDIT_CODE";
    private final List<String> NOT_FLOWING_STATE = Arrays.asList("使用单位待提交", "一级受理已驳回", "使用单位已撤回", "已作废", "已完成");

    private final static String BUSINESS_TYPE = "改造登记";
    private final static String BUSINESS_TYPE_KEY = "changeRegistration";
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    RedisUtils redisUtils;
    @Autowired
    CommonServiceImpl commonServiceImpl;
    @Autowired
    ICmWorkflowService iCmWorkflowService;
    @Autowired
    IIdxBizJgTechParamsElevatorService iIdxBizJgTechParamsElevatorService;
    @Autowired
    IIdxBizJgTechParamsVehicleService iIdxBizJgTechParamsVehicleService;
    @Autowired
    IIdxBizJgTechParamsRopewayService iIdxBizJgTechParamsRopewayService;
    @Autowired
    IIdxBizJgTechParamsRidesService iIdxBizJgTechParamsRidesService;
    @Autowired
    IIdxBizJgTechParamsBoilerService iIdxBizJgTechParamsBoilerService;
    @Autowired
    IIdxBizJgTechParamsVesselService iIdxBizJgTechParamsVesselService;
    @Autowired
    IIdxBizJgTechParamsPipelineService iIdxBizJgTechParamsPipelineService;
    @Autowired
    IIdxBizJgTechParamsLiftingService iIdxBizJgTechParamsLiftingService;
    @Autowired
    private IdxBizJgUseInfoServiceImpl idxBizJgUseInfoService;
    @Autowired
    private IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Autowired
    private IdxBizJgFactoryInfoServiceImpl idxBizJgFactoryInfoService;
    @Autowired
    private OtherInfoMapper otherInfoMapper;
    @Autowired
    private ESEquipmentCategory esEquipmentCategory;
    //改造登记关系表mapper
    @Autowired
    private JgChangeRegistrationReformEqMapper jgChangeRegistrationReformEqMapper;
    //移装登记关系表
    @Autowired
    private JgChangeRegistrationTransferEqMapper jgChangeRegistrationTransferEqMapper;
    @Autowired
    private IdxBizJgTechParamsElevatorMapper idxBizJgTechParamsElevatorMapper;
    @Autowired
    private JgRegistrationHistoryMapper jgRegistrationHistoryMapper;
    //使用登记关系表mapper
    @Autowired
    private JgUseRegistrationEqMapper jgUseRegistrationEqMapper;
    @Autowired
    private IdxBizJgRegisterInfoMapper idxBizJgRegisterInfoMapper;
    //单位变更登记关系表mapper
    @Autowired
    private JgChangeRegistrationUnitEqMapper jgChangeRegistrationUnitEqMapper;
    //更名变更登记关系表mapper
    @Autowired
    private JgChangeRegistrationNameEqMapper jgChangeRegistrationNameEqMapper;

    @Autowired
    private RedissonClient redissonClient;


    @Autowired
    private IdxBizJgRegisterInfoServiceImpl jgRegisterInfoService;

    @Autowired
    private JgUseRegistrationManageServiceImpl jgUseRegistrationManageService;

    @Autowired
    private JgCertificateChangeRecordServiceImpl jgCertificateChangeRecordService;

    @Autowired
    private JgCertificateChangeRecordEqServiceImpl jgCertificateChangeRecordEqService;

    @Autowired
    private SnowflakeIdUtil sequence;

    @Resource
    IdxBizJgProjectContraptionServiceImpl jgProjectContraptionService;
    @Autowired
    private JgChangeRegistrationReformEqServiceImpl jgChangeRegistrationReformEqServiceImpl;

    @Autowired
    private InspectionDetectionInfoMapper inspectionDetectionInfoMapper;
    @Autowired
    private JgRegistrationHistoryServiceImpl jgRegistrationHistoryServiceImpl;

    @Autowired
    private ChangeRegisterReformBackupManager  backupManager;
    @Autowired
    private IdxBizJgTechParamsPipelineServiceImpl idxBizJgTechParamsPipelineServiceImpl;

    /***
     * @deprecated 根据查询调教获取分页对象
     * @param dto 查询的dto对象
     * @param page 分页对象
     * @param roleIds 当前登陆人的角色id值
     * @return
     */
    public Page<Map<String, Object>> getList(JgChangeRegistrationReformDto dto, String sort, Page<Map<String, Object>> page, List<String> roleIds) {
        SortVo sortMap = commonServiceImpl.sortFieldConversion(sort);
        return this.baseMapper.getListPage(page, sortMap, dto, roleIds, RequestContext.getExeUserId());
    }

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

    private void checkForRepeatUsedEquip(JSONObject map, String equId, ReginParams reginParams) {
        CompanyBo company = reginParams.getCompany();
        if (!ObjectUtils.isEmpty(map.get("submit"))) {
            EquipUsedCheckStrategyContext.getUsedStrategy(BUSINESS_TYPE_KEY)
                    .equipRepeatUsedCheck(equId, CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ?
                            company.getCompanyCode().split("_")[1] :
                            company.getCompanyCode());
        }
    }

    private void clearDataForCheckEquipRepeatUsed(JgChangeRegistrationReform data) {
        // 新查询原因 useRegistration 数据状态是旧的
        JgChangeRegistrationReform dbData = this.getById(data.getSequenceNbr());
        LambdaQueryWrapper<JgChangeRegistrationReformEq> lambda = new QueryWrapper<JgChangeRegistrationReformEq>().lambda();
        lambda.eq(JgChangeRegistrationReformEq::getEquipTransferId, data.getSequenceNbr());
        lambda.select(JgChangeRegistrationReformEq::getEquId);
        List<JgChangeRegistrationReformEq> eqList = jgChangeRegistrationReformEqMapper.selectList(lambda);
        // 在使用单位待提交、一级受理已驳回、使用单位已撤回后清除关联的设备，保证可以再次新提单子选择相同的设备进行提交及原有单子的提交校验数据准备
        if (NOT_FLOWING_STATE.contains(dbData.getStatus())) {
            List<String> records = eqList.stream().map(JgChangeRegistrationReformEq::getEquId).collect(toList());
            EquipUsedCheckStrategyContext.getUsedStrategy(BUSINESS_TYPE_KEY)
                    .delDataForCheckEquipRepeatUsed(records, data.getUseUnitCreditCode());
        }
    }

    private void clearDataForCheckEquipRepeatUsed2(JgChangeRegistrationReform data) {
        LambdaQueryWrapper<JgChangeRegistrationReformEq> lambda = new QueryWrapper<JgChangeRegistrationReformEq>().lambda();
        lambda.eq(JgChangeRegistrationReformEq::getEquipTransferId, data.getSequenceNbr());
        lambda.select(JgChangeRegistrationReformEq::getEquId);
        List<JgChangeRegistrationReformEq> eqList = jgChangeRegistrationReformEqMapper.selectList(lambda);
        List<String> records = eqList.stream().map(JgChangeRegistrationReformEq::getEquId).collect(toList());
        EquipUsedCheckStrategyContext.getUsedStrategy(BUSINESS_TYPE_KEY).delDataForCheckEquipRepeatUsed(records, data.getUseUnitCreditCode());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public List<Map<String, Object>> save(JSONObject map) {
        try {
            ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            String companyCode = CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                    reginParams.getCompany().getCompanyCode().split("_")[1] : reginParams.getCompany().getCompanyCode();
            String equListCode = map.getString("EQU_LIST_CODE");
            if(!equListCode.equals(EquipmentClassifityEnum.YLGD.getCode())){
                UseInfo useInfo = new UseInfo();
                String equipId = map.get("record").toString();
                LambdaQueryWrapper<UseInfo> lambda = new QueryWrapper<UseInfo>().lambda();
                lambda.eq(UseInfo::getRecord, equipId);
                // 提交时进行校验设备是否在流程中使用（并发及同时打开多个相同的页面时才会出现此种情况）
                this.checkForRepeatUsedEquip(map, equipId, reginParams);
                // 使用登记信息
                JgChangeRegistrationReform jgChangeRegistrationReform = new JgChangeRegistrationReform();
                LambdaQueryWrapper<OtherInfo> otherLambda = new QueryWrapper<OtherInfo>().lambda();
                otherLambda.eq(OtherInfo::getRecord, equipId);
                OtherInfo otherInfo = otherInfoMapper.selectOne(otherLambda);
                String supervisoryCode = otherInfo.getSupervisoryCode();
                jgChangeRegistrationReform.setSupervisoryCode(supervisoryCode);
                jgChangeRegistrationReform.setUseUnitName(ObjectUtils.isEmpty(useInfo.getUseUnitName()) ? reginParams.getCompany().getCompanyName() : useInfo.getUseUnitName());
                jgChangeRegistrationReform.setUseUnitCreditCode(ObjectUtils.isEmpty(useInfo.getUseUnitCreditCode()) ? companyCode : useInfo.getUseUnitCreditCode());
                setUploadField(map, jgChangeRegistrationReform);
                // 使用单位提交
                jgChangeRegistrationReform.setUseUnitCreditCode(companyCode);
                if (!ObjectUtils.isEmpty(map.get("inspectUnitCreditCode"))) {
                    jgChangeRegistrationReform.setInspectUnitCreditCode(map.get("inspectUnitCreditCode").toString());
                } else {
                    jgChangeRegistrationReform.setInspectUnitCreditCode(companyCode);
                }
                if (!ObjectUtils.isEmpty(map.get("inspectOrgName"))) {
                    jgChangeRegistrationReform.setInspectUnitName(map.get("inspectOrgName").toString());
                } else {
                    jgChangeRegistrationReform.setInspectUnitName(reginParams.getCompany().getCompanyName());
                }
                setReceiveCompanyFields(map, jgChangeRegistrationReform);
                // 统计用
                CompanyBo companyBo = commonServiceImpl.getOneCompany(jgChangeRegistrationReform.getReceiveCompanyCode());
                jgChangeRegistrationReform.setReceiveCompanyOrgCode(companyBo.getOrgCode());
                JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
                //使用登记编号
                jgRegistrationHistory.setUseRegistrationCode(idxBizJgRegisterInfoMapper.getUseOrgCodeByEquip(equipId));
                //登记类别
                jgRegistrationHistory.setRegistrationClass(BUSINESS_TYPE);
                //设备id
                jgRegistrationHistory.setEquId(equipId);
                //修改数据
                jgRegistrationHistory.setChangeData(JSONObject.toJSONString(map));
                //设备监管码
                jgRegistrationHistory.setSupervisoryCode(supervisoryCode);
                // 原始的技术参数，在作废时，需要用来恢复之前的数据使用
                jgRegistrationHistory.setOldData(JSONObject.toJSONString(idxBizJgRegisterInfoService.getEquipParamsMap(equipId, "", getEquListCode(jgRegistrationHistory))));
                //数据状态
                jgChangeRegistrationReform.setUseRegistrationCode(jgRegistrationHistory.getUseRegistrationCode());
                String equipListName = Optional.ofNullable(map.get("equListDesc")).orElse("无").toString();
                jgChangeRegistrationReform.setEquipListName(equipListName);
                jgChangeRegistrationReform.setCreateUserId(reginParams.getUserModel().getUserId());
                jgChangeRegistrationReform.setCreateUserName(reginParams.getUserModel().getRealName());
                jgChangeRegistrationReform.setCreateUserCompanyName(reginParams.getCompany().getCompanyName());
                jgRegistrationHistory.setStatus("new");
                if (map.containsKey("type") && "edit".equals(String.valueOf(map.get("type")))) {
                    jgChangeRegistrationReform.setSequenceNbr(Long.valueOf(String.valueOf(map.get("sequenceNbr"))));
                    this.getBaseMapper().updateById(jgChangeRegistrationReform);
                    jgChangeRegistrationReform = this.getBaseMapper().selectById(jgChangeRegistrationReform.getSequenceNbr());
                    JgChangeRegistrationReformEq jgChangeRegistrationReformEq = jgChangeRegistrationReformEqMapper.selectOne(new QueryWrapper<JgChangeRegistrationReformEq>().eq("equip_transfer_id", jgChangeRegistrationReform.getSequenceNbr()));
                    jgChangeRegistrationReformEq.setEquId(equipId);
                    jgChangeRegistrationReformEqMapper.updateById(jgChangeRegistrationReformEq);
                    jgRegistrationHistory.setSequenceNbr(jgRegistrationHistoryMapper.getSequenceNbrByRegistratioClassAndDocumentId(BUSINESS_TYPE, String.valueOf(map.get("applyNo"))));
                    jgRegistrationHistoryMapper.updateById(jgRegistrationHistory);
                } else {
                    //暂存处理
                    // 业务管理设备信息保存
                    JgChangeRegistrationReformEq jgChangeRegistrationReformEq = new JgChangeRegistrationReformEq();
                    jgChangeRegistrationReformEq.setEquId(equipId);
                    ResponseModel<List<String>> result = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.GZBG.getCode(), 1);
                    if (!result.getResult().isEmpty()) {
                        jgChangeRegistrationReform.setApplyNo(result.getResult().get(0));
                    } else {
                        throw new BadRequest("申请单编号生成失败,请稍后重试!");
                    }
                    jgChangeRegistrationReform.setRegDate(new Date());
                    jgChangeRegistrationReform.setCreateDate(new Date());
                    jgChangeRegistrationReform.setStatus(WorkFlowStatusEnum.CHANGE_SUBMIT.getPass());
                    jgChangeRegistrationReform.setAuditStatus(WorkFlowStatusEnum.CHANGE_SUBMIT.getPass());
                    this.save(jgChangeRegistrationReform);
                    jgChangeRegistrationReformEq.setEquipTransferId(jgChangeRegistrationReform.getSequenceNbr().toString());
                    jgChangeRegistrationReformEqMapper.insert(jgChangeRegistrationReformEq);
                    //当前单据id
                    jgRegistrationHistory.setCurrentDocumentId(jgChangeRegistrationReform.getApplyNo());
                    jgRegistrationHistoryMapper.insert(jgRegistrationHistory);
                    //暂存时生成待办数据
                    List<TaskModelDto> taskModelDtoList = Arrays.asList(getTaskModelDtoList(jgChangeRegistrationReform, null));
                    commonServiceImpl.buildTaskModel(taskModelDtoList);
                }
                if (!ObjectUtils.isEmpty(map.get("submit"))) {
                    String instanceId = "";
                    if (!ObjectUtils.isEmpty(jgChangeRegistrationReform.getSequenceNbr()) && !ObjectUtils.isEmpty(jgChangeRegistrationReform.getInstanceId())) {
                        // 如果是旧流程则执行一步
                        flowExecute(jgChangeRegistrationReform.getSequenceNbr(), jgChangeRegistrationReform.getInstanceId(), "0", "", jgChangeRegistrationReform.getNextTaskId());
                    } else {
                        // 如果是新启动的流程开启自动访问
                        jgChangeRegistrationReform.setAuditStatus(WorkFlowStatusEnum.CHANGE_RECEIVE.getPass());
                        jgChangeRegistrationReform.setStatus(WorkFlowStatusEnum.CHANGE_RECEIVE.getPass());
                        ProcessTaskDTO processTaskDTO = startByVariable(jgChangeRegistrationReform);
                        updateExecuteIds(instanceId, jgChangeRegistrationReform, "startWorkfow", processTaskDTO);
                        List<TaskModelDto> taskModelDtoList = Arrays.asList(getTaskModelDtoList(jgChangeRegistrationReform, processTaskDTO));
                        //启动之前删除暂存生成的待办
                        commonServiceImpl.deleteTasksByRelationId(String.valueOf(jgChangeRegistrationReform.getSequenceNbr()));
                        //重新生成新的待办数据
                        commonServiceImpl.buildTaskModel(taskModelDtoList);
                    }
                }
                return this.getBaseMapper().getDetailById(jgChangeRegistrationReform.getSequenceNbr(), null);
            } else {
                List<Map<String, Object>> equipmentLists = (List<Map<String, Object>>) map.get("equipmentLists");
                if (CollectionUtils.isEmpty(equipmentLists)) {
                    throw new BadRequest("请选择设备信息!");
                }
                // 压力管道变更登记逻辑
                for (Map<String, Object> equip : equipmentLists) {
                    // 提交时进行校验设备是否在流程中使用（并发及同时打开多个相同的页面时才会出现此种情况）
                    checkForRepeatUsedEquip(map, equip.get("record").toString(), reginParams);
                }
                String projectContraptionId = map.getString("projectContraptionId");
                IdxBizJgProjectContraption jgProjectContraption = jgProjectContraptionService.getById(projectContraptionId);
                // 使用登记信息
                JgChangeRegistrationReform jgChangeRegistrationReform = new JgChangeRegistrationReform();
                jgChangeRegistrationReform.setSupervisoryCode(jgProjectContraption.getSupervisoryCode());
                jgChangeRegistrationReform.setUseUnitName(reginParams.getCompany().getCompanyName());
                jgChangeRegistrationReform.setUseUnitCreditCode(companyCode);
                jgChangeRegistrationReform.setProjectContraptionId(projectContraptionId);
                jgChangeRegistrationReform.setProjectContraption(map.getString("projectContraption"));
                setUploadField(map, jgChangeRegistrationReform);
                // 使用单位提交
                jgChangeRegistrationReform.setUseUnitCreditCode(companyCode);
                setReceiveCompanyFields(map, jgChangeRegistrationReform);
                // 统计用
                CompanyBo companyBo = commonServiceImpl.getOneCompany(jgChangeRegistrationReform.getReceiveCompanyCode());
                jgChangeRegistrationReform.setReceiveCompanyOrgCode(companyBo.getOrgCode());
                JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
                //使用登记编号
                jgRegistrationHistory.setUseRegistrationCode(map.getString("useRegistrationCode"));
                //登记类别
                jgRegistrationHistory.setRegistrationClass(BUSINESS_TYPE);
                //设备id
                jgRegistrationHistory.setEquId(jgProjectContraption.getSequenceNbr().toString());
                //修改数据
                jgRegistrationHistory.setChangeData(JSONObject.toJSONString(map));
                //设备监管码
                jgRegistrationHistory.setSupervisoryCode(jgProjectContraption.getSupervisoryCode());
                // 原始的技术参数，在作废时，需要用来恢复之前的数据使用
                jgRegistrationHistory.setOldData(JSONObject.toJSONString(this.getDeviceListByProjectContraption(jgProjectContraption.getSequenceNbr().toString())));
                //数据状态
                jgChangeRegistrationReform.setUseRegistrationCode(map.getString("useRegistrationCode"));
                jgChangeRegistrationReform.setEquipListName("压力管道");
                jgChangeRegistrationReform.setCreateUserId(reginParams.getUserModel().getUserId());
                jgChangeRegistrationReform.setCreateUserName(reginParams.getUserModel().getRealName());
                jgChangeRegistrationReform.setCreateUserCompanyName(reginParams.getCompany().getCompanyName());
                jgRegistrationHistory.setStatus("new");
                // 提交、保存、保存并提交逻辑
                if (map.containsKey("type") && "edit".equals(String.valueOf(map.get("type")))) {
                    jgChangeRegistrationReform.setSequenceNbr(Long.valueOf(String.valueOf(map.get("sequenceNbr"))));
                    this.getBaseMapper().updateById(jgChangeRegistrationReform);
                    jgChangeRegistrationReform = this.getBaseMapper().selectById(jgChangeRegistrationReform.getSequenceNbr());
                    // 1.eq更新【先删除再插入】
                    jgChangeRegistrationReformEqMapper.delete(new LambdaQueryWrapper<JgChangeRegistrationReformEq>().eq(JgChangeRegistrationReformEq::getEquipTransferId, jgChangeRegistrationReform.getSequenceNbr()));
                    saveEqRelation(reginParams, equipmentLists, jgChangeRegistrationReform);
                    // 2.历史表更新
                    jgRegistrationHistory.setSequenceNbr(jgRegistrationHistoryMapper.getSequenceNbrByRegistratioClassAndDocumentId(BUSINESS_TYPE, String.valueOf(map.get("applyNo"))));
                    jgRegistrationHistoryMapper.updateById(jgRegistrationHistory);
                } else {
                    // 新增逻辑
                    // 1.主表保存
                    ResponseModel<List<String>> result = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.GZBG.getCode(), 1);
                    if (!result.getResult().isEmpty()) {
                        jgChangeRegistrationReform.setApplyNo(result.getResult().get(0));
                    } else {
                        throw new BadRequest("申请单编号生成失败,请稍后重试!");
                    }
                    jgChangeRegistrationReform.setRegDate(new Date());
                    jgChangeRegistrationReform.setCreateDate(new Date());
                    jgChangeRegistrationReform.setStatus(WorkFlowStatusEnum.CHANGE_SUBMIT.getPass());
                    jgChangeRegistrationReform.setAuditStatus(WorkFlowStatusEnum.CHANGE_SUBMIT.getPass());
                    this.save(jgChangeRegistrationReform);
                    // 2.关系表保存
                    saveEqRelation(reginParams, equipmentLists, jgChangeRegistrationReform);
                    // 3.历史表保存
                    jgRegistrationHistory.setCurrentDocumentId(jgChangeRegistrationReform.getApplyNo());
                    // 原有汇总表保存 用来来恢复技术参数
                    this.setOldData(jgRegistrationHistory, jgChangeRegistrationReform);
                    jgRegistrationHistoryMapper.insert(jgRegistrationHistory);
                }
                if (!ObjectUtils.isEmpty(map.get("submit"))) {
                    String instanceId = "";
                    if (!ObjectUtils.isEmpty(jgChangeRegistrationReform.getSequenceNbr()) && !ObjectUtils.isEmpty(jgChangeRegistrationReform.getInstanceId())) {
                        // 如果是旧流程则执行一步
                        flowExecute(jgChangeRegistrationReform.getSequenceNbr(), jgChangeRegistrationReform.getInstanceId(), "0", "", jgChangeRegistrationReform.getNextTaskId());
                    } else {
                        // 如果是新启动的流程开启自动访问
                        jgChangeRegistrationReform.setAuditStatus(WorkFlowStatusEnum.CHANGE_RECEIVE.getPass());
                        jgChangeRegistrationReform.setStatus(WorkFlowStatusEnum.CHANGE_RECEIVE.getPass());
                        ProcessTaskDTO processTaskDTO = startByVariable(jgChangeRegistrationReform);
                        updateExecuteIds(instanceId, jgChangeRegistrationReform, "startWorkfow", processTaskDTO);
                        List<TaskModelDto> taskModelDtoList = Collections.singletonList(getTaskModelDtoList(jgChangeRegistrationReform, processTaskDTO));
                        //启动之前删除暂存生成的待办
                        commonServiceImpl.deleteTasksByRelationId(String.valueOf(jgChangeRegistrationReform.getSequenceNbr()));
                        //重新生成新的待办数据
                        commonServiceImpl.buildTaskModel(taskModelDtoList);
                    }
                }
                return this.getBaseMapper().getDetailById(jgChangeRegistrationReform.getSequenceNbr(), "8000");
            }
        } 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 setOldData(JgRegistrationHistory jgRegistrationHistory, JgChangeRegistrationReform jgChangeRegistrationReform) {
        Map<String, Object> detailMap = getDeviceListByProjectContraption(jgChangeRegistrationReform.getProjectContraptionId());
        jgRegistrationHistory.setOldData(JSONObject.toJSONString(detailMap));
    }

    private static void setReceiveCompanyFields(JSONObject map, JgChangeRegistrationReform jgChangeRegistrationReform) {
        if (map.containsKey("receiveCompanyCode")) {
            String receiveCompanyCode = String.valueOf(map.getString("receiveCompanyCode"));
            String[] receiveCompany = receiveCompanyCode.split("_");
            if (!ValidationUtil.isEmpty(receiveCompany)) {
                jgChangeRegistrationReform.setReceiveCompanyCode(receiveCompanyCode.split("_")[0]);
                jgChangeRegistrationReform.setReceiveOrgCode(receiveCompanyCode.split("_")[0]);
                if (receiveCompany.length > 1) {
                    jgChangeRegistrationReform.setReceiveOrgName(receiveCompanyCode.split("_")[1]);
                } else {
                    jgChangeRegistrationReform.setReceiveOrgName(String.valueOf(map.get("receiveOrgName")));
                }
            }

        } else {
            jgChangeRegistrationReform.setReceiveCompanyCode("610000");
        }
    }

    private static void setUploadField(JSONObject map, JgChangeRegistrationReform jgChangeRegistrationReform) {
        if (!ObjectUtils.isEmpty(map.get("otherAccessories"))) {
            jgChangeRegistrationReform.setOtherAccessories(JSONObject.toJSONString(map.get("otherAccessories")));
        }
        if (!ObjectUtils.isEmpty(map.get("transformationQualityCertificate"))) {
            jgChangeRegistrationReform.setTransformationQualityCertificate(JSONObject.toJSONString(map.get("transformationQualityCertificate")));
        }
        if (!ObjectUtils.isEmpty(map.get("renovationSupervisioninspectionCertificate"))) {
            jgChangeRegistrationReform.setRenovationSupervisioninspectionCertificate(JSONObject.toJSONString(map.get("renovationSupervisioninspectionCertificate")));
        }
    }

    private void saveEqRelation(ReginParams reginParams, List<Map<String, Object>> equipmentLists, JgChangeRegistrationReform jgChangeRegistrationReform) {
        List<JgChangeRegistrationReformEq> registrationReformEqs = new ArrayList<>();
        for (Map<String, Object> equip : equipmentLists) {
            String record = equip.get("record").toString();
            JgChangeRegistrationReformEq jgChangeRegistrationReformEq =  new JgChangeRegistrationReformEq();
            jgChangeRegistrationReformEq.setEquId(record);
            jgChangeRegistrationReformEq.setEquipTransferId(jgChangeRegistrationReform.getSequenceNbr().toString());
            jgChangeRegistrationReformEq.setRecUserId(reginParams.getUserModel().getUserId());
            jgChangeRegistrationReformEq.setRecDate(new Date());
            registrationReformEqs.add(jgChangeRegistrationReformEq);
        }
        jgChangeRegistrationReformEqServiceImpl.saveBatch(registrationReformEqs);
    }


    public ProcessTaskDTO startByVariable(JgChangeRegistrationReform jgChangeRegistrationReform) {
        ProcessTaskDTO processTaskDTO = new ProcessTaskDTO();
        //启动流程
        ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
        dto.setProcessDefinitionKey("renovationRegistrationReviewNew");
        dto.setBusinessKey("submit");
        dto.setCompleteFirstTask(Boolean.TRUE);
        dto.setNextExecuteUserCompanyCode(jgChangeRegistrationReform.getReceiveCompanyCode());
        List<ActWorkflowStartDTO> actWorkflowStartDTOList = Arrays.asList(dto);
        ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
        actWorkflowBatchDTO.setProcess(actWorkflowStartDTOList);
        List<ProcessTaskDTO> result = iCmWorkflowService.startBatch(actWorkflowBatchDTO);
        if (!result.isEmpty()) {
            processTaskDTO = result.get(0);
        }
        return processTaskDTO;
    }

    public void updateExecuteIds(String instanceId, JgChangeRegistrationReform jgChangeRegistrationReform, String operate, ProcessTaskDTO processTaskDTO) {
        Boolean updateTodoAndCreate = Boolean.TRUE;
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        WorkflowResultDto workflowResultDto = conveterProcessTaskDTO2WorkflowResultDto(processTaskDTO);
        jgChangeRegistrationReform.setNextExecutorIds(workflowResultDto.getNextExecutorRoleIds());
        jgChangeRegistrationReform.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        String nextTaskId = Optional.ofNullable(workflowResultDto.getNextTaskId()).orElse("");
        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        if (!ObjectUtils.isEmpty(workflowResultDto.getNextTaskCode())) {
            taskCode = Optional.ofNullable(workflowResultDto.getNextTaskCode()).orElse("");
        }
        String role = Optional.ofNullable(workflowResultDto.getNextExecutorRoleIds()).orElse("");
        if (operate.equals("startWorkfow")) {
            role = Optional.ofNullable(workflowResultDto.getExecutorRoleIds()).orElse("") + "," + Optional.ofNullable(workflowResultDto.getNextExecutorRoleIds()).orElse("");
            operate = "0";
            instanceId = workflowResultDto.getInstanceId();
            updateTodoAndCreate = Boolean.FALSE;
        }
        if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
            jgChangeRegistrationReform.setNextTaskId(nextTaskId);
            jgChangeRegistrationReform.setNextExecutorIds(role);
            jgChangeRegistrationReform.setPromoter(reginParams.getUserModel().getUserId());
            jgChangeRegistrationReform.setInstanceId(instanceId);
            if (!ObjectUtils.isEmpty(jgChangeRegistrationReform.getInstanceStatus())) {
                jgChangeRegistrationReform.setInstanceStatus(jgChangeRegistrationReform.getInstanceStatus() + "," + role);
            } else {
                jgChangeRegistrationReform.setInstanceStatus(role);
            }
            if ("0".equals(operate)) {
                // 通过操作
                jgChangeRegistrationReform.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
                jgChangeRegistrationReform.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
            } else {
                // 驳回操作
                jgChangeRegistrationReform.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                jgChangeRegistrationReform.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                jgChangeRegistrationReform.setPromoter("");
            }
            if (updateTodoAndCreate) {
                // 上个代办改为已办
                HashMap<String, Object> map = new HashMap<>();
                if ("0".equals(operate)) {
                    map.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                    map.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                } else {
                    map.put("taskStatus", FlowStatusEnum.REJECTED.getCode());
                    map.put("taskStatusLabel", FlowStatusEnum.REJECTED.getName());
                }
                map.put("flowStatus", commonServiceImpl.getDictionaryCodeByName(jgChangeRegistrationReform.getStatus()));
                map.put("flowStatusLabel", jgChangeRegistrationReform.getStatus());
                map.put("relationId", jgChangeRegistrationReform.getInstanceId());
                TaskV2Model taskV2Model = commonServiceImpl.updateTaskModel(map);
                TaskModelDto taskModelDto = new TaskModelDto();
                BeanUtils.copyProperties(taskV2Model, taskModelDto);
                taskModelDto.setFlowCode(jgChangeRegistrationReform.getNextTaskId());
                taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                if (WorkFlowStatusEnum.CHANGE_SUBMIT.getCode().equals(taskCode) && "1".equals(operate)) {
                    taskModelDto.setPageType("edit");
                }
                // 创建新的代办
                taskModelDto.setModel(conveterTaskMessageDTO(jgChangeRegistrationReform));
                commonServiceImpl.buildTaskModel(Collections.singletonList(taskModelDto));
            }
        } else {
            jgChangeRegistrationReform.setAuditPassDate(new Date());
            jgChangeRegistrationReform.setAuditStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
            jgChangeRegistrationReform.setStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
            jgChangeRegistrationReform.setNextExecuteUserIds("");
            jgChangeRegistrationReform.setNextTaskId(nextTaskId);
            Map<String, Object> map = new HashMap<>();
            map.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
            map.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
            map.put("flowStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
            map.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
            map.put("relationId", jgChangeRegistrationReform.getInstanceId());
            map.put("model", conveterTaskMessageDTO(jgChangeRegistrationReform));
            TaskV2Model taskV2Model = commonServiceImpl.updateTaskModel(map);
            if(!jgChangeRegistrationReform.getEquipListName().equals(EquipmentClassifityEnum.YLGD.getName())){ // 非压力管道逻辑
                JgChangeRegistrationReformEq jgChangeRegistrationReformEq = jgChangeRegistrationReformEqMapper.selectOne(new QueryWrapper<JgChangeRegistrationReformEq>().eq("equip_transfer_id", jgChangeRegistrationReform.getSequenceNbr()));
                updateTechparamsByEquIdAndCurrentDoucumentId(jgChangeRegistrationReformEq.getEquId(), jgChangeRegistrationReform.getSequenceNbr().toString(), null, jgChangeRegistrationReform.getApplyNo());
                // 生成流水信息
                saveRecord(jgChangeRegistrationReformEq.getEquId(), jgChangeRegistrationReform, taskV2Model);
            }  else {                                                                                         // 压力管道逻辑
                // 1.批量更新技术参数
                // 1.1 技术参数更新
                List<IdxBizJgTechParamsPipeline> paramsPipelines = updatePieLineTechAndInspection(jgChangeRegistrationReform);
                // 2.按照装置生成证流水
                saveCertFlowBatch(jgChangeRegistrationReform, paramsPipelines, taskV2Model);
                // 3.清除设备及装置的安改维单位信息
                this.clearUscWithEquipAndCon(jgChangeRegistrationReform);
            }

        }
        // redis流程实时数据更新
        commonServiceImpl.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgChangeRegistrationReform));
        this.getBaseMapper().updateById(jgChangeRegistrationReform);
    }

    /**
     * 审批通过后删除安改维单位信息
     *
     * @param reform
     */
    private void clearUscWithEquipAndCon(JgChangeRegistrationReform reform) {
        // 装置表
        jgProjectContraptionService.lambdaUpdate()
                .eq(IdxBizJgProjectContraption::getSequenceNbr, reform.getProjectContraptionId())
                .set(IdxBizJgProjectContraption::getUscUnitCreditCode, null)
                .set(IdxBizJgProjectContraption::getUscUnitName, null)
                .update();
        // es
        List<JgChangeRegistrationReformEq> reformEqs = jgChangeRegistrationReformEqMapper.selectList(new LambdaQueryWrapper<JgChangeRegistrationReformEq>().eq(JgChangeRegistrationReformEq::getEquipTransferId, reform.getSequenceNbr()));
        reformEqs.forEach(reformEq -> {
            Optional<ESEquipmentCategoryDto> optional = esEquipmentCategory.findById(reformEq.getEquId());
            if (optional.isPresent()) {
                ESEquipmentCategoryDto esEquipmentCategoryDto = optional.get();
                esEquipmentCategoryDto.setUSC_UNIT_NAME(null);
                esEquipmentCategoryDto.setUSC_UNIT_CREDIT_CODE(null);
                esEquipmentCategory.save(esEquipmentCategoryDto);
            }
        });
    }

    private void saveCertFlowBatch(JgChangeRegistrationReform jgChangeRegistrationReform, List<IdxBizJgTechParamsPipeline> paramsPipelines, TaskV2Model taskV2Model) {
        // 1.更新使用登记证信息
        JgUseRegistrationManage jgUseRegistrationManage = jgUseRegistrationManageService.lambdaQuery()
                .eq(JgUseRegistrationManage::getUseRegistrationCode, jgChangeRegistrationReform.getUseRegistrationCode())
                .eq(JgUseRegistrationManage::getIsDelete, 0)
                .one();
        jgUseRegistrationManage.setAuditPassDate(new Date());
        jgUseRegistrationManage.setApplyNo(jgChangeRegistrationReform.getApplyNo());
        jgUseRegistrationManage.setRecDate(new Date());
        jgUseRegistrationManageService.updateById(jgUseRegistrationManage);
        // 2.生成业务流水信息
        JgCertificateChangeRecord jgCertificateChangeRecord = new JgCertificateChangeRecord();
        jgCertificateChangeRecord.setApplyNo(jgChangeRegistrationReform.getApplyNo());
        jgCertificateChangeRecord.setReceiveOrgName(jgChangeRegistrationReform.getReceiveOrgName());
        jgCertificateChangeRecord.setAuditPassDate(new Date());
        jgCertificateChangeRecord.setRegType(BUSINESS_TYPE);
        jgCertificateChangeRecord.setRegDate(jgChangeRegistrationReform.getCreateDate());
        FeignClientResult<AgencyUserModel> agencyUserModelFeignClientResult = Privilege.agencyUserClient.queryByUserId(jgChangeRegistrationReform.getCreateUserId());
        jgCertificateChangeRecord.setChangeContent(jgChangeRegistrationReform.getUseUnitName()+"的"+agencyUserModelFeignClientResult.getResult().getRealName() +"办理了【" + BUSINESS_TYPE + "】," + "单号【" + jgChangeRegistrationReform.getApplyNo() +
                "】" + ",办理日期" + DateUtil.format(jgChangeRegistrationReform.getAuditPassDate(),DatePattern.NORM_DATE_PATTERN));
        jgCertificateChangeRecord.setRecUserId(jgChangeRegistrationReform.getRecUserId());
        jgCertificateChangeRecord.setRecDate(new Date());
        jgCertificateChangeRecord.setCreateDate(new Date());
        jgCertificateChangeRecord.setCreateUserId(jgChangeRegistrationReform.getCreateUserId());
        jgCertificateChangeRecord.setUseRegistrationCode(jgChangeRegistrationReform.getUseRegistrationCode());
        jgCertificateChangeRecord.setCertificateNo(jgUseRegistrationManage.getCertificateNo());
        jgCertificateChangeRecord.setUseUnitCreditCode(jgChangeRegistrationReform.getUseUnitCreditCode());
        jgCertificateChangeRecord.setUseUnitName(jgChangeRegistrationReform.getUseUnitName());
        jgCertificateChangeRecord.setEquCategory("8300");
        jgCertificateChangeRecord.setReceiveCompanyCode(jgChangeRegistrationReform.getReceiveOrgCode());
        jgCertificateChangeRecord.setRoutePath(taskV2Model.getRoutePath());
        // 保存证流水信息
        jgCertificateChangeRecordService.save(jgCertificateChangeRecord);
        List<JgCertificateChangeRecordEq> changeRecordEqs = paramsPipelines.stream().map(p->{
            JgCertificateChangeRecordEq jgCertificateChangeRecordEq = new JgCertificateChangeRecordEq();
            jgCertificateChangeRecordEq.setEquId(p.getRecord());
            jgCertificateChangeRecordEq.setChangeRecordId(jgCertificateChangeRecord.getSequenceNbr().toString());
            return jgCertificateChangeRecordEq;
        }).collect(toList());
        // 生成设备流水信息
        jgCertificateChangeRecordEqService.saveBatch(changeRecordEqs);
    }

    public JSONObject getHisData(String applyNo){
        return commonServiceImpl.queryHistoryData(applyNo);
    }

    /**
     * 管道的技术参数及检验信息更新
     * @param jgChangeRegistrationReform 改造变更登记单据
     * @return 更新的管道信息
     */
    private List<IdxBizJgTechParamsPipeline> updatePieLineTechAndInspection(JgChangeRegistrationReform jgChangeRegistrationReform) {
        JSONObject hisData = commonServiceImpl.queryHistoryData(jgChangeRegistrationReform.getApplyNo());
        JSONArray piePines = hisData.getJSONArray("equipmentLists");
        List<IdxBizJgTechParamsPipeline> paramsPipelines =  new ArrayList<>();
        for(int i = 0; i < piePines.size(); i++){
            JSONObject item = piePines.getJSONObject(i);
            IdxBizJgTechParamsPipeline pipeline = new IdxBizJgTechParamsPipeline();
            pipeline.setMedium(item.getString("medium"));
            pipeline.setPressure(item.getString("pressure"));
            pipeline.setNominalDiameter(item.getString("nominalDiameter"));
            pipeline.setTemperature(item.getString("temperature"));
            pipeline.setWallThickness(item.getString("wallThickness"));
            pipeline.setWorkMedium(item.getString("workMedium"));
            pipeline.setWorkPressure(item.getString("workPressure"));
            pipeline.setWorkTemperature(item.getString("workTemperature"));
            pipeline.setPipeLength(item.getString("pipeLength"));
            LambdaUpdateWrapper<IdxBizJgTechParamsPipeline>  updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(IdxBizJgTechParamsPipeline::getRecord, item.getString("record"));
            // 技术参数更新
            iIdxBizJgTechParamsPipelineService.update(pipeline, updateWrapper);
            pipeline.setRecord(String.valueOf(item.getString("record")));
            // 检验信息更新或者插入及记录原始数据用来作废时恢复数据用
            updateOrCreateInspectionDetection(item, jgChangeRegistrationReform);
            paramsPipelines.add(pipeline);
            // 更新注册信息表的使用登记证
            LambdaUpdateWrapper<IdxBizJgRegisterInfo> registerInfoLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            registerInfoLambdaUpdateWrapper.eq(IdxBizJgRegisterInfo::getRecord, item.getString("record"));
            registerInfoLambdaUpdateWrapper.set(IdxBizJgRegisterInfo::getUseOrgCode, jgChangeRegistrationReform.getUseRegistrationCode());
            idxBizJgRegisterInfoService.update(registerInfoLambdaUpdateWrapper);
            // 更新使用信息表的纳管状态
            LambdaUpdateWrapper<IdxBizJgUseInfo> useInfoLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            useInfoLambdaUpdateWrapper.eq(IdxBizJgUseInfo::getRecord, item.getString("record"));
            useInfoLambdaUpdateWrapper.set(IdxBizJgUseInfo::getIsIntoManagement, true);
            idxBizJgUseInfoService.update(useInfoLambdaUpdateWrapper);
        }
        return paramsPipelines;
    }

    public void saveRecord(String equipId, JgChangeRegistrationReform jgChangeRegistrationReform, TaskV2Model taskV2Model) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryMapper.selectOne(new QueryWrapper<JgRegistrationHistory>()
//                .eq("equ_id", equipId)
                .eq("current_document_id", jgChangeRegistrationReform.getApplyNo())
                .eq("registration_class", BUSINESS_TYPE));

        JSONObject object = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
        // 更新使用登记证信息
        JgUseRegistrationManage useRegistrationCode = jgUseRegistrationManageService.lambdaQuery()
                .eq(JgUseRegistrationManage::getUseRegistrationCode, object.get("useRegistrationCode"))
                .eq(JgUseRegistrationManage::getIsDelete, 0)
                .one();
        useRegistrationCode.setAuditPassDate(new Date());
        jgUseRegistrationManageService.updateById(useRegistrationCode);
        // 生成业务流水信息
        JgCertificateChangeRecord jgCertificateChangeRecord = new JgCertificateChangeRecord();
        jgCertificateChangeRecord.setApplyNo(jgChangeRegistrationReform.getApplyNo());
        jgCertificateChangeRecord.setReceiveOrgName(jgChangeRegistrationReform.getReceiveOrgName());
        jgCertificateChangeRecord.setAuditPassDate(new Date());
        jgCertificateChangeRecord.setRegType(BUSINESS_TYPE);
        jgCertificateChangeRecord.setRegDate(jgChangeRegistrationReform.getCreateDate());
        FeignClientResult<AgencyUserModel> agencyUserModelFeignClientResult = Privilege.agencyUserClient.queryByUserId(jgChangeRegistrationReform.getCreateUserId());
        jgCertificateChangeRecord.setChangeContent(jgChangeRegistrationReform.getUseUnitName()+"的"+agencyUserModelFeignClientResult.getResult().getRealName() +"办理了【" + BUSINESS_TYPE + "】," + "单号【" + jgChangeRegistrationReform.getApplyNo() +
                "】" + ",办理日期" + sdf.format(jgChangeRegistrationReform.getAuditPassDate()));
        jgCertificateChangeRecord.setRecUserId(jgChangeRegistrationReform.getRecUserId());
        jgCertificateChangeRecord.setRecDate(new Date());
        jgCertificateChangeRecord.setCreateDate(new Date());
        jgCertificateChangeRecord.setCreateUserId(jgChangeRegistrationReform.getCreateUserId());
        jgCertificateChangeRecord.setUseRegistrationCode(!ObjectUtils.isEmpty(object.get("useRegistrationCode")) ? object.get("useRegistrationCode").toString() : null);
        jgCertificateChangeRecord.setCertificateNo(useRegistrationCode.getCertificateNo());
        jgCertificateChangeRecord.setUseUnitCreditCode(jgChangeRegistrationReform.getUseUnitCreditCode());
        jgCertificateChangeRecord.setUseUnitName(jgChangeRegistrationReform.getUseUnitName());
        jgCertificateChangeRecord.setEquCategory(!ObjectUtils.isEmpty(object.get("equCategory")) ? object.get("equCategory").toString() : null);
        jgCertificateChangeRecord.setReceiveCompanyCode(jgChangeRegistrationReform.getReceiveOrgCode());
        jgCertificateChangeRecord.setRoutePath(taskV2Model.getRoutePath());
        // 保存证流水信息
        jgCertificateChangeRecordService.save(jgCertificateChangeRecord);
        // 生成设备流水信息
        JgCertificateChangeRecordEq jgCertificateChangeRecordEq = new JgCertificateChangeRecordEq();
        jgCertificateChangeRecordEq.setEquId(!ObjectUtils.isEmpty(object.get("record")) ? object.get("record").toString() : null);
        jgCertificateChangeRecordEq.setChangeRecordId(jgCertificateChangeRecord.getSequenceNbr().toString());
        jgCertificateChangeRecordEq.setProductCode(!ObjectUtils.isEmpty(object.get("factoryNum")) ? object.get("factoryNum").toString() : null);
        jgCertificateChangeRecordEqService.save(jgCertificateChangeRecordEq);
    }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void flowExecute(Long id, String instanceId, String operate, String comment, String nextTaskId) {
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonServiceImpl.checkForExecuteFlow(nextTaskId, instanceId);
            ProcessTaskDTO processTaskDTO;
            JgChangeRegistrationReform jgChangeRegistrationReform = this.getBaseMapper().selectById(id);
            String taskId = jgChangeRegistrationReform.getNextTaskId();
            //组装信息
            TaskResultDTO dto = new TaskResultDTO();
            dto.setResultCode("approvalStatus");
            dto.setTaskId(taskId);
            dto.setComment(comment);
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", operate);
            //2023年12月27日16点33分 流程状态为起草人撤回或者一级审批驳回时需要将提交时的已同意修改为已提交
            if (!ObjectUtils.isEmpty(jgChangeRegistrationReform) && (jgChangeRegistrationReform.getStatus().equals(WorkFlowStatusEnum.CHANGE_SUBMIT.getRollBack()) || jgChangeRegistrationReform.getStatus().equals(WorkFlowStatusEnum.CHANGE_SUBMIT.getReject()))) {
                map.put("approvalStatus", "提交");
            }
            dto.setVariable(map);
            dto.setNextExecuteUserCompanyCode(getNextUserOrgCode(operate, jgChangeRegistrationReform));
            //执行流程
            processTaskDTO = iCmWorkflowService.completeOrReject(taskId, dto, operate);
            // 更新下一步执行人
            updateExecuteIds(instanceId, jgChangeRegistrationReform, operate, processTaskDTO);
            this.clearDataForCheckEquipRepeatUsed(jgChangeRegistrationReform);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void withdraw(String instanceId, String nextTaskId) {
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonServiceImpl.checkForRevocationFlow(nextTaskId, instanceId);
            ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            JgChangeRegistrationReform jgChangeRegistrationReform = this.getBaseMapper().selectOne(new QueryWrapper<JgChangeRegistrationReform>().eq("instance_id", instanceId));
            ProcessTaskDTO processTaskDTO = iCmWorkflowService.rollBack(instanceId);
            WorkflowResultDto workflowResultDto = conveterProcessTaskDTO2WorkflowResultDto(processTaskDTO);
            String taskCode = Optional.ofNullable(workflowResultDto.getNextTaskCode()).orElse("");
            String role = Optional.ofNullable(workflowResultDto.getNextExecutorRoleIds()).orElse("");
            if (!ObjectUtils.isEmpty(taskCode)) {
                jgChangeRegistrationReform.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getRollBack());
                jgChangeRegistrationReform.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getRollBack());
            }
            jgChangeRegistrationReform.setPromoter(reginParams.getUserModel().getUserId());
            jgChangeRegistrationReform.setNextTaskId(workflowResultDto.getNextTaskId());
            jgChangeRegistrationReform.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            jgChangeRegistrationReform.setNextExecutorIds(role);
            this.getBaseMapper().updateById(jgChangeRegistrationReform);
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(jgChangeRegistrationReform));
            jsonObject.put("flowStatus", commonServiceImpl.getDictionaryCodeByName(jgChangeRegistrationReform.getAuditStatus()));
            jsonObject.put("flowStatusLabel", jgChangeRegistrationReform.getAuditStatus());
            jsonObject.put("nextTaskId", jgChangeRegistrationReform.getNextTaskId());
            jsonObject.put("nextExecuteUser", jgChangeRegistrationReform.getNextExecutorIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_RENOVATION_REGISTRATION.getCode());
            jsonObject.put("pageType", "look");
            //如果创建人等于当前人则打开编辑页面
            if (taskCode.equals(WorkFlowStatusEnum.CHANGE_SUBMIT.getCode())) {
                jsonObject.put("pageType", "edit");
            }
            jsonObject.put("model", conveterTaskMessageDTO(jgChangeRegistrationReform));
            commonServiceImpl.rollbackTask(instanceId, jsonObject);
            // redis流程实时数据更新
            commonServiceImpl.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgChangeRegistrationReform));
            this.clearDataForCheckEquipRepeatUsed(jgChangeRegistrationReform);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void deleteBatch(List<Long> ids) {
        // 删除暂存的待办
        ids.forEach(id -> {
            JgChangeRegistrationReform registrationReform = this.baseMapper.selectById(id);
            // 删除代办 + 流程流程
            commonServiceImpl.deleteTaskModel(String.valueOf(id), registrationReform.getInstanceId());
            // 删除单子
            this.baseMapper.deleteById(id);
            // 删除单子对应eq
            jgChangeRegistrationReformEqMapper.delete(new LambdaQueryWrapper<JgChangeRegistrationReformEq>()
                    .eq(JgChangeRegistrationReformEq::getEquipTransferId, id));
            // 删除单子对应历史表数据
            jgRegistrationHistoryMapper.delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getCurrentDocumentId, registrationReform.getApplyNo()));
        });
    }

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

    @Override
    public Map<String, Object> getDetail(String currentDocumentId, String equipId, CompanyBo companyBo) {
        JgChangeRegistrationReform jgChangeRegistrationReform = this.getBaseMapper().selectById(currentDocumentId);
        this.doCompensate(jgChangeRegistrationReform);
        Map<String, Object> detail = new HashMap<>();
        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryMapper.selectOne(new QueryWrapper<JgRegistrationHistory>()
                .eq("current_document_id", jgChangeRegistrationReform.getApplyNo())
                .eq("registration_class", BUSINESS_TYPE));
        Map<String, Object> originalData = JSONObject.parseObject(jgRegistrationHistory.getChangeData(), Map.class);
        detail.putAll(originalData);
        jgChangeRegistrationReform.setReceiveCompanyCode(jgChangeRegistrationReform.getReceiveOrgCode() + "_" + jgChangeRegistrationReform.getReceiveOrgName());
        detail.putAll(JSONObject.parseObject(JSONObject.toJSONString(jgChangeRegistrationReform), Map.class));
        if(jgChangeRegistrationReform.getCancelDate() != null){
            detail.put("cancelDate", DateUtil.format(jgChangeRegistrationReform.getCancelDate(), DatePattern.NORM_DATETIME_PATTERN));
        }
        if (!ObjectUtils.isEmpty(detail.get("transformationQualityCertificate"))) {
            detail.put("transformationQualityCertificate", JSONObject.parse(detail.get("transformationQualityCertificate").toString()));
        }
        if (!ObjectUtils.isEmpty(detail.get("renovationSupervisioninspectionCertificate"))) {
            detail.put("renovationSupervisioninspectionCertificate", JSONObject.parse(detail.get("renovationSupervisioninspectionCertificate").toString()));
        }
        if (!ObjectUtils.isEmpty(detail.get("otherAccessories"))) {
            detail.put("otherAccessories", JSONObject.parse(detail.get("otherAccessories").toString()));
        }
        detail.remove("submit");
        detail.remove("instanceId");
        this.fillingEquCategoryNameForHisData(detail, jgChangeRegistrationReform);
        // 设置登录人公司类型区分监管还是企业及编辑权限
        return new FillingEditPermForCurrentUser(new JSONObject(detail),companyBo, BusinessTypeEnum.JG_RENOVATION_REGISTRATION).getData();
    }


    /**
     * 批量设置设备无效(使用登记、移装登记、改造登记)
     *
     * @param equipmentId       装备id
     * @param currentDocumentId 当前文档id
     */
    public void makeEquipmentsInvalid(String equipmentId, String currentDocumentId) {
        jgChangeRegistrationReformEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equipmentId, currentDocumentId);
        jgChangeRegistrationTransferEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equipmentId, currentDocumentId);
        jgUseRegistrationEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equipmentId, currentDocumentId);
        //单位变更登记
        jgChangeRegistrationUnitEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equipmentId, currentDocumentId);
        //更名变更登记
        jgChangeRegistrationNameEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equipmentId, currentDocumentId);
    }

    /**
     * 流程完成之后互换数据并更新设备状态
     *
     * @param equipId
     * @param currentDocumentId
     */
    public void updateTechparamsByEquIdAndCurrentDoucumentId(String equipId, String currentDocumentId, String newUseRegistrationCertificateNumber, String applyNo) {

        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryMapper.selectOne(new QueryWrapper<JgRegistrationHistory>()
                .eq("equ_id", equipId)
                .eq("current_document_id", applyNo)
                .eq("registration_class", BUSINESS_TYPE));

        if (!ObjectUtils.isEmpty(jgRegistrationHistory)) {
            //当前数据
            String newData = jgRegistrationHistory.getChangeData();
            //将历史数据更新到技术参数表中
            JSONObject allData = JSONObject.parseObject(newData);
            Map<String, Object> techInfo = (Map<String, Object>) allData.get("techInfo");
            String equList = techInfo.get("EQU_LIST").toString();
            //电梯
            if (EquipmentClassifityEnum.DT.getCode().equals(equList)) {
                IdxBizJgTechParamsElevator idxBizJgTechParamsElevatorNew = JSONObject.parseObject(JSONObject.toJSONString(techInfo), IdxBizJgTechParamsElevator.class);

                IdxBizJgTechParamsElevator elevator = JSON.parseObject(JSON.toJSONString(techInfo), IdxBizJgTechParamsElevator.class);
                if (!ValidationUtil.isEmpty(elevator)) {
                    if (!ObjectUtils.isEmpty(techInfo.get("ELEVATOR_SEQ"))) {
                        elevator.setSequenceNbr(String.valueOf(techInfo.get("ELEVATOR_SEQ")));
                    }
                    iIdxBizJgTechParamsElevatorService.saveOrUpdateData(elevator);
                }
            }
            // 厂车
            else if (EquipmentClassifityEnum.CC.getCode().equals(equList)) {
                IdxBizJgTechParamsVehicle vehicle = JSON.parseObject(JSON.toJSONString(techInfo), IdxBizJgTechParamsVehicle.class);
                if (!ValidationUtil.isEmpty(vehicle)) {
                    if (!ObjectUtils.isEmpty(techInfo.get("VEHICLE_SEQ"))) {
                        vehicle.setSequenceNbr(String.valueOf(techInfo.get("VEHICLE_SEQ")));
                    }
                    iIdxBizJgTechParamsVehicleService.saveOrUpdateData(vehicle);
                }

                //主要零部件
//                List<String> subFormMainPartsList = new ArrayList<>();
//                subFormMainPartsList.add("subForm_sey164b51a");
//                subFormMainPartsList.add("subForm_tef7yf5fbr");
//                mainPartsList = this.getAccessoryEntity(equipmentParamsForm, subFormMainPartsList, EQUIP_MAINPARTS_FORM_ID, record, date, operateType);

            }
            // 索道
            else if (EquipmentClassifityEnum.KYSD.getCode().equals(equList)) {
                IdxBizJgTechParamsRopeway ropeway = JSON.parseObject(JSON.toJSONString(techInfo), IdxBizJgTechParamsRopeway.class);
                if (!ValidationUtil.isEmpty(ropeway)) {
                    if (!ObjectUtils.isEmpty(techInfo.get("ROPEWAY_SEQ"))) {
                        ropeway.setSequenceNbr(String.valueOf(techInfo.get("ROPEWAY_SEQ")));
                    }
                    ropeway.setSequenceNbr(String.valueOf(techInfo.get("ROPEWAY_SEQ")));
                    iIdxBizJgTechParamsRopewayService.saveOrUpdateData(ropeway);
                }

//                //主要零部件
//                List<String> subFormMainPartsList = new ArrayList<>();
//                subFormMainPartsList.add("subForm_5fi0jewuyh");
//                mainPartsList = this.getAccessoryEntity(equipmentParamsForm, subFormMainPartsList, EQUIP_MAINPARTS_FORM_ID, record, date, operateType);

            }
            // 游乐设施
            else if (EquipmentClassifityEnum.YLSS.getCode().equals(equList)) {
                IdxBizJgTechParamsRides rides = JSON.parseObject(JSON.toJSONString(techInfo), IdxBizJgTechParamsRides.class);
                if (!ValidationUtil.isEmpty(rides)) {
                    if (!ObjectUtils.isEmpty(techInfo.get("RIDES_SEQ"))) {
                        rides.setSequenceNbr(String.valueOf(techInfo.get("RIDES_SEQ")));
                    }
                    iIdxBizJgTechParamsRidesService.saveOrUpdateData(rides);
                }
            }
            // 锅炉
            else if (EquipmentClassifityEnum.GL.getCode().equals(equList)) {
                IdxBizJgTechParamsBoiler boiler = JSON.parseObject(JSON.toJSONString(techInfo), IdxBizJgTechParamsBoiler.class);
                if (!ValidationUtil.isEmpty(boiler)) {
                    if (!ObjectUtils.isEmpty(techInfo.get("BOILER_SEQ"))) {
                        boiler.setSequenceNbr(String.valueOf(techInfo.get("BOILER_SEQ")));
                    }
                    iIdxBizJgTechParamsBoilerService.saveOrUpdateData(boiler);
                }

                //主要零部件
//                List<String> subFormMainPartsList = new ArrayList<>();
//                subFormMainPartsList.add("subForm_1hh88r4m69");
//                mainPartsList = this.getAccessoryEntity(equipmentParamsForm, subFormMainPartsList, EQUIP_MAINPARTS_FORM_ID, record, date, operateType);
            }
            // 压力容器
            else if (EquipmentClassifityEnum.YLRQ.getCode().equals(equList)) {
                IdxBizJgTechParamsVessel vessel = JSON.parseObject(JSON.toJSONString(techInfo), IdxBizJgTechParamsVessel.class);
                if (!ValidationUtil.isEmpty(vessel)) {
                    if (!ObjectUtils.isEmpty(techInfo.get("VESSEL_SEQ"))) {
                        vessel.setSequenceNbr(String.valueOf(techInfo.get("VESSEL_SEQ")));
                    }
                    iIdxBizJgTechParamsVesselService.saveOrUpdateData(vessel);
                }

//                //主要零部件
//                List<String> subFormMainPartsList = new ArrayList<>();
//                subFormMainPartsList.add("subForm_fie04854f2");
//                mainPartsList = this.getAccessoryEntity(equipmentParamsForm, subFormMainPartsList, EQUIP_MAINPARTS_FORM_ID, record, date, operateType);
//
//                //安全附件
//                List<String> subFormProtectionDevicesList = new ArrayList<>();
//                subFormProtectionDevicesList.add("subForm_d4xdzhsgdj");
//                protectionDevicesList = this.getAccessoryEntity(equipmentParamsForm, subFormProtectionDevicesList, EQUIP_PROTECTIONDEVICES_FORM_ID, record, date, operateType);

            }
            // 压力管道
            else if (EquipmentClassifityEnum.YLGD.getCode().equals(equList)) {
                IdxBizJgTechParamsPipeline pipeline = JSON.parseObject(JSON.toJSONString(techInfo), IdxBizJgTechParamsPipeline.class);
                if (!ValidationUtil.isEmpty(pipeline)) {
                    if (!ObjectUtils.isEmpty(techInfo.get("PIPELINE_SEQ"))) {
                        pipeline.setSequenceNbr(String.valueOf(techInfo.get("PIPELINE_SEQ")));
                    }
                    iIdxBizJgTechParamsPipelineService.saveOrUpdateData(pipeline);
                }

//                //主要零部件
//                List<String> subFormMainPartsList = new ArrayList<>();
//                subFormMainPartsList.add("subForm_9n7nu55z8r");
//                mainPartsList = this.getAccessoryEntity(equipmentParamsForm, subFormMainPartsList, EQUIP_MAINPARTS_FORM_ID, record, date, operateType);

            }
            // 起重机械
            else if (EquipmentClassifityEnum.QZJX.getCode().equals(equList)) {
                IdxBizJgTechParamsLifting lifting = JSON.parseObject(JSON.toJSONString(techInfo), IdxBizJgTechParamsLifting.class);
                if (!ValidationUtil.isEmpty(lifting)) {
                    if (!ObjectUtils.isEmpty(techInfo.get("LIFTING_SEQ"))) {
                        lifting.setSequenceNbr(String.valueOf(techInfo.get("LIFTING_SEQ")));
                    }
                    iIdxBizJgTechParamsLiftingService.saveOrUpdateData(lifting);
                }

//                //主要零部件
//                List<String> subFormMainPartsList = new ArrayList<>();
//                subFormMainPartsList.add("subForm_bqirdyvztt");
//                mainPartsList = this.getAccessoryEntity(equipmentParamsForm, subFormMainPartsList, EQUIP_MAINPARTS_FORM_ID, record, date, operateType);
//
//                //安全附件
//                List<String> subFormProtectionDevicesList = new ArrayList<>();
//                subFormProtectionDevicesList.add("subForm_29yy3pdzhl");
//                subFormProtectionDevicesList.add("subForm_h5h4x0zhur");
//                protectionDevicesList = this.getAccessoryEntity(equipmentParamsForm, subFormProtectionDevicesList, EQUIP_PROTECTIONDEVICES_FORM_ID, record, date, operateType);

            }

            //八大类技术参数和主要零部件和安全附件表
//            if (!ValidationUtil.isEmpty(mainPartsList)) {
//                iIdxBizJgMainPartsService.saveOrUpdateBatchData(mainPartsList);
//            }
//            if (!ValidationUtil.isEmpty(protectionDevicesList)) {
//                iIdxBizJgProtectionDevicesService.saveOrUpdateBatchData(protectionDevicesList);
//            }


            //将历史数据回填到历史记录表中
            jgRegistrationHistory.setChangeData(newData);
            jgRegistrationHistory.setStatus("history");
            jgRegistrationHistoryMapper.updateById(jgRegistrationHistory);
            //         makeEquipmentsInvalid(equipId, currentDocumentId);
            //更新使用注册登记证编号
            // 改造变更登记使用登记证不变
            //idxBizJgRegisterInfoMapper.updateUseOrgCodeByEquip(equipId, newUseRegistrationCertificateNumber);
            //es中的编号信息
//            Map<String, Map<String, Object>> resultMap = new HashMap<>();
//            Map<String, Object> map1 = new HashMap<>();
//            map1.put("USE_ORG_CODE", newUseRegistrationCertificateNumber);
//            resultMap.put(equipId, map1);
//            try {
//                tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
//            }catch (Exception e){
//                log.error("改造变更登记------------更新es中的编号信息失败，请及时检查ES的状态");
//            }
        }
    }

    /*
     * 获取电梯的原始技术参数
     * @param equipId
     */
    public Map<String, Object> getOriginalTechParams(String equipId) {
        Map<String, Object> result = new HashMap<>();
        IdxBizJgTechParamsElevator idxBizJgTechParamsElevator = idxBizJgTechParamsElevatorMapper.selectOne(new QueryWrapper<IdxBizJgTechParamsElevator>().eq("RECORD", equipId));
        if (!ObjectUtils.isEmpty(idxBizJgTechParamsElevator)) {
            result = JSONObject.parseObject(JSONObject.toJSONString(idxBizJgTechParamsElevator), Map.class);
            result.remove("sequenceNbr");
        }
        return result;
    }

    @Override
    public void exportUseRegistrationCertificate(String sequenceNbr, HttpServletResponse response, String printType) {
        Map<String, Object> exportParamsMap = new HashMap<>();
        //查询移装变更详情
        JgChangeRegistrationReform jgChangeRegistrationReform = this.getById(sequenceNbr);
        JgChangeRegistrationReformEq jgChangeRegistrationReformEq = jgChangeRegistrationReformEqMapper.selectOne(new QueryWrapper<JgChangeRegistrationReformEq>().eq("equip_transfer_id", sequenceNbr));
        if (ValidationUtil.isEmpty(jgChangeRegistrationReform) || ValidationUtil.isEmpty(jgChangeRegistrationReformEq)) {
            throw new BadRequest("使用登记证导出失败,请稍后重试!");
        }
        //是否废弃
        exportParamsMap.put("isInvalid", jgChangeRegistrationReformEq.getIsInvalid());
        if (ValidationUtil.isEmpty(jgChangeRegistrationReform.getReceiveOrgName())) {
            throw new BadRequest("使用登记证导出失败,登记机关为空!");
        }
        exportParamsMap.put("receiveOrgName", jgChangeRegistrationReform.getReceiveOrgName());
        //使用登记证编号
        if (ValidationUtil.isEmpty(jgChangeRegistrationReform.getUseRegistrationCode())) {
            throw new BadRequest("使用登记证导出失败,使用登记证编号为空!");
        }
        exportParamsMap.put("useRegistrationCode", jgChangeRegistrationReform.getUseRegistrationCode());
        //使用单位名称
        if (ValidationUtil.isEmpty(jgChangeRegistrationReform.getUseUnitName())) {
            throw new BadRequest("使用登记证导出失败,使用单位名称为空!");
        }
        exportParamsMap.put("useUnitName", jgChangeRegistrationReform.getUseUnitName());
        //监管码
        if (ValidationUtil.isEmpty(jgChangeRegistrationReform.getSupervisoryCode())) {
            throw new BadRequest("使用登记证导出失败,监管码为空!");
        }
        exportParamsMap.put("supervisoryCode", jgChangeRegistrationReform.getSupervisoryCode());

        getAuditPassedDate(jgChangeRegistrationReform.getAuditPassDate(), exportParamsMap);

        //查询设备注册信息
        IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoService.getOne(new QueryWrapper<IdxBizJgRegisterInfo>().eq("RECORD", jgChangeRegistrationReformEq.getEquId()));
        if (!ValidationUtil.isEmpty(registerInfo)) {
            //设备种类、类别、品种
            String equList = registerInfo.getEquList();//设备种类
            String equCategory = registerInfo.getEquCategory();//设备类别
            String equDefine = registerInfo.getEquDefine();//设备品种
            List<EquipmentCategory> categoryList0 = commonServiceImpl.getEquipmentCategoryList(equList, null);
            List<EquipmentCategory> categoryList1 = commonServiceImpl.getEquipmentCategoryList(equCategory, null);
            List<EquipmentCategory> categoryList2 = commonServiceImpl.getEquipmentCategoryList(equDefine, null);
            if (CollectionUtils.isNotEmpty(categoryList0)) {
                if (ValidationUtil.isEmpty(categoryList0.get(0).getName())) {
                    throw new BadRequest("使用登记证导出失败,设备种类为空!");
                }
                exportParamsMap.put("equList", categoryList0.get(0).getName());
            }
            if (CollectionUtils.isNotEmpty(categoryList1)) {
                if (ValidationUtil.isEmpty(categoryList1.get(0).getName())) {
                    throw new BadRequest("使用登记证导出失败,设备类别为空!");
                }
                exportParamsMap.put("equCategory", categoryList1.get(0).getName());
            }
            if (CollectionUtils.isNotEmpty(categoryList2)) {
                if (ValidationUtil.isEmpty(categoryList2.get(0).getName())) {
                    throw new BadRequest("使用登记证导出失败,设备品种为空!");
                }
                exportParamsMap.put("equDefine", categoryList2.get(0).getName());
            }
            //设备代码
            if (ValidationUtil.isEmpty(registerInfo.getEquCode())) {
                throw new BadRequest("使用登记证导出失败,设备代码为空!");
            }
            exportParamsMap.put("equCode", registerInfo.getEquCode());
        }

        //单位内部编码
        IdxBizJgUseInfo useInfo = idxBizJgUseInfoService.getOneData(jgChangeRegistrationReformEq.getEquId());
        if (!ValidationUtil.isEmpty(useInfo)) {
            if (ValidationUtil.isEmpty(useInfo.getUseInnerCode())) {
                throw new BadRequest("使用登记证导出失败,设备单位内部编码为空!");
            }
            exportParamsMap.put("useInnerCode", useInfo.getUseInnerCode());

            String fullAddress = "";
            String province = useInfo.getProvinceName();
            String city = useInfo.getCityName();
            String county = useInfo.getCountyName();
            String street = useInfo.getStreetName();
            String address = useInfo.getAddress();
            if (!ObjectUtils.isEmpty(province)) {
                fullAddress += province;
            }
            if (!ObjectUtils.isEmpty(city)) {
                fullAddress += city;
            }
            if (!ObjectUtils.isEmpty(county)) {
                fullAddress += county;
            }
            if (!ObjectUtils.isEmpty(street)) {
                fullAddress += street;
            }
            if (!ObjectUtils.isEmpty(address)) {
                fullAddress += address;
            }
            if (ValidationUtil.isEmpty(fullAddress)) {
                throw new BadRequest("使用登记证导出失败,设备使用地址为空!");
            }
            exportParamsMap.put("fullAddress", fullAddress);
        }
        IdxBizJgFactoryInfo factoryInfo = idxBizJgFactoryInfoService.getOneData(jgChangeRegistrationReformEq.getEquId());
        //产品编号(出厂编号)
        if (!ValidationUtil.isEmpty(factoryInfo)) {
            if (ValidationUtil.isEmpty(factoryInfo.getFactoryNum())) {
                throw new BadRequest("使用登记证导出失败,产品编号为空!");
            }
            exportParamsMap.put("factoryNum", factoryInfo.getFactoryNum());
        }
        exportParamsMap.put("applyNo", jgChangeRegistrationReform.getApplyNo());
        if ("0".equals(printType)) {
            //调用生成使用登记证
            commonServiceImpl.generateCertificateReport(exportParamsMap, response);
        } else {
            //套打
            commonServiceImpl.generatePdfPrint(exportParamsMap, response);
        }
    }

    /**
     * @return String
     * @deprecated 动态获取
     */
    public String getSummaryInfo(JgChangeRegistrationReform jgChangeRegistrationReform) {
        String result = "发起【%s】的业务申请，【申请单号：%s】";
        return String.format(result, BUSINESS_TYPE, jgChangeRegistrationReform.getApplyNo());
    }

    /**
     * 构建工作台待办实体类
     *
     * @param jgChangeRegistrationReform
     * @param processTaskDTO
     * @return
     */
    public TaskModelDto getTaskModelDtoList(JgChangeRegistrationReform jgChangeRegistrationReform, ProcessTaskDTO processTaskDTO) {
        //设置实体无需字段为空
        TaskModelDto taskModelDto = new TaskModelDto();
        if (ObjectUtils.isEmpty(processTaskDTO)) {

            //taskCode 使用申请单编号
            taskModelDto.setTaskCode(jgChangeRegistrationReform.getApplyNo());
            //摘要
            taskModelDto.setTaskContent(getSummaryInfo(jgChangeRegistrationReform));
            //任务类型
            taskModelDto.setTaskType(BusinessTypeEnum.JG_RENOVATION_REGISTRATION.getCode());
            //工作流实例id
            taskModelDto.setRelationId(String.valueOf(jgChangeRegistrationReform.getSequenceNbr()));
            taskModelDto.setModel(conveterTaskMessageDTO(jgChangeRegistrationReform));
        } else {
            List<WorkflowResultDto> workflowResultDtoList = commonServiceImpl.buildWorkFlowInfo(Arrays.asList(processTaskDTO));
            WorkflowResultDto workflowResultDto = conveterProcessTaskDTO2WorkflowResultDto(processTaskDTO);
            //工作流创建时间
            taskModelDto.setFlowCreateDate(jgChangeRegistrationReform.getCreateDate());
            //工作流返回节点名称
            taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
            //taskCode 使用申请单编号
            taskModelDto.setTaskCode(jgChangeRegistrationReform.getApplyNo());
            //摘要
            taskModelDto.setTaskContent(getSummaryInfo(jgChangeRegistrationReform));
            //任务描述-非必填
            taskModelDto.setTaskDesc(null);
            //任务类型
            taskModelDto.setTaskType(BusinessTypeEnum.JG_RENOVATION_REGISTRATION.getCode());
            //任务类型名称
            taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_RENOVATION_REGISTRATION.getName());
            //工作流实例id
            taskModelDto.setRelationId(jgChangeRegistrationReform.getInstanceId());
            //执行人id
            taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            //任务状态code
            taskModelDto.setTaskStatus(commonServiceImpl.getDictionaryCodeByName(jgChangeRegistrationReform.getStatus()));
            taskModelDto.setFlowStatus(taskModelDto.getTaskStatus());
            //任务状态名称
            taskModelDto.setTaskStatusLabel(jgChangeRegistrationReform.getStatus());
            taskModelDto.setFlowStatusLabel(jgChangeRegistrationReform.getStatus());
            //任务创建人id
            taskModelDto.setStartUserId(jgChangeRegistrationReform.getCreateUserId());
            //任务创建人名称
            taskModelDto.setStartUser(jgChangeRegistrationReform.getCreateUserName());
            //任务发起人所在单位
            taskModelDto.setStartUserCompanyName(jgChangeRegistrationReform.getCreateUserCompanyName());
            //任务发起人发起时间
            taskModelDto.setStartDate(new Date());
            taskModelDto.setFlowCode(jgChangeRegistrationReform.getNextTaskId());
            taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
            //跳转路径
//        taskModelDto.setRoutePath();
            taskModelDto.setModel(conveterTaskMessageDTO(jgChangeRegistrationReform));
        }
        return taskModelDto;
    }

    /**
     * 将processTaskDTO转换成WorkflowResultDto
     *
     * @param processTaskDTO
     * @return
     */
    public WorkflowResultDto conveterProcessTaskDTO2WorkflowResultDto(ProcessTaskDTO processTaskDTO) {
        List<WorkflowResultDto> workflowResultDtoList = commonServiceImpl.buildWorkFlowInfo(Arrays.asList(processTaskDTO));
        WorkflowResultDto workflowResultDto = new WorkflowResultDto();
        if (!workflowResultDtoList.isEmpty()) {
            workflowResultDto = workflowResultDtoList.get(0);
        }
        return workflowResultDto;
    }

    /**
     * 将jgChangeRegistrationReform转换成TaskModelDto
     *
     * @param jgChangeRegistrationReform
     * @return
     */
    public TaskMessageDto conveterTaskMessageDTO(JgChangeRegistrationReform jgChangeRegistrationReform) {
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        //设置流程实例id
        taskMessageDto.setInstanceId(jgChangeRegistrationReform.getInstanceId());
        //设置流程状态
        taskMessageDto.setStatus(jgChangeRegistrationReform.getStatus());
        //设置办理状态
        taskMessageDto.setAuditStatus(jgChangeRegistrationReform.getStatus());
        //设置流程执行人
        taskMessageDto.setPromoter(jgChangeRegistrationReform.getPromoter());
        //设置流程下一步执行人id
        taskMessageDto.setNextExecuteUserIds(jgChangeRegistrationReform.getNextExecuteUserIds());
        //设置业务sequencenber
        taskMessageDto.setSequenceNbr(jgChangeRegistrationReform.getSequenceNbr());
        //设置流程下一步执行人角色
        taskMessageDto.setNextExecuteIds(jgChangeRegistrationReform.getNextExecutorIds());
        //设置nextTaskid
        taskMessageDto.setNextTaskId(jgChangeRegistrationReform.getNextTaskId());
        return taskMessageDto;
    }

    /**
     * @param operate
     * @param jgChangeRegistrationReform
     * @return
     * @deprecated 根据流程执行情况获取下一步执行公司code用于工作流过滤人员
     */
    private String getNextUserOrgCode(String operate, JgChangeRegistrationReform jgChangeRegistrationReform) {
        if ("0".equals(operate)) {
            // 执行通过节点，单位code为接收机构单位信息
            return jgChangeRegistrationReform.getReceiveCompanyCode();
        }
        if (jgChangeRegistrationReform.getAuditStatus().equals(WorkFlowStatusEnum.CHANGE_RECEIVE.getPass())
                || jgChangeRegistrationReform.getAuditStatus().equals(WorkFlowStatusEnum.CHANGE_RECEIVE.getReject())
                || jgChangeRegistrationReform.getAuditStatus().equals(WorkFlowStatusEnum.CHANGE_RECEIVE.getRollBack())) {
            // 驳回且当前节点为一键节点时，单位code为发起人单位信息
            return jgChangeRegistrationReform.getUseUnitCreditCode();
        }
        // 2、3级驳回时，单位code为接收单位code
        return jgChangeRegistrationReform.getReceiveCompanyCode();
    }

    public Map<String, Object> getEquDetail(String useRegistrationCode) {
        IdxBizJgRegisterInfo registerInfo = jgRegisterInfoService.lambdaQuery().eq(IdxBizJgRegisterInfo::getUseOrgCode, useRegistrationCode).one();
        HashMap<String, Object> detail = new HashMap<>();
        if (!ObjectUtils.isEmpty(registerInfo)) {
            Map<String, Object> originalData = idxBizJgRegisterInfoService.getDetailByRecord(registerInfo.getRecord());
            Map<String, Object> originalDataOther = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(registerInfo.getRecord());
            detail.putAll(originalDataOther);
            detail.put("techInfo", originalData);
//            return jgChangeRegistrationTransferService.getDetailFieldCamelCase(registerInfo.getRecord());
//
        }
        return detail;
    }

    public Page<JgUseRegistrationManageDto> getUseRegistrationCodeData(Page<JgUseRegistrationManageDto> page,
                                                                       JgUseRegistrationManageDto dto) {
        return jgUseRegistrationManageService.queryForJgUseRegistrationManagePage(page, dto, null);
    }


    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public JgChangeRegistrationReform cancelApplication(Long sequenceNbr, String cancelReason, String realName) {
        // 1.更新为已作废
        JgChangeRegistrationReform jgChangeRegistrationReform = this.getById(sequenceNbr);
        String oldStatus = jgChangeRegistrationReform.getAuditStatus();
        jgChangeRegistrationReform.setAuditStatus(String.valueOf(FlowStatusEnum.TO_BE_DISCARD.getName()));
        jgChangeRegistrationReform.setStatus(String.valueOf(FlowStatusEnum.TO_BE_DISCARD.getName()));
        jgChangeRegistrationReform.setCancelReason(cancelReason);
        jgChangeRegistrationReform.setCancelDate(new Date());
        jgChangeRegistrationReform.setCancelUserId(RequestContext.getExeUserId());
        jgChangeRegistrationReform.setCancelUserName(realName);
        jgChangeRegistrationReform.setNextExecuteUserIds(null);
        jgChangeRegistrationReform.setPromoter(null);
        this.updateById(jgChangeRegistrationReform);
        // 2.更新关联的业务
        this.processElseDataByStatus(oldStatus, jgChangeRegistrationReform);
        return jgChangeRegistrationReform;
    }

    private void processElseDataByStatus(String oldStatus, JgChangeRegistrationReform jgChangeRegistrationReform) {
        switch (oldStatus) {
            case "使用单位待提交":
                // do no thing
                break;
            case "已完成":
                // 1.技术参数恢复原数据
                this.restoreTechParams(jgChangeRegistrationReform);
                break;
            default:
                // 流程中（驳回、撤回等）
                // 1.待办任务更新为已完成
                this.finishedTask(jgChangeRegistrationReform);
                // 2.终止流程
                iCmWorkflowService.stopProcess(jgChangeRegistrationReform.getInstanceId(), jgChangeRegistrationReform.getCancelReason());
                // 3.清空redis（缓存的流程中的设备）
                this.clearDataForCheckEquipRepeatUsed2(jgChangeRegistrationReform);
                if(jgChangeRegistrationReform.getProjectContraptionId()!=null){
                    // 编辑过则按照编辑的数据进行恢复管道信息
                    Boolean isRollBack = backupManager.restore(jgChangeRegistrationReform.getSequenceNbr() + "");
                    if(isRollBack){ // 进行过编辑逻辑
                        // 1.装置重新计算管道长度
                        this.updateTotalPieLineLength(jgChangeRegistrationReform.getProjectContraptionId());
                    }
                }
        }
    }

    private void updateTotalPieLineLength(String pid) {
        List<String> records = idxBizJgUseInfoService.list(new LambdaQueryWrapper<IdxBizJgUseInfo>().in(IdxBizJgUseInfo::getProjectContraptionId, pid)).stream().map(IdxBizJgUseInfo::getRecord).collect(toList());
        List<IdxBizJgTechParamsPipeline> paramsPipelines = idxBizJgTechParamsPipelineServiceImpl.list(new LambdaQueryWrapper<IdxBizJgTechParamsPipeline>().in(IdxBizJgTechParamsPipeline::getRecord, records).select(IdxBizJgTechParamsPipeline::getRecord,IdxBizJgTechParamsPipeline::getPipeLength));
        double totalLength = paramsPipelines.stream()
                .map(IdxBizJgTechParamsPipeline::getPipeLength)       // 先提取长度字符串
                .filter(Objects::nonNull)          // 过滤掉null值
                .mapToDouble(Double::parseDouble)  // 解析字符串为double并转为DoubleStream
                .sum();
        LambdaUpdateWrapper<IdxBizJgProjectContraption> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(IdxBizJgProjectContraption::getPipelineLength, totalLength);
        updateWrapper.eq(BaseEntity::getSequenceNbr, pid);
        jgProjectContraptionService.update(updateWrapper);
    }

    private void finishedTask(JgChangeRegistrationReform jgChangeRegistrationReform) {
        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", jgChangeRegistrationReform.getInstanceId());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        jgChangeRegistrationReform.setOtherAccessories(null);
        BeanUtils.copyProperties(jgChangeRegistrationReform, taskMessageDto);
        taskMap.put("model", taskMessageDto);
        commonServiceImpl.updateTaskModel(taskMap);
    }


    private void restoreTechParams(JgChangeRegistrationReform jgChangeRegistrationReform) {
        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryMapper.selectOne(
                new LambdaQueryWrapper<JgRegistrationHistory>()
                        .eq(JgRegistrationHistory::getCurrentDocumentId, jgChangeRegistrationReform.getApplyNo())
                        .eq(JgRegistrationHistory::getIsDelete, false));
        if (jgRegistrationHistory == null) {
            return;
        }
        String record = jgRegistrationHistory.getEquId();
        String equList = getEquListCode(jgRegistrationHistory, jgChangeRegistrationReform);
        String oldTechInfo = jgRegistrationHistory.getOldData();
        //将历史数据更新到技术参数表中
        EquipmentClassifityEnum anEnum = EquipmentClassifityEnum.getOne(equList);
        assert anEnum != null;
        if (StringUtils.isEmpty(oldTechInfo)) {
            log.warn("技术参数为空，无法进行回滚技术参数，单据编号：{}", jgChangeRegistrationReform.getApplyNo());
            return;
        }
        switch (anEnum) {
            //电梯
            case DT:
                IdxBizJgTechParamsElevator elevator = JSON.parseObject(oldTechInfo, IdxBizJgTechParamsElevator.class);
                // 删除
                iIdxBizJgTechParamsElevatorService.remove(new LambdaQueryWrapper<IdxBizJgTechParamsElevator>().eq(IdxBizJgTechParamsElevator::getRecord, record));
                // 新插入
                elevator.setSequenceNbr(sequence.nextId() + "");
                iIdxBizJgTechParamsElevatorService.save(elevator);
                break;
            // 厂车
            case CC:
                IdxBizJgTechParamsVehicle vehicle = JSON.parseObject(oldTechInfo, IdxBizJgTechParamsVehicle.class);
                // 删除
                iIdxBizJgTechParamsVehicleService.remove(new LambdaQueryWrapper<IdxBizJgTechParamsVehicle>().eq(IdxBizJgTechParamsVehicle::getRecord, record));
                // 插入
                vehicle.setSequenceNbr(sequence.nextId() + "");
                iIdxBizJgTechParamsVehicleService.save(vehicle);
                break;
            // 索道
            case KYSD:
                IdxBizJgTechParamsRopeway ropeway = JSON.parseObject(oldTechInfo, IdxBizJgTechParamsRopeway.class);
                // 删除
                iIdxBizJgTechParamsRopewayService.remove(new LambdaQueryWrapper<IdxBizJgTechParamsRopeway>().eq(IdxBizJgTechParamsRopeway::getRecord, record));
                // 插入
                ropeway.setSequenceNbr(sequence.nextId() + "");
                iIdxBizJgTechParamsRopewayService.save(ropeway);
                break;
            // 游乐设施
            case YLSS:
                IdxBizJgTechParamsRides rides = JSON.parseObject(oldTechInfo, IdxBizJgTechParamsRides.class);
                // 删除
                iIdxBizJgTechParamsRidesService.remove(new LambdaQueryWrapper<IdxBizJgTechParamsRides>().eq(IdxBizJgTechParamsRides::getRecord, record));
                // 插入
                rides.setSequenceNbr(sequence.nextId() + "");
                iIdxBizJgTechParamsRidesService.save(rides);
                break;
            // 锅炉
            case GL:
                IdxBizJgTechParamsBoiler boiler = JSON.parseObject(oldTechInfo, IdxBizJgTechParamsBoiler.class);
                // 删除
                iIdxBizJgTechParamsBoilerService.remove(new LambdaQueryWrapper<IdxBizJgTechParamsBoiler>().eq(IdxBizJgTechParamsBoiler::getRecord, record));
                // 插入
                boiler.setSequenceNbr(sequence.nextId() + "");
                iIdxBizJgTechParamsBoilerService.save(boiler);
                break;
            // 压力容器
            case YLRQ:
                IdxBizJgTechParamsVessel vessel = JSON.parseObject(oldTechInfo, IdxBizJgTechParamsVessel.class);
                // 删除
                iIdxBizJgTechParamsVesselService.remove(new LambdaQueryWrapper<IdxBizJgTechParamsVessel>().eq(IdxBizJgTechParamsVessel::getRecord, record));
                // 插入
                vessel.setSequenceNbr(sequence.nextId() + "");
                iIdxBizJgTechParamsVesselService.save(vessel);
                break;

            // 压力管道
            case YLGD:
                // 编辑过则按照编辑的数据进行恢复管道信息
                Boolean isRollBack = backupManager.restore(jgChangeRegistrationReform.getSequenceNbr() + "");
                if(isRollBack){ // 进行过编辑逻辑
                    // 1.原装置、新装置重新计算管道长度
                    this.updateTotalPieLineLength(jgChangeRegistrationReform.getProjectContraptionId());
                } else {      //未编辑过，走原有逻辑
                    JSONObject jsonObject = JSONObject.parseObject(oldTechInfo);
                    JSONArray piePines = jsonObject.getJSONArray("equipmentLists");
                    // 装置和设备es中的安改维单位信息恢复
                    String uscUnitCreditCode = jsonObject.getString(USC_UNIT_CREDIT_CODE);
                    String uscUnitName = jsonObject.getString(USC_UNIT_NAME);
                    jgProjectContraptionService.lambdaUpdate()
                            .eq(IdxBizJgProjectContraption::getSequenceNbr, jgChangeRegistrationReform.getProjectContraptionId())
                            .set(IdxBizJgProjectContraption::getUscUnitCreditCode, uscUnitCreditCode)
                            .set(IdxBizJgProjectContraption::getUscUnitName, uscUnitName)
                            .update();
                    for(int i = 0; i < piePines.size(); i++){
                        JSONObject item = piePines.getJSONObject(i);
                        String rcd = item.getString("record");
                        // 删除
                        iIdxBizJgTechParamsPipelineService.remove(new LambdaQueryWrapper<IdxBizJgTechParamsPipeline>().eq(IdxBizJgTechParamsPipeline::getRecord, rcd));
                        // 插入
                        IdxBizJgTechParamsPipeline pipeline = BeanUtil.copyProperties(item, IdxBizJgTechParamsPipeline.class);
                        pipeline.setSequenceNbr(sequence.nextId() + "");
                        iIdxBizJgTechParamsPipelineService.save(pipeline);
                        // es
                        Map<String, Map<String, Object>> resultMap = MapBuilder.<String, Map<String, Object>>create()
                                .put(rcd, MapBuilder.<String, Object>create()
                                        .put(USC_UNIT_NAME, uscUnitName)
                                        .put(USC_UNIT_CREDIT_CODE, uscUnitCreditCode)
                                        .build())
                                .build();
                        tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
                    }
                    // 检验信息恢复
                    JSONObject inspectData = jsonObject.getJSONObject("inspectData");
                    if(inspectData != null){
                        // 被更新前的检验信息
                        JSONArray oData = Optional.ofNullable(inspectData.getJSONArray("oData")).orElse(new JSONArray());
                        // 改造登记本次插入的检验信息主键sequenceNbr数组
                        JSONArray insertIds = Optional.ofNullable(inspectData.getJSONArray("insertIds")).orElse(new JSONArray());
                        // 更新的检验信息换成原来的
                        for(int i = 0; i < oData.size(); i++){
                            JSONObject item = oData.getJSONObject(i);
                            InspectionDetectionInfo inspectionDetectionInfo = BeanUtil.copyProperties(item, InspectionDetectionInfo.class);
                            inspectionDetectionInfoMapper.deleteById(inspectionDetectionInfo.getSequenceNbr());
                            inspectionDetectionInfoMapper.insert(inspectionDetectionInfo);
                        }
                        // 新插入的删除
                        if(!insertIds.isEmpty()){
                            List<String> ids = insertIds.toJavaList(String.class);
                            inspectionDetectionInfoMapper.deleteBatchIds(ids);
                        }
                    }
                }
                break;
            // 起重机械
            case QZJX:
                IdxBizJgTechParamsLifting lifting = JSON.parseObject(oldTechInfo, IdxBizJgTechParamsLifting.class);
                // 删除
                iIdxBizJgTechParamsLiftingService.remove(new LambdaQueryWrapper<IdxBizJgTechParamsLifting>().eq(IdxBizJgTechParamsLifting::getRecord, record));
                // 插入
                lifting.setSequenceNbr(sequence.nextId() + "");
                iIdxBizJgTechParamsLiftingService.save(lifting);
                break;
            default:
                log.warn("un support type of {}", equList);
        }
    }

    private String getEquListCode(JgRegistrationHistory jgRegistrationHistory, JgChangeRegistrationReform jgChangeRegistrationReform) {
        if(StringUtils.isNotEmpty(jgChangeRegistrationReform.getProjectContraptionId())){
            return EquipmentClassifityEnum.YLGD.getCode();
        } else {
            return getEquListCode(jgRegistrationHistory);
        }
    }


    private String getEquListCode(JgRegistrationHistory jgRegistrationHistory) {
        String record = jgRegistrationHistory.getEquId();
        IdxBizJgRegisterInfo idxBizJgRegisterInfo = jgRegisterInfoService.getOne(new LambdaQueryWrapper<IdxBizJgRegisterInfo>().eq(IdxBizJgRegisterInfo::getRecord, record));
        return idxBizJgRegisterInfo.getEquList();
    }

    @Override
    public boolean beforeCheck(JgChangeRegistrationReform jgChangeRegistrationReform) {
        return jgChangeRegistrationReform.getInstanceId() != null && !jgChangeRegistrationReform.getStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName()) &&!jgChangeRegistrationReform.getStatus().equals(FlowStatusEnum.TO_BE_DISCARD.getName());
    }

    @Override
    public void compensate(JgChangeRegistrationReform jgChangeRegistrationReform) {
        commonServiceImpl.saveExecuteFlowData2Redis(jgChangeRegistrationReform.getInstanceId(), this.buildInstanceRuntimeData(jgChangeRegistrationReform));
    }

    public IPage<IdxBizJgProjectContraption> getJgProjectContraptionPage(String useUnitCreditCode, Page<IdxBizJgProjectContraption> page, String sequenceNbr) {
        // 兼容个人业务
        if(useUnitCreditCode.contains("_")){
            useUnitCreditCode = useUnitCreditCode.split("_")[1];
        }
        // 查询流程中的装置
        List<JgChangeRegistrationReform> flowIngPros = this.list(new LambdaQueryWrapper<JgChangeRegistrationReform>().notIn(JgChangeRegistrationReform::getStatus, NOT_FLOWING_STATE).select(BaseEntity::getSequenceNbr, JgChangeRegistrationReform::getProjectContraptionId));
        Set<String> proIds = flowIngPros.stream().map(JgChangeRegistrationReform::getProjectContraptionId).collect(toSet());
        proIds.remove(null);
        proIds.remove("");
        // 编辑时要有自己
        if(StringUtils.isNotEmpty(sequenceNbr)){
            proIds.remove(sequenceNbr);
        }
        return this.getBaseMapper().queryJgProjectContraptionPage(page, useUnitCreditCode, proIds);
    }


    /**
     * 查询指定装置下的装置基本信息、施工/使用信息、管道信息（前缀装置列表已进行过滤，故不进行状态的过滤）
     *
     * @param projectContraptionSeq 装置id
     * @return 装置的详情
     */
    public Map<String, Object> getDeviceListByProjectContraption(String projectContraptionSeq) {
        IdxBizJgProjectContraption projectContraption = jgProjectContraptionService.getBaseMapper().selectById(projectContraptionSeq);
        Map<String, Object> re = new HashMap<>();
        List<Map<String, Object>> equList = this.getBaseMapper().selectPieLineListByProjectId(projectContraptionSeq);
        // 检验报告数据格式化 转json
        equList.stream().filter(e-> e.get("inspectReport") != null).forEach(item->{
            item.put("inspectReport", JSON.parse(item.get("inspectReport").toString()));
        });
        re.put("equipmentLists", equList);
        re.put("projectContraption", projectContraption.getProjectContraption());
        re.put("projectContraptionId", projectContraptionSeq);
        re.put("projectContraptionNo", projectContraption.getProjectContraptionNo());
        re.put("pipelineLength", projectContraption.getPipelineLength());
        re.put("useRegistrationCode", projectContraption.getUseRegistrationCode());
        this.setUseAddress(projectContraption, re);
        return re;
    }

    private void updateOrCreateInspectionDetection(Map<String, Object> equipment, JgChangeRegistrationReform registrationReform) {
        InspectionDetectionInfo inspectionDetectionInfo = new InspectionDetectionInfo();
        BeanUtil.copyProperties(equipment, inspectionDetectionInfo);
        // 编辑时会有此数据，所以用来做标识，根据设备record + 检验报告编号判定唯一一条检验流水，有进行更新，无则进行插入
        if(inspectionDetectionInfo.getInspectReportNo() != null && inspectionDetectionInfo.getInspectReport() != null){
            String record = equipment.get("record").toString();
            String jySeq = equipment.get("jySeq") == null  ? null : equipment.get("jySeq").toString();
            inspectionDetectionInfo.setInspectConclusion((String) equipment.get("inspectConclusionCode"));
            inspectionDetectionInfo.setSequenceNbr(jySeq);
            saveEquipOfPieLineInspectData(record, inspectionDetectionInfo, registrationReform);
        }
    }

    private void saveEquipOfPieLineInspectData(String record, InspectionDetectionInfo inspectionDetectionInfo, JgChangeRegistrationReform registrationReform) {
        // 1.检验机构 + 设备+ 检验报告编号时 ， 是唯一的为了防止老数据有重复的，程序健壮，故使用list进行处理
        String insertId = null;
        InspectionDetectionInfo inspectionDetectionInfoOld = null;
        if(inspectionDetectionInfo.getSequenceNbr() != null){ // 编辑
            inspectionDetectionInfoOld = inspectionDetectionInfoMapper.selectById(inspectionDetectionInfo.getSequenceNbr());
            inspectionDetectionInfo.setRecDate(new Date());
            inspectionDetectionInfoMapper.updateById(inspectionDetectionInfo);
        } else {                                              // 新增
            insertId = sequence.nextId() + "";
            inspectionDetectionInfo.setRecord(record);
            inspectionDetectionInfo.setRecDate(new Date());
            inspectionDetectionInfo.setSequenceNbr(sequence.nextId() + "");
            inspectionDetectionInfoMapper.insert(inspectionDetectionInfo);
        }
        // 2.记录原始检验流水用来作废时恢复数据
        JSONObject oldData = commonServiceImpl.queryHisOldData(registrationReform.getApplyNo());
        JSONObject inspectData = oldData.getJSONObject("inspectData") == null ? new JSONObject() : oldData.getJSONObject("inspectData");
        // 插入的检验数据ids
        this.setInsertIds(inspectData, insertId);
        // 被更新的原行数据
        this.setOData(inspectData, inspectionDetectionInfoOld);
        oldData.put("inspectData", inspectData);
        // 保存一份安改维单位信息，作废回滚用
        IdxBizJgProjectContraption projectContraption = jgProjectContraptionService.lambdaQuery()
                .eq(IdxBizJgProjectContraption::getSequenceNbr, registrationReform.getProjectContraptionId())
                .one();
        oldData.put(USC_UNIT_NAME, projectContraption.getUscUnitName());
        oldData.put(USC_UNIT_CREDIT_CODE, projectContraption.getUscUnitCreditCode());
        LambdaUpdateWrapper<JgRegistrationHistory> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(JgRegistrationHistory::getCurrentDocumentId, registrationReform.getApplyNo());
        updateWrapper.set(JgRegistrationHistory::getOldData, JSONObject.toJSONString(oldData));
        jgRegistrationHistoryServiceImpl.update(updateWrapper);
    }

    private void setOData(JSONObject inspectData, InspectionDetectionInfo oInspectionDetectionInfo) {
        JSONArray oData = inspectData.getJSONArray("oData");
        if(oData == null){
            oData = new JSONArray();
            inspectData.put("oData",oData);
        }
        if(oInspectionDetectionInfo != null){
            oData.add(oInspectionDetectionInfo);
        }
    }

    private void setInsertIds(JSONObject inspectData, String insertId) {
        JSONArray existInsertIds = inspectData.getJSONArray("insertIds");
        if(existInsertIds == null){
            existInsertIds = new JSONArray();
            inspectData.put("insertIds",existInsertIds);
        }
        if(insertId != null){
            existInsertIds.add(insertId);
        }
    }


    /**
     * 使用地点-使用登记完成后回把使用登记的地点信息写到装置表。定期检验时显示
     * @param projectContraption 装置
     * @param re                 返回结果：增加使用地点（工业管道是使用登记时的地址）；公用、长输管道是安装地址（无使用登记证）
     */
    private void setUseAddress(IdxBizJgProjectContraption projectContraption, Map<String, Object> re) {
        re.put("useAddress", getDetailAddress(projectContraption));
    }

    private String getDetailAddress(IdxBizJgProjectContraption projectContraption) {
        return trimIfNull(projectContraption.getProvinceName()) + trimIfNull(projectContraption.getCityName()) + trimIfNull(projectContraption.getCountyName()) + trimIfNull(projectContraption.getStreetName() + trimIfNull(projectContraption.getAddress()));
    }

    private String trimIfNull(String str) {
        if (StringUtils.isBlank(str)) {
            return "";
        }
        return str.trim();
    }
}