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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
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.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.olym.shaded.org.apache.commons.collections4.MapUtils;
import com.yeejoin.amos.boot.biz.common.annotation.EnableEsRollback;
import com.yeejoin.amos.boot.biz.common.annotation.ResultFieldMapping;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.enums.TcmUnitTypeEnum;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.boot.module.common.api.dao.ESEquipmentCategory;
import com.yeejoin.amos.boot.module.common.api.dao.EsEquipmentDao;
import com.yeejoin.amos.boot.module.common.api.dto.ESEquipmentCategoryDto;
import com.yeejoin.amos.boot.module.common.api.entity.ESEquipmentInfo;
import com.yeejoin.amos.boot.module.common.api.enums.CylinderTypeEnum;
import com.yeejoin.amos.boot.module.common.api.service.ICompensateFlowDataOfRedis;
import com.yeejoin.amos.boot.module.common.biz.refresh.DataRefreshEvent;
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.*;
import com.yeejoin.amos.boot.module.jg.api.mapper.*;
import com.yeejoin.amos.boot.module.jg.api.service.IJgChangeRegistrationUnitService;
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.equip.PieLineDataChangeServiceImpl;
import com.yeejoin.amos.boot.module.jg.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.ICommonService;
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.EquipmentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.*;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.systemctl.model.TaskV2Model;
import com.yeejoin.amos.feign.workflow.Workflow;
import com.yeejoin.amos.feign.workflow.model.*;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.ObjectUtils;
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.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.yeejoin.amos.boot.module.jg.biz.service.impl.JgChangeRegistrationNameServiceImpl.DB_BATCH_SIZE;
import static com.yeejoin.amos.boot.module.jg.biz.service.impl.JgChangeRegistrationNameServiceImpl.ES_BATCH_SIZE;
import static com.yeejoin.amos.boot.module.jg.biz.service.impl.JgUseRegistrationServiceImpl.getAuditPassedDate;

/**
 * 单位变更登记服务实现类
 *
 * @author system_generator
 * @date 2023-12-22
 */
@Service
public class JgChangeRegistrationUnitServiceImpl extends BaseService<JgChangeRegistrationUnitDto, JgChangeRegistrationUnit, JgChangeRegistrationUnitMapper> implements IJgChangeRegistrationUnitService, ICompensateFlowDataOfRedis<JgChangeRegistrationUnit> {
    private static final String SUBMIT_TYPE_FLOW = "1";
    private static final String PROCESS_DEFINITION_KEY = "unitChange";
    private static final String TABLE_PAGE_ID = "1734141426742095873";
    private static final String RECORD = "record";
    private static final String SEQUENCE_NBR = "sequenceNbr";
    private static final String EQU_CODE_CC = "5000";
    private static final int ONCE_MAX_SUBMIT = 20000;

    private static final int ONE_BATCH_SIZE = 1000;
    private final List<String> NOT_FLOWING_STATE = Arrays.asList("使用单位待提交", "一级受理已驳回", "使用单位已撤回", "已作废", "已完成");


    @Autowired
    EquipmentCategoryMapper equipmentCategoryMapper;
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    JgChangeRegistrationUnitEqMapper JgChangeRegistrationUnitEqMapper;

    @Autowired
    JgChangeRegistrationUnitEqServiceImpl registrationUnitEqService;

    @Autowired
    CmWorkflowServiceImpl cmWorkflowService;
    @Autowired
    private JgChangeRegistrationUnitMapper JgChangeRegistrationUnitMapper;
    @Autowired
    private IdxBizJgRegisterInfoMapper idxBizJgRegisterInfoMapper;
    @Autowired
    RegistrationInfoMapper tzsJgRegistrationInfoMapper;
    @Autowired
    OtherInfoMapper tzsJgOtherInfoMapper;
    @Autowired
    IdxBizJgUseInfoMapper useInfoMapper;
    @Autowired
    IdxBizJgRegisterInfoMapper registerInfoMapper;
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;

    @Autowired
    CommonServiceImpl commonServiceImpl;


    @Autowired
    private JgRegistrationHistoryMapper jgRegistrationHistoryMapper;

    @Autowired
    private JgScrapCancelMapper jgScrapCancelMapper;

    @Autowired
    private JgScrapCancelEqMapper jgScrapCancelEqMapper;

    @Autowired
    private SuperviseInfoMapper superviseInfoMapper;

    @Autowired
    private IdxBizJgUseInfoMapper idxBizJgUseInfoMapper;

    @Autowired
    private JgUseRegistrationManageMapper jgUseRegistrationManageMapper;

    @Autowired
    private JgCertificateChangeRecordEqServiceImpl jgCertificateChangeRecordEqServiceImpl;

    //改造登记关系表mapper
    @Autowired
    private JgChangeRegistrationReformEqMapper jgChangeRegistrationReformEqMapper;
    //移装登记关系表
    @Autowired
    private JgChangeRegistrationTransferEqMapper jgChangeRegistrationTransferEqMapper;
    //使用登记关系表mapper
    @Autowired
    private JgUseRegistrationEqMapper jgUseRegistrationEqMapper;
    //单位变更登记关系表mapper
    @Autowired
    private JgChangeRegistrationUnitEqMapper jgChangeRegistrationUnitEqMapper;
    //更名变更登记关系表mapper
    @Autowired
    private JgChangeRegistrationNameEqMapper jgChangeRegistrationNameEqMapper;

    @Autowired
    private IdxBizJgUseInfoServiceImpl idxBizJgUseInfoService;
    @Autowired
    private IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Autowired
    private IdxBizJgFactoryInfoServiceImpl idxBizJgFactoryInfoService;
    @Autowired
    private IdxBizJgOtherInfoServiceImpl idxBizJgOtherInfoService;
    @Autowired
    ICommonService commonService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    JgUseRegistrationManageServiceImpl registrationManageService;
    @Autowired
    JgRegistrationHistoryServiceImpl registrationHistoryService;

    @Autowired
    private SnowflakeIdUtil sequence;

    @Autowired
    JgCertificateChangeRecordServiceImpl certificateChangeRecordService;

    @Autowired
    JgCertificateChangeRecordEqServiceImpl certificateChangeRecordEqService;

    @Autowired
    JgUseRegistrationManageServiceImpl useRegistrationManageService;
    @Autowired
    private TzBaseEnterpriseInfoMapper tzBaseEnterpriseInfoMapper;
    @Autowired
    private IdxBizJgProjectContraptionServiceImplService projectContraptionService;
    @Autowired
    private EventPublisher eventPublisher;
    @Autowired
    private JgResumeInfoServiceImpl jgResumeInfoService;
    @Autowired
    private IdxBizJgSupervisionInfoMapper idxBizJgSupervisionInfoMapper;
    @Autowired
    private JgUseRegistrationManageServiceImpl jgUseRegistrationManageService;
    @Autowired
    private ESEquipmentCategory esEquipmentCategory;
    @Autowired
    private EsEquipmentDao esEquipmentDao;
    @Autowired
    private PieLineDataChangeServiceImpl pipelineDataChangeService;
    @Autowired
    private JgUseRegistrationServiceImpl jgUseRegistrationService;
    @Autowired
    private JgResumeInfoEqServiceImpl jgResumeInfoEqService;

    /**
     * 根据sequenceNbr查询：1、查询单位变更信息，2、查询使用登记证列表
     *
     * @param sequenceNbr     主键
     * @param selectedOrgInfo
     * @return 单位变更
     */
    @Override
    @ResultFieldMapping({@ResultFieldMapping.ResultFieldMap(sourceField = "changeRegisInfo.useUnitCreditCode", targetField = "changeRegisInfo.useUnitSeq", serviceClass = CommonServiceImpl.class, queryMethod = "queryUnitInfoByCreditCode")})
    public Map<String, Map<String, Object>> queryBySequenceNbr(Long sequenceNbr, ReginParams selectedOrgInfo) {
        // 单位变更信息
        JgChangeRegistrationUnit notice = JgChangeRegistrationUnitMapper.selectById(sequenceNbr);
        if (Objects.isNull(notice)) {
            return null;
        }
        this.doCompensate(notice);
        Map<String, Object> changeInfo = BeanUtil.beanToMap(notice, false, true);
        //回填新单位地址，台套办理的使用登记证打印时 需要，用来校验必输
        if (!ObjectUtils.isEmpty(notice.getNewUseUnitCreditCode())) {
            TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().eq(TzBaseEnterpriseInfo::getUseUnitCode, notice.getNewUseUnitCreditCode()));
            if (useCodeResult != null) {
                changeInfo.put("address", useCodeResult.getAddress());
            }
        }
        //组装下拉数据
        if (!ValidationUtil.isEmpty(notice.getReceiveOrgCode()) && !ValidationUtil.isEmpty(notice.getReceiveOrgName())) {
            changeInfo.put("receiveOrgCode", notice.getReceiveOrgCode() + "_" + notice.getReceiveOrgName());
        }
        if (!ValidationUtil.isEmpty(notice.getReceiveOrgCode()) && !ValidationUtil.isEmpty(notice.getReceiveOrgName())) {
            changeInfo.put("orgBranchCode", notice.getOrgBranchCode() + "_" + notice.getOrgBranchName());
        }
        if (!ValidationUtil.isEmpty(notice.getUseUnitCreditCode()) && !ValidationUtil.isEmpty(notice.getUseUnitName())) {
            changeInfo.put("useUnitCreditCode", notice.getUseUnitCreditCode() + "_" + notice.getUseUnitName());
        }
        if (!ValidationUtil.isEmpty(notice.getNewUseUnitCreditCode()) && !ValidationUtil.isEmpty(notice.getNewUseUnitName())) {
            changeInfo.put("newUseUnitCreditCode", notice.getNewUseUnitCreditCode() + "_" + notice.getNewUseUnitName());
        }
        //附件格式处理
        changeInfo.put("changeCertificateList", JSON.parse(notice.getChangeCertificate()));
        changeInfo.put("otherAccessoriesList", JSON.parse(notice.getOtherAccessories()));
        //查询使用登记证列表
        JgRegistrationHistory historyServiceOne = registrationHistoryService.getOne(
                new LambdaQueryWrapper<JgRegistrationHistory>()
                        .eq(JgRegistrationHistory::getCurrentDocumentId, notice.getApplyNo())
                        .eq(JgRegistrationHistory::getIsDelete, false));
        if (PipelineEnum.PRESSURE_PIPELINE.getCode().equals(notice.getEquListCode())) {
            //添加申请编号
            JSONArray jsonArray = JSON.parseArray(historyServiceOne.getChangeData());
            if (!CollectionUtils.isEmpty(jsonArray)) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i); // 直接获取 JSONObject
                    jsonObject.put("applyNo", notice.getApplyNo());
                }
                changeInfo.put("projectContraptionList", jsonArray);
            }
        }
        if (CylinderTypeEnum.CYLINDER.getCode().equals(notice.getEquCategoryCode())) {
            changeInfo.put("deviceList", JSON.parse(historyServiceOne.getChangeData()));
            if (!ValidationUtil.isEmpty(notice.getSafetyManager())) {
                changeInfo.put("safetyManagerName", notice.getSafetyManager().split("_")[1]);
            }
        } else {
            JSONArray registrationList = JSON.parseArray(historyServiceOne.getChangeData());
            if (!ValidationUtil.isEmpty(registrationList)) {
                registrationList.stream().map(obj -> (JSONObject) obj).forEach(jsonObject -> {
                    String estateUnitSeq = jsonObject.getString("estateUnitSeq");
                    String estateUnitName = jsonObject.getString("estateUnitName");
                    // 兼容历史数据（历史数据estateUnitName字段存的是base_info表主键）
                    // 如果estateUnitSeq字段存在则表示是新加的单子不用特殊处理
                    if (ValidationUtil.isEmpty(estateUnitSeq) && !ValidationUtil.isEmpty(estateUnitName)) {
                        Map<String, String> propertyUnitInfo = commonServiceImpl.queryTcmUnitInfoBySeq(estateUnitName, TcmUnitTypeEnum.CQ.getCode());
                        jsonObject.put("estateUnitName", MapUtil.getStr(propertyUnitInfo, "sequenceNbr"));
                    }
                });
            }
            changeInfo.put("registrationList", registrationList);
        }
        changeInfo.put("havingPermission", notice.getNextExecuteUserIds() != null && notice.getNextExecuteUserIds().contains(RequestContext.getExeUserId()));
        String companyType = selectedOrgInfo.getCompany().getCompanyType();
        // todo 1 公共权限赋值查询
        new FillingEditPermForCurrentUser(new JSONObject(changeInfo), selectedOrgInfo.getCompany(), BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION).getData();
        // todo 注意顺序 通用的FillingEditPermForCurrentUser里有companyType了 但是和此业务不一样，故还是使用原来的，否则页面需要调整较多
        if ("个人主体".equals(companyType)) {
            changeInfo.put("companyType", "person");
        } else {
            changeInfo.put("companyType", "company");
        }
        // todo 本来FillingEditPermForCurrentUser已赋值但是此业务也使用的key companyType故新赋值key
        changeInfo.put("companyType2", CommonServiceImpl.getCompanyType(selectedOrgInfo.getCompany()));
        return new HashMap<String, Map<String, Object>>() {{
//            this.put("changeRegisInfo", fillEquipInfoWithRuntimeOrHistoryData(notice, changeInfo));
            this.put("changeRegisInfo", changeInfo);
        }};
    }

    private Map<String, Object> fillEquipInfoWithRuntimeOrHistoryData(JgChangeRegistrationUnit notice, Map<String, Object> changeInfo) {
        // 已完成时显示历史数据
        if (notice.getStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName())) {
            JSONObject his = commonService.queryHistoryData(notice.getSequenceNbr());
            // 兼容老数据
            if (his == null) {
                return getEquipInfo(notice.getSequenceNbr(), changeInfo);
            }
            CommonServiceImpl.formatTime2StrDateForEquip(his);
            his.putAll(changeInfo);
            return his;
        }
        // 非完成状态返回实时使用登记证数据
        return getEquipInfo(notice.getSequenceNbr(), changeInfo);
    }


    private Map<String, Object> getEquipInfo(Long sequenceNbr, Map<String, Object> changeInfo) {
        String[] fields = {"productPhoto", "designDoc", "designStandard", "factoryStandard",
                "productQualityYieldProve", "insUseMaintainExplain", "inspectReport", "otherAccessoriesList",
                "proxyStatementAttachment", "installContractAttachment", "changeCertificateList"};

        // 设备信息
        List<Map<String, Object>> equipmentInfos = JgChangeRegistrationUnitMapper.queryEquipInformation(sequenceNbr);
        String equipId = JgChangeRegistrationUnitMapper.queryEquipIdBySeq(sequenceNbr);
        Map<String, Object> detailFieldCamelCaseByRecord = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(equipId);
        detailFieldCamelCaseByRecord.remove("useUnitCreditCode");


        for (String s : fields) {
            if (changeInfo.containsKey(s) && !ObjectUtils.isEmpty(changeInfo.get(s))) {
                changeInfo.put(s, JSON.parseArray(changeInfo.get(s).toString()));
            }
            if (equipmentInfos.get(0).containsKey(s) && !ObjectUtils.isEmpty(equipmentInfos.get(0).get(s))) {
                equipmentInfos.get(0).put(s, JSON.parseArray(equipmentInfos.get(0).get(s).toString()));
            }
        }

        Map<String, Object> newMap = new HashMap<>();
        newMap.putAll(detailFieldCamelCaseByRecord);
        newMap.putAll(changeInfo);
        newMap.putAll(equipmentInfos.get(0));
        return newMap;
    }

    /**
     * 更新单位变更
     *
     * @param noticeDto 单位变更
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    public JgChangeRegistrationUnitDto updateInstallationNotice(String submitType, JgChangeRegistrationUnitDto noticeDto, String op, ReginParams reginParams) {
        try {
            if (Objects.isNull(noticeDto) || StringUtils.isEmpty(submitType)) {
                throw new IllegalArgumentException("参数不能为空");
            }
            if (PipelineEnum.PRESSURE_PIPELINE.getCode().equals(noticeDto.getEquListCode())) {
                dealProjectContraptionToUpdate(submitType, noticeDto, op, reginParams);
            } else if (CylinderTypeEnum.CYLINDER.getCode().equals(noticeDto.getEquCategoryCode())) {
                this.dealCylinderToUpdate(submitType, noticeDto, op, reginParams);
            } else {
                // 字段转换
                this.convertField(noticeDto);
                // 获取单位变更使用登记证列表
                List<Map<String, Object>> registrationList = noticeDto.getRegistrationList();
                if (CollectionUtils.isEmpty(registrationList)) {
                    throw new BadRequest("使用登记证不能为空");
                }
                //根据使用登记证查询设备
                List<Long> registrationIdList = registrationList.stream().filter(v -> v.containsKey(SEQUENCE_NBR) &&
                                ObjectUtils.isNotEmpty(v.get(SEQUENCE_NBR)) && canConvertToLong(v.get(SEQUENCE_NBR).toString()))
                        .map(v -> Long.parseLong(v.get(SEQUENCE_NBR).toString())).collect(Collectors.toList());
                // 获取单位变更设备列表
                if (CollectionUtils.isEmpty(registrationIdList)) {
                    throw new BadRequest("使用登记证不能为空");
                }
                List<JSONObject> deviceList = registrationManageService.queryEquByCertificateSeqList(registrationIdList);
                // 获取单位变更设备列表
                if (CollectionUtils.isEmpty(deviceList)) {
                    throw new BadRequest("使用登记证下无设备");
                }
                //场车区分区外还是区内
                if (EQU_CODE_CC.equals(noticeDto.getEquListCode())) {
                    String city = Objects.toString(noticeDto.getCity(), "");
                    String userCity = Optional.ofNullable(city).map(c -> c.split("_")[0]).orElseThrow(() -> new BadRequest("请选择地市后暂存！"));
                    this.validateDeviceCity(deviceList, userCity, "0".equals(noticeDto.getChangeType()));
                    this.setEquAddress(noticeDto);
                }
                ArrayList<String> roleListAll = new ArrayList<>();
                ArrayList<String> roleListNext = new ArrayList<>();
                if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                    // 发起流程
                    if (!StringUtils.hasText(noticeDto.getInstanceId())) {
                        List<ProcessTaskDTO> processTasks = new ArrayList<>();
                        ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                        List<ActWorkflowStartDTO> list = new ArrayList<>();
                        ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                        dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
                        dto.setBusinessKey(String.valueOf(new Date().getTime()));
                        dto.setCompleteFirstTask(true);
                        list.add(dto);
                        actWorkflowBatchDTO.setProcess(list);
                        dto.setNextExecuteUserCompanyCode(noticeDto.getReceiveCompanyCode());
                        processTasks = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                        String instanceId = processTasks.get(0).getProcessInstance().getId();
                        String nextTaskId = processTasks.get(0).getNextTask().get(0).getId();
                        String taskname = processTasks.get(0).getNextTask().get(0).getName();
                        this.buildRoleList(processTasks, roleListNext, roleListAll);
                        List<WorkflowResultDto> workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(processTasks);
                        String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();

                        JgChangeRegistrationUnit notice = new JgChangeRegistrationUnit();
                        BeanUtils.copyProperties(noticeDto, notice);
                        notice.setChangeCertificate(noticeDto.getChangeCertificate());
                        notice.setRemark(noticeDto.getRemark());
                        if (!ObjectUtils.isEmpty(notice.getInstanceStatus())) {
                            notice.setInstanceStatus(notice.getInstanceStatus() + "," + roleListAll);
                        } else {
                            notice.setInstanceStatus(String.join(",", roleListAll));
                        }
                        notice.setInstanceId(instanceId);
                        notice.setNextTaskId(nextTaskId);
                        notice.setSupervisoryCode(noticeDto.getSupervisoryCode());
                        notice.setPromoter(RequestContext.getExeUserId());
                        notice.setNextExecutorIds(String.join(",", roleListNext));
                        notice.setStatus(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
                        notice.setNextExecuteUserIds(nextUserIds);
                        setNewUnitInfo(reginParams, notice);
                        JgChangeRegistrationUnitMapper.updateById(notice);
                        commonServiceImpl.deleteTasksByRelationId(notice.getSequenceNbr() + "");
                        createTaskModel(notice, taskname, "1", nextUserIds);
                        commonServiceImpl.saveExecuteFlowData2Redis(notice.getInstanceId(), buildInstanceRuntimeData(notice));
                    } else {
                        ArrayList<String> roleList = new ArrayList<>();
                        String taskId = noticeDto.getNextTaskId();
                        //组装信息
                        TaskResultDTO task = new TaskResultDTO();
                        task.setResultCode("approvalStatus");
                        task.setTaskId(taskId);
                        task.setComment("");
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("approvalStatus", op);
                        if (!ObjectUtils.isEmpty(noticeDto.getInstanceStatus()) &&
                                (noticeDto.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject()) ||
                                        noticeDto.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack()))) {
                            map.put("approvalStatus", "提交");
                        }
                        task.setVariable(map);
                        //执行流程
                        task.setNextExecuteUserCompanyCode(noticeDto.getReceiveCompanyCode());
                        ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(taskId, task, op);
                        JgChangeRegistrationUnit bean = new JgChangeRegistrationUnit();
                        BeanUtils.copyProperties(noticeDto, bean);
                        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
                        String taskName1 = "";
                        String nextTaskId = "";
                        this.buildRoleList(Collections.singletonList(processTaskDTO), roleList, roleListAll);
                        List<WorkflowResultDto> workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
                        String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
                        if (processTaskDTO != null && processTaskDTO.getNextTask() != null && processTaskDTO.getNextTask().size() > 0) {
                            taskCode = processTaskDTO.getNextTask().get(0).getKey();
                            taskName1 = processTaskDTO.getNextTask().get(0).getName();
                            nextTaskId = processTaskDTO.getNextTask().get(0).getId();
                        }
                        bean.setNextExecutorIds(String.join(",", roleList));
                        if (!ObjectUtils.isEmpty(bean.getInstanceStatus())) {
                            bean.setInstanceStatus(bean.getInstanceStatus() + "," + String.join(",", roleList));
                        } else {
                            bean.setInstanceStatus(String.join(",", roleList));
                        }
                        bean.setNextTaskId(nextTaskId);
                        bean.setPromoter(RequestContext.getExeUserId());
                        bean.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
                        executeOneStep(bean, taskName1, nextUserIds, op);
                        bean.setNextExecuteUserIds(nextUserIds);
                        setNewUnitInfo(reginParams, bean);
                        JgChangeRegistrationUnitMapper.updateById(bean);
                        commonServiceImpl.saveExecuteFlowData2Redis(bean.getInstanceId(), buildInstanceRuntimeData(bean));
                    }
                } else {
                    JgChangeRegistrationUnit bean = new JgChangeRegistrationUnit();
                    BeanUtils.copyProperties(noticeDto, bean);
                    setNewUnitInfo(reginParams, bean);
                    JgChangeRegistrationUnitMapper.updateById(bean);
                }
                List<JgChangeRegistrationUnitEq> jgRelationEquipList = new ArrayList<>();
                deviceList.forEach(device -> {
                    JgChangeRegistrationUnitEq unitEq = new JgChangeRegistrationUnitEq();
                    if (device.containsKey("USE_ORG_CODE")) {
                        unitEq.setRegistrationCertificate(device.getString("USE_ORG_CODE"));//使用登记证主键
                    }
                    if (device.containsKey("SEQUENCE_NBR")) {
                        unitEq.setEquId(device.getString("SEQUENCE_NBR"));//设备主键
                    }
                    unitEq.setUnitChangeRegistrationId(noticeDto.getSequenceNbr().toString());//单位变更业务主键
                    unitEq.setDeviceInfo(JSONObject.toJSONString(device));//设备信息json
                    jgRelationEquipList.add(unitEq);
                });
                JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
                //登记类别
                jgRegistrationHistory.setRegistrationClass("单位变更登记");
                jgRegistrationHistory.setCurrentDocumentId(noticeDto.getApplyNo());
                //使用登记证历史数据
                jgRegistrationHistory.setChangeData(JSONObject.toJSONString(registrationList));
                //先删除之前设备关系数据，在插入最新设备关系数据
                registrationUnitEqService.getBaseMapper().delete(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                        .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, noticeDto.getSequenceNbr()));
                registrationUnitEqService.saveBatch(jgRelationEquipList);
                //先删除之前未提交的历史使用登记证信息，在插入最新的使用登记证信息
                registrationHistoryService.getBaseMapper().delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                        .eq(JgRegistrationHistory::getCurrentDocumentId, noticeDto.getApplyNo()));
                registrationHistoryService.save(jgRegistrationHistory);

                if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                    //如果是提交，用于校验设备是否已经在流程中，如果不在标记设备已经在流程中
                    CompanyBo company = reginParams.getCompany();
                    deviceList.forEach(jsonObject -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                            .equipRepeatUsedCheck(String.valueOf(jsonObject.get("SEQUENCE_NBR")),
                                    CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ?
                                            company.getCompanyCode().split("_")[1] :
                                            company.getCompanyCode()));
                }
            }
            return noticeDto;
        } catch (BadRequest | LocalBadRequest e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw new BadRequest(e.getMessage());
        } finally {
            FlowingEquipRedisContext.clean();
        }
    }

    private void dealCylinderToUpdate(String submitType, JgChangeRegistrationUnitDto changeRegistrationUnitDto, String op, ReginParams reginParams) {
        // 字段转换
        this.convertField(changeRegistrationUnitDto);
        // 获取单位变更设备列表
        List<Map<String, Object>> deviceList = changeRegistrationUnitDto.getDeviceList();
        if (CollectionUtils.isEmpty(deviceList)) {
            throw new BadRequest("请选择设备后提交");
        }
        if (deviceList.size() > ONCE_MAX_SUBMIT) {
            throw new BadRequest("单次提交最多允许 " + ONCE_MAX_SUBMIT + " 条数据，请分批提交！");
        }
        if (SUBMIT_TYPE_FLOW.equals(submitType)) { //放在最后面防止前面有异常
            //如果是提交，用于校验设备是否已经在流程中，如果不在标记设备已经在流程中
            CompanyBo company = reginParams.getCompany();
            deviceList.forEach(jsonObject -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .equipRepeatUsedCheck(String.valueOf(jsonObject.get(RECORD)),
                            CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ? company.getCompanyCode().split("_")[1] : company.getCompanyCode()));
        }
        ArrayList<String> roleListAll = new ArrayList<>();
        ArrayList<String> roleListNext = new ArrayList<>();
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            // 发起流程
            if (!StringUtils.hasText(changeRegistrationUnitDto.getInstanceId())) {
                List<ProcessTaskDTO> processTasks = new ArrayList<>();
                ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                List<ActWorkflowStartDTO> list = new ArrayList<>();
                ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
                dto.setBusinessKey(String.valueOf(new Date().getTime()));
                dto.setCompleteFirstTask(true);
                list.add(dto);
                actWorkflowBatchDTO.setProcess(list);
                dto.setNextExecuteUserCompanyCode(changeRegistrationUnitDto.getReceiveCompanyCode());
                processTasks = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                String instanceId = processTasks.get(0).getProcessInstance().getId();
                String nextTaskId = processTasks.get(0).getNextTask().get(0).getId();
                String taskname = processTasks.get(0).getNextTask().get(0).getName();
                this.buildRoleList(processTasks, roleListNext, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(processTasks);
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();

                JgChangeRegistrationUnit notice = new JgChangeRegistrationUnit();
                BeanUtils.copyProperties(changeRegistrationUnitDto, notice);
                notice.setChangeCertificate(changeRegistrationUnitDto.getChangeCertificate());
                notice.setRemark(changeRegistrationUnitDto.getRemark());
                if (!ObjectUtils.isEmpty(notice.getInstanceStatus())) {
                    notice.setInstanceStatus(notice.getInstanceStatus() + "," + roleListAll);
                } else {
                    notice.setInstanceStatus(String.join(",", roleListAll));
                }
                notice.setInstanceId(instanceId);
                notice.setNextTaskId(nextTaskId);
                notice.setPromoter(RequestContext.getExeUserId());
                notice.setNextExecutorIds(String.join(",", roleListNext));
                notice.setStatus(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
                notice.setNextExecuteUserIds(nextUserIds);
                setNewUnitInfo(reginParams, notice);
                JgChangeRegistrationUnitMapper.updateById(notice);
                commonServiceImpl.deleteTasksByRelationId(notice.getSequenceNbr() + "");
                createTaskModel(notice, taskname, "1", nextUserIds);
                commonServiceImpl.saveExecuteFlowData2Redis(notice.getInstanceId(), buildInstanceRuntimeData(notice));
            } else {
                ArrayList<String> roleList = new ArrayList<>();
                String taskId = changeRegistrationUnitDto.getNextTaskId();
                //组装信息
                TaskResultDTO task = new TaskResultDTO();
                task.setResultCode("approvalStatus");
                task.setTaskId(taskId);
                task.setComment("");
                HashMap<String, Object> map = new HashMap<>();
                map.put("approvalStatus", op);
                if (!ObjectUtils.isEmpty(changeRegistrationUnitDto.getInstanceStatus()) &&
                        (changeRegistrationUnitDto.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject()) ||
                                changeRegistrationUnitDto.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack()))) {
                    map.put("approvalStatus", "提交");
                }
                task.setVariable(map);
                //执行流程
                task.setNextExecuteUserCompanyCode(changeRegistrationUnitDto.getReceiveCompanyCode());
                ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(taskId, task, op);
                JgChangeRegistrationUnit bean = new JgChangeRegistrationUnit();
                BeanUtils.copyProperties(changeRegistrationUnitDto, bean);
                String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
                String taskName1 = "";
                String nextTaskId = "";
                this.buildRoleList(Collections.singletonList(processTaskDTO), roleList, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
                if (processTaskDTO != null && processTaskDTO.getNextTask() != null && !processTaskDTO.getNextTask().isEmpty()) {
                    taskCode = processTaskDTO.getNextTask().get(0).getKey();
                    taskName1 = processTaskDTO.getNextTask().get(0).getName();
                    nextTaskId = processTaskDTO.getNextTask().get(0).getId();
                }
                bean.setNextExecutorIds(String.join(",", roleList));
                if (!ObjectUtils.isEmpty(bean.getInstanceStatus())) {
                    bean.setInstanceStatus(bean.getInstanceStatus() + "," + String.join(",", roleList));
                } else {
                    bean.setInstanceStatus(String.join(",", roleList));
                }
                bean.setNextTaskId(nextTaskId);
                bean.setPromoter(RequestContext.getExeUserId());
                bean.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
                executeOneStep(bean, taskName1, nextUserIds, op);
                bean.setNextExecuteUserIds(nextUserIds);
                setNewUnitInfo(reginParams, bean);
                JgChangeRegistrationUnitMapper.updateById(bean);
                commonServiceImpl.saveExecuteFlowData2Redis(bean.getInstanceId(), buildInstanceRuntimeData(bean));
            }
        } else {
            JgChangeRegistrationUnit bean = new JgChangeRegistrationUnit();
            BeanUtils.copyProperties(changeRegistrationUnitDto, bean);
            setNewUnitInfo(reginParams, bean);
            JgChangeRegistrationUnitMapper.updateById(bean);
        }
        List<JgChangeRegistrationUnitEq> jgRelationEquipList = new ArrayList<>();
        deviceList.forEach(device -> {
            JgChangeRegistrationUnitEq unitEq = new JgChangeRegistrationUnitEq();
            unitEq.setRegistrationCertificate(changeRegistrationUnitDto.getUseRegistrationCertificate());
            unitEq.setEquId(Objects.toString(device.get(RECORD)));
            unitEq.setUnitChangeRegistrationId(changeRegistrationUnitDto.getSequenceNbr().toString());
            unitEq.setDeviceInfo(JSONObject.toJSONString(device));//设备信息json
            jgRelationEquipList.add(unitEq);
        });
        JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
        //登记类别
        jgRegistrationHistory.setRegistrationClass("单位变更登记");
        jgRegistrationHistory.setCurrentDocumentId(changeRegistrationUnitDto.getApplyNo());
        //使用登记证历史数据
        jgRegistrationHistory.setChangeData(JSON.toJSONString(deviceList));
        //先删除之前设备关系数据，在插入最新设备关系数据
        registrationUnitEqService.getBaseMapper().delete(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, changeRegistrationUnitDto.getSequenceNbr()));
        registrationUnitEqService.saveBatch(jgRelationEquipList);
        //先删除之前未提交的历史使用登记证信息，在插入最新的使用登记证信息
        registrationHistoryService.getBaseMapper().delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, changeRegistrationUnitDto.getApplyNo()));
        registrationHistoryService.save(jgRegistrationHistory);
    }

    /**
     * 气瓶单位变更业务
     * @param submitType 提交类型
     * @param dto 提交参数
     * @param op
     * @param reginParams
     */
    private void saveOrUpdateCylinder(String submitType, JgChangeRegistrationUnitDto dto, String op, ReginParams reginParams) {
        // 1️⃣ 字段转换与前置校验
        convertField(dto);
        validateDeviceList(dto.getDeviceList());

        // 2️⃣ 获取申请编号
        List<String> applyNoList = resolveApplyNo(dto);
        dto.setApplyNo(applyNoList.get(0));

        // 3️⃣ 校验设备是否正在流程中
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            validateEquipUsed(dto.getDeviceList(), reginParams);
        }

        // 4️⃣ 流程逻辑统一处理
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            handleFlow(dto, op, reginParams);
        } else {
            handleSaveOnly(dto, reginParams);
        }
        // 5️⃣ 保存设备关系与历史
        saveUnitEquipAndHistory(dto);
    }

    private void validateDeviceList(List<Map<String, Object>> deviceList) {
        if (CollectionUtils.isEmpty(deviceList)) {
            throw new BadRequest("请选择设备后提交");
        }
    }

    private List<String> resolveApplyNo(JgChangeRegistrationUnitDto dto) {
        if (ValidationUtil.isEmpty(dto.getApplyNo())) {
            return Optional.ofNullable(
                            tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.DWBG.getCode(), 1)
                    ).filter(r -> r.getStatus() == HttpStatus.OK.value() && CollUtil.isNotEmpty(r.getResult()))
                    .map(ResponseModel::getResult)
                    .orElseThrow(() -> new BadRequest("生成申请变更单位编码失败！"));
        }
        return Collections.singletonList(dto.getApplyNo());
    }

    private void validateEquipUsed(List<Map<String, Object>> deviceList, ReginParams reginParams) {
        CompanyBo company = reginParams.getCompany();
        String companyCode = CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType())
                ? company.getCompanyCode().split("_")[1]
                : company.getCompanyCode();

        deviceList.forEach(json -> EquipUsedCheckStrategyContext
                .getUsedStrategy(PROCESS_DEFINITION_KEY)
                .equipRepeatUsedCheck(String.valueOf(json.get(RECORD)), companyCode));
    }

    private void handleFlow(JgChangeRegistrationUnitDto dto, String op, ReginParams reginParams) {
        if (!StringUtils.hasText(dto.getInstanceId())) {
            startNewFlow(dto, reginParams);
        } else {
            updateExistingFlow(dto, op, reginParams);
        }
    }

    private void startNewFlow(JgChangeRegistrationUnitDto dto, ReginParams reginParams) {
        ActWorkflowStartDTO startDTO = new ActWorkflowStartDTO();
        startDTO.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
        startDTO.setBusinessKey(String.valueOf(System.currentTimeMillis()));
        startDTO.setCompleteFirstTask(true);
        startDTO.setNextExecuteUserCompanyCode(dto.getReceiveCompanyCode());

        ActWorkflowBatchDTO batch = new ActWorkflowBatchDTO();
        batch.setProcess(Collections.singletonList(startDTO));

        List<ProcessTaskDTO> processTasks = cmWorkflowService.startBatch(batch);
        ProcessTaskDTO first = processTasks.get(0);

        String instanceId = first.getProcessInstance().getId();
        String nextTaskId = first.getNextTask().get(0).getId();
        String taskName = first.getNextTask().get(0).getName();

        ArrayList<String> roleListAll = new ArrayList<>();
        ArrayList<String> roleListNext = new ArrayList<>();
        buildRoleList(processTasks, roleListNext, roleListAll);

        List<WorkflowResultDto> workflowInfos = commonServiceImpl.buildWorkFlowInfo(processTasks);
        String nextUserIds = workflowInfos.get(0).getNextExecutorUserIds();

        JgChangeRegistrationUnit entity = new JgChangeRegistrationUnit();
        BeanUtils.copyProperties(dto, entity);
        entity.setInstanceId(instanceId);
        entity.setNextTaskId(nextTaskId);
        entity.setPromoter(RequestContext.getExeUserId());
        entity.setNextExecutorIds(String.join(",", roleListNext));
        entity.setNextExecuteUserIds(nextUserIds);
        entity.setStatus(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
        entity.setInstanceStatus(String.join(",", roleListAll));

        setNewUnitInfo(reginParams, entity);
        JgChangeRegistrationUnitMapper.updateById(entity);

        commonServiceImpl.deleteTasksByRelationId(entity.getSequenceNbr() + "");
        createTaskModel(entity, taskName, "1", nextUserIds);
        commonServiceImpl.saveExecuteFlowData2Redis(entity.getInstanceId(), buildInstanceRuntimeData(entity));
    }

    private void handleProcessUpdate(JgChangeRegistrationUnitDto dto, ProcessTaskDTO processTask, String op, ReginParams reginParams) {
        ArrayList<String> roleList = new ArrayList<>();
        ArrayList<String> roleListAll = new ArrayList<>();

        buildRoleList(Collections.singletonList(processTask), roleList, roleListAll);
        List<WorkflowResultDto> workflowInfos = commonServiceImpl.buildWorkFlowInfo(Collections.singletonList(processTask));
        String nextUserIds = workflowInfos.get(0).getNextExecutorUserIds();

        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        String taskName = "";
        String nextTaskId = "";

        if (processTask.getNextTask() != null && !processTask.getNextTask().isEmpty()) {
            taskCode = processTask.getNextTask().get(0).getKey();
            taskName = processTask.getNextTask().get(0).getName();
            nextTaskId = processTask.getNextTask().get(0).getId();
        }

        JgChangeRegistrationUnit entity = new JgChangeRegistrationUnit();
        BeanUtils.copyProperties(dto, entity);
        entity.setNextTaskId(nextTaskId);
        entity.setPromoter(RequestContext.getExeUserId());
        entity.setNextExecutorIds(String.join(",", roleList));
        entity.setNextExecuteUserIds(nextUserIds);
        entity.setInstanceStatus(String.join(",", roleListAll));
        entity.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());

        executeOneStep(entity, taskName, nextUserIds, op);
        setNewUnitInfo(reginParams, entity);
        JgChangeRegistrationUnitMapper.updateById(entity);
        commonServiceImpl.saveExecuteFlowData2Redis(entity.getInstanceId(), buildInstanceRuntimeData(entity));
    }

    private void updateExistingFlow(JgChangeRegistrationUnitDto dto, String op, ReginParams reginParams) {
        String taskId = dto.getNextTaskId();

        TaskResultDTO task = new TaskResultDTO();
        task.setResultCode("approvalStatus");
        task.setTaskId(taskId);
        task.setComment("");

        HashMap<String, Object> variable = new HashMap<>();
        variable.put("approvalStatus", op);
        if (!ObjectUtils.isEmpty(dto.getInstanceStatus())
                && (WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject().equals(dto.getStatus())
                || WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack().equals(dto.getStatus()))) {
            variable.put("approvalStatus", "提交");
        }
        task.setVariable(variable);
        task.setNextExecuteUserCompanyCode(dto.getReceiveCompanyCode());

        ProcessTaskDTO processTask = cmWorkflowService.completeOrReject(taskId, task, op);
        handleProcessUpdate(dto, processTask, op, reginParams);
    }

    private void handleSaveOnly(JgChangeRegistrationUnitDto dto, ReginParams reginParams) {
        JgChangeRegistrationUnit entity = new JgChangeRegistrationUnit();
        BeanUtils.copyProperties(dto, entity);
        setNewUnitInfo(reginParams, entity);
        JgChangeRegistrationUnitMapper.updateById(entity);
    }

    private void saveUnitEquipAndHistory(JgChangeRegistrationUnitDto dto) {
        List<Map<String, Object>> deviceList = dto.getDeviceList();

        List<JgChangeRegistrationUnitEq> unitEqs = deviceList.stream().map(device -> {
            JgChangeRegistrationUnitEq eq = new JgChangeRegistrationUnitEq();
            eq.setRegistrationCertificate(dto.getUseRegistrationCertificate());
            eq.setEquId(String.valueOf(device.get(RECORD)));
            eq.setUnitChangeRegistrationId(dto.getSequenceNbr().toString());
            eq.setDeviceInfo(JSONObject.toJSONString(device));
            return eq;
        }).collect(Collectors.toList());

        registrationUnitEqService.remove(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, dto.getSequenceNbr()));
        registrationUnitEqService.saveBatch(unitEqs);

        JgRegistrationHistory history = new JgRegistrationHistory();
        history.setRegistrationClass("单位变更登记");
        history.setCurrentDocumentId(dto.getApplyNo());
        history.setChangeData(JSON.toJSONString(deviceList));

        registrationHistoryService.remove(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, dto.getApplyNo()));
        registrationHistoryService.save(history);
    }

    /**
     * 气瓶单位变更业务新增
     * @param submitType
     * @param changeRegistrationUnitDto
     * @param reginParams
     */
    private void dealCylinderToSave(String submitType, JgChangeRegistrationUnitDto changeRegistrationUnitDto, ReginParams reginParams) {
        String[] taskName = new String[]{"流程结束"};
        // 字段转换
        this.convertField(changeRegistrationUnitDto);
        // 获取单位变更设备列表
        List<Map<String, Object>> deviceList = changeRegistrationUnitDto.getDeviceList();
        if (CollectionUtils.isEmpty(deviceList)) {
            throw new BadRequest("请选择设备后提交");
        }

        String applyNo = changeRegistrationUnitDto.getApplyNo();
        List<String> applyNoList = ValidationUtil.isEmpty(applyNo)
                ? Optional.ofNullable(tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.DWBG.getCode(), 1))
                .filter(r -> r.getStatus() == HttpStatus.OK.value() && !CollectionUtils.isEmpty(r.getResult()))
                .map(ResponseModel::getResult)
                .orElseThrow(() -> new BadRequest("生成申请变更单位编码失败！"))
                : Collections.singletonList(applyNo);

        if (SUBMIT_TYPE_FLOW.equals(submitType)) {//放在最后面防止前面有异常
            //如果是提交，用于校验设备是否已经在流程中，如果不在标记设备已经在流程中
            CompanyBo company = reginParams.getCompany();
            deviceList.forEach(jsonObject -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .equipRepeatUsedCheck(String.valueOf(jsonObject.get(RECORD)),
                            CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ?
                                    company.getCompanyCode().split("_")[1] :
                                    company.getCompanyCode()));
        }
        ArrayList<String> roleListFirst = new ArrayList<>();
        List<String> instanceIdList = new ArrayList<>();
        List<String> nextExecutorUserIds = new ArrayList<>();
        List<String> taskIds = new ArrayList<>();
        List<WorkflowResultDto> workflowResultDtos = new ArrayList<>();
        String nextExecutorRoleIds = "";
        // 判断当前是否为提交
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            //发起流程
            ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
            List<ActWorkflowStartDTO> list = new ArrayList<>();
            ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
            dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
            dto.setBusinessKey(String.valueOf(new Date().getTime()));
            dto.setNextExecuteUserCompanyCode(changeRegistrationUnitDto.getReceiveCompanyCode());
            dto.setCompleteFirstTask(true);
            list.add(dto);
            actWorkflowBatchDTO.setProcess(list);
            List<ProcessTaskDTO> processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
            workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
            nextExecutorRoleIds = workflowResultDtos.get(0).getNextExecutorRoleIds();
            nextExecutorUserIds.add(workflowResultDtos.get(0).getNextExecutorUserIds());
            for (WorkflowResultDto processTaskDTO : workflowResultDtos) {
                instanceIdList.add(processTaskDTO.getInstanceId());
                taskIds.add(processTaskDTO.getNextTaskId());
            }
        }

        String finalNextExecutorRoleIds = nextExecutorRoleIds;
        CompanyBo companyBo = commonServiceImpl.getOneCompany(changeRegistrationUnitDto.getReceiveCompanyCode());
        changeRegistrationUnitDto.setApplyNo(applyNoList.get(0));
        changeRegistrationUnitDto.setReceiveCompanyOrgCode(companyBo.getOrgCode());
        changeRegistrationUnitDto.setReceiveOrgCode(companyBo.getCompanyCode());
        changeRegistrationUnitDto.setCreateUserId(RequestContext.getExeUserId());
        changeRegistrationUnitDto.setApplyDate(new Date());
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            changeRegistrationUnitDto.setNextExecutorIds(finalNextExecutorRoleIds);
            changeRegistrationUnitDto.setInstanceStatus(String.join(",", roleListFirst));
            changeRegistrationUnitDto.setPromoter(reginParams.getUserModel().getUserId());
            changeRegistrationUnitDto.setStatus(taskName[0]);
        }
        if (!CollectionUtils.isEmpty(nextExecutorUserIds)) {
            changeRegistrationUnitDto.setNextExecuteUserIds(nextExecutorUserIds.get(0));
        }
        if (!CollectionUtils.isEmpty(instanceIdList)) {
            changeRegistrationUnitDto.setInstanceId(instanceIdList.get(0));
            changeRegistrationUnitDto.setStatus(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
        } else {
            changeRegistrationUnitDto.setStatus(WorkFlowStatusEnum.UNITCHANGE_SUBMIT.getPass());
        }
        if (!CollectionUtils.isEmpty(taskIds)) {
            changeRegistrationUnitDto.setNextTaskId(taskIds.get(0));
        }
        changeRegistrationUnitDto.setSequenceNbr(sequence.nextId());
        changeRegistrationUnitDto.setCreateDate(new Date());
        changeRegistrationUnitDto.setCreateUserName(reginParams.getUserModel().getRealName());
        changeRegistrationUnitDto.setUseRegistCode(changeRegistrationUnitDto.getUseRegistCode());
        Optional.of(deviceList)
                .filter(list -> !list.isEmpty())
                .map(list -> list.get(0).get("equListName"))
                .map(Object::toString)
                .ifPresent(changeRegistrationUnitDto::setEquList);
        JgChangeRegistrationUnit registrationUnit = new JgChangeRegistrationUnit();
        BeanUtils.copyProperties(changeRegistrationUnitDto, registrationUnit);
        setNewUnitInfo(reginParams, registrationUnit);
        JgChangeRegistrationUnitMapper.insert(registrationUnit);

        List<TaskModelDto> modelDtos = new ArrayList<>();
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            TaskModelDto taskModelDto = new TaskModelDto();
            TaskMessageDto ta = new TaskMessageDto();
            ta.setInstanceId(registrationUnit.getInstanceId());
            ta.setStatus(registrationUnit.getStatus());
            ta.setPromoter(registrationUnit.getPromoter());
            ta.setNextExecuteUserIds(registrationUnit.getNextExecuteUserIds());
            ta.setSequenceNbr(registrationUnit.getSequenceNbr());
            ta.setNextTaskId(registrationUnit.getNextTaskId());
            taskModelDto.setModel(ta);
            taskModelDto.setFlowCreateDate(new Date());
            taskModelDto.setTaskName(workflowResultDtos.get(0).getNextTaskName());
            taskModelDto.setFlowCode(registrationUnit.getNextTaskId());
            taskModelDto.setTaskContent(this.buildTaskContent(registrationUnit));
            taskModelDto.setTaskCode(registrationUnit.getApplyNo());
            taskModelDto.setTaskType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getCode());
            taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
            taskModelDto.setRelationId(registrationUnit.getInstanceId());
            taskModelDto.setExecuteUserIds(workflowResultDtos.get(0).getNextExecutorUserIds());
            taskModelDto.setTaskStatusLabel("未处理");
            taskModelDto.setFlowStatus(commonServiceImpl.getDictionaryCodeByName(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass()));
            taskModelDto.setFlowStatusLabel(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
            taskModelDto.setStartUserId(RequestContext.getExeUserId());
            taskModelDto.setStartUser(workflowResultDtos.get(0).getStartUserName());
            taskModelDto.setStartUserCompanyName(reginParams.getCompany().getCompanyName());
            taskModelDto.setStartDate(new Date());
            taskModelDto.setNextExecuteUser(workflowResultDtos.get(0).getNextExecutorRoleIds());
            modelDtos.add(taskModelDto);
        } else {
            TaskModelDto taskModelDto = new TaskModelDto();
            //行数据
            taskModelDto.setModel(registrationUnit);
            //摘要 按原有规则组装
            taskModelDto.setTaskContent(this.buildTaskContent(registrationUnit));
            //申请单号
            taskModelDto.setTaskCode(registrationUnit.getApplyNo());
            //业务类型枚举code值
            taskModelDto.setTaskType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getCode());
            ////业务主键
            taskModelDto.setRelationId(registrationUnit.getSequenceNbr() + "");
            modelDtos.add(taskModelDto);
//            }
        }
        commonServiceImpl.saveExecuteFlowData2Redis(registrationUnit.getInstanceId(), buildInstanceRuntimeData(registrationUnit));
        commonServiceImpl.buildTaskModel(modelDtos);

        List<JgChangeRegistrationUnitEq> jgRelationEquipList = new ArrayList<>();
        deviceList.forEach(device -> {
            JgChangeRegistrationUnitEq unitEq = new JgChangeRegistrationUnitEq();
            unitEq.setRegistrationCertificate(changeRegistrationUnitDto.getUseRegistrationCertificate());
            unitEq.setEquId(Objects.toString(device.get(RECORD)));
            unitEq.setUnitChangeRegistrationId(registrationUnit.getSequenceNbr().toString());//单位变更业务主键
            unitEq.setDeviceInfo(JSONObject.toJSONString(device));//设备信息json
            jgRelationEquipList.add(unitEq);
        });
        JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
        //登记类别
        jgRegistrationHistory.setRegistrationClass("单位变更登记");
        jgRegistrationHistory.setCurrentDocumentId(registrationUnit.getApplyNo());
        //使用登记证历史数据
        jgRegistrationHistory.setChangeData(JSONObject.toJSONString(deviceList));
        //先删除之前设备关系数据，在插入最新设备关系数据
        registrationUnitEqService.getBaseMapper().delete(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registrationUnit.getSequenceNbr()));
        registrationUnitEqService.saveBatch(jgRelationEquipList);
        //先删除之前未提交的历史使用登记证信息，在插入最新的使用登记证信息
        registrationHistoryService.getBaseMapper().delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, registrationUnit.getApplyNo()));
        registrationHistoryService.save(jgRegistrationHistory);
    }

    /**
     * 更新装置的单位变更
     *
     * @param submitType
     * @param noticeDto
     * @param op
     * @param reginParams
     */
    private void dealProjectContraptionToUpdate(String submitType, JgChangeRegistrationUnitDto noticeDto, String op, ReginParams reginParams) {
        // 字段转换
        this.convertField(noticeDto);
        // 获取单位变更装置列表
        List<Map<String, Object>> projectContraptionList = noticeDto.getProjectContraptionList();
        if (CollectionUtils.isEmpty(projectContraptionList)) {
            throw new BadRequest("工程/装置列表不能为空");
        }
        //根据使用登记证查询设备
        List<String> registrationNoList = new ArrayList<>(); //使用登记证编号
        Map<String, String> useRegistrationCodeMap = new HashMap<>();
        for (Map<String, Object> objectMap : projectContraptionList) {
            if (objectMap.containsKey("useRegistrationCode") && ObjectUtils.isNotEmpty(objectMap.get("useRegistrationCode"))) {
                registrationNoList.add(objectMap.get("useRegistrationCode").toString());
                useRegistrationCodeMap.put(objectMap.get(SEQUENCE_NBR).toString(), objectMap.get("useRegistrationCode").toString());
            }
        }
        //查询装置下的管道信息
        List<Map<String, Object>> deviceList = this.queryPipelineList(projectContraptionList);
        if (CollUtil.isEmpty(deviceList)) {
            throw new BadRequest("工程/装置下没有管道信息");
        }
        if (SUBMIT_TYPE_FLOW.equals(submitType)) { //放在最后面防止前面有异常
            //如果是提交，用于校验设备是否已经在流程中，如果不在标记设备已经在流程中
            CompanyBo company = reginParams.getCompany();
            deviceList.forEach(jsonObject -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .equipRepeatUsedCheck(String.valueOf(jsonObject.get("record")),
                            CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ? company.getCompanyCode().split("_")[1] : company.getCompanyCode()));
        }
        ArrayList<String> roleListAll = new ArrayList<>();
        ArrayList<String> roleListNext = new ArrayList<>();
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            // 发起流程
            if (!StringUtils.hasText(noticeDto.getInstanceId())) {
                List<ProcessTaskDTO> processTasks = new ArrayList<>();
                ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                List<ActWorkflowStartDTO> list = new ArrayList<>();
                ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
                dto.setBusinessKey(String.valueOf(new Date().getTime()));
                dto.setCompleteFirstTask(true);
                list.add(dto);
                actWorkflowBatchDTO.setProcess(list);
                dto.setNextExecuteUserCompanyCode(noticeDto.getReceiveCompanyCode());
                processTasks = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                String instanceId = processTasks.get(0).getProcessInstance().getId();
                String nextTaskId = processTasks.get(0).getNextTask().get(0).getId();
                String taskname = processTasks.get(0).getNextTask().get(0).getName();
                this.buildRoleList(processTasks, roleListNext, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(processTasks);
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();

                JgChangeRegistrationUnit notice = new JgChangeRegistrationUnit();
                BeanUtils.copyProperties(noticeDto, notice);
                notice.setChangeCertificate(noticeDto.getChangeCertificate());
                notice.setRemark(noticeDto.getRemark());
                if (!ObjectUtils.isEmpty(notice.getInstanceStatus())) {
                    notice.setInstanceStatus(notice.getInstanceStatus() + "," + roleListAll);
                } else {
                    notice.setInstanceStatus(String.join(",", roleListAll));
                }
                notice.setInstanceId(instanceId);
                notice.setNextTaskId(nextTaskId);
                notice.setSupervisoryCode(noticeDto.getSupervisoryCode());
                notice.setPromoter(RequestContext.getExeUserId());
                notice.setNextExecutorIds(String.join(",", roleListNext));
                notice.setStatus(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
                notice.setNextExecuteUserIds(nextUserIds);
                setNewUnitInfo(reginParams, notice);
                JgChangeRegistrationUnitMapper.updateById(notice);
                commonServiceImpl.deleteTasksByRelationId(notice.getSequenceNbr() + "");
                createTaskModel(notice, taskname, "1", nextUserIds);
                commonServiceImpl.saveExecuteFlowData2Redis(notice.getInstanceId(), buildInstanceRuntimeData(notice));
            } else {
                ArrayList<String> roleList = new ArrayList<>();
                String taskId = noticeDto.getNextTaskId();
                //组装信息
                TaskResultDTO task = new TaskResultDTO();
                task.setResultCode("approvalStatus");
                task.setTaskId(taskId);
                task.setComment("");
                HashMap<String, Object> map = new HashMap<>();
                map.put("approvalStatus", op);
                if (!ObjectUtils.isEmpty(noticeDto.getInstanceStatus()) &&
                        (noticeDto.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject()) ||
                                noticeDto.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack()))) {
                    map.put("approvalStatus", "提交");
                }
                task.setVariable(map);
                //执行流程
                task.setNextExecuteUserCompanyCode(noticeDto.getReceiveCompanyCode());
                ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(taskId, task, op);
                JgChangeRegistrationUnit bean = new JgChangeRegistrationUnit();
                BeanUtils.copyProperties(noticeDto, bean);
                String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
                String taskName1 = "";
                String nextTaskId = "";
                this.buildRoleList(Collections.singletonList(processTaskDTO), roleList, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
                if (processTaskDTO != null && processTaskDTO.getNextTask() != null && processTaskDTO.getNextTask().size() > 0) {
                    taskCode = processTaskDTO.getNextTask().get(0).getKey();
                    taskName1 = processTaskDTO.getNextTask().get(0).getName();
                    nextTaskId = processTaskDTO.getNextTask().get(0).getId();
                }
                bean.setNextExecutorIds(String.join(",", roleList));
                if (!ObjectUtils.isEmpty(bean.getInstanceStatus())) {
                    bean.setInstanceStatus(bean.getInstanceStatus() + "," + String.join(",", roleList));
                } else {
                    bean.setInstanceStatus(String.join(",", roleList));
                }
                bean.setNextTaskId(nextTaskId);
                bean.setPromoter(RequestContext.getExeUserId());
                bean.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
                executeOneStep(bean, taskName1, nextUserIds, op);
                bean.setNextExecuteUserIds(nextUserIds);
                setNewUnitInfo(reginParams, bean);
                JgChangeRegistrationUnitMapper.updateById(bean);
                commonServiceImpl.saveExecuteFlowData2Redis(bean.getInstanceId(), buildInstanceRuntimeData(bean));
            }
        } else {
            JgChangeRegistrationUnit bean = new JgChangeRegistrationUnit();
            BeanUtils.copyProperties(noticeDto, bean);
            setNewUnitInfo(reginParams, bean);
            JgChangeRegistrationUnitMapper.updateById(bean);
        }
        List<JgChangeRegistrationUnitEq> jgRelationEquipList = new ArrayList<>();
        deviceList.forEach(device -> {
            JgChangeRegistrationUnitEq unitEq = new JgChangeRegistrationUnitEq();
            if (device.containsKey("projectContraptionId")) {
                String projectContraptionId = (String) device.get("projectContraptionId");
                unitEq.setRegistrationCertificate(useRegistrationCodeMap.get(projectContraptionId));
                unitEq.setProjectContraptionId(projectContraptionId);
            }
            if (device.containsKey("record")) {
                unitEq.setEquId((String) device.get("record")); //设备主键
            }
            unitEq.setUnitChangeRegistrationId(noticeDto.getSequenceNbr().toString());//单位变更业务主键
            unitEq.setDeviceInfo(JSON.toJSONString(device));//设备信息json
            jgRelationEquipList.add(unitEq);
        });
        JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
        //登记类别
        jgRegistrationHistory.setRegistrationClass("单位变更登记");
        jgRegistrationHistory.setCurrentDocumentId(noticeDto.getApplyNo());
        //使用登记证历史数据
        jgRegistrationHistory.setChangeData(JSON.toJSONString(projectContraptionList));
        //先删除之前设备关系数据，在插入最新设备关系数据
        registrationUnitEqService.getBaseMapper().delete(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, noticeDto.getSequenceNbr()));
        registrationUnitEqService.saveBatch(jgRelationEquipList);
        //先删除之前未提交的历史使用登记证信息，在插入最新的使用登记证信息
        registrationHistoryService.getBaseMapper().delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, noticeDto.getApplyNo()));
        registrationHistoryService.save(jgRegistrationHistory);
    }

    private void setNewUnitInfo(ReginParams reginParams, JgChangeRegistrationUnit notice) {
        notice.setNewUseUnitName(CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                reginParams.getCompany().getCompanyName().split("_")[1] : reginParams.getCompany().getCompanyName());
        notice.setNewUseUnitCreditCode(CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                reginParams.getCompany().getCompanyCode().split("_")[1] :
                reginParams.getCompany().getCompanyCode());
    }


    /**
     * 分页查询
     *
     * @param page  分页对象
     * @param model 查询参数
     * @param type  类型：enterprise-企业端、supervision-监管端
     * @return 单位变更列表
     */
    @Override
    public Page<JgChangeRegistrationUnitDto> queryForJgChangeRegistrationUnitPage(Page<JgChangeRegistrationUnit> page,
                                                                                  String sort,
                                                                                  JgChangeRegistrationUnitDto model,
                                                                                  String type,
                                                                                  ReginParams reginParams,
                                                                                  String orgCode) {
        String companyCode = reginParams.getCompany().getCompanyCode();
        if (CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType())) {
            companyCode = reginParams.getCompany().getCompanyCode().split("_")[1];
        }
        String companyType = reginParams.getCompany().getCompanyType();
        String currentUserId = reginParams.getUserModel().getUserId();
        SortVo sortMap = commonServiceImpl.sortFieldConversion(sort);
        Page<JgChangeRegistrationUnit> noticePage = JgChangeRegistrationUnitMapper.queryForPage(page, sortMap, model, type, companyCode, model.getRoleIds(), currentUserId, orgCode);

        Page<JgChangeRegistrationUnitDto> noticeDtoPage = new Page<>();
        BeanUtils.copyProperties(noticePage, noticeDtoPage, "records");
        List<JgChangeRegistrationUnitDto> records = noticePage.getRecords().stream().map(notice -> {
            JgChangeRegistrationUnitDto noticeDto = new JgChangeRegistrationUnitDto();
            BeanUtils.copyProperties(notice, noticeDto);
            noticeDto.setCompanyType(companyType);
            return noticeDto;
        }).collect(Collectors.toList());
        noticeDtoPage.setRecords(records);

        return noticeDtoPage;
    }

    /**
     * 批量删除
     *
     * @param sequenceNbrs 主键
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteForBatch(Long[] sequenceNbrs) {
        if (Objects.isNull(sequenceNbrs) || sequenceNbrs.length == 0) {
            return false;
        }
        for (Long sequenceNbr : sequenceNbrs) {
            JgChangeRegistrationUnit changeRegistrationUnit = this.baseMapper.selectById(sequenceNbr);
            // 删除代办 + 中止流程
            commonServiceImpl.deleteTaskModel(String.valueOf(sequenceNbr), changeRegistrationUnit.getInstanceId());
            // 删除单子
            this.baseMapper.deleteById(sequenceNbr);
            // 删除单子对应eq
            jgChangeRegistrationUnitEqMapper.delete(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                    .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, sequenceNbr));
            // 删除单子对应历史表数据
            jgRegistrationHistoryMapper.delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getCurrentDocumentId, changeRegistrationUnit.getApplyNo()));
        }
        return Boolean.TRUE;
    }

    public void saveRecord(JgChangeRegistrationUnit registrationUnit) {
        Long sequenceNbr = registrationUnit.getSequenceNbr();
        List<JgChangeRegistrationUnitEq> eqList = registrationUnitEqService.lambdaQuery().eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, sequenceNbr).list();
        List<JgRegistrationHistory> historyList = registrationHistoryService.lambdaQuery().eq(JgRegistrationHistory::getCurrentDocumentId, registrationUnit.getApplyNo()).list();
        if (historyList.size() != 1) {
            return;
        }
        List<JgCertificateChangeRecord> changeRecordList = new ArrayList<>();
        List<JgCertificateChangeRecordEq> changeRecordEqList = new ArrayList<>();
        JSONArray historyJson = JSON.parseArray(historyList.get(0).getChangeData());
        FeignClientResult<AgencyUserModel> agencyUserModelFeignClientResult = Privilege.agencyUserClient.queryByUserId(registrationUnit.getCreateUserId());
        registrationUnit.setCreateUserName(agencyUserModelFeignClientResult.getResult().getRealName());
        for (Object object : historyJson) {
            JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord();
            long nextId = sequence.nextId();
            JSONObject jsonObject = JSON.parseObject(object.toString());
            String registrationCode = jsonObject.getString("useRegistrationCode");
            String certificateNo = jsonObject.getString("certificateNo");
            String equCategoryCode = jsonObject.getString("equCategoryCode");
            changeRecord.setApplyNo(registrationUnit.getApplyNo());//申请编号
            changeRecord.setReceiveOrgName(registrationUnit.getReceiveOrgName());//接收机构/登记机关
            changeRecord.setAuditPassDate(registrationUnit.getApplyDate());//办理日期
            changeRecord.setRegType("单位变更登记");//登记类别
            changeRecord.setRegDate(registrationUnit.getCreateDate());//申请日期
            changeRecord.setChangeContent(this.buildRecordContent(registrationUnit));//变更内容
            changeRecord.setUseRegistrationCode(registrationCode);//使用登记编号
            changeRecord.setReceiveCompanyCode(registrationUnit.getReceiveCompanyCode());//接收机构公司代码
            changeRecord.setCertificateNo(certificateNo);//登记证书唯一码
            changeRecord.setUseUnitCreditCode(registrationUnit.getNewUseUnitCreditCode());//使用单位统一信用代码
            changeRecord.setUseUnitName(registrationUnit.getNewUseUnitName());//使用单位名称
            changeRecord.setEquCategory(equCategoryCode);//设备类别编码
            changeRecord.setCreateDate(new Date());
            changeRecord.setSequenceNbr(nextId);
            changeRecordList.add(changeRecord);
            for (JgChangeRegistrationUnitEq unitEq : eqList) {
                if (!StringUtils.isEmpty(unitEq.getRegistrationCertificate()) && !StringUtils.isEmpty(registrationCode) &&
                        unitEq.getRegistrationCertificate().equals(registrationCode)) {
                    JSONObject deviceJson = JSON.parseObject(unitEq.getDeviceInfo());
                    JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
                    changeRecordEq.setChangeRecordId(String.valueOf(nextId));//登记证记录主键
                    changeRecordEq.setEquId(deviceJson.getString("SEQUENCE_NBR"));//设备主键
                    changeRecordEqList.add(changeRecordEq);
                }
            }
        }
        if (!changeRecordList.isEmpty()) {
            certificateChangeRecordService.saveBatch(changeRecordList);
        }
        if (!changeRecordEqList.isEmpty()) {
            certificateChangeRecordEqService.saveBatch(changeRecordEqList);
        }
    }

    private void checkForRepeatUsedEquip(JSONObject map, CompanyBo company) {
        if (!ObjectUtils.isEmpty(map.get("submit"))) {
            // 流程中或已完成
            EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY).equipRepeatUsedCheck(map.get("equipId").toString(), company.getCompanyCode());
        }
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public List<JgChangeRegistrationUnitDto> saveNotice(String submitType, JSONObject map, ReginParams reginParams) {
        try {
            JgChangeRegistrationUnitDto model = BeanUtil.toBeanIgnoreError(map.get("changeRegisInfo"), JgChangeRegistrationUnitDto.class);
            Map<String, Object> tableData = (Map<String, Object>) map.get("changeRegisInfo");
            String[] taskName = new String[]{"流程结束"};
            // 字段转换
            convertField(model);
            if (CylinderTypeEnum.CYLINDER.getCode().equals(model.getEquCategoryCode())) {
                this.dealCylinderToSave(submitType, model, reginParams);
            } else{
                // 获取单位变更使用登记证列表
                List<Map<String, Object>> registrationList = model.getRegistrationList();
                if (CollectionUtils.isEmpty(registrationList)) {
                    throw new BadRequest("使用登记证不能为空");
                }
                //根据使用登记证查询设备
                List<Long> registrationIdList = new ArrayList<>();//使用登记证id
                List<String> registrationNoList = new ArrayList<>();//使用登记证编号
                for (Map<String, Object> objectMap : registrationList) {
                    if (objectMap.containsKey(SEQUENCE_NBR) && ObjectUtils.isNotEmpty(objectMap.get(SEQUENCE_NBR))
                            && canConvertToLong(objectMap.get(SEQUENCE_NBR).toString())) {
                        registrationIdList.add(Long.parseLong(objectMap.get(SEQUENCE_NBR).toString()));
                    }
                    if (objectMap.containsKey("useRegistrationCode") && ObjectUtils.isNotEmpty(objectMap.get("useRegistrationCode"))) {
                        registrationNoList.add(objectMap.get("useRegistrationCode").toString());
                    }
                    // 处理产权单位
                    // 使用用户输入的产权单位信息未查询到数据，则保存新的产权单位信息
                    if (!ValidationUtil.isEmpty(objectMap.get("estateUnitName"))) {
                        String estateUnitSeq = String.valueOf(objectMap.get("estateUnitName"));
                        Map<String, String> propertyUnitInfo = commonServiceImpl.queryTcmUnitInfoBySeq(estateUnitSeq, TcmUnitTypeEnum.CQ.getCode());
                        objectMap.put("estateUnitSeq", propertyUnitInfo.get("sequenceNbr"));
                    }
                }
                if (CollectionUtils.isEmpty(registrationIdList)) {
                    throw new BadRequest("使用登记证不能为空");
                }
                List<JSONObject> deviceList = registrationManageService.queryEquByCertificateSeqList(registrationIdList);
                // 获取单位变更设备列表
                if (CollectionUtils.isEmpty(deviceList)) {
                    throw new BadRequest("使用登记证下无设备");
                }
                //场车区分区外还是区内
                if (EQU_CODE_CC.equals(model.getEquListCode())) {
                    String city = Objects.toString(tableData.get("city"), "");
                    String userCity = Optional.ofNullable(city).map(c -> c.split("_")[0]).orElseThrow(() -> new BadRequest("请选择地市后暂存！"));
                    this.validateDeviceCity(deviceList, userCity, "0".equals(model.getChangeType()));
                    this.setEquAddress(model);
                }

                // 获取单位变更单号
                ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.DWBG.getCode(), 1);
                List<String> applyNoList = listResponseModel.getResult();
                if (CollectionUtils.isEmpty(applyNoList)) {
                    log.error("生成申请变更单位编码失败");
                    return new ArrayList<>();
                }
                if (SUBMIT_TYPE_FLOW.equals(submitType)) {//放在最后面防止前面有异常
                    //如果是提交，用于校验设备是否已经在流程中，如果不在标记设备已经在流程中
                    CompanyBo company = reginParams.getCompany();
                    deviceList.forEach(jsonObject -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                            .equipRepeatUsedCheck(String.valueOf(jsonObject.get("SEQUENCE_NBR")),
                                    CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ?
                                            company.getCompanyCode().split("_")[1] :
                                            company.getCompanyCode()));
                }
                ArrayList<String> roleListFirst = new ArrayList<>();
                List<String> instanceIdList = new ArrayList<>();
                List<String> nextExecutorUserIds = new ArrayList<>();
                List<String> taskIds = new ArrayList<>();
                List<WorkflowResultDto> workflowResultDtos = new ArrayList<>();
                String nextExecutorRoleIds = "";
                // 判断当前是否为提交
                if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                    //发起流程
                    ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                    List<ActWorkflowStartDTO> list = new ArrayList<>();
                    ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                    dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
                    dto.setBusinessKey(String.valueOf(new Date().getTime()));
                    dto.setNextExecuteUserCompanyCode(model.getReceiveCompanyCode());
                    dto.setCompleteFirstTask(true);
                    list.add(dto);
                    actWorkflowBatchDTO.setProcess(list);
                    List<ProcessTaskDTO> processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                    workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
                    nextExecutorRoleIds = workflowResultDtos.get(0).getNextExecutorRoleIds();
                    nextExecutorUserIds.add(workflowResultDtos.get(0).getNextExecutorUserIds());
                    for (WorkflowResultDto processTaskDTO : workflowResultDtos) {
                        instanceIdList.add(processTaskDTO.getInstanceId());
                        taskIds.add(processTaskDTO.getNextTaskId());
                    }
                }

                String finalNextExecutorRoleIds = nextExecutorRoleIds;
                CompanyBo companyBo = commonServiceImpl.getOneCompany(model.getReceiveCompanyCode());
                model.setApplyNo(applyNoList.get(0));
                model.setReceiveCompanyOrgCode(companyBo.getOrgCode());
                model.setCreateUserId(RequestContext.getExeUserId());
                model.setApplyDate(new Date());
                if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                    model.setNextExecutorIds(finalNextExecutorRoleIds);
                    model.setInstanceStatus(String.join(",", roleListFirst));
                    model.setPromoter(reginParams.getUserModel().getUserId());
                    model.setStatus(taskName[0]);
                }
                if (!CollectionUtils.isEmpty(nextExecutorUserIds)) {
                    model.setNextExecuteUserIds(nextExecutorUserIds.get(0));
                }
                if (!CollectionUtils.isEmpty(instanceIdList)) {
                    model.setInstanceId(instanceIdList.get(0));
                    model.setStatus(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
                } else {
                    model.setStatus(WorkFlowStatusEnum.UNITCHANGE_SUBMIT.getPass());
                }
                if (!CollectionUtils.isEmpty(taskIds)) {
                    model.setNextTaskId(taskIds.get(0));
                }
                model.setSequenceNbr(sequence.nextId());
                model.setCreateDate(new Date());
                model.setCreateUserName(reginParams.getUserModel().getRealName());
                model.setUseRegistCode(String.join(",", registrationNoList));
                model.setEquList(registrationList.get(0).get("equList").toString());
                JgChangeRegistrationUnit registrationUnit = new JgChangeRegistrationUnit();
                BeanUtils.copyProperties(model, registrationUnit);
                setNewUnitInfo(reginParams, registrationUnit);
                JgChangeRegistrationUnitMapper.insert(registrationUnit);

                List<TaskModelDto> modelDtos = new ArrayList<>();
                if (SUBMIT_TYPE_FLOW.equals(submitType)) {
                    TaskModelDto taskModelDto = new TaskModelDto();
                    TaskMessageDto ta = new TaskMessageDto();
                    ta.setInstanceId(registrationUnit.getInstanceId());
                    ta.setStatus(registrationUnit.getStatus());
                    ta.setPromoter(registrationUnit.getPromoter());
                    ta.setNextExecuteUserIds(registrationUnit.getNextExecuteUserIds());
                    ta.setSequenceNbr(registrationUnit.getSequenceNbr());
                    ta.setNextTaskId(registrationUnit.getNextTaskId());
                    taskModelDto.setModel(ta);
                    taskModelDto.setFlowCreateDate(new Date());
                    taskModelDto.setTaskName(workflowResultDtos.get(0).getNextTaskName());
                    taskModelDto.setFlowCode(registrationUnit.getNextTaskId());
                    taskModelDto.setTaskContent(this.buildTaskContent(registrationUnit));
                    taskModelDto.setTaskCode(registrationUnit.getApplyNo());
                    taskModelDto.setTaskType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getCode());
                    taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
                    taskModelDto.setRelationId(registrationUnit.getInstanceId());
                    taskModelDto.setExecuteUserIds(workflowResultDtos.get(0).getNextExecutorUserIds());
                    taskModelDto.setTaskStatusLabel("未处理");
                    taskModelDto.setFlowStatus(commonServiceImpl.getDictionaryCodeByName(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass()));
                    taskModelDto.setFlowStatusLabel(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
                    taskModelDto.setStartUserId(RequestContext.getExeUserId());
                    taskModelDto.setStartUser(workflowResultDtos.get(0).getStartUserName());
                    taskModelDto.setStartUserCompanyName(reginParams.getCompany().getCompanyName());
                    taskModelDto.setStartDate(new Date());
                    taskModelDto.setNextExecuteUser(workflowResultDtos.get(0).getNextExecutorRoleIds());
                    modelDtos.add(taskModelDto);
                } else {
                    TaskModelDto taskModelDto = new TaskModelDto();
                    //行数据
                    taskModelDto.setModel(registrationUnit);
                    //摘要 按原有规则组装
                    taskModelDto.setTaskContent(this.buildTaskContent(registrationUnit));
                    //申请单号
                    taskModelDto.setTaskCode(registrationUnit.getApplyNo());
                    //业务类型枚举code值
                    taskModelDto.setTaskType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getCode());
                    ////业务主键
                    taskModelDto.setRelationId(registrationUnit.getSequenceNbr() + "");
                    modelDtos.add(taskModelDto);
//            }
                }
                commonServiceImpl.saveExecuteFlowData2Redis(registrationUnit.getInstanceId(), buildInstanceRuntimeData(registrationUnit));
                commonServiceImpl.buildTaskModel(modelDtos);

                List<JgChangeRegistrationUnitEq> jgRelationEquipList = new ArrayList<>();
                deviceList.forEach(device -> {
                    JgChangeRegistrationUnitEq unitEq = new JgChangeRegistrationUnitEq();
                    if (device.containsKey("USE_ORG_CODE")) {
                        unitEq.setRegistrationCertificate(device.getString("USE_ORG_CODE"));//使用登记证主键
                    }
                    if (device.containsKey("SEQUENCE_NBR")) {
                        unitEq.setEquId(device.getString("SEQUENCE_NBR"));//设备主键
                    }
                    unitEq.setUnitChangeRegistrationId(registrationUnit.getSequenceNbr().toString());//单位变更业务主键
                    unitEq.setDeviceInfo(JSONObject.toJSONString(device));//设备信息json
                    jgRelationEquipList.add(unitEq);
                });
                JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
                //登记类别
                jgRegistrationHistory.setRegistrationClass("单位变更登记");
                jgRegistrationHistory.setCurrentDocumentId(registrationUnit.getApplyNo());
                //使用登记证历史数据
                jgRegistrationHistory.setChangeData(JSONObject.toJSONString(registrationList));
                //先删除之前设备关系数据，在插入最新设备关系数据
                registrationUnitEqService.getBaseMapper().delete(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                        .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registrationUnit.getSequenceNbr()));
                registrationUnitEqService.saveBatch(jgRelationEquipList);
                //先删除之前未提交的历史使用登记证信息，在插入最新的使用登记证信息
                registrationHistoryService.getBaseMapper().delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                        .eq(JgRegistrationHistory::getCurrentDocumentId, registrationUnit.getApplyNo()));
                registrationHistoryService.save(jgRegistrationHistory);
                return Collections.singletonList(model);
            }
            return Collections.singletonList(model);
        } 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(e.getMessage());
        } finally {
            FlowingEquipRedisContext.clean();
        }
    }

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

    public void setEquAddress(JgChangeRegistrationUnitDto model) {
        String address = Stream.of(getRegionNameByCode("province", model.getProvince()),
                        getRegionNameByCode("city", model.getCity()),
                        getRegionNameByCode("region", model.getCounty()),
                        getRegionNameByCode("street", model.getStreet()))
                .filter(s -> s != null && !s.isEmpty())
                .collect(Collectors.joining())
                + Objects.toString(model.getFullAddress(), "");
        model.setEquAddress(address);
        model.setFullAddress(Objects.toString(model.getFullAddress(), ""));
    }

    /**
     * 根据code获取市区县名字
     *
     * @param type type
     * @return name
     */
    private String getRegionNameByCode(String type, String code) {
        List<LinkedHashMap<String, Object>> regions = (List<LinkedHashMap<String, Object>>) redisUtils.get(type.toUpperCase());
        return regions.stream()
                .filter(item -> String.valueOf(item.get("regionCode")).equals(code))
                .map(item -> (String) item.get("regionName"))
                .findFirst()
                .orElse("");
    }

    // 获取设备的地市编码
    private String getDeviceCity(Map<String, Object> device) {
        Object usePlaceCodeObj = device.get("USE_PLACE_CODE");
        if (usePlaceCodeObj == null) {
            throw new BadRequest("没有查询到地市信息");
        }
        String[] parts = ((String) usePlaceCodeObj).split("#");
        if (parts.length < 2 || parts[1] == null || parts[1].isEmpty()) {
            throw new BadRequest("没有查询到地市信息");
        }
        return parts[1];
    }

    // 校验设备地市
    private void validateDeviceCity(List<JSONObject> deviceList, String userCity, boolean isIntraDistrictChange) {
        for (Map<String, Object> device : deviceList) {
            String deviceCity = getDeviceCity(device);

            if (isIntraDistrictChange && !userCity.equals(deviceCity)) {
                throw new BadRequest("区内变更只能选择与设备地址中相同地市！");
            }

            if (!isIntraDistrictChange && userCity.equals(deviceCity)) {
                throw new BadRequest("区外变更只能选择与设备地址中不同地市！");
            }
        }
    }

    public boolean canConvertToLong(String str) {
        try {
            Long.parseLong(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    private void updateHistoryAsync(List<JgChangeRegistrationUnitEq> jgRelationEquipList) {
        jgRelationEquipList.forEach(j -> {
            commonService.saveOrUpdateHistory(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName(),
                    getEquipInfoJson(j.getUnitChangeRegistrationId()), j.getEquId(), j.getUnitChangeRegistrationId());
        });
    }

    private JSONObject getEquipInfoJson(String id) {
        return new JSONObject(getEquipInfo(Long.parseLong(id), new HashMap<>()));
    }


    private void convertField(JgChangeRegistrationUnitDto model) {
        // 处理图片
        if (!ValidationUtil.isEmpty(model.getChangeCertificateList())) {
            model.setChangeCertificate(JSON.toJSONString(model.getChangeCertificateList()));
        }
        // 处理其他附件
        if (!ValidationUtil.isEmpty(model.getOtherAccessoriesList())) {
            model.setOtherAccessories(JSON.toJSONString(model.getOtherAccessoriesList()));
        }
        // 分割单位
        String useUnitId = model.getUseUnitCreditCode();
        if (!ObjectUtils.isEmpty(useUnitId)) {
            String[] useUnitList = useUnitId.split("_");
            if (useUnitList.length > 1) {
                model.setUseUnitCreditCode(useUnitList[0]);
                model.setUseUnitName(useUnitList[1]);
            }
        }

        // 分割单位
        String orgBranchCode = model.getOrgBranchCode();
        if (!ObjectUtils.isEmpty(orgBranchCode)) {
            String[] orgBranchCodeList = orgBranchCode.split("_");
            if (orgBranchCodeList.length > 1) {
                model.setOrgBranchCode(orgBranchCodeList[0]);
                model.setOrgBranchName(orgBranchCodeList[1]);
            }
        }

        String receiveOrgCode = model.getReceiveOrgCode();
        if (!ObjectUtils.isEmpty(receiveOrgCode)) {
            String[] receiveOrgCodeList = receiveOrgCode.split("_");
            if (receiveOrgCodeList.length > 1) {
                model.setReceiveOrgCode(receiveOrgCodeList[0]);
                model.setReceiveCompanyCode(receiveOrgCodeList[0]);
                model.setReceiveOrgName(receiveOrgCodeList[1]);
            }
        }
        this.setEquAddress(model);
    }


    @GlobalTransactional(rollbackFor = Exception.class)
    public boolean submit(JgChangeRegistrationUnit notice, String op) {

        AjaxResult ajaxResult = Workflow.taskClient.getTask(notice.getInstanceId());
        JSONObject dataObject = JSON.parseObject(JSON.toJSONString(ajaxResult.get("data")));
        String taskId = dataObject.getString("id");
        //组装信息
        TaskResultDTO dto = new TaskResultDTO();
        dto.setResultCode("approvalStatus");
        dto.setTaskId(taskId);
        if (!ValidationUtil.isEmpty(notice.getProcessAdvice())) {
            dto.setComment(notice.getProcessAdvice());
        }
        HashMap<String, Object> map = new HashMap<>();
        if (notice.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject()) || notice.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack())) {
            map.put("approvalStatus", "提交");
        } else {
            map.put("approvalStatus", op);
        }
        dto.setVariable(map);
        //执行流程
        AjaxResult ajaxResult1;
        try {
            ajaxResult1 = Workflow.taskClient.completeByTask(taskId, dto);
            if (ajaxResult1.get("code").equals(200)) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            log.error("提交失败：{}", e);
            return false;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void cancel(JgChangeRegistrationUnitDto noticeDto) {
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(noticeDto.getInstanceId());
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 撤回校验
            commonServiceImpl.checkForRevocationFlow(noticeDto.getNextTaskId(), noticeDto.getInstanceId());

            String taskCode;
            List<String> roleListNext = new ArrayList<>();
            List<String> roleListAll = new ArrayList<>();
            ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(noticeDto.getInstanceId());
            String nextTaskId = processTaskDTO.getNextTask().get(0).getId();
            this.buildRoleList(Collections.singletonList(processTaskDTO), roleListNext, roleListAll);
            List<WorkflowResultDto> workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));

            // 待调整
            taskCode = processTaskDTO.getNextTask().get(0).getKey();
            JgChangeRegistrationUnit changeUnit = this.baseMapper.selectById(noticeDto.getSequenceNbr());
            changeUnit.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getRollBack());
            changeUnit.setPromoter("");
            changeUnit.setNextTaskId(nextTaskId);
            changeUnit.setNextExecuteUserIds(workflowResultDtos.get(0).getNextExecutorUserIds());
            changeUnit.setNextExecutorIds(String.join(",", roleListNext));
            JgChangeRegistrationUnitMapper.updateById(changeUnit);
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(changeUnit));
            jsonObject.put("nextTaskId", changeUnit.getNextTaskId());
            jsonObject.put("nextExecuteUser", changeUnit.getNextExecutorIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getCode());
            jsonObject.put("flowStatus", this.getTaskCodeByName(changeUnit.getStatus()));
            jsonObject.put("flowStatusLabel", changeUnit.getStatus());

            commonServiceImpl.rollbackTask(noticeDto.getInstanceId(), jsonObject);

            // redis流程实时数据更新
            commonServiceImpl.saveExecuteFlowData2Redis(noticeDto.getInstanceId(), this.buildInstanceRuntimeData(changeUnit));
            this.delRepeatUseEquipData(changeUnit.getApplyNo(), changeUnit.getStatus(), changeUnit.getNewUseUnitCreditCode());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

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

    /**
     * @param dto
     * @param op          void
     * @description 执行流程
     * @author wangguo
     * @date 2024/7/18 11:00
     **/
    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 6000000)
    @EnableEsRollback
    public void accept(JgChangeRegistrationUnitDto dto, String op) {
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(dto.getInstanceId());
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonServiceImpl.checkForExecuteFlow(dto.getNextTaskId(), dto.getInstanceId());

            String[] taskName = new String[]{"已完成"};
            String userId = RequestContext.getExeUserId();
            String taskId = dto.getNextTaskId();
            JgChangeRegistrationUnit registration = this.JgChangeRegistrationUnitMapper.selectById(dto.getSequenceNbr());
            registration.setProcessAdvice(dto.getProcessAdvice());
            List<String> roleListAll = new ArrayList<>();
            ArrayList<String> roleList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(dto.getRegistrationList()) && EQU_CODE_CC.equals(dto.getEquListCode())) {
                dto.getRegistrationList().forEach(v -> {
                    String newCarNumber = String.valueOf(v.get("newCarNumber"));
                    String useOrgCode = String.valueOf(v.get("useRegistrationCode"));
                    if (!ObjectUtils.isEmpty(newCarNumber) && !"null".equals(newCarNumber) && "0".equals(op)) {
                        // 更新安全追溯-场内车辆中的“车牌号字段” 保证唯一性
                        Integer count = idxBizJgRegisterInfoMapper.checkCarNumberUniqueness(newCarNumber, useOrgCode);
                        if (count > 0) {
                            throw new BadRequest("车牌号已存在，请重新输入！");
                        }
                    }
                });
            }

            //组装信息
            TaskResultDTO task = new TaskResultDTO();
            task.setResultCode("approvalStatus");
            task.setTaskId(taskId);
            task.setComment(StringUtils.isEmpty(dto.getProcessAdvice()) ? "" : dto.getProcessAdvice());
            task.setNextExecuteUserCompanyCode(this.getNextUserOrgCode(op, registration));

            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", op);
            if (!ObjectUtils.isEmpty(registration.getInstanceStatus()) &&
                    (registration.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject()) ||
                            registration.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack()))) {
                map.put("approvalStatus", "提交");
            }
            task.setVariable(map);
            //执行流程
            ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(taskId, task, op);
            String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
            String taskName1 = "";
            String nextTaskId = "";
            this.buildRoleList(Collections.singletonList(processTaskDTO), roleList, roleListAll);
            List<WorkflowResultDto> workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
            String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            if (processTaskDTO != null && processTaskDTO.getNextTask() != null && processTaskDTO.getNextTask().size() > 0) {
                taskCode = processTaskDTO.getNextTask().get(0).getKey();
                taskName1 = processTaskDTO.getNextTask().get(0).getName();
                nextTaskId = processTaskDTO.getNextTask().get(0).getId();
            }
            registration.setStatus(taskName[0]);
            JgRegistrationHistory history = registrationHistoryService.lambdaQuery()
                    .eq(JgRegistrationHistory::getCurrentDocumentId, registration.getApplyNo())
                    .eq(JgRegistrationHistory::getIsDelete, false).one();
            if ("0".equals(op)) {
                if (roleList.isEmpty()) {
                    registration.setStatus(taskName[0]);
                    registration.setAuditPassDate(new Date());
                    //如果是工业管道 如果工程装置对应一个证就直接变更给新单位；如果工程装置对应证下还有其他装置就变更后直接给新单位再重新生成一个登记证号；如果两个工程装置对应同一个使用登记证变更后生成两个新的登记证
                    if (PipelineEnum.PRESSURE_PIPELINE.getCode().equals(dto.getEquListCode())) {
                        this.dealProjectContraption(dto, nextTaskId, registration, op);
                    } else if(CylinderTypeEnum.CYLINDER.getCode().equals(dto.getEquCategoryCode())) {
                        //气瓶单位变更，如果新单位没有证，则生成新的使用登记证，如果新单位有证且是系统生成的证，则选择增补到已有的证下面同时，更新设备其他信息
                        this.dealCylinderAuditPassData(dto, nextTaskId, registration, op);
                    } else {
                        // 生成新的使用登记编号，使用登记证  修改设备的使用登记信息表，使用单位名称，使用单位统一信用代码，使用登记证编号，更新ES
                        LambdaQueryWrapper<JgChangeRegistrationUnitEq> queryWrapper = new LambdaQueryWrapper<>();
                        queryWrapper.eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, dto.getSequenceNbr());
                        List<JgChangeRegistrationUnitEq> jgChangeRegistrationUnitEqs = JgChangeRegistrationUnitEqMapper.selectList(queryWrapper);
                        //更新产权信息
                        dto.getRegistrationList().forEach(v -> {
                            String useCode = String.valueOf(v.get("useRegistrationCode"));
                            String newCarNumber = String.valueOf(v.get("newCarNumber"));
                            String estateUnitSeq = String.valueOf(v.get("estateUnitName"));
                            Map<String, String> propertyUnitInfo = commonServiceImpl.queryTcmUnitInfoBySeq(estateUnitSeq, TcmUnitTypeEnum.CQ.getCode());
                            List<String> records = idxBizJgRegisterInfoService.getBaseMapper()
                                    .selectList(new LambdaQueryWrapper<IdxBizJgRegisterInfo>()
                                            .eq(IdxBizJgRegisterInfo::getUseOrgCode, useCode))
                                    .stream()
                                    .map(IdxBizJgRegisterInfo::getRecord)
                                    .collect(Collectors.toList());
                            if (!records.isEmpty()) {
                                idxBizJgUseInfoService.update(
                                        new IdxBizJgUseInfo()
                                                .setEstateUnitCreditCode(propertyUnitInfo.get("unitCode"))
                                                .setEquState(EquipmentEnum.ZAIYONG.getCode().toString())
                                                .setEstateUnitName(propertyUnitInfo.get("unitName")),
                                        new LambdaQueryWrapper<IdxBizJgUseInfo>()
                                                .in(IdxBizJgUseInfo::getRecord, records)
                                );
                            }
                            //场车更新车牌号
                            if (EQU_CODE_CC.equals(dto.getEquListCode()) && newCarNumber != null && !"null".equals(newCarNumber) && useCode != null) {
                                idxBizJgRegisterInfoService.update(new IdxBizJgRegisterInfo().setCarNumber(newCarNumber),
                                        new LambdaQueryWrapper<IdxBizJgRegisterInfo>().in(IdxBizJgRegisterInfo::getUseOrgCode, useCode)
                                );
                            }
                        });
                        Map<String, String> seqToEquId = new HashMap<>();
                        List<ESEquipmentCategoryDto> esEquipmentCategoryDtos = new ArrayList<>();
                        for (JgChangeRegistrationUnitEq jgChangeRegistrationUnitEq : jgChangeRegistrationUnitEqs) {
                            String equipId = jgChangeRegistrationUnitEq.getEquId();
                            LambdaQueryWrapper<IdxBizJgUseInfo> useInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                            useInfoLambdaQueryWrapper.eq(IdxBizJgUseInfo::getRecord, equipId);
                            IdxBizJgUseInfo useInfo = useInfoMapper.selectOne(useInfoLambdaQueryWrapper);
                            if (ObjectUtils.isNotEmpty(useInfo)) {
                                useInfo.setUseUnitName(registration.getNewUseUnitName());
                                useInfo.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
                                // 只有变更类型为场车时，更新地址相关字段
                                if (EQU_CODE_CC.equals(registration.getEquListCode())) {
                                    this.updateUseInfoAddress(useInfo, registration);
                                    IdxBizJgSupervisionInfo supervisionInfo = new IdxBizJgSupervisionInfo();
                                    supervisionInfo.setOrgBranchCode(registration.getOrgBranchCode());
                                    supervisionInfo.setOrgBranchName(registration.getOrgBranchName());
                                    idxBizJgSupervisionInfoMapper.update(supervisionInfo, Wrappers.<IdxBizJgSupervisionInfo>lambdaQuery()
                                            .eq(IdxBizJgSupervisionInfo::getRecord, equipId));
                                }
                                useInfoMapper.updateById(useInfo);
                            }
                            LambdaQueryWrapper<IdxBizJgRegisterInfo> registerInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                            registerInfoLambdaQueryWrapper.eq(IdxBizJgRegisterInfo::getRecord, equipId);
                            IdxBizJgRegisterInfo registerInfo = registerInfoMapper.selectOne(registerInfoLambdaQueryWrapper);
                            Optional<ESEquipmentCategoryDto> optional = esEquipmentCategory.findById(equipId);
                            String[] companyCode = registration.getNewUseUnitCreditCode().split("_");
                            if (optional.isPresent()) {
                                ESEquipmentCategoryDto esEquipmentCategoryDto = optional.get();
                                esEquipmentCategoryDto.setUSE_UNIT_CREDIT_CODE(companyCode.length > 1 ? companyCode[1] : registration.getNewUseUnitCreditCode());
                                esEquipmentCategoryDto.setUSE_UNIT_NAME(registration.getNewUseUnitName());
                                esEquipmentCategoryDto.setEQU_STATE(EquipmentEnum.ZAIYONG.getCode());
                                esEquipmentCategoryDto.setREC_DATE(new Date().getTime());
                                if (EQU_CODE_CC.equals(registration.getEquListCode())) {
                                    esEquipmentCategoryDto.setUSE_PLACE(joinWithSeparator("/", useInfo.getProvinceName(), useInfo.getCityName(), useInfo.getCountyName(), useInfo.getStreetName()));
                                    esEquipmentCategoryDto.setUSE_PLACE_CODE(joinWithSeparator("#", useInfo.getProvince(), useInfo.getCity(), useInfo.getCounty(), useInfo.getFactoryUseSiteStreet()));
                                    esEquipmentCategoryDto.setOrgBranchCode(registration.getOrgBranchCode());
                                    esEquipmentCategoryDto.setORG_BRANCH_NAME(registration.getOrgBranchName());
                                }
                                // 如果是变更类型=1，还需要更新证号到 ES
                                if ("1".equals(registration.getChangeType()) && EQU_CODE_CC.equals(dto.getEquListCode())) {
                                    // 新证号生成逻辑
                                    String newCode = commonServiceImpl.generateRegistrationCode(equipId, registration.getReceiveCompanyCode(), false);
                                    esEquipmentCategoryDto.setUSE_ORG_CODE(newCode);
                                    seqToEquId.put(registerInfo.getUseOrgCode(), newCode);
                                    registerInfo.setUseOrgCode(newCode);
                                    registerInfoMapper.updateById(registerInfo);
                                }
//                                if (ObjectUtils.isNotEmpty(registerInfo) && ObjectUtils.isNotEmpty(registerInfo.getCarNumber())) {
//                                    esUpdateParams.put("CAR_NUMBER", registerInfo.getCarNumber());
//                                }
                                //修改各类告知列表，置为废弃
                                this.updataInvalidStatusByHistory(equipId, registration.getApplyNo());
                                esEquipmentCategoryDtos.add(esEquipmentCategoryDto);
                            }
                            esEquipmentCategory.saveAllWithFallback(esEquipmentCategoryDtos);
                        }
                        registration.setNextTaskId(nextTaskId);
                        TaskV2Model taskV2Model = updateTaskModel(registration, op);

                        JSONArray historyJson = JSON.parseArray(history.getChangeData());
                        // 更新历史表中一二级审批车牌号
                        history.setChangeData(JSONObject.toJSONString(dto.getRegistrationList()));
                        registrationHistoryService.updateById(history);
                        List<String> ids = historyJson.stream().map(v -> JSON.parseObject(v.toString()).getString(SEQUENCE_NBR)).collect(Collectors.toList());
                        List<JgUseRegistrationManage> list = useRegistrationManageService.lambdaQuery().in(BaseEntity::getSequenceNbr, ids).list();
                        // 用来存放新生成的登记证
                        List<JgUseRegistrationManage> newList = new ArrayList<>();
                        for (JgUseRegistrationManage registrationManage : list) {
                            // 修改使用登记证管理使用单位信息
                            registrationManage.setAuditPassDate(registration.getAuditPassDate());
                            registrationManage.setVersion(registrationManage.getVersion() + 1);
                            if ("1".equals(registration.getChangeType()) && EQU_CODE_CC.equals(dto.getEquListCode())) {
                                // -------------------- 旧证处理 --------------------
                                registrationManage.setCertificateStatus("已注销");
                                registrationManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());

                                // -------------------- 新证处理 --------------------
                                JgUseRegistrationManage newManage = new JgUseRegistrationManage();
                                BeanUtils.copyProperties(registrationManage, newManage);

                                String newCode = seqToEquId.get(registrationManage.getUseRegistrationCode());
                                newManage.setUseRegistrationCode(newCode);
                                registration.setUseRegistCode(newCode);
                                // 新证属性重置
                                newManage.setCertificateStatus("已登记");
                                newManage.setVersion(1);
                                newManage.setRegistrationType("0");
                                newManage.setEquUseAddress(registration.getEquAddress());
                                newManage.setUseUnitName(registration.getNewUseUnitName());
                                newManage.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
                                newManage.setReceiveOrgName(registration.getReceiveOrgName());
                                newManage.setReceiveCompanyCode(registration.getReceiveOrgCode());
                                newManage.setSuperviseOrgCode(registration.getOrgBranchCode());
                                newManage.setSuperviseOrgName(registration.getOrgBranchName());
                                // 如果 equListCode = 5000，则设置车牌号
                                if (EQU_CODE_CC.equals(registrationManage.getEquListCode())) {
                                    String targetCode = registrationManage.getUseRegistrationCode();
                                    dto.getRegistrationList().stream()
                                            .filter(item -> targetCode.equals(item.get("useRegistrationCode")))
                                            .map(item -> String.valueOf(item.get("newCarNumber")))
                                            .filter(carNumber -> carNumber != null && !"null".equalsIgnoreCase(carNumber.trim()))
                                            .findFirst()
                                            .ifPresent(newManage::setCarNumber);
                                }

                                newManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());

                                // 回填新单位地址
                                if (!ObjectUtils.isEmpty(registration.getNewUseUnitCreditCode())) {
                                    TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(
                                            new QueryWrapper<TzBaseEnterpriseInfo>()
                                                    .eq("use_unit_code", registration.getNewUseUnitCreditCode())
                                    );
                                    if (useCodeResult != null) {
                                        newManage.setUseUnitAddress(useCodeResult.getAddress());
                                    }
                                }
                                newManage.setSequenceNbr(null);
                                newList.add(newManage);
                            } else {
                                registrationManage.setUseUnitName(registration.getNewUseUnitName());
                                registrationManage.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
                                registrationManage.setReceiveOrgName(registration.getReceiveOrgName());
                                registrationManage.setReceiveCompanyCode(registration.getReceiveOrgCode());
                                registrationManage.setSuperviseOrgCode(registration.getOrgBranchCode());
                                registrationManage.setSuperviseOrgName(registration.getOrgBranchName());
                                registrationManage.setCertificateStatus("已登记");
                                if (EQU_CODE_CC.equals(registrationManage.getEquListCode())) {
                                    String targetCode = registrationManage.getUseRegistrationCode();
                                    dto.getRegistrationList().stream()
                                            .filter(item -> targetCode.equals(item.get("useRegistrationCode")))
                                            .map(item -> String.valueOf(item.get("newCarNumber")))
                                            .filter(carNumber -> carNumber != null && !"null".equalsIgnoreCase(carNumber.trim()))
                                            .findFirst()
                                            .ifPresent(registrationManage::setCarNumber);
                                    registrationManage.setEquUseAddress(registration.getEquAddress());
                                }
                                registrationManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
                                if (!ObjectUtils.isEmpty(registration.getNewUseUnitCreditCode())) {
                                    TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(
                                            new QueryWrapper<TzBaseEnterpriseInfo>()
                                                    .eq("use_unit_code", registration.getNewUseUnitCreditCode())
                                    );
                                    if (useCodeResult != null) {
                                        registrationManage.setUseUnitAddress(useCodeResult.getAddress());
                                    }
                                }
                            }
                        }

                        if (CollUtil.isNotEmpty(newList)) {
                            list.addAll(newList);
                        }
                        useRegistrationManageService.saveOrUpdateBatch(list);
                        this.createResume(registration,jgChangeRegistrationUnitEqs, taskV2Model.getRoutePath());
                    }
                    //新增使用登记证和设备变更记录
                    this.saveRecord(registration);
                    // 发送数据变更消息
                    this.sendDataRefreshMsg(registration);
                } else {
                    registration.setNextExecutorIds(String.join(",", roleList));
                    if (!ObjectUtils.isEmpty(registration.getInstanceStatus())) {
                        registration.setInstanceStatus(registration.getInstanceStatus() + "," + String.join(",", roleList));
                    } else {
                        registration.setInstanceStatus(String.join(",", roleList));
                    }
                    registration.setPromoter(userId);
                    registration.setNextExecuteUserIds(nextUserIds);
                    registration.setNextTaskId(nextTaskId);
                    registration.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
                    executeOneStep(registration, taskName1, nextUserIds, op);
                    if (EQU_CODE_CC.equals(dto.getEquListCode())) {
                        history.setChangeData(JSONObject.toJSONString(dto.getRegistrationList()));
                        registrationHistoryService.updateById(history);
                    }
                }
            } else {
                registration.setPromoter("");
                registration.setNextExecutorIds(String.join(",", roleList));
                registration.setNextTaskId(nextTaskId);
                registration.setNextExecuteUserIds(nextUserIds);
                registration.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                executeOneStep(registration, taskName1, nextUserIds, op);
            }
            JgChangeRegistrationUnitMapper.updateById(registration);
            // redis流程实时数据更新
            commonServiceImpl.saveExecuteFlowData2Redis(dto.getInstanceId(), this.buildInstanceRuntimeData(registration));
            this.delRepeatUseEquipData(registration.getApplyNo(), registration.getStatus(), registration.getNewUseUnitCreditCode());
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new BadRequest("数据异常，请联系管理员");
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequest("数据异常，请联系管理员");
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    private void extractDeviceBaseInfo(List<Map<String, Object>> deviceList, JgChangeRegistrationUnit registration) {
        if (CollUtil.isEmpty(deviceList)) {
            return;
        }
        Map<String, Object> first = deviceList.get(0);
        registration.setEquCategory(MapUtils.getString(first, "equCategoryName"));
        registration.setEquDefine(MapUtils.getString(first, "equDefineName"));
        registration.setEquDefineCode(MapUtils.getString(first, "equDefine"));
    }

    private IdxBizJgUseInfo buildUseInfo(JgChangeRegistrationUnitDto dto, JgChangeRegistrationUnit registration) {
        IdxBizJgUseInfo useInfo = new IdxBizJgUseInfo();

        Map<String, String> propertyUnitInfo =
                commonServiceImpl.queryTcmUnitInfoBySeq(dto.getEstateUnitSeq(), TcmUnitTypeEnum.CQ.getCode());

        if (!ValidationUtil.isEmpty(propertyUnitInfo)) {
            useInfo.setEstateUnitCreditCode(propertyUnitInfo.get("unitCode"));
            useInfo.setEstateUnitName(propertyUnitInfo.get("unitName"));
        }

        // 安全管理员
        String safetyManager = Optional.ofNullable(registration.getSafetyManager())
                .map(s -> s.split("_"))
                .filter(arr -> arr.length > 1)
                .map(arr -> arr[1])
                .orElse("");

        // 使用单位信息
        useInfo.setPhone(registration.getPhone());
        useInfo.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
        useInfo.setUseUnitName(registration.getNewUseUnitName());
        useInfo.setSafetyManager(safetyManager);
        useInfo.setUsePlace(registration.getUsePlace());
        useInfo.setProvinceName("陕西省");
        useInfo.setProvince(dto.getProvince());
        useInfo.setCity(dto.getCity());
        useInfo.setCityName(getRegionNameByCode("city", dto.getCity()));
        useInfo.setCounty(dto.getCounty());
        useInfo.setCountyName(getRegionNameByCode("region", dto.getCounty()));
        useInfo.setFactoryUseSiteStreet(dto.getStreet());
        useInfo.setStreetName(getRegionNameByCode("street", dto.getStreet()));
        useInfo.setAddress(dto.getFullAddress());
        useInfo.setUseDate(dto.getUseDate());
        return useInfo;
    }

    /**
     * 处理气瓶单位变更三级审核完成后数据
     */
    private void dealCylinderAuditPassData(JgChangeRegistrationUnitDto dto, String nextTaskId, JgChangeRegistrationUnit registration, String op) {
        List<Map<String, Object>> deviceList = dto.getDeviceList();
        if (CollUtil.isEmpty(deviceList)) {
            throw new BadRequest("设备列表不能为空！");
        }

        // 1. 更新代办
        registration.setNextTaskId(nextTaskId);
        TaskV2Model taskV2Model = updateTaskModel(registration, op);

        // 2. 确定使用登记证代码（优先复用已有，否者生成）
        AtomicReference<Boolean> existedRegistrationFlag = new AtomicReference<>(Boolean.FALSE);
        String useRegistrationCode = findOrGenerateUseRegistrationCode(dto, registration, deviceList, existedRegistrationFlag);

        List<String> records = new ArrayList<>(deviceList.size());

        this.extractDeviceBaseInfo(deviceList, registration);
        IdxBizJgUseInfo useInfo = this.buildUseInfo(dto, registration);
        deviceList.stream().map(device -> MapUtils.getString(device, RECORD))
                .filter(ObjectUtils::isNotEmpty)
                .forEach(records::add);

        Lists.partition(records, DB_BATCH_SIZE).forEach(batch -> {
            useInfoMapper.batchUpdateUseInfoByRecords(useInfo, batch);
            registerInfoMapper.batchUpdateUseOrgCodeByRecord(useRegistrationCode, batch);
            idxBizJgSupervisionInfoMapper.batchUpdateSupervisionInfo(registration.getOrgBranchCode(), registration.getOrgBranchName(), batch);
        });

        // 7. 新增或更新使用登记证管理表
        this.upsertUseRegistrationManage(registration, useRegistrationCode, existedRegistrationFlag.get());

        this.createResumeForCylinder(records, registration, taskV2Model.getRoutePath());

        Lists.partition(records, ES_BATCH_SIZE).forEach(batch -> {
            Iterable<ESEquipmentCategoryDto> iterable = esEquipmentCategory.findAllById(batch);
            List<ESEquipmentCategoryDto> updateList = new ArrayList<>(batch.size());
            for (ESEquipmentCategoryDto categoryDto : iterable) {
                categoryDto.setUSE_UNIT_CREDIT_CODE(registration.getNewUseUnitCreditCode());
                categoryDto.setUSE_UNIT_NAME(registration.getNewUseUnitName());
                categoryDto.setREC_DATE(System.currentTimeMillis());
                categoryDto.setUSE_PLACE(joinWithSeparator("/", useInfo.getProvinceName(), useInfo.getCityName(), useInfo.getCountyName(), useInfo.getStreetName()));
                categoryDto.setUSE_PLACE_CODE(joinWithSeparator("#", useInfo.getProvince(), useInfo.getCity(), useInfo.getCounty(), useInfo.getFactoryUseSiteStreet()));
                categoryDto.setOrgBranchCode(registration.getOrgBranchCode());
                categoryDto.setORG_BRANCH_NAME(registration.getOrgBranchName());
                categoryDto.setUSE_ORG_CODE(useRegistrationCode);
                updateList.add(categoryDto);
            }
            if (!updateList.isEmpty()) {
                esEquipmentCategory.saveAllWithFallback(updateList);
            }
        });
    }

    private void createResumeForCylinder(List<String> records, JgChangeRegistrationUnit registration, String routePath) {
        if (!records.isEmpty()) {
            JgResumeInfo resumeInfo = JgResumeInfo.builder()
                    .businessType(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getName())
                    .applyNo(registration.getApplyNo())
                    .businessId(String.valueOf(registration.getSequenceNbr()))
                    .status("正常")
                    .approvalUnitCode(registration.getReceiveCompanyCode())
                    .approvalUnit(registration.getReceiveOrgName())
                    .changeContent(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName() + "业务办理")
                    .routePath(routePath)
                    .build();
            jgResumeInfoService.save(resumeInfo);
            jgResumeInfoEqService.saveBatchResumeEq(records.stream()
                    .map(e -> JgResumeInfoEq.builder()
                            .resumeId(String.valueOf(resumeInfo.getSequenceNbr()))
                            .equId(e)
                            .build())
                    .collect(Collectors.toList()));
        }
    }

    private String findOrGenerateUseRegistrationCode(JgChangeRegistrationUnitDto dto, JgChangeRegistrationUnit registration,
                                                     List<Map<String, Object>> deviceList, AtomicReference<Boolean> existedFlag) {

        // 查询新单位存在的已登记使用登记证（只取以 "瓶30" 开头的）系统生成的证号
        JgUseRegistrationManageDto queryDto = new JgUseRegistrationManageDto();
        queryDto.setCertificateStatus(CertificateStatusEnum.YIDENGJI.getName());
        queryDto.setRegistrationType("0");
        queryDto.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
        List<JgUseRegistrationManageDto> found = jgUseRegistrationManageMapper.queryByUseUnitCreditCode(queryDto);
        if (!CollectionUtils.isEmpty(found)) {
            for (JgUseRegistrationManageDto m : found) {
                String code = m.getUseRegistrationCode();
                if (StringUtils.hasText(code) && code.startsWith("瓶30")) {
                    existedFlag.set(Boolean.TRUE);
                    return code;
                }
            }
        }

        // 若企业没有系统生成的使用登记证，则生成（使用第一个设备ID）
        String firstRecord = Objects.toString(deviceList.get(0).get(RECORD), null);
        return commonServiceImpl.generateRegistrationCode(firstRecord, dto.getReceiveCompanyCode(), true);
    }

    private IdxBizJgUseInfo fetchUseInfoByRecord(String record) {
        LambdaQueryWrapper<IdxBizJgUseInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(IdxBizJgUseInfo::getRecord, record);
        return useInfoMapper.selectOne(wrapper);
    }

    private void updateUseInfoFields(IdxBizJgUseInfo useInfo, JgChangeRegistrationUnitDto dto, JgChangeRegistrationUnit registration,
                                     Map<String, String> propertyUnitInfo) {
        if (!ValidationUtil.isEmpty(propertyUnitInfo)) {
            useInfo.setEstateUnitCreditCode(propertyUnitInfo.get("unitCode"))
                    .setEstateUnitName(propertyUnitInfo.get("unitName"));
        }

        String safetyManager = Optional.ofNullable(registration.getSafetyManager())
                .map(s -> s.split("_"))
                .filter(arr -> arr.length > 1)
                .map(arr -> arr[1])
                .orElse("");
        useInfo.setPhone(registration.getPhone());
        useInfo.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
        useInfo.setUseUnitName(registration.getNewUseUnitName());
        useInfo.setSafetyManager(safetyManager);
        useInfo.setUsePlace(registration.getUsePlace());

        // 地区/地址字段回填（保持原字段赋值顺序与语义）
        useInfo.setProvinceName("陕西省")
                .setProvince(dto.getProvince())
                .setCity(dto.getCity())
                .setCityName(getRegionNameByCode("city", dto.getCity()))
                .setCounty(dto.getCounty())
                .setCountyName(getRegionNameByCode("region", dto.getCounty()))
                .setFactoryUseSiteStreet(dto.getStreet())
                .setStreetName(getRegionNameByCode("street", dto.getStreet()))
                .setAddress(dto.getFullAddress())
                .setUseDate(dto.getUseDate());
    }

    private void upsertUseRegistrationManage(JgChangeRegistrationUnit registration, String useRegistrationCode, boolean existed) {
        Map<String, String> equType = new HashMap<>();
        equType.put("equListCode", registration.getEquListCode());
        equType.put("equCategoryCode", registration.getEquCategoryCode());
        if (existed) {
            // 查询并更新已有管理表记录
            LambdaQueryWrapper<JgUseRegistrationManage> q = new LambdaQueryWrapper<>();
            q.eq(JgUseRegistrationManage::getUseRegistrationCode, useRegistrationCode)
                    .isNotNull(JgUseRegistrationManage::getUseRegistrationCode)
                    .eq(JgUseRegistrationManage::getCertificateStatus, "已登记")
                    .eq(BaseEntity::getIsDelete, false);
            JgUseRegistrationManage manage = useRegistrationManageService.getBaseMapper().selectOne(q);
            if (manage != null) {
                manage.setAuditPassDate(registration.getAuditPassDate());
                manage.setVersion(manage.getVersion() + 1);
                manage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
                manage.setRecUserId(registration.getCreateUserId());
                useRegistrationManageService.updateById(manage);
            }
        } else {
            // 新增证管理信息
            JgUseRegistrationManage newManage = new JgUseRegistrationManage();
            newManage.setSequenceNbr(sequence.nextId());
            newManage.setUseRegistrationCode(useRegistrationCode);
            newManage.setUseUnitName(registration.getNewUseUnitName());
            newManage.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
            newManage.setReceiveOrgName(registration.getReceiveOrgName());
            newManage.setReceiveCompanyCode(registration.getReceiveOrgCode());
            newManage.setAuditPassDate(registration.getAuditPassDate());
            newManage.setVersion(1);
            newManage.setRegType("单位变更登记");
            newManage.setRegistrationType("0");
            newManage.setManageType("unit");
            newManage.setApplyNo(registration.getApplyNo());
            newManage.setEquUseAddress(registration.getEquAddress());
            newManage.setRegDate(new Date());
            newManage.setEquList(registration.getEquList());
            newManage.setEquListCode(registration.getEquListCode());
            newManage.setEquCategory(registration.getEquCategory());
            newManage.setEquCategoryCode(registration.getEquCategoryCode());
            newManage.setEquDefine(registration.getEquDefine());
            newManage.setEquDefineCode(registration.getEquDefineCode());
            newManage.setCertificateStatus(CertificateStatusEnum.YIDENGJI.getName());
            newManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
            newManage.setRecUserName(registration.getCreateUserName());
            newManage.setRecUserId(registration.getCreateUserId());
            newManage.setRecDate(new Date());
            newManage.setCreateUserId(registration.getCreateUserId());
            newManage.setCreateDate(new Date());
            if (!ObjectUtils.isEmpty(registration.getNewUseUnitCreditCode())) {
                TzBaseEnterpriseInfo info = tzBaseEnterpriseInfoMapper.selectOne(new QueryWrapper<TzBaseEnterpriseInfo>().eq("use_unit_code", registration.getNewUseUnitCreditCode()));
                if (info != null) {
                    newManage.setUseUnitAddress(info.getAddress());
                }
            }
            newManage.setSuperviseOrgCode(registration.getOrgBranchCode());
            newManage.setSuperviseOrgName(registration.getOrgBranchName());
            newManage.setCertificateNo(commonServiceImpl.generateCertificateNo(equType, new Date(), registration.getReceiveCompanyCode()));
            useRegistrationManageService.save(newManage);
        }
    }

    private void updateUseInfoAddress(IdxBizJgUseInfo useInfo, JgChangeRegistrationUnit registration) {
        useInfo.setProvince(registration.getProvince());
        useInfo.setCity(registration.getCity());
        useInfo.setCounty(registration.getCounty());
        useInfo.setFactoryUseSiteStreet(registration.getStreet());
        useInfo.setAddress(registration.getFullAddress());
        useInfo.setProvinceName(getRegionNameByCode("province", useInfo.getProvince()));
        useInfo.setCityName(getRegionNameByCode("city", useInfo.getCity()));
        useInfo.setCountyName(getRegionNameByCode("region", useInfo.getCounty()));
        useInfo.setStreetName(getRegionNameByCode("street", useInfo.getFactoryUseSiteStreet()));
    }

    private String joinWithSeparator(String separator, String... values) {
        return Arrays.stream(values)
                .map(v -> ObjectUtils.defaultIfNull(v, ""))
                .collect(Collectors.joining(separator));
    }

    private void createResume(JgChangeRegistrationUnit registration, List<JgChangeRegistrationUnitEq> jgChangeRegistrationUnitEqs, String routePath) {
        jgResumeInfoService.saveBatchResume(jgChangeRegistrationUnitEqs.stream().map(eq-> JgResumeInfo.builder().applyNo(registration.getApplyNo())
                .businessType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName())
                .businessId(String.valueOf(registration.getSequenceNbr()))
                .equId(eq.getEquId())
                .approvalUnit(registration.getReceiveOrgName())
                .approvalUnitCode(registration.getReceiveCompanyCode())
                .status("正常")
                .changeContent(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName() + "业务办理")
                .routePath(routePath)
                .build()).collect(Collectors.toList())
        );
    }

    private void sendDataRefreshMsg(JgChangeRegistrationUnit registration) {
        LambdaQueryWrapper<JgChangeRegistrationUnitEq> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registration.getSequenceNbr());
        queryWrapper.select(JgChangeRegistrationUnitEq::getEquId);
        List<String> records = JgChangeRegistrationUnitEqMapper.selectList(queryWrapper).stream().map(JgChangeRegistrationUnitEq::getEquId).filter(Objects::nonNull).collect(Collectors.toList());
        eventPublisher.publish(new DataRefreshEvent(this, records, DataRefreshEvent.DataType.equipment.name(), DataRefreshEvent.Operation.UPDATE));
    }

    /**
     * 处理工业管道
     *
     * @param dto
     * @param nextTaskId
     * @param registration
     */
    private void dealProjectContraption(JgChangeRegistrationUnitDto dto, String nextTaskId, JgChangeRegistrationUnit registration, String op) {
        List<Map<String, Object>> projectContraptionList = dto.getProjectContraptionList();
        if (CollUtil.isEmpty(projectContraptionList)) {
            throw new BadRequest("工程/装置列表为空");
        }
        registration.setNextTaskId(nextTaskId);
        TaskV2Model taskV2Model = updateTaskModel(registration, op);
        List<String> projectContraptionIds = new ArrayList<>();
        List<String> projectContraptionIdsInThisApply = new ArrayList<>();
        for (Map<String, Object> map : projectContraptionList) {
            String projectSequenceNbr = (String) map.get(SEQUENCE_NBR);
            projectContraptionIdsInThisApply.add(projectSequenceNbr);
        }
        String firstProjectContraptionId = null; // 同一使用登记证下第一个装置id
        for (Map<String, Object> map : projectContraptionList) {
            String useRegistrationCode = (String) map.get("useRegistrationCode");
            String projectSequenceNbr = (String) map.get(SEQUENCE_NBR);
            projectContraptionIds.add(projectSequenceNbr);
            String estateUnitSeq = String.valueOf(map.get("estateUnitName"));
            Map<String, String> propertyUnitInfo = commonServiceImpl.queryTcmUnitInfoBySeq(estateUnitSeq, TcmUnitTypeEnum.CQ.getCode());
            LambdaQueryWrapper<IdxBizJgProjectContraption> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(IdxBizJgProjectContraption::getUseRegistrationCode, useRegistrationCode)
                    .isNotNull(IdxBizJgProjectContraption::getUseRegistrationCode)
                    .eq(BaseEntity::getIsDelete, false);
            List<IdxBizJgProjectContraption> projectsUnderSameUseOrgCode = projectContraptionService.list(wrapper).stream().sorted(Comparator.comparing(IdxBizJgProjectContraption::getSequenceNbr)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(projectsUnderSameUseOrgCode)) {
                throw new BadRequest("使用登记证编号：" + useRegistrationCode + "对应的工程/装置列表不存在");
            }
            if (ValidationUtil.isEmpty(firstProjectContraptionId)) {
                firstProjectContraptionId = String.valueOf(projectsUnderSameUseOrgCode.get(0).getSequenceNbr());
            }
            //更新产权信息
            if (!ValidationUtil.isEmpty(propertyUnitInfo)) {
                idxBizJgUseInfoService.update(
                        new IdxBizJgUseInfo().setEstateUnitCreditCode(propertyUnitInfo.get("unitCode"))
                                .setEstateUnitName(propertyUnitInfo.get("unitName")),
                        new LambdaQueryWrapper<IdxBizJgUseInfo>().eq(IdxBizJgUseInfo::getProjectContraptionId, projectSequenceNbr)
                );
            }
            // 根据装置id查询装置下所有管道使用信息
            List<IdxBizJgUseInfo> useInfos = idxBizJgUseInfoService.list(new LambdaQueryWrapper<IdxBizJgUseInfo>()
                    .eq(IdxBizJgUseInfo::getProjectContraptionId, projectSequenceNbr));

            //如果工程装置对应一个证就直接变更给新单位 否则重新生成一个登记证
            if (projectsUnderSameUseOrgCode.size() == 1) {
                IdxBizJgProjectContraption targetProjectContraption = projectsUnderSameUseOrgCode.get(0);
                this.processSingleProjectContraption(registration, useInfos, targetProjectContraption, projectContraptionIds, useRegistrationCode, false);
            } else {
                // 本次待处理装置
                IdxBizJgProjectContraption projectContraption = projectContraptionService.getById(projectSequenceNbr);
                // 找到同一使用登记证下所有装置中不在本次变更列表的装置
                List<IdxBizJgProjectContraption> projectsUnderSameUseOrgCodeNotInThisApply = projectsUnderSameUseOrgCode.stream().filter(pc -> !projectContraptionIdsInThisApply.contains(String.valueOf(pc.getSequenceNbr()))).collect(Collectors.toList());
                // 如果同一使用登记证下【有】装置【不在】本次变更列表中，则该装置和原使用登记证留给原单位；每一个变更给新单位的装置都重新生成使用登记证
                if (!ValidationUtil.isEmpty(projectsUnderSameUseOrgCodeNotInThisApply)) {
                    String newUseOrgCode = commonServiceImpl.generateRegistrationCode(useInfos.get(0).getRecord(), registration.getReceiveCompanyCode(), true);
                    this.processSingleProjectContraption(registration, useInfos, projectContraption, projectContraptionIds, newUseOrgCode, true);
                    // 如果projectsUnderSameUseOrgCodeNotInThisApply下的所有设备都是报废或者注销状态或均是报废注销的，则把对应证变更成已注销状态
                    this.dealProjectsUnderSameUseOrgCodeNotInThisApply(projectsUnderSameUseOrgCodeNotInThisApply, useRegistrationCode);
                } else {
                    // 如果同一使用登记证下所有装置都在本次变更列表中，则将其中一个装置保留原使用登记证并变更给新单位，其他装置则重新生成使用登记证并变更给新单位
                    // 第一个装置保留原使用登记证
                    if (firstProjectContraptionId.equals(projectSequenceNbr)) {
                        this.processSingleProjectContraption(registration, useInfos, projectContraption, projectContraptionIds, useRegistrationCode, false);
                    } else {
                        String newUseOrgCode = commonServiceImpl.generateRegistrationCode(useInfos.get(0).getRecord(), registration.getReceiveCompanyCode(), true);
                        this.processSingleProjectContraption(registration, useInfos, projectContraption, projectContraptionIds, newUseOrgCode, true);
                    }
                }


//                IdxBizJgProjectContraption idxBizJgProjectContraption = projectContraptionService.getBaseMapper().selectById(Long.valueOf(projectSequenceNbr));
//                //查询使用登记表eq 查询和装置关联的管道，取第一个用于生成登记编号
//                LambdaQueryWrapper<JgChangeRegistrationUnitEq> registrationUnitEqWrapper = new LambdaQueryWrapper<>();
//                registrationUnitEqWrapper.eq(JgChangeRegistrationUnitEq::getProjectContraptionId, idxBizJgProjectContraption.getSequenceNbr())
//                        .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registration.getSequenceNbr())
//                        .eq(JgChangeRegistrationUnitEq::getIsDelete, false);
//                List<JgChangeRegistrationUnitEq> changeRegistrationUnitEqs = registrationUnitEqService.list(registrationUnitEqWrapper);
//                if (CollUtil.isEmpty(changeRegistrationUnitEqs)) {
//                    throw new BadRequest("使用登记表没有找到工程/装置对应的信息");
//                }
//                //重新生成使用登记证
//                LambdaQueryWrapper<JgUseRegistrationManage> useRegistrationManageWrapper = new LambdaQueryWrapper<>();
//                useRegistrationManageWrapper.eq(JgUseRegistrationManage::getUseRegistrationCode, useRegistrationCode)
//                        .isNotNull(JgUseRegistrationManage::getUseRegistrationCode)
//                        .eq(JgUseRegistrationManage::getCertificateStatus, "已登记")
//                        .eq(BaseEntity::getIsDelete, false);
//                List<JgUseRegistrationManage> registrationManages = useRegistrationManageService.getBaseMapper().selectList(useRegistrationManageWrapper);
//                if (CollUtil.isEmpty(registrationManages)) {
//                    throw new BadRequest("使用登记编号为：" + useRegistrationCode + "不存在");
//                }
//                if (registrationManages.size() != 1) {
//                    throw new BadRequest("使用登记编号为：" + useRegistrationCode + "有重复数据,请排查");
//                }
//                JgUseRegistrationManage registrationManage = registrationManages.get(0);
//                registrationManage.setSequenceNbr(sequence.nextId());
//                String code = commonServiceImpl.generateRegistrationCode(changeRegistrationUnitEqs.get(0).getEquId(), registration.getReceiveCompanyCode(), true);
//                registrationManage.setUseRegistrationCode(code);
//                //修改使用登记证管理使用单位地址、使用单位代码、接收机构、接收机构公司代码、办理日期、使用单位地址
//                registrationManage.setUseUnitName(registration.getNewUseUnitName());
//                registrationManage.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
//                registrationManage.setReceiveOrgName(registration.getReceiveOrgName());
//                registrationManage.setReceiveCompanyCode(registration.getReceiveOrgCode());
//                registrationManage.setAuditPassDate(registration.getAuditPassDate());
//                registrationManage.setVersion(1);
//                registrationManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
//                if (!ObjectUtils.isEmpty(registration.getNewUseUnitCreditCode())) {//回填新单位地址
//                    TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().eq(TzBaseEnterpriseInfo::getUseUnitCode, registration.getNewUseUnitCreditCode()));
//                    if (useCodeResult != null) {
//                        registrationManage.setUseUnitAddress(useCodeResult.getAddress());
//                    }
//                }
//                registrationManage.setRecUserId(registration.getCreateUserId());
//                registrationManage.setRegistrationType("0");
//                registrationManage.setRegType(BusinessTypeEnum.JG_USAGE_REGISTRATION.getName());
//                useRegistrationManageService.save(registrationManage);
//                //更新装置表
//                idxBizJgProjectContraption.setUseRegistrationCode(code);
//                idxBizJgProjectContraption.setUseUnitName(registration.getNewUseUnitName());
//                idxBizJgProjectContraption.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
//                idxBizJgProjectContraption.setRecUserId(registration.getCreateUserId());
//                projectContraptionService.updateById(idxBizJgProjectContraption);
                //新增使用登记证和设备变更记录
//                List<String> eqList =  registrationUnitEqService.lambdaQuery().eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registration.getSequenceNbr()).list().stream().map(JgChangeRegistrationUnitEq::getEquId).collect(Collectors.toList());
//                this.saveRecordByProjectContraption(registrationManage, registration, eqList);
//                this.updateUseInfoAndEs(eqList, registration, Boolean.TRUE, code);
            }
        }
        //  创建设备履历
        this.createResume(projectContraptionIds, registration, taskV2Model.getRoutePath());
    }

    /**
     * 处理不在一次单位变更单据下的工程装置
     */
    private void dealProjectsUnderSameUseOrgCodeNotInThisApply(List<IdxBizJgProjectContraption> projectsUnderSameUseOrgCodeNotInThisApply, String useRegistrationCode) {
        List<Long> projectSeqs = projectsUnderSameUseOrgCodeNotInThisApply.stream().map(IdxBizJgProjectContraption::getSequenceNbr).collect(Collectors.toList());
        Integer usedEquipCount = idxBizJgUseInfoService.lambdaQuery()
                .in(IdxBizJgUseInfo::getProjectContraptionId, projectSeqs)
                .notIn(IdxBizJgUseInfo::getEquState, EquipmentEnum.BAOFEI.getCode().toString(), EquipmentEnum.ZHUXIAO.getCode().toString())
                .select(IdxBizJgUseInfo::getRecord)
                .count();
        if (usedEquipCount == 0) {
            // 所有装置下没有在用的管道，则更新原使用登记证状态为已注销
            useRegistrationManageService.lambdaUpdate()
                    .eq(JgUseRegistrationManage::getUseRegistrationCode, useRegistrationCode)
                    .set(JgUseRegistrationManage::getCertificateStatus, CertificateStatusEnum.YIZHUXIAO.getName())
                    .update();
        }
    }

    /**
      增加管道报废业务后需求调整：
      如果装置下有报废的管道，则不变更报废的管道（留在原单位），只变更非报废的管道（给新单位）；
      原装置的登记证号给新单位，并重新生成工程装置，并把非报废的管道变更到新装置
      原单位报废的管道和原装置保留，清除掉装置和管道的使用登记证号
     */
    private void processSingleProjectContraption(JgChangeRegistrationUnit registrationUnit, List<IdxBizJgUseInfo> useInfosOfOneProject, IdxBizJgProjectContraption targetProjectContraption, List<String> projectContraptionIds, String useRegistrationCode, Boolean isNewCode) {
        Map<Boolean, List<IdxBizJgUseInfo>> groupedUseInfos = useInfosOfOneProject.stream()
                .collect(Collectors.partitioningBy(useInfo -> EquipmentEnum.BAOFEI.getCode().toString().equals(useInfo.getEquState())));
        List<IdxBizJgUseInfo> useInfosForScrap = groupedUseInfos.get(true);  // 报废的管道设备
        List<IdxBizJgUseInfo> useInfosForNotScrap = groupedUseInfos.get(false);  // 非报废的管道设备

        List<String> targetEqIdList = useInfosForNotScrap.stream().map(IdxBizJgUseInfo::getRecord).collect(Collectors.toList());

        // 对应设备的注册信息
        List<IdxBizJgRegisterInfo> registerInfos = new ArrayList<>();
        for (int i = 0; i < targetEqIdList.size(); i += ONE_BATCH_SIZE) {
            List<String> batch = targetEqIdList.subList(i, Math.min(i + ONE_BATCH_SIZE, targetEqIdList.size()));
            List<IdxBizJgRegisterInfo> batchResults = idxBizJgRegisterInfoService.list(
                    new LambdaQueryWrapper<IdxBizJgRegisterInfo>().in(IdxBizJgRegisterInfo::getRecord, batch)
            );
            registerInfos.addAll(batchResults);
        }
        // 对应设备的其他信息
        List<IdxBizJgOtherInfo> otherInfos = new ArrayList<>();
        for (int i = 0; i < targetEqIdList.size(); i += ONE_BATCH_SIZE) {
            List<String> batch = targetEqIdList.subList(i, Math.min(i + ONE_BATCH_SIZE, targetEqIdList.size()));
            List<IdxBizJgOtherInfo> batchResults = idxBizJgOtherInfoService.list(
                    new LambdaQueryWrapper<IdxBizJgOtherInfo>().in(IdxBizJgOtherInfo::getRecord, batch)
            );
            otherInfos.addAll(batchResults);
        }

        // 没有报废的管道设备，直接将装置和证都变更到新单位;有部分报废的管道需给新单位新建管道
        if (!ValidationUtil.isEmpty(useInfosForScrap)) { // 有部分报废的管道
            IdxBizJgProjectContraption newProjectContraption = new IdxBizJgProjectContraption();
            IdxBizJgProjectContraption oldProjectContraption = targetProjectContraption;
            BeanUtils.copyProperties(oldProjectContraption, newProjectContraption);
            // 1、老装置保留报废管道，
            // 1.1 装置清除使用登记证关联
            oldProjectContraption.setUseRegistrationCode(null);
            projectContraptionService.updateById(oldProjectContraption);
            pipelineDataChangeService.updatePipelineLength(String.valueOf(oldProjectContraption.getSequenceNbr()));
            // 1.2 设备清除使用登记证关联
            this.terminateRelationOfUseRegistration(useInfosForScrap);
            // 2、生成新装置
            newProjectContraption.setSequenceNbr(sequence.nextId());
            newProjectContraption.setIsIntoManagement(true);
            newProjectContraption.setIsFirstMerge(false);
            newProjectContraption.setProjectContraptionParentId(null);
            newProjectContraption.setDataSource("jg");
            newProjectContraption.setUseDate(DateUtils.getDateNowShortStr());

            // 为新装置生成设备代码和监管码
            String equCode = jgUseRegistrationService.getEquCode(registerInfos.get(0), registrationUnit.getReceiveCompanyCode());
            newProjectContraption.setEquCode(equCode);
            String prefix = oldProjectContraption.getSupervisoryCode().substring(0, 1);
            String categoryCode = oldProjectContraption.getEquCategory();
            Map<String, Object> equCodeMap = new HashMap<>();
            equCodeMap.put("prefix", prefix);
            equCodeMap.put("categoryCode", categoryCode);
            String supervisoryCode = tzsServiceFeignClient.createSupervisoryCodeWithPrefix(equCodeMap).getResult();
            newProjectContraption.setSupervisoryCode(supervisoryCode);
            projectContraptionService.save(newProjectContraption);

            // 2.1 把非报废管道关联到新装置
            List<List<IdxBizJgUseInfo>> useInfoBatches = new ArrayList<>();
            for (int i = 0; i < useInfosForNotScrap.size(); i += ONE_BATCH_SIZE) {
                useInfoBatches.add(useInfosForNotScrap.subList(i, Math.min(i + ONE_BATCH_SIZE, useInfosForNotScrap.size())));
            }
            for (List<IdxBizJgUseInfo> batch : useInfoBatches) {
                batch.forEach(useInfo -> {
                    useInfo.setProjectContraptionId(String.valueOf(newProjectContraption.getSequenceNbr()));
                    useInfo.setEquState(String.valueOf(EquipmentEnum.ZAIYONG.getCode()));
                });
                idxBizJgUseInfoService.updateBatchById(batch);
            }

            // 2.2 更新新装置下管道的设备代码
            List<List<IdxBizJgRegisterInfo>> registerInfoBatches = new ArrayList<>();
            for (int i = 0; i < registerInfos.size(); i += ONE_BATCH_SIZE) {
                registerInfoBatches.add(registerInfos.subList(i, Math.min(i + ONE_BATCH_SIZE, registerInfos.size())));
            }
            for (List<IdxBizJgRegisterInfo> batch : registerInfoBatches) {
                batch.forEach(registerInfo -> registerInfo.setEquCode(equCode));
                idxBizJgRegisterInfoService.updateBatchById(batch);
            }

            // 2.3 更新新装置下管道的监管码
            List<List<IdxBizJgOtherInfo>> otherInfoBatches = new ArrayList<>();
            for (int i = 0; i < otherInfos.size(); i += ONE_BATCH_SIZE) {
                otherInfoBatches.add(otherInfos.subList(i, Math.min(i + ONE_BATCH_SIZE, otherInfos.size())));
            }
            for (List<IdxBizJgOtherInfo> batch : otherInfoBatches) {
                batch.forEach(otherInfo -> otherInfo.setSupervisoryCode(supervisoryCode));
                idxBizJgOtherInfoService.updateBatchById(batch);
            }

            // 重新计算新装置长度
            pipelineDataChangeService.updatePipelineLength(String.valueOf(newProjectContraption.getSequenceNbr()));
            targetProjectContraption = newProjectContraption;

            // 新装置ID加人到待生成履历装置ID
            projectContraptionIds.add(String.valueOf(newProjectContraption.getSequenceNbr()));
        } else {
            // 没有报废的管道设备，直接将装置变更到新单位;
            // 如果是新生成证号，则更新装置和管道对应证号信息
            if (isNewCode) {
                targetProjectContraption.setUseRegistrationCode(useRegistrationCode);
                projectContraptionService.updateById(targetProjectContraption);

                List<List<IdxBizJgRegisterInfo>> registerInfoBatches = new ArrayList<>();
                for (int i = 0; i < registerInfos.size(); i += ONE_BATCH_SIZE) {
                    registerInfoBatches.add(registerInfos.subList(i, Math.min(i + ONE_BATCH_SIZE, registerInfos.size())));
                }
                for (List<IdxBizJgRegisterInfo> batch : registerInfoBatches) {
                    batch.forEach(registerInfo -> registerInfo.setUseOrgCode(useRegistrationCode));
                    idxBizJgRegisterInfoService.updateBatchById(batch);
                }

                List<List<IdxBizJgUseInfo>> useInfoBatches = new ArrayList<>();
                for (int i = 0; i < useInfosForNotScrap.size(); i += ONE_BATCH_SIZE) {
                    useInfoBatches.add(useInfosForNotScrap.subList(i, Math.min(i + ONE_BATCH_SIZE, useInfosForNotScrap.size())));
                }
                for (List<IdxBizJgUseInfo> batch : useInfoBatches) {
                    batch.forEach(useInfo -> {
                        useInfo.setEquState(String.valueOf(EquipmentEnum.ZAIYONG.getCode()));
                    });
                    idxBizJgUseInfoService.updateBatchById(batch);
                }
            }
        }
        this.updateProjectContraptionAndRegistrationManage(registrationUnit, targetProjectContraption, useRegistrationCode, targetEqIdList, isNewCode);
        this.updateUseInfoAndEs(targetEqIdList, registrationUnit, isNewCode, isNewCode ? useRegistrationCode : null);
    }

    private void terminateRelationOfUseRegistration(List<IdxBizJgUseInfo> useInfosForScrap) {
        if (!ValidationUtil.isEmpty(useInfosForScrap)) {
            List<String> eqIdList = useInfosForScrap.stream().map(IdxBizJgUseInfo::getRecord).collect(Collectors.toList());
            for (int i = 0; i < eqIdList.size(); i += ONE_BATCH_SIZE) {
                List<String> batch = eqIdList.subList(i, Math.min(i + ONE_BATCH_SIZE, eqIdList.size()));

                idxBizJgRegisterInfoService.lambdaUpdate()
                        .setSql("\"USE_ORG_CODE\" = NULL")
                        .in(IdxBizJgRegisterInfo::getRecord, batch)
                        .update();

                Iterable<ESEquipmentCategoryDto> jgAllEsDtos = esEquipmentCategory.findAllById(batch);
                jgAllEsDtos.forEach(dto -> dto.setUSE_ORG_CODE(null));
                esEquipmentCategory.saveAll(jgAllEsDtos);
                Iterable<ESEquipmentInfo> newEsDtos = esEquipmentDao.findAllById(batch);
                newEsDtos.forEach(dto -> dto.setUSE_ORG_CODE(null));
                esEquipmentDao.saveAll(newEsDtos);
            }
        }
    }

    private void updateProjectContraptionAndRegistrationManage(JgChangeRegistrationUnit registration, IdxBizJgProjectContraption idxBizJgProjectContraption, String useRegistrationCode, List<String> eqList, Boolean isNewCode) {
        idxBizJgProjectContraption.setUseUnitName(registration.getNewUseUnitName());
        idxBizJgProjectContraption.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
        idxBizJgProjectContraption.setRecUserId(registration.getCreateUserId());
        projectContraptionService.updateById(idxBizJgProjectContraption);
        JgUseRegistrationManage registrationManage;
        if (isNewCode) {
            registrationManage = new JgUseRegistrationManage();
            registrationManage.setSequenceNbr(sequence.nextId());
            registrationManage.setUseRegistrationCode(useRegistrationCode);
            registrationManage.setRegDate(new Date());
            registrationManage.setCreateDate(new Date());
            registrationManage.setRegistrationType("0");
            registrationManage.setRegType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
            registrationManage.setApplyNo(registration.getApplyNo());
            registrationManage.setManageType("unit");
            registrationManage.setEquList(idxBizJgProjectContraption.getEquListName());
            registrationManage.setEquListCode(idxBizJgProjectContraption.getEquList());
            registrationManage.setEquCategory(idxBizJgProjectContraption.getEquCategoryName());
            registrationManage.setEquCategoryCode(idxBizJgProjectContraption.getEquCategory());
            registrationManage.setEquDefine(idxBizJgProjectContraption.getEquDefineName());
            registrationManage.setEquDefineCode(idxBizJgProjectContraption.getEquDefine());
            registrationManage.setEquUseAddress(Stream.of(idxBizJgProjectContraption.getProvinceName(), idxBizJgProjectContraption.getCityName(), idxBizJgProjectContraption.getCountyName(), idxBizJgProjectContraption.getStreetName(), idxBizJgProjectContraption.getAddress())
                    .map(value -> value == null || "null".equals(value) ? "" : value)
                    .collect(Collectors.joining()));
            registrationManage.setSuperviseOrgCode(idxBizJgProjectContraption.getOrgCode());
            registrationManage.setSuperviseOrgName(idxBizJgProjectContraption.getOrgName());
        } else {
            //获取使用登记证
            LambdaQueryWrapper<JgUseRegistrationManage> useRegistrationManageWrapper = new LambdaQueryWrapper<>();
            useRegistrationManageWrapper.eq(JgUseRegistrationManage::getUseRegistrationCode, useRegistrationCode)
                    .isNotNull(JgUseRegistrationManage::getUseRegistrationCode)
                    .eq(BaseEntity::getIsDelete, false);
            registrationManage = useRegistrationManageService.getBaseMapper().selectOne(useRegistrationManageWrapper);
            if (ValidationUtil.isEmpty(registrationManage)) {
                String errorMsg = "使用登记证【" + useRegistrationCode + "】不存在";
                log.error(errorMsg);
                throw new BadRequest(errorMsg);
            }
            registrationManage.setVersion(registrationManage.getVersion() + 1);
        }
        //修改使用登记证管理使用单位地址、使用单位代码、接收机构、接收机构公司代码、办理日期、使用单位地址
        registrationManage.setUseUnitName(registration.getNewUseUnitName());
        registrationManage.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
        registrationManage.setReceiveOrgName(registration.getReceiveOrgName());
        registrationManage.setReceiveCompanyCode(registration.getReceiveOrgCode());
        registrationManage.setAuditPassDate(registration.getAuditPassDate());
        registrationManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
        registrationManage.setCertificateStatus(CertificateStatusEnum.YIDENGJI.getName());
        if (!ObjectUtils.isEmpty(registration.getNewUseUnitCreditCode())) {//回填新单位地址
            TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(new QueryWrapper<TzBaseEnterpriseInfo>().eq("use_unit_code", registration.getNewUseUnitCreditCode()));
            if (useCodeResult != null) {
                registrationManage.setUseUnitAddress(useCodeResult.getAddress());
            }
        }
        registrationManage.setRecUserId(registration.getCreateUserId());
        useRegistrationManageService.saveOrUpdate(registrationManage);
        //新增使用登记证和设备变更记录
        this.saveRecordByProjectContraption(registrationManage, registration, eqList);
    }

    private void createResume(List<String> projectContraptionIds, JgChangeRegistrationUnit registration, String routePath) {
        jgResumeInfoService.saveBatchResume(projectContraptionIds.stream().map(projectContraptionId-> JgResumeInfo.builder().applyNo(registration.getApplyNo())
                .businessType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName())
                .businessId(String.valueOf(registration.getSequenceNbr()))
                .equId(projectContraptionId)
                .approvalUnit(registration.getReceiveOrgName())
                .approvalUnitCode(registration.getReceiveCompanyCode())
                .status("正常")
                .changeContent(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName() + "业务办理")
                .routePath(routePath)
                .build()).collect(Collectors.toList())
        );
    }

    /**
     * 更新使用信息表和两个设备es
     *
     * @param eqIdList 待更新设备ID集合
     * @param registration 本次单位变更单据
     * @param isNewUseOrgCode 是否使用新的使用登记证号
     * @param useOrgCode 新使用登记证号
     */
    private void updateUseInfoAndEs(List<String> eqIdList, JgChangeRegistrationUnit registration, Boolean isNewUseOrgCode, String useOrgCode) {
        if (!ValidationUtil.isEmpty(eqIdList)) {
            String[] companyCode = registration.getNewUseUnitCreditCode().split("_");
            String newCompanyCode = companyCode.length > 1 ? companyCode[1] : registration.getNewUseUnitCreditCode();
            for (int i = 0; i < eqIdList.size(); i += ONE_BATCH_SIZE) {
                List<String> batch = eqIdList.subList(i, Math.min(i + ONE_BATCH_SIZE, eqIdList.size()));
                idxBizJgUseInfoService.lambdaUpdate()
                        .set(IdxBizJgUseInfo::getUseUnitCreditCode, newCompanyCode)
                        .set(IdxBizJgUseInfo::getUseUnitName, registration.getNewUseUnitName())
                        .in(IdxBizJgUseInfo::getRecord, batch)
                        .update();

                Iterable<ESEquipmentCategoryDto> jgAllEsDtos = esEquipmentCategory.findAllById(batch);
                jgAllEsDtos.forEach(dto -> {
                    dto.setUSE_UNIT_CREDIT_CODE(newCompanyCode);
                    dto.setUSE_UNIT_NAME(registration.getNewUseUnitName());
                    dto.setREC_DATE(new Date().getTime());
                    if (Boolean.TRUE.equals(isNewUseOrgCode)) {
                        dto.setUSE_ORG_CODE(useOrgCode);
                    }
                    dto.setEQU_STATE(EquipmentEnum.ZAIYONG.getCode());
                });
                esEquipmentCategory.saveAllWithFallback(jgAllEsDtos);
                Iterable<ESEquipmentInfo> newEsDtos = esEquipmentDao.findAllById(batch);
                newEsDtos.forEach(dto -> {
                    dto.setUSE_UNIT_CREDIT_CODE(newCompanyCode);
                    dto.setUSE_UNIT_NAME(registration.getNewUseUnitName());
                    dto.setREC_DATE(new Date().getTime());
                    if (Boolean.TRUE.equals(isNewUseOrgCode)) {
                        dto.setUSE_ORG_CODE(useOrgCode);
                    }
                    dto.setEQU_STATE(EquipmentEnum.ZAIYONG.getCode());
                });
                esEquipmentDao.saveAll(newEsDtos);
            }
        }
    }

    /**
     * 更新关系表
     *
     * @param sequenceNbr
     * @param registration
     * @param isNewUseOrgCode
     * @param useOrgCode
     */
    private void updateRelationTable(Long sequenceNbr, JgChangeRegistrationUnit registration, Boolean isNewUseOrgCode, String useOrgCode) {
        LambdaQueryWrapper<JgChangeRegistrationUnitEq> unitEqWrapper = new LambdaQueryWrapper<>();
        unitEqWrapper.eq(JgChangeRegistrationUnitEq::getProjectContraptionId, sequenceNbr)
                .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registration.getSequenceNbr())
                .eq(JgChangeRegistrationUnitEq::getIsDelete, false);
        List<JgChangeRegistrationUnitEq> changeRegistrationUnitEqs = registrationUnitEqService.list(unitEqWrapper);
        if (!CollectionUtils.isEmpty(changeRegistrationUnitEqs)) {
            Map<String, Map<String, Object>> resultMap = new HashMap<>();
            for (JgChangeRegistrationUnitEq jgChangeRegistrationUnitEq : changeRegistrationUnitEqs) {
                String equipId = jgChangeRegistrationUnitEq.getEquId();
                LambdaQueryWrapper<IdxBizJgUseInfo> queryWrapper2 = new LambdaQueryWrapper<>();
                queryWrapper2.eq(IdxBizJgUseInfo::getRecord, equipId);
                IdxBizJgUseInfo useInfo = useInfoMapper.selectOne(queryWrapper2);
                if (ObjectUtils.isNotEmpty(useInfo)) {
                    useInfo.setUseUnitName(registration.getNewUseUnitName());
                    useInfo.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
                    useInfoMapper.updateById(useInfo);
                }
                //修改ES中使用单位信息和使用单位代码
                Map<String, Object> map1 = new HashMap<>();
                String[] companyCode = registration.getNewUseUnitCreditCode().split("_");
                map1.put("USE_UNIT_CREDIT_CODE", companyCode.length > 1 ? companyCode[1] : registration.getNewUseUnitCreditCode());
                map1.put("USE_UNIT_NAME", registration.getNewUseUnitName());
                map1.put("REC_DATE", new Date());// 更新时间
                if (Boolean.TRUE.equals(isNewUseOrgCode)) {
                    map1.put("USE_ORG_CODE", useOrgCode);
                }
                resultMap.put(equipId, map1);
                //修改各类告知列表，置为废弃
                this.updataInvalidStatusByHistory(equipId, registration.getApplyNo());
                tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
            }
        }
    }

    /**
     * 保存装置单位变更记录
     *
     * @param registrationManage
     */
    private void saveRecordByProjectContraption(JgUseRegistrationManage registrationManage, JgChangeRegistrationUnit registrationUnit, List<String> eqList) {
        List<JgCertificateChangeRecordEq> changeRecordEqList = new ArrayList<>();
        JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord();
        long nextId = sequence.nextId();
        changeRecord.setApplyNo(registrationUnit.getApplyNo());//申请编号
        changeRecord.setReceiveOrgName(registrationUnit.getReceiveOrgName());//接收机构/登记机关
        changeRecord.setAuditPassDate(registrationUnit.getAuditPassDate());//办理通过日期
        changeRecord.setRegType("单位变更登记");//登记类别
        changeRecord.setRegDate(registrationUnit.getCreateDate());//申请日期
        changeRecord.setChangeContent(this.buildRecordContent(registrationUnit));//变更内容
        changeRecord.setUseRegistrationCode(registrationManage.getUseRegistrationCode());//使用登记编号
        changeRecord.setReceiveCompanyCode(registrationUnit.getReceiveCompanyCode());//接收机构公司代码
        changeRecord.setCertificateNo(registrationManage.getCertificateNo());//登记证书唯一码
        changeRecord.setUseUnitCreditCode(registrationUnit.getNewUseUnitCreditCode());//使用单位统一信用代码
        changeRecord.setUseUnitName(registrationUnit.getNewUseUnitName());//使用单位名称
        changeRecord.setEquCategory(registrationManage.getEquCategory());//设备类别编码
        changeRecord.setCreateDate(new Date());
        changeRecord.setSequenceNbr(nextId);
        for (String eqId : eqList) {
            JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
            changeRecordEq.setChangeRecordId(String.valueOf(nextId));//登记证记录主键
            changeRecordEq.setEquId(eqId);//设备主键
            changeRecordEqList.add(changeRecordEq);
        }
        certificateChangeRecordService.save(changeRecord);
        if (!changeRecordEqList.isEmpty()) {
            certificateChangeRecordEqService.saveBatch(changeRecordEqList);
        }
    }

    /**
     * 删除 redis校验重复引用设备的数据
     */
    private void delRepeatUseEquipData(String applyNo, String status, String companyCode) {
        JgRegistrationHistory history = registrationHistoryService.lambdaQuery()
                .eq(JgRegistrationHistory::getCurrentDocumentId, applyNo)
                .eq(JgRegistrationHistory::getIsDelete, false)
                .one();
        // 获取使用登记证列表
        JSONArray registrationList = JSON.parseArray(history.getChangeData());
        if (CollectionUtils.isEmpty(registrationList)) {
            return;
        }
        List<Long> registrationIdList = new ArrayList<>();
        List<String> projectContraptionIdList = new ArrayList<>();
        //根据使用登记证查询设备
        for (Object o : registrationList) {
            JSONObject parseObject = JSON.parseObject(o.toString());
            if (parseObject.containsKey("sequenceNbr") && ObjectUtils.isNotEmpty(parseObject.get("sequenceNbr")) &&
                    canConvertToLong(parseObject.get("sequenceNbr").toString())) {
                registrationIdList.add(Long.parseLong(parseObject.get("sequenceNbr").toString()));
                projectContraptionIdList.add(parseObject.get("sequenceNbr").toString());
            }
        }
        List<String> records = new ArrayList<>();
        JSONObject firstObj = registrationList.stream()
                .findFirst()
                .map(Object::toString)
                .map(JSON::parseObject)
                .orElse(new JSONObject());
        String equListCode = Optional.ofNullable(firstObj.getString("equList"))
                .filter(ObjectUtils::isNotEmpty)
                .orElse(null);
        String equCategoryCode = Optional.ofNullable(firstObj.getString("equCategory"))
                .filter(ObjectUtils::isNotEmpty)
                .orElse(null);

        if (PipelineEnum.PRESSURE_PIPELINE.getCode().equals(equListCode)) {
            JgChangeRegistrationUnit registrationUnit = this.lambdaQuery().eq(JgChangeRegistrationUnit::getApplyNo, applyNo)
                    .eq(JgChangeRegistrationUnit::getIsDelete, false)
                    .one();
            if (Objects.nonNull(registrationUnit)) {
                LambdaQueryWrapper<JgChangeRegistrationUnitEq> wrapper = new LambdaQueryWrapper<>();
                wrapper.in(JgChangeRegistrationUnitEq::getProjectContraptionId, projectContraptionIdList)
                        .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registrationUnit.getSequenceNbr())
                        .eq(JgChangeRegistrationUnitEq::getIsDelete, false);
                List<JgChangeRegistrationUnitEq> changeRegistrationUnitEqs = registrationUnitEqService.list(wrapper);
                if (CollUtil.isNotEmpty(changeRegistrationUnitEqs)) {
                    changeRegistrationUnitEqs.forEach(item -> records.add(item.getEquId()));
                }
            }
        } else if (CylinderTypeEnum.CYLINDER.getCode().equals(equCategoryCode)) {
            records.addAll(registrationList.stream()
                            .map(Object::toString)
                            .map(JSON::parseObject)
                            .map(obj -> obj.getString("sequenceNbr"))
                            .filter(ObjectUtils::isNotEmpty)
                            .collect(Collectors.toList())
            );
        } else {
            List<JSONObject> equList = registrationManageService.queryEquByCertificateSeqList(registrationIdList);
            // 获取单位变更设备列表
            if (CollectionUtils.isEmpty(equList)) {
                return;
            }

            for (JSONObject jsonObject : equList) {
                records.add(jsonObject.getString("SEQUENCE_NBR"));
            }
        }
        if (NOT_FLOWING_STATE.contains(status)) {
            EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .delDataForCheckEquipRepeatUsed(records, companyCode);
        }
    }

    private Integer getTaskCodeByName(String auditStatus) {
        return commonServiceImpl.getDictionaryCodeByName(auditStatus);
    }


    /**
     * 修改各类告知列表，置为废弃
     *
     * @param equId           设备id
     * @param equipTransferId 当前告知单Id
     */
    public void updataInvalidStatusByHistory(String equId, String equipTransferId) {
        //改造变更登记
        jgChangeRegistrationReformEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
        //移装变更登记
        jgChangeRegistrationTransferEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
        //使用登记
        jgUseRegistrationEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
        //单位变更登记
        jgChangeRegistrationUnitEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
        //更名变更登记
        jgChangeRegistrationNameEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
    }

    /**
     * 导出使用登记证
     *
     * @param sequenceNbr
     */
    public void exportUseRegistrationCertificate(String sequenceNbr, HttpServletResponse response, String printType) {
        Map<String, Object> exportParamsMap = new HashMap<>();
        //查询移装变更详情
        JgChangeRegistrationUnit transfer = this.getById(sequenceNbr);
        LambdaQueryWrapper<JgChangeRegistrationUnitEq> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, transfer.getSequenceNbr());
        JgChangeRegistrationUnitEq jgChangeRegistrationUnitEq = JgChangeRegistrationUnitEqMapper.selectOne(queryWrapper);
        if (ValidationUtil.isEmpty(transfer) || ValidationUtil.isEmpty(jgChangeRegistrationUnitEq)) {
            throw new BadRequest("使用登记证导出失败,请稍后重试!");
        }
        //是否废弃
        exportParamsMap.put("isInvalid", ValidationUtil.isEmpty(jgChangeRegistrationUnitEq.getIsInvalid()) ? "0" : jgChangeRegistrationUnitEq.getIsInvalid());
        //登记机关
        exportParamsMap.put("receiveOrgName", transfer.getReceiveOrgName());
        //使用登记证编号
        exportParamsMap.put("useRegistrationCode", ValidationUtil.isEmpty(transfer.getUseRegistCode()) ? "" : transfer.getUseRegistCode());
        //使用单位名称
        exportParamsMap.put("useUnitName", transfer.getNewUseUnitName());
        //监管码
        LambdaQueryWrapper<OtherInfo> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(OtherInfo::getRecord, jgChangeRegistrationUnitEq.getEquId());
        OtherInfo tzsJgOtherInfo = tzsJgOtherInfoMapper.selectOne(queryWrapper1);
        exportParamsMap.put("supervisoryCode", tzsJgOtherInfo.getSupervisoryCode());
        getAuditPassedDate(transfer.getAuditPassDate(), exportParamsMap);
        //查询设备注册信息
        IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoService.getOne(new QueryWrapper<IdxBizJgRegisterInfo>().eq("RECORD", jgChangeRegistrationUnitEq.getEquId()));
        if (!ValidationUtil.isEmpty(registerInfo)) {
            //设备种类、类别、品种
            String equList = registerInfo.getEquList();//设备种类
            String equCategory = registerInfo.getEquCategory();//设备类别
            String equDefine = registerInfo.getEquDefine();//设备品种
            List<EquipmentCategory> categoryList0 = commonService.getEquipmentCategoryList(equList, null);
            List<EquipmentCategory> categoryList1 = commonService.getEquipmentCategoryList(equCategory, null);
            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(categoryList1)) {
                exportParamsMap.put("equList", categoryList0.get(0).getName());
            }
            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(categoryList1)) {
                exportParamsMap.put("equCategory", categoryList1.get(0).getName());
            }
            if (!ValidationUtil.isEmpty(equDefine)) {
                List<EquipmentCategory> categoryList2 = commonService.getEquipmentCategoryList(equDefine, null);
                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(categoryList2)) {
                    exportParamsMap.put("equDefine", categoryList2.get(0).getName());
                }
            }
            //设备代码
            exportParamsMap.put("equCode", registerInfo.getEquCode());
        }

        //单位内部编码
        IdxBizJgUseInfo useInfo = idxBizJgUseInfoService.getOneData(jgChangeRegistrationUnitEq.getEquId());
        if (!ValidationUtil.isEmpty(useInfo)) {
            exportParamsMap.put("useInnerCode", useInfo.getUseInnerCode());

            String fullAddress = "";
            String province = ValidationUtil.isEmpty(useInfo.getProvinceName()) ? "" : useInfo.getProvinceName();
            String city = ValidationUtil.isEmpty(useInfo.getCityName()) ? "" : useInfo.getCityName();
            String county = ValidationUtil.isEmpty(useInfo.getCountyName()) ? "" : useInfo.getCountyName();
            String street = ValidationUtil.isEmpty(useInfo.getStreetName()) ? "" : useInfo.getStreetName();
            String address = ValidationUtil.isEmpty(useInfo.getAddress()) ? "" : useInfo.getAddress();
            fullAddress = province + city + county + street + address;
            exportParamsMap.put("fullAddress", fullAddress);
        }
        IdxBizJgFactoryInfo factoryInfo = idxBizJgFactoryInfoService.getOneData(jgChangeRegistrationUnitEq.getEquId());
        //产品编号(出厂编号)
        if (!ValidationUtil.isEmpty(factoryInfo)) {
            exportParamsMap.put("factoryNum", factoryInfo.getFactoryNum());
        }
        //调用生成使用登记证
        exportParamsMap.put("excelType", "变更登记");
        exportParamsMap.put("tableName", "特种设备单位变更登记");
        exportParamsMap.put("applyNo", transfer.getApplyNo());
        if ("0".equals(printType)) {
            //调用生成使用登记证
            commonService.generateCertificateReport(exportParamsMap, response);
        } else {
            commonService.generatePdfPrint(exportParamsMap, response);
        }
    }


    private String buildTaskContent(JgChangeRegistrationUnit obj) {
        //发起电梯登记业务申请，【申请单号SYDJ202400001】
        return "发起了【单位变更登记】业务申请，【申请单号" + obj.getApplyNo() + "】";
    }

    private String buildRecordContent(JgChangeRegistrationUnit obj) {
        //张三办理了【单位变更】 ，单号【DWBG202407050001】，原恒星电梯单位变更为新恒星电梯有限公司，办理日期2024-07-05
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        return obj.getNewUseUnitName() + "的" + obj.getCreateUserName() + "办理了【单位变更登记】，单号【"
                + obj.getApplyNo() + "】，原" + obj.getUseUnitName() + "变更为新"
                + obj.getNewUseUnitName() + "，申请日期" + simpleDateFormat.format(obj.getCreateDate());
    }

    private void createTaskModel(JgChangeRegistrationUnit dto, String taskName, String submitType, String nextUserIds) {
        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        if ("1".equals(submitType)) {
            TaskModelDto taskModelDto = new TaskModelDto();
            taskModelDto.setFlowCreateDate(dto.getApplyDate());
            taskModelDto.setTaskName(taskName);
            taskModelDto.setTaskCode(dto.getApplyNo());
            taskModelDto.setTaskContent(this.buildTaskContent(dto));
            taskModelDto.setTaskDesc("");
            taskModelDto.setTaskType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getCode());
            taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
            taskModelDto.setRelationId(dto.getInstanceId());
            taskModelDto.setExecuteUserIds(nextUserIds);
            taskModelDto.setFlowStatus(this.getTaskStatusByName(dto.getStatus()));
            taskModelDto.setFlowStatusLabel(dto.getStatus());
            taskModelDto.setTaskStatusLabel(dto.getAuditStatus());
            taskModelDto.setStartUserId(RequestContext.getExeUserId());
            taskModelDto.setStartUser(reginParams.getUserModel().getRealName());
            taskModelDto.setStartUserCompanyName(dto.getUseUnitName());
            taskModelDto.setNextExecuteUser(dto.getNextExecutorIds());
            taskModelDto.setStartDate(dto.getCreateDate());
            TaskMessageDto obj = new TaskMessageDto();
            obj.setInstanceId(dto.getInstanceId());
            obj.setStatus(dto.getStatus());
            obj.setPromoter(dto.getPromoter());
            obj.setNextExecuteUserIds(dto.getNextExecuteUserIds());
            obj.setSequenceNbr(dto.getSequenceNbr());
            obj.setNextTaskId(dto.getNextTaskId());
            taskModelDto.setModel(obj);
            commonServiceImpl.buildTaskModel(Collections.singletonList(taskModelDto));
        }
    }

    private void buildRoleList(List<ProcessTaskDTO> processTasks, List<String> roleListNext, List<String> roleListAll) {
        processTasks.forEach(p -> {
            p.getNextCandidateGroups().values().forEach(e -> {
                roleListNext.addAll(e);
                roleListAll.addAll(e);
            });
            roleListAll.addAll(p.getCandidateGroups());
        });
    }

    private void executeOneStep(JgChangeRegistrationUnit jgChangeRegistrationName, String taskName, String nextUserIds, String operate) {
        // 先更新之前的待办
        TaskV2Model taskV2Model = updateTaskModel(jgChangeRegistrationName, operate);
        taskV2Model.setTaskDesc("");
        taskV2Model.setTaskName(taskName);
        taskV2Model.setTaskDesc("");
        taskV2Model.setTaskCode(jgChangeRegistrationName.getApplyNo());
        taskV2Model.setExecuteUserIds(nextUserIds);
        taskV2Model.setRelationId(jgChangeRegistrationName.getInstanceId());
        FlowStatusEnum flowStatusEnum = this.getTaskStatus(operate);
        taskV2Model.setTaskStatus(this.getTaskStatusByName(jgChangeRegistrationName.getStatus()));
        taskV2Model.setTaskStatusLabel(jgChangeRegistrationName.getStatus());
        taskV2Model.setFlowStatus(this.getTaskStatusByName(jgChangeRegistrationName.getStatus()));
        taskV2Model.setFlowStatusLabel(jgChangeRegistrationName.getStatus());
        taskV2Model.setExecuteUserIds(nextUserIds);
        TaskModelDto modelDto = new TaskModelDto();
        BeanUtil.copyProperties(taskV2Model, modelDto);
        modelDto.setNextExecuteUser(jgChangeRegistrationName.getNextExecutorIds());
        if (jgChangeRegistrationName.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject())) {
            modelDto.setPageType("edit");
        }
        TaskMessageDto obj = new TaskMessageDto();
        obj.setInstanceId(jgChangeRegistrationName.getInstanceId());
        obj.setStatus(jgChangeRegistrationName.getStatus());
        obj.setPromoter(jgChangeRegistrationName.getPromoter());
        obj.setNextExecuteUserIds(jgChangeRegistrationName.getNextExecuteUserIds());
        obj.setSequenceNbr(jgChangeRegistrationName.getSequenceNbr());
        obj.setNextTaskId(jgChangeRegistrationName.getNextTaskId());
        modelDto.setModel(obj);
        // 再插入新代办、数据待定
        commonServiceImpl.buildTaskModel(Collections.singletonList(modelDto));
    }


    private TaskV2Model updateTaskModel(JgChangeRegistrationUnit jgChangeRegistrationName, String operate) {
        Map<String, Object> params = new HashMap<>();
        FlowStatusEnum flowStatusEnum = this.getTaskStatus(operate);
        params.put("relationId", jgChangeRegistrationName.getInstanceId());
        params.put("taskStatus", flowStatusEnum.getCode());
        params.put("taskStatusLabel", flowStatusEnum.getName());
        params.put("flowStatus", this.getTaskStatusByName(jgChangeRegistrationName.getStatus()));
        params.put("flowStatusLabel", jgChangeRegistrationName.getStatus());
        params.put("model", jgChangeRegistrationName);
        return commonServiceImpl.updateTaskModel(params);
    }

    private FlowStatusEnum getTaskStatus(String operate) {
        if ("0".equals(operate)) {
            return FlowStatusEnum.TO_BE_FINISHED;
        } else {
            return FlowStatusEnum.REJECTED;
        }
    }


    private String getNextUserOrgCode(String operate, JgChangeRegistrationUnit jgChangeRegistrationName) {
        if ("0".equals(operate)) {
            // 执行通过节点，单位code为接收机构单位信息
            return jgChangeRegistrationName.getReceiveOrgCode();
        }
        if (jgChangeRegistrationName.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getPass())
                || jgChangeRegistrationName.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getReject())
                || jgChangeRegistrationName.getStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getRollBack())) {
            // 驳回且当前节点为一键节点时，单位code为发起人单位信息
            return jgChangeRegistrationName.getUseUnitCreditCode();
        }
        // 2、3级驳回时，单位code为接收单位code
        return jgChangeRegistrationName.getReceiveOrgCode();
    }

    private Integer getTaskStatusByName(String auditStatus) {
        return commonServiceImpl.getDictionaryCodeByName(auditStatus);
    }

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

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

    /**
     * bug24304脏数据处理（单位变更登记一勾选过多，部分变更设备失败，现在将变更失败的设备变更过去）
     */
    @Transactional(rollbackFor = Exception.class)
    public void bug24304Handle(String businessType, String applyNos) {
        /* // 查询单位变更登记的历史数据
        List<JgRegistrationHistory> historyList = jgRegistrationHistoryMapper.selectList(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getRegistrationClass, "单位变更登记"));
        // 过滤出异常数据
        List<JgRegistrationHistory> targetHistory = historyList
                .stream()
                .filter(item -> {
                    try {
                        return JSONArray.parseArray(item.getChangeData()).size() > 10;
                    } catch (Exception ex) {
                        return false;
                    }
                })
                .collect(Collectors.toList()); */

        List<String> applyNoList = Arrays.asList(applyNos.split(","));
        switch (businessType) {
            case "1":
                changeRegistrationUnitHandler(applyNoList);
                break;
            case "2":
                scrapCancelHandler(applyNoList);
                break;
            default:
                break;
        }

    }

    /**
     * 注销-数据处理
     *
     * @param applyNoList 申请单号list
     */
    private void scrapCancelHandler(List<String> applyNoList) {
        applyNoList.forEach(applyNo -> {
            // 查询注销数据
            JgScrapCancel scrapCancel = jgScrapCancelMapper.selectOne(new LambdaQueryWrapper<JgScrapCancel>()
                    .eq(JgScrapCancel::getApplyNo, applyNo));
            // 查询注销的历史数据
            JgRegistrationHistory history = jgRegistrationHistoryMapper.selectOne(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getRegistrationClass, "注销")
                    .eq(JgRegistrationHistory::getCurrentDocumentId, scrapCancel.getSequenceNbr()));
            // 查询已经入库的设备id
            List<String> inEqTableEquId = jgScrapCancelEqMapper.selectList(new LambdaQueryWrapper<JgScrapCancelEq>()
                            .eq(JgScrapCancelEq::getEquipTransferId, scrapCancel.getSequenceNbr()))
                    .stream()
                    .map(JgScrapCancelEq::getEquId)
                    .collect(Collectors.toList());
            // 查询单子下的所有使用登记证的seq
            List<Long> certificateSeq = JSONArray.parseArray(JSON.toJSONString(JSONObject.parseObject(history.getChangeData()).get("certificates"))).stream().map(item -> Long.valueOf((String) JSONObject.parseObject(JSONObject.toJSONString(item)).get(SEQUENCE_NBR))).collect(Collectors.toList());
            // 使用登记证下的所有设备
            List<JSONObject> equJSONList = registrationManageService.queryEquByCertificateSeqList(certificateSeq);
            // 过滤出未入库的设备
            List<JSONObject> toBeProcessedEq = equJSONList.stream().filter(item -> !inEqTableEquId.contains(item.getString("SEQUENCE_NBR"))).collect(Collectors.toList());
            // 未入库的设备record
            List<String> toBeProcessedEqRecord = toBeProcessedEq.stream().map(item -> String.valueOf(item.get("SEQUENCE_NBR"))).collect(Collectors.toList());
            // 保存到对应的eq表
            ArrayList<JgScrapCancelEq> jgScrapCancelEqs = new ArrayList<>();
            toBeProcessedEqRecord.forEach(eq -> {
                IdxBizJgRegisterInfo jgRegisterInfo = idxBizJgRegisterInfoService.getBaseMapper().selectOne(new LambdaQueryWrapper<IdxBizJgRegisterInfo>().eq(IdxBizJgRegisterInfo::getRecord, eq));
                JgScrapCancelEq cancelEq = new JgScrapCancelEq();
                cancelEq.setEquipTransferId(String.valueOf(scrapCancel.getSequenceNbr()));
                cancelEq.setEquId(eq);
                cancelEq.setIsDelete(Boolean.FALSE);
                cancelEq.setEquCode(jgRegisterInfo.getEquCode());
                cancelEq.setUseRegistrationCode(jgRegisterInfo.getUseOrgCode());
                jgScrapCancelEqs.add(cancelEq);
                jgScrapCancelEqMapper.insert(cancelEq);
            });
            // 修改监督管理信息
            SuperviseInfo superviseInfo = new SuperviseInfo();
            superviseInfo.setOrgBranchCode("");
            superviseInfo.setOrgBranchName("");
            LambdaQueryWrapper<SuperviseInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(SuperviseInfo::getRecord, toBeProcessedEqRecord);
            superviseInfoMapper.update(superviseInfo, wrapper);
            // 修改设备状态
            idxBizJgUseInfoMapper.batchUpdateUseInfo(toBeProcessedEqRecord, EquipmentEnum.ZHUXIAO.getCode());
            // 修改证管理表中的证的状态
            List<JgUseRegistrationManage> jgUseRegistrationManages = jgUseRegistrationManageMapper.selectList(new LambdaQueryWrapper<JgUseRegistrationManage>()
                    .in(JgUseRegistrationManage::getSequenceNbr, certificateSeq)
                    .eq(JgUseRegistrationManage::getCertificateStatus, CertificateStatusEnum.YIDENGJI.getName()));
            LambdaUpdateWrapper<JgUseRegistrationManage> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.in(JgUseRegistrationManage::getSequenceNbr, jgUseRegistrationManages.stream().map(BaseEntity::getSequenceNbr).collect(Collectors.toList()));
            updateWrapper.set(JgUseRegistrationManage::getCertificateStatus, CertificateStatusEnum.YIZHUXIAO.getName());
            jgUseRegistrationManageMapper.update(null, updateWrapper);
            // 修改es数据
            Map<String, Object> map = new HashMap<>();
            map.put("ORG_BRANCH_CODE", "");
            map.put("ORG_BRANCH_NAME", "");
            map.put("EQU_STATE", String.valueOf(EquipmentEnum.ZHUXIAO.getCode()));
            Map<String, Map<String, Object>> resultMap = new HashMap<>();
            for (String equipId : toBeProcessedEqRecord) {
                resultMap.put(equipId, map);
            }
            tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
            // 添加流水记录
            String userId = scrapCancel.getCreateUserId();
            String realName = Privilege.agencyUserClient.queryByUserId(userId).getResult().getRealName();
            String content = scrapCancel.getUseUnitName() + "的" + realName + "办理了【" + CancelTypeEnum.getNameByType(scrapCancel.getCancelType()) + "】" +
                    "单号【" + scrapCancel.getApplyNo() + "】，办理日期" + DateUtils.getDateNowShortStr();
            List<JgCertificateChangeRecord> certificateChangeRecords = new ArrayList<>();
            List<JgCertificateChangeRecordEq> changeRecordEqList = new ArrayList<>();
            Optional<JgCertificateChangeRecord> first = certificateChangeRecordService.getBaseMapper().selectList(new LambdaQueryWrapper<JgCertificateChangeRecord>().eq(JgCertificateChangeRecord::getApplyNo, applyNo)).stream().findFirst();
            for (JgUseRegistrationManage jgUseRegistrationManage : jgUseRegistrationManages) {
                long seq = sequence.nextId();
                JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord();
                changeRecord.setSequenceNbr(seq);
                changeRecord.setApplyNo(scrapCancel.getApplyNo());
                changeRecord.setReceiveOrgName(scrapCancel.getReceiveOrgName());
                changeRecord.setAuditPassDate(new Date());
                changeRecord.setRegType(CancelTypeEnum.getNameByType(scrapCancel.getCancelType()));
                changeRecord.setRegDate(scrapCancel.getCreateDate());
                changeRecord.setChangeContent(content);
                changeRecord.setUseRegistrationCode(jgUseRegistrationManage.getUseRegistrationCode());
                changeRecord.setReceiveCompanyCode(scrapCancel.getReceiveOrgCode());
                changeRecord.setUseUnitCreditCode(scrapCancel.getUseUnitCode());
                changeRecord.setUseUnitName(scrapCancel.getUseUnitName());
                changeRecord.setEquCategory(jgUseRegistrationManage.getEquCategoryCode());
                changeRecord.setCreateDate(new Date());
                first.ifPresent(item -> changeRecord.setRoutePath(item.getRoutePath()));
                changeRecord.setCreateUserId(scrapCancel.getCreateUserId());
                changeRecord.setCertificateNo(jgUseRegistrationManage.getCertificateNo());
                certificateChangeRecords.add(changeRecord);
                jgScrapCancelEqs.stream().filter(eq -> eq.getUseRegistrationCode().equals(jgUseRegistrationManage.getUseRegistrationCode())).forEach(e -> {
                    JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
                    changeRecordEq.setChangeRecordId(changeRecord.getSequenceNbr().toString()); // 登记证记录主键
                    changeRecordEq.setEquId(e.getEquId()); // 设备主键
                    changeRecordEq.setProductCode(e.getEquCode()); // 设备代码
                    changeRecordEqList.add(changeRecordEq);
                });
            }
            if (!certificateChangeRecords.isEmpty()) {
                certificateChangeRecordService.saveBatch(certificateChangeRecords);
            }
            if (!changeRecordEqList.isEmpty()) {
                jgCertificateChangeRecordEqServiceImpl.saveBatch(changeRecordEqList);
            }
        });
    }

    /**
     * 单位变更数据处理
     *
     * @param applyNoList 申请编号list
     */
    private void changeRegistrationUnitHandler(List<String> applyNoList) {
        applyNoList.forEach(applyNo -> {
            // 查询单位变更登记的历史数据
            JgRegistrationHistory history = jgRegistrationHistoryMapper.selectOne(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getRegistrationClass, "单位变更登记")
                    .eq(JgRegistrationHistory::getCurrentDocumentId, applyNo));
            // 查询变更数据
            JgChangeRegistrationUnit registrationUnit = this.baseMapper.selectOne(new LambdaQueryWrapper<JgChangeRegistrationUnit>()
                    .eq(JgChangeRegistrationUnit::getApplyNo, history.getCurrentDocumentId()));
            // 查询已经入库的设备id
            List<String> inEqTableEquId = jgChangeRegistrationUnitEqMapper.selectList(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                            .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registrationUnit.getSequenceNbr()))
                    .stream()
                    .map(JgChangeRegistrationUnitEq::getEquId)
                    .collect(Collectors.toList());

            // 查询单子下的所有使用登记证的seq
            List<Long> certificateSeq = JSONArray.parseArray(history.getChangeData()).stream().map(item -> Long.valueOf((String) JSONObject.parseObject(JSONObject.toJSONString(item)).get(SEQUENCE_NBR))).collect(Collectors.toList());
            // 使用登记证下的所有设备
            List<JSONObject> equJSONList = registrationManageService.queryEquByCertificateSeqList(certificateSeq);
            // 过滤出未入库的设备
            List<JSONObject> toBeProcessedEq = equJSONList.stream().filter(item -> !inEqTableEquId.contains(item.getString("SEQUENCE_NBR"))).collect(Collectors.toList());
            // 将未入库设备 保存到eq表
            this.changeRegistrationUnitSaveLackEqu(toBeProcessedEq, registrationUnit);
            // 将未入库设备 更新es和otherInfo表的使用单位信息
            this.changeRegistrationUnitUpdateLackEquForES(toBeProcessedEq, registrationUnit);
            this.changeRegistrationUnitUpdateLackEquForUseInfo(toBeProcessedEq, registrationUnit);
        });
    }

    /**
     * 单位变更-保存漏掉的设备
     */
    public void changeRegistrationUnitSaveLackEqu(List<JSONObject> deviceList, JgChangeRegistrationUnit registrationUnit) {
        List<JgChangeRegistrationUnitEq> jgRelationEquipList = new ArrayList<>();
        deviceList.forEach(device -> {
            JgChangeRegistrationUnitEq unitEq = new JgChangeRegistrationUnitEq();
            if (device.containsKey("USE_ORG_CODE")) {
                unitEq.setRegistrationCertificate(device.getString("USE_ORG_CODE"));//使用登记证主键
            }
            if (device.containsKey("SEQUENCE_NBR")) {
                unitEq.setEquId(device.getString("SEQUENCE_NBR"));//设备主键
            }
            unitEq.setUnitChangeRegistrationId(registrationUnit.getSequenceNbr().toString());//单位变更业务主键
            unitEq.setDeviceInfo(JSONObject.toJSONString(device));//设备信息json
            jgRelationEquipList.add(unitEq);
        });
        registrationUnitEqService.saveBatch(jgRelationEquipList);
    }

    /**
     * 单位变更-修改es漏掉的设备
     */
    public void changeRegistrationUnitUpdateLackEquForES(List<JSONObject> deviceList, JgChangeRegistrationUnit registration) {
        deviceList.forEach(device -> {
            Map<String, Map<String, Object>> resultMap = new HashMap<>();
            Map<String, Object> map1 = new HashMap<>();
            String[] companyCode = registration.getNewUseUnitCreditCode().split("_");
            map1.put("USE_UNIT_CREDIT_CODE", companyCode.length > 1 ? companyCode[1] : registration.getNewUseUnitCreditCode());
            map1.put("USE_UNIT_NAME", registration.getNewUseUnitName());
            map1.put("REC_DATE", registration.getCreateDate());
            resultMap.put(device.getString("SEQUENCE_NBR"), map1);
            tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
        });
    }

    /**
     * 单位变更-修改使用信息表中漏掉的设备
     */
    public void changeRegistrationUnitUpdateLackEquForUseInfo(List<JSONObject> deviceList, JgChangeRegistrationUnit registration) {
        deviceList.forEach(device -> {
            LambdaQueryWrapper<IdxBizJgUseInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(IdxBizJgUseInfo::getRecord, device.getString("SEQUENCE_NBR"));
            IdxBizJgUseInfo useInfo = useInfoMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(useInfo)) {
                useInfo.setUseUnitName(registration.getNewUseUnitName());
                useInfo.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
                useInfoMapper.updateById(useInfo);
            }
        });
    }

    /**
     * 保存工业管道的单位变更
     *
     * @param submitType
     * @param map
     * @param reginParams
     * @return
     */
    public List<JgChangeRegistrationUnitDto> saveUnitByProjectContraption(String submitType, JSONObject map, ReginParams reginParams) {
        JgChangeRegistrationUnitDto model = BeanUtil.toBeanIgnoreError(map.get("changeRegisInfo"), JgChangeRegistrationUnitDto.class);
        String[] taskName = new String[]{"流程结束"};
        // 字段转换
        convertField(model);
        // 获取单位变更装置列表
        List<Map<String, Object>> projectContraptionList = model.getProjectContraptionList();
        if (CollectionUtils.isEmpty(projectContraptionList)) {
            throw new BadRequest("工程/装置列表不能为空");
        }
        //根据使用登记证查询设备
        List<String> registrationNoList = new ArrayList<>();//使用登记证编号
        Map<String, String> useRegistrationCodeMap = new HashMap<>();
        for (Map<String, Object> objectMap : projectContraptionList) {
            if (objectMap.containsKey("useRegistrationCode") && ObjectUtils.isNotEmpty(objectMap.get("useRegistrationCode"))) {
                registrationNoList.add(objectMap.get("useRegistrationCode").toString());
                useRegistrationCodeMap.put(objectMap.get(SEQUENCE_NBR).toString(), objectMap.get("useRegistrationCode").toString());
            }
        }
        //查询装置下的管道信息
        List<Map<String, Object>> deviceList = this.queryPipelineList(projectContraptionList);
        if (CollUtil.isEmpty(deviceList)) {
            throw new BadRequest("工程/装置下没有管道信息");
        }
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {//放在最后面防止前面有异常
            //如果是提交，用于校验设备是否已经在流程中，如果不在标记设备已经在流程中
            CompanyBo company = reginParams.getCompany();
            deviceList.forEach(jsonObject -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .equipRepeatUsedCheck(String.valueOf(jsonObject.get("record")),
                            CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ?
                                    company.getCompanyCode().split("_")[1] :
                                    company.getCompanyCode()));
        }

        // 获取单位变更单号
        ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.DWBG.getCode(), 1);
        List<String> applyNoList = listResponseModel.getResult();
        if (CollectionUtils.isEmpty(applyNoList)) {
            log.error("生成申请变更单位编码失败");
            return new ArrayList<>();
        }
        ArrayList<String> roleListFirst = new ArrayList<>();
        List<String> instanceIdList = new ArrayList<>();
        List<String> nextExecutorUserIds = new ArrayList<>();
        List<String> taskIds = new ArrayList<>();
        List<WorkflowResultDto> workflowResultDtos = new ArrayList<>();
        String nextExecutorRoleIds = "";
        // 判断当前是否为提交
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            //发起流程
            ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
            List<ActWorkflowStartDTO> list = new ArrayList<>();
            ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
            dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
            dto.setBusinessKey(String.valueOf(new Date().getTime()));
            dto.setNextExecuteUserCompanyCode(model.getReceiveCompanyCode());
            dto.setCompleteFirstTask(true);
            list.add(dto);
            actWorkflowBatchDTO.setProcess(list);
            List<ProcessTaskDTO> processTaskDTOS = cmWorkflowService.startBatch(actWorkflowBatchDTO);
            workflowResultDtos = commonServiceImpl.buildWorkFlowInfo(processTaskDTOS);
            nextExecutorRoleIds = workflowResultDtos.get(0).getNextExecutorRoleIds();
            nextExecutorUserIds.add(workflowResultDtos.get(0).getNextExecutorUserIds());
            for (WorkflowResultDto processTaskDTO : workflowResultDtos) {
                instanceIdList.add(processTaskDTO.getInstanceId());
                taskIds.add(processTaskDTO.getNextTaskId());
            }
        }

        String finalNextExecutorRoleIds = nextExecutorRoleIds;
        CompanyBo companyBo = commonServiceImpl.getOneCompany(model.getReceiveCompanyCode());
        model.setApplyNo(applyNoList.get(0));
        model.setReceiveCompanyOrgCode(companyBo.getOrgCode());
        model.setCreateUserId(RequestContext.getExeUserId());
        model.setApplyDate(new Date());
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            model.setNextExecutorIds(finalNextExecutorRoleIds);
            model.setInstanceStatus(String.join(",", roleListFirst));
            model.setPromoter(reginParams.getUserModel().getUserId());
            model.setStatus(taskName[0]);
        }
        if (!CollectionUtils.isEmpty(nextExecutorUserIds)) {
            model.setNextExecuteUserIds(nextExecutorUserIds.get(0));
        }
        if (!CollectionUtils.isEmpty(instanceIdList)) {
            model.setInstanceId(instanceIdList.get(0));
            model.setStatus(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
        } else {
            model.setStatus(WorkFlowStatusEnum.UNITCHANGE_SUBMIT.getPass());
        }
        if (!CollectionUtils.isEmpty(taskIds)) {
            model.setNextTaskId(taskIds.get(0));
        }
        model.setSequenceNbr(sequence.nextId());
        model.setCreateDate(new Date());
        model.setCreateUserName(reginParams.getUserModel().getRealName());
        model.setUseRegistCode(String.join("，", registrationNoList));
        model.setEquList(projectContraptionList.get(0).get("equListName").toString());
        JgChangeRegistrationUnit registrationUnit = new JgChangeRegistrationUnit();
        BeanUtils.copyProperties(model, registrationUnit);
        setNewUnitInfo(reginParams, registrationUnit);
        JgChangeRegistrationUnitMapper.insert(registrationUnit);

        List<TaskModelDto> modelDtos = new ArrayList<>();
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            TaskModelDto taskModelDto = new TaskModelDto();
            TaskMessageDto ta = new TaskMessageDto();
            ta.setInstanceId(registrationUnit.getInstanceId());
            ta.setStatus(registrationUnit.getStatus());
            ta.setPromoter(registrationUnit.getPromoter());
            ta.setNextExecuteUserIds(registrationUnit.getNextExecuteUserIds());
            ta.setSequenceNbr(registrationUnit.getSequenceNbr());
            ta.setNextTaskId(registrationUnit.getNextTaskId());
            taskModelDto.setModel(ta);
            taskModelDto.setFlowCreateDate(new Date());
            taskModelDto.setTaskName(workflowResultDtos.get(0).getNextTaskName());
            taskModelDto.setFlowCode(registrationUnit.getNextTaskId());
            taskModelDto.setTaskContent(this.buildTaskContent(registrationUnit));
            taskModelDto.setTaskCode(registrationUnit.getApplyNo());
            taskModelDto.setTaskType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getCode());
            taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
            taskModelDto.setRelationId(registrationUnit.getInstanceId());
            taskModelDto.setExecuteUserIds(workflowResultDtos.get(0).getNextExecutorUserIds());
            taskModelDto.setTaskStatusLabel("未处理");
            taskModelDto.setFlowStatus(commonServiceImpl.getDictionaryCodeByName(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass()));
            taskModelDto.setFlowStatusLabel(WorkFlowStatusEnum.UNITCHANGE_RECEIVE.getPass());
            taskModelDto.setStartUserId(RequestContext.getExeUserId());
            taskModelDto.setStartUser(workflowResultDtos.get(0).getStartUserName());
            taskModelDto.setStartUserCompanyName(reginParams.getCompany().getCompanyName());
            taskModelDto.setStartDate(new Date());
            taskModelDto.setNextExecuteUser(workflowResultDtos.get(0).getNextExecutorRoleIds());
            modelDtos.add(taskModelDto);
        } else {
            TaskModelDto taskModelDto = new TaskModelDto();
            //行数据
            taskModelDto.setModel(registrationUnit);
            //摘要 按原有规则组装
            taskModelDto.setTaskContent(this.buildTaskContent(registrationUnit));
            //申请单号
            taskModelDto.setTaskCode(registrationUnit.getApplyNo());
            //业务类型枚举code值
            taskModelDto.setTaskType(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getCode());
            ////业务主键
            taskModelDto.setRelationId(registrationUnit.getSequenceNbr() + "");
            modelDtos.add(taskModelDto);
//            }
        }
        commonServiceImpl.saveExecuteFlowData2Redis(registrationUnit.getInstanceId(), buildInstanceRuntimeData(registrationUnit));
        commonServiceImpl.buildTaskModel(modelDtos);

        List<JgChangeRegistrationUnitEq> jgRelationEquipList = new ArrayList<>();
        deviceList.forEach(device -> {
            JgChangeRegistrationUnitEq unitEq = new JgChangeRegistrationUnitEq();
            if (device.containsKey("projectContraptionId")) {
                String projectContraptionId = (String) device.get("projectContraptionId");
                unitEq.setRegistrationCertificate(useRegistrationCodeMap.get(projectContraptionId));
                unitEq.setProjectContraptionId(projectContraptionId);
            }
            if (device.containsKey("record")) {
                unitEq.setEquId((String) device.get("record"));//设备主键
            }
            unitEq.setUnitChangeRegistrationId(registrationUnit.getSequenceNbr().toString());//单位变更业务主键
            unitEq.setDeviceInfo(JSON.toJSONString(device));//设备信息json
            jgRelationEquipList.add(unitEq);
        });
        JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
        //登记类别
        jgRegistrationHistory.setRegistrationClass("单位变更登记");
        jgRegistrationHistory.setCurrentDocumentId(registrationUnit.getApplyNo());
        //使用登记证历史数据
        jgRegistrationHistory.setChangeData(JSON.toJSONString(projectContraptionList));
        //先删除之前设备关系数据，在插入最新设备关系数据
        registrationUnitEqService.getBaseMapper().delete(new LambdaQueryWrapper<JgChangeRegistrationUnitEq>()
                .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registrationUnit.getSequenceNbr()));
        registrationUnitEqService.saveBatch(jgRelationEquipList);
        //先删除之前未提交的历史使用登记证信息，在插入最新的使用登记证信息
        registrationHistoryService.getBaseMapper().delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, registrationUnit.getApplyNo()));
        registrationHistoryService.save(jgRegistrationHistory);
        return Collections.singletonList(model);
    }

    /**
     * 获取装置下的管道信息
     *
     * @param projectContraptionList
     * @return
     */
    public List<Map<String, Object>> queryPipelineList(List<Map<String, Object>> projectContraptionList) {
        List<Map<String, Object>> result = new ArrayList<>();
        projectContraptionList.forEach(item -> result.addAll(projectContraptionService.getBaseMapper().selectEquipList((String) item.get(SEQUENCE_NBR))));
        return result;
    }

    public Map<String, Map<String, Object>> detailsByProjectContraption(String sequenceNbr, String applyNo) {
        String[] jsonFields = {"productPhoto", "otherAccessories", "productQualificationCertificate", "startLatitudeLongitude",
                "endLatitudeLongitude"};
        Map<String, Map<String, Object>> resultMap = new HashMap<>();
        if (StringUtils.isEmpty(sequenceNbr)) {
            resultMap.put("equipInfo", Collections.emptyMap());
            return resultMap;
        }
        JgChangeRegistrationUnit registrationUnit = this.lambdaQuery().eq(JgChangeRegistrationUnit::getApplyNo, applyNo)
                .eq(JgChangeRegistrationUnit::getIsDelete, false)
                .one();
        if (Objects.isNull(registrationUnit)) {
            resultMap.put("equipInfo", Collections.emptyMap());
            return resultMap;
        }
        //如果单位变更关系表没有管道数据返回空
        LambdaQueryWrapper<JgChangeRegistrationUnitEq> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(JgChangeRegistrationUnitEq::getProjectContraptionId, sequenceNbr)
                .eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registrationUnit.getSequenceNbr())
                .eq(JgChangeRegistrationUnitEq::getIsDelete, false);
        List<JgChangeRegistrationUnitEq> changeRegistrationUnitEqs = registrationUnitEqService.list(wrapper);
        if (CollUtil.isEmpty(changeRegistrationUnitEqs)) {
            resultMap.put("equipInfo", Collections.emptyMap());
            return resultMap;
        }
        JgChangeRegistrationUnit jgChangeRegistrationUnit = this.baseMapper.selectById(changeRegistrationUnitEqs.get(0).getUnitChangeRegistrationId());
        //如果历史表没有数据返回空
        Map<String, Object> projectContraptionDetail = new HashMap<>();
        JgRegistrationHistory history = registrationHistoryService.lambdaQuery()
                .eq(JgRegistrationHistory::getCurrentDocumentId, jgChangeRegistrationUnit.getApplyNo())
                .eq(JgRegistrationHistory::getIsDelete, false)
                .one();
        JSONArray historyJson = JSON.parseArray(history.getChangeData());
        if (CollUtil.isEmpty(historyJson)) {
            resultMap.put("equipInfo", Collections.emptyMap());
            return resultMap;
        }
        historyJson.forEach(item -> {
            JSONObject jsonObject = JSON.parseObject(item.toString());
            if (sequenceNbr.equals(jsonObject.getString(SEQUENCE_NBR))) {
                projectContraptionDetail.putAll(jsonObject);
            }
        });
        Map<String, Object> projectContraptionMap = Optional.of(projectContraptionDetail)
                .map(map -> {
                    commonServiceImpl.convertStringToJsonobject(map, jsonFields);
                    List<JSONObject> pipelineList = new ArrayList<>();
                    changeRegistrationUnitEqs.forEach(item -> {
                        JSONObject jsonObject = JSON.parseObject(item.getDeviceInfo());
                        //如果日期格式是时间戳的话需要处理
                        if (jsonObject.containsKey("uscDate") && !StringUtils.isEmpty(jsonObject.get("uscDate")) && !jsonObject.getString("uscDate").contains("-")) {
                            // 转换为 Instant 并指定时区（默认系统时区）
                            Instant instant = Instant.ofEpochMilli(Long.parseLong(jsonObject.getString("uscDate")));
                            ZoneId zoneId = ZoneId.systemDefault();
                            // 定义日期格式
                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                                    .withZone(zoneId);
                            jsonObject.put("uscDate", formatter.format(instant));
                        }
                        pipelineList.add(jsonObject);
                    });
                    map.put("pipelineList", pipelineList);
                    return map;
                }).orElse(Collections.emptyMap());

        resultMap.put("equipInfo", projectContraptionMap);
        return resultMap;
    }

    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 6000000)
    public void handleChangeRegistrationUnitWrongData(String applyNo) {
        String[] taskName = new String[]{"已完成"};
        JgChangeRegistrationUnit registration = this.baseMapper.selectOne(new LambdaQueryWrapper<JgChangeRegistrationUnit>()
                .eq(JgChangeRegistrationUnit::getApplyNo, applyNo)
                .eq(JgChangeRegistrationUnit::getIsDelete, 0));
        WorkflowResultDto workflowResultDto = new WorkflowResultDto();
        workflowResultDto.setNextTaskCode("已完成");
        workflowResultDto.setNextTaskId(registration.getNextTaskId());
        workflowResultDto.setNextExecutorUserIds(registration.getNextExecuteUserIds());
        registration.setStatus(taskName[0]);
        registration.setAuditPassDate(new Date());
        JgChangeRegistrationUnitDto dto = new JgChangeRegistrationUnitDto();
        BeanUtils.copyProperties(registration, dto);
        JgRegistrationHistory history = registrationHistoryService.lambdaQuery()
                .eq(JgRegistrationHistory::getCurrentDocumentId, registration.getApplyNo())
                .eq(JgRegistrationHistory::getIsDelete, false).one();
        //如果是工业管道 如果工程装置对应一个证就直接变更给新单位；如果工程装置对应证下还有其他装置就变更后直接给新单位再重新生成一个登记证号；如果两个工程装置对应同一个使用登记证变更后生成两个新的登记证
        if (PipelineEnum.PRESSURE_PIPELINE.getCode().equals(registration.getEquListCode())) {
            dto.setProjectContraptionList(JSON.parseObject(history.getChangeData(),new TypeReference<List<Map<String, Object>>>(){}));
            this.dealProjectContraption(dto, registration.getNextTaskId(), registration, "0");
        }
        //气瓶单位变更，如果新单位没有证，则生成新的使用登记证，如果新单位有证且是系统生成的证，则选择增补到已有的证下面同时，更新设备其他信息
        else if(CylinderTypeEnum.CYLINDER.getCode().equals(registration.getEquCategoryCode())) {
            dto.setDeviceList(JSON.parseObject(history.getChangeData(),new TypeReference<List<Map<String, Object>>>(){}));
            this.dealCylinderAuditPassData(dto, registration.getNextTaskId(), registration, "0");
        } else {
            dto.setRegistrationList(JSON.parseObject(history.getChangeData(),new TypeReference<List<Map<String, Object>>>(){}));
            // 生成新的使用登记编号，使用登记证修改设备的使用登记信息表，使用单位名称，使用单位统一信用代码，使用登记证编号，更新ES
            LambdaQueryWrapper<JgChangeRegistrationUnitEq> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JgChangeRegistrationUnitEq::getUnitChangeRegistrationId, registration.getSequenceNbr());
            List<JgChangeRegistrationUnitEq> jgChangeRegistrationUnitEqs = JgChangeRegistrationUnitEqMapper.selectList(queryWrapper);
            //修改ES中使用单位信息和使用单位代码
            Map<String, Map<String, Object>> resultMap = new HashMap<>();
            //更新产权信息
            dto.getRegistrationList().forEach(v -> {
                String useCode = String.valueOf(v.get("useRegistrationCode"));
                String newCarNumber = String.valueOf(v.get("newCarNumber"));
                String estateUnitSeq = String.valueOf(v.get("estateUnitName"));
                TzBaseEnterpriseInfo enterpriseInfo = (estateUnitSeq != null && !estateUnitSeq.isEmpty())
                        ? tzBaseEnterpriseInfoMapper.selectById(estateUnitSeq)
                        : null;
                List<String> records = idxBizJgRegisterInfoService.getBaseMapper()
                        .selectList(new LambdaQueryWrapper<IdxBizJgRegisterInfo>()
                                .eq(IdxBizJgRegisterInfo::getUseOrgCode, useCode))
                        .stream()
                        .map(IdxBizJgRegisterInfo::getRecord)
                        .collect(Collectors.toList());
                if (!records.isEmpty() && enterpriseInfo != null) {
                    idxBizJgUseInfoService.update(
                            new IdxBizJgUseInfo()
                                    .setEstateUnitCreditCode(enterpriseInfo.getUseUnitCode())
                                    .setEquState(EquipmentEnum.ZAIYONG.getCode().toString())
                                    .setEstateUnitName(enterpriseInfo.getUseUnit()),
                            new LambdaQueryWrapper<IdxBizJgUseInfo>()
                                    .in(IdxBizJgUseInfo::getRecord, records)
                    );
                }
                //场车更新车牌号
                if (EQU_CODE_CC.equals(dto.getEquListCode()) && newCarNumber != null && !"null".equals(newCarNumber) && useCode != null) {
                    idxBizJgRegisterInfoService.update(new IdxBizJgRegisterInfo().setCarNumber(newCarNumber),
                            new LambdaQueryWrapper<IdxBizJgRegisterInfo>().in(IdxBizJgRegisterInfo::getUseOrgCode, useCode)
                    );
                }
            });
            Map<String, String> seqToEquId = new HashMap<>();
            for (JgChangeRegistrationUnitEq jgChangeRegistrationUnitEq : jgChangeRegistrationUnitEqs) {
                String equipId = jgChangeRegistrationUnitEq.getEquId();
                LambdaQueryWrapper<IdxBizJgUseInfo> useInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                useInfoLambdaQueryWrapper.eq(IdxBizJgUseInfo::getRecord, equipId);
                IdxBizJgUseInfo useInfo = useInfoMapper.selectOne(useInfoLambdaQueryWrapper);
                if (ObjectUtils.isNotEmpty(useInfo)) {
                    useInfo.setUseUnitName(registration.getNewUseUnitName());
                    useInfo.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
                    // 只有变更类型为场车时，更新地址相关字段
                    if (EQU_CODE_CC.equals(registration.getEquListCode())) {
                        this.updateUseInfoAddress(useInfo, registration);
                        IdxBizJgSupervisionInfo supervisionInfo = new IdxBizJgSupervisionInfo();
                        supervisionInfo.setOrgBranchCode(registration.getOrgBranchCode());
                        supervisionInfo.setOrgBranchName(registration.getOrgBranchName());
                        idxBizJgSupervisionInfoMapper.update(supervisionInfo, Wrappers.<IdxBizJgSupervisionInfo>lambdaQuery()
                                .eq(IdxBizJgSupervisionInfo::getRecord, equipId));
                    }
                    useInfoMapper.updateById(useInfo);
                }
                LambdaQueryWrapper<IdxBizJgRegisterInfo> registerInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                registerInfoLambdaQueryWrapper.eq(IdxBizJgRegisterInfo::getRecord, equipId);
                IdxBizJgRegisterInfo registerInfo = registerInfoMapper.selectOne(registerInfoLambdaQueryWrapper);
                Map<String, Object> esUpdateParams = new HashMap<>();
                String[] companyCode = registration.getNewUseUnitCreditCode().split("_");
                esUpdateParams.put("USE_UNIT_CREDIT_CODE", companyCode.length > 1 ? companyCode[1] : registration.getNewUseUnitCreditCode());
                esUpdateParams.put("USE_UNIT_NAME", registration.getNewUseUnitName());
                esUpdateParams.put("REC_DATE", new Date());// 更新时间，设备筛选时排在前面 bug-21476
                esUpdateParams.put("EQU_STATE", "1");
                if (EQU_CODE_CC.equals(registration.getEquListCode())) {
                    esUpdateParams.put("USE_PLACE", joinWithSeparator("/", useInfo.getProvinceName(), useInfo.getCityName(), useInfo.getCountyName(), useInfo.getStreetName()));
                    esUpdateParams.put("USE_PLACE_CODE", joinWithSeparator("#", useInfo.getProvince(), useInfo.getCity(), useInfo.getCounty(), useInfo.getFactoryUseSiteStreet()));
                    esUpdateParams.put("ORG_BRANCH_CODE", registration.getOrgBranchCode());
                    esUpdateParams.put("ORG_BRANCH_NAME", registration.getOrgBranchName());
                }
                // 如果是变更类型=1，还需要更新证号到 ES
                if ("1".equals(registration.getChangeType()) && EQU_CODE_CC.equals(registration.getEquListCode())) {
                    // 新证号生成逻辑
                    String newCode = commonServiceImpl.generateRegistrationCode(equipId, registration.getReceiveCompanyCode(), false);
                    esUpdateParams.put("USE_ORG_CODE", newCode);
                    seqToEquId.put(registerInfo.getUseOrgCode(), newCode);
                    registerInfo.setUseOrgCode(newCode);
                    registerInfoMapper.updateById(registerInfo);
                }
                if (ObjectUtils.isNotEmpty(registerInfo) && ObjectUtils.isNotEmpty(registerInfo.getCarNumber())) {
                    esUpdateParams.put("CAR_NUMBER", registerInfo.getCarNumber());
                }
                resultMap.put(equipId, esUpdateParams);
                //修改各类告知列表，置为废弃
                this.updataInvalidStatusByHistory(equipId, registration.getApplyNo());
                tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
            }

            registration.setNextTaskId(registration.getNextTaskId());
            TaskV2Model taskV2Model = updateTaskModel(registration, "0");

            JSONArray historyJson = JSON.parseArray(history.getChangeData());
            // 更新历史表中一二级审批车牌号
            history.setChangeData(JSONObject.toJSONString(dto.getRegistrationList()));
            registrationHistoryService.updateById(history);
            List<String> ids = historyJson.stream().map(v -> JSON.parseObject(v.toString()).getString(SEQUENCE_NBR)).collect(Collectors.toList());
            List<JgUseRegistrationManage> list = useRegistrationManageService.lambdaQuery().in(BaseEntity::getSequenceNbr, ids).list();
            // 用来存放新生成的登记证
            List<JgUseRegistrationManage> newList = new ArrayList<>();
            for (JgUseRegistrationManage registrationManage : list) {
                // 修改使用登记证管理使用单位信息
                registrationManage.setUseUnitName(registration.getNewUseUnitName());
                registrationManage.setUseUnitCreditCode(registration.getNewUseUnitCreditCode());
                registrationManage.setReceiveOrgName(registration.getReceiveOrgName());
                registrationManage.setReceiveCompanyCode(registration.getReceiveOrgCode());
                registrationManage.setAuditPassDate(registration.getAuditPassDate());
                registrationManage.setVersion(registrationManage.getVersion() + 1);
                if ("1".equals(registration.getChangeType()) && EQU_CODE_CC.equals(dto.getEquListCode())) {
                    // -------------------- 旧证处理 --------------------
                    registrationManage.setCertificateStatus("已注销");
                    registrationManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());

                    // -------------------- 新证处理 --------------------
                    JgUseRegistrationManage newManage = new JgUseRegistrationManage();
                    BeanUtils.copyProperties(registrationManage, newManage);

                    String newCode = seqToEquId.get(registrationManage.getUseRegistrationCode());
                    newManage.setUseRegistrationCode(newCode);
                    registration.setUseRegistCode(newCode);
                    // 新证属性重置
                    newManage.setCertificateStatus("已登记");
                    newManage.setVersion(1);
                    newManage.setRegistrationType("0");
                    newManage.setEquUseAddress(registration.getEquAddress());
                    // 如果 equListCode = 5000，则设置车牌号
                    if (EQU_CODE_CC.equals(registrationManage.getEquListCode())) {
                        String targetCode = registrationManage.getUseRegistrationCode();
                        dto.getRegistrationList().stream()
                                .filter(item -> targetCode.equals(item.get("useRegistrationCode")))
                                .map(item -> String.valueOf(item.get("newCarNumber")))
                                .filter(carNumber -> carNumber != null && !"null".equalsIgnoreCase(carNumber.trim()))
                                .findFirst()
                                .ifPresent(newManage::setCarNumber);
                    }

                    newManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());

                    // 回填新单位地址
                    if (!ObjectUtils.isEmpty(registration.getNewUseUnitCreditCode())) {
                        TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(
                                new QueryWrapper<TzBaseEnterpriseInfo>()
                                        .eq("use_unit_code", registration.getNewUseUnitCreditCode())
                        );
                        if (useCodeResult != null) {
                            newManage.setUseUnitAddress(useCodeResult.getAddress());
                        }
                    }
                    newManage.setSequenceNbr(null);
                    newList.add(newManage);
                } else {
                    registrationManage.setCertificateStatus("已登记");
                    registrationManage.setEquUseAddress(registration.getEquAddress());
                    if (EQU_CODE_CC.equals(registrationManage.getEquListCode())) {
                        String targetCode = registrationManage.getUseRegistrationCode();
                        dto.getRegistrationList().stream()
                                .filter(item -> targetCode.equals(item.get("useRegistrationCode")))
                                .map(item -> String.valueOf(item.get("newCarNumber")))
                                .filter(carNumber -> carNumber != null && !"null".equalsIgnoreCase(carNumber.trim()))
                                .findFirst()
                                .ifPresent(registrationManage::setCarNumber);
                    }
                    registrationManage.setChangeReason(BusinessTypeEnum.JG_COMPANY_CHANGE_REGISTRATION.getName());
                    if (!ObjectUtils.isEmpty(registration.getNewUseUnitCreditCode())) {
                        TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(
                                new QueryWrapper<TzBaseEnterpriseInfo>()
                                        .eq("use_unit_code", registration.getNewUseUnitCreditCode())
                        );
                        if (useCodeResult != null) {
                            registrationManage.setUseUnitAddress(useCodeResult.getAddress());
                        }
                    }
                }
            }

            if (CollUtil.isNotEmpty(newList)) {
                list.addAll(newList);
            }
            useRegistrationManageService.saveOrUpdateBatch(list);
            this.createResume(registration,jgChangeRegistrationUnitEqs, taskV2Model.getRoutePath());
        }
        //新增使用登记证和设备变更记录
        this.saveRecord(registration);
        // 发送数据变更消息
        this.sendDataRefreshMsg(registration);
        JgChangeRegistrationUnitMapper.updateById(registration);
        // redis流程实时数据更新
        commonServiceImpl.saveExecuteFlowData2Redis(dto.getInstanceId(), this.buildInstanceRuntimeData(registration));
        this.delRepeatUseEquipData(registration.getApplyNo(), registration.getStatus(), registration.getNewUseUnitCreditCode());
    }

    @ResultFieldMapping({@ResultFieldMapping.ResultFieldMap(sourceField = "estateUnitCode", targetField = "estateUnitSeq", serviceClass = CommonServiceImpl.class, queryMethod = "queryTcmUnitSeqByCreditCode", secondParamValue = "CQ")})
    public Map<String, Object> queryEquipInfoByRegistrationCode(String useRegistrationCode) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("useRegistrationCode", useRegistrationCode);
        JgUseRegistrationManage registrationManage =
                jgUseRegistrationManageService.lambdaQuery()
                        .eq(JgUseRegistrationManage::getUseRegistrationCode, useRegistrationCode)
                        .eq(JgUseRegistrationManage::getIsDelete, 0)
                        .last("LIMIT 1")
                        .one();
        List<JSONObject> jsonObjects = registrationManage == null ? Collections.emptyList():
                Optional.ofNullable(jgUseRegistrationManageService.queryEquByCertificateSeq(registrationManage.getSequenceNbr())
                ).orElse(Collections.emptyList());
        if (!org.springframework.util.ObjectUtils.isEmpty(jsonObjects)) {
            List<String> records = jsonObjects.stream().map(a -> String.valueOf(a.get("SEQUENCE_NBR"))).collect(Collectors.toList());
            List<Map<String, Object>> equList = this.getBaseMapper().getEstateUnitInfo(records);
            String estateUnitName = equList.stream()
                    .map(e -> e.get("estateUnitName"))
                    .filter(Objects::nonNull)
                    .filter(String.class::isInstance)
                    .map(String.class::cast)
                    .findFirst()
                    .orElse("");
            if (!ValidationUtil.isEmpty(estateUnitName) && estateUnitName.contains("_")) {
                map.put("estateUnitCode", estateUnitName.split("_")[0]);
                map.put("estateUnitName", estateUnitName.split("_")[1]);
            }
        }
        return map;
    }
}