package com.zt.plat.module.contractorder.service.contract;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.framework.datapermission.core.annotation.CompanyDataPermissionIgnore;
import com.zt.plat.framework.datapermission.core.annotation.DeptDataPermissionIgnore;
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.zt.plat.framework.security.core.LoginUser;
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
import com.zt.plat.module.base.controller.admin.templtp.vo.TmplInscBsnRelRespVO;
import com.zt.plat.module.base.controller.admin.templtp.vo.TmplInscBsnRelSaveReqVO;
import com.zt.plat.module.base.controller.admin.templtp.vo.TmplInscDatBsnSaveReqVO;
import com.zt.plat.module.base.controller.admin.templtp.vo.TmplInscItmBsnSaveReqVO;
import com.zt.plat.module.base.dal.dataobject.tmpltp.TmplInscBsnRelDO;
import com.zt.plat.module.base.dal.mysql.tmpltp.TmplInscBsnRelMapper;
import com.zt.plat.module.base.service.tmpltp.TmplInscBsnRelService;
import com.zt.plat.module.base.service.tmpltp.TmplInscDatBsnService;
import com.zt.plat.module.base.service.tmpltp.TmplInscItmBsnService;
import com.zt.plat.module.bpm.api.task.BpmProcessInstanceApi;
import com.zt.plat.module.bpm.api.task.BpmTaskApi;
import com.zt.plat.module.bpm.api.task.dto.*;
import com.zt.plat.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import com.zt.plat.module.contractorder.api.dto.contract.*;
import com.zt.plat.module.contractorder.api.vo.contract.*;
import com.zt.plat.module.contractorder.dal.dataobject.amountdismantle.AmountDismantleDO;
import com.zt.plat.module.contractorder.dal.dataobject.contract.*;
import com.zt.plat.module.contractorder.dal.mysql.contract.*;
import com.zt.plat.module.contractorder.enums.DateConstants;
import com.zt.plat.module.contractorder.enums.DictTypeConstants;
import com.zt.plat.module.contractorder.enums.ProcessConstants;
import com.zt.plat.module.contractorder.enums.TableFieldConstants;
import com.zt.plat.module.contractorder.enums.contract.DictEnum;
import com.zt.plat.module.contractorder.service.amountdismantle.AmountDismantleService;
import com.zt.plat.module.contractorder.service.contractreceivesend.ContractReceiveSendService;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpContractPageReqVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpContractSaveReqVO;
import com.zt.plat.module.erp.dal.dataobject.erp.ErpContractDO;
import com.zt.plat.module.erp.service.erp.ErpContractService;
import com.zt.plat.module.infra.api.file.FileApi;
import com.zt.plat.module.infra.api.file.dto.FileRespDTO;
import com.zt.plat.module.system.api.dept.DeptApi;
import com.zt.plat.module.system.api.user.AdminUserApi;
import com.zt.plat.module.system.api.user.dto.AdminUserRespDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.contractorder.enums.ErrorCodeConstants.*;

/**
 * 后台合同编制 Service 实现类
 *
 * @author ZT
 */
@Slf4j
@Service
public class ContractServiceImpl implements ContractService {

    @Resource
    private ContractMainMapper contractMainMapper;
    @Resource
    private ContractDetailMapper contractDetailMapper;
    @Resource
    private ContractPlanMapper contractPlanMapper;
    @Resource
    private ContractFormulaMapper contractFormulaMapper;
    @Resource
    private ContractCoefficientMapper contractCoefficientMapper;
    @Resource
    private ContractGradeMapper contractGradeMapper;
    @Resource
    private ContractDeductMapper contractDeductMapper;
    @Resource
    private ContractPriceMapper contractPriceMapper;
    @Resource
    private ContractNotMapper contractNotMapper;
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Resource
    private BpmTaskApi bpmTaskApi;
    @Resource
    private ContractDemoteMapper contractDemoteMapper;
    @Resource
    private ErpContractService erpContractService;
    @Resource
    private SystemRelativityMapper systemRelativityMapper;
    @Resource
    private FileApi fileApi;
    @Resource
    private TmplInscBsnRelMapper tmplInscBsnRelMapper;
    @Resource
    private TmplInscBsnRelService tmplInscBsnRelService;
    @Resource
    private TmplInscDatBsnService tmplInscDatBsnService;
    @Resource
    private TmplInscItmBsnService tmplInscItmBsnService;

    @Resource
    private ContractReceiveSendService contractReceiveSendService;
    @Resource
    private AmountDismantleService amountDismantleService;
    @Resource
    private DeptApi deptApi;

    private static final Map<String, String> VALID_RELATIONS = new HashMap<>();

    static {
        VALID_RELATIONS.put("ENT", "ENTED");
        VALID_RELATIONS.put("ENTED", "ENT");
        VALID_RELATIONS.put("PUR", "SALE");
        VALID_RELATIONS.put("SALE", "PUR");
    }

    @Override
    public PageResult<ContractMainDO> getContractPage(ContractPageReqVO pageReqVO) {
        return contractMainMapper.selectContractPage(pageReqVO);
    }

    @Override
    public PageResult<ContractMainDO> getPageNoPermission(ContractPageReqVO pageReqVO) {
        if (pageReqVO.getId() == null) {
            throw exception(PARAMETER_ID_EMPTY);
        }
        ContractMainDO contractMainDO = contractMainMapper.selectById(pageReqVO.getId());
        String businessType = VALID_RELATIONS.getOrDefault(contractMainDO.getBusinessType(), null);
        if (businessType == null) {
            throw exception(PARAMETER_BUSINESS_TYPE_INVALID);
        }
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String visitCompanyCode = loginUser.getVisitCompanyCode();
        //判断当前人应该查询哪个公司
        if (visitCompanyCode.equals(contractMainDO.getErpPurchaseCompanyNumber())) {
            //查乙方
            pageReqVO.setErpSalesCompanyNumber(contractMainDO.getErpSalesCompanyNumber());
        } else if (visitCompanyCode.equals(contractMainDO.getErpSalesCompanyNumber())) {
            //查甲方
            pageReqVO.setErpPurchaseCompanyNumber(contractMainDO.getErpPurchaseCompanyNumber());
        }
        pageReqVO.setBusinessType(businessType);
        return contractMainMapper.selectContractPageNoPermission(pageReqVO);
    }

    boolean isContractReceiveSendValid(List<ContractReceiveSendSaveReqVO> contractReceiveSends) {
        if (CollectionUtils.isEmpty(contractReceiveSends)) {
            return true;
        }
        return false;

    }

    @Transactional
    @Override
    public Long createContract(ContractSaveReqVO reqVO) {
        //校验收发货的规则的合法性
        isContractReceiveSendValid(reqVO.getContractReceiveSends());
        // 校验合同名称是否存在
        ContractMainDO contract = contractMainMapper
                .selectOne(TableFieldConstants.BSE_CTRT_MAIN_CTRT_NAME, reqVO.getContractName());
        if (contract != null) {
            throw exception(CONTRACT_NAME_EXISTS);
        }

        if (StringUtils.isNotEmpty(reqVO.getContractPaperNumber())) {
            // 校验合同编号是否存在
            contract = contractMainMapper
                    .selectOne(TableFieldConstants.BSE_CTRT_MAIN_CTRT_PPR_NUM, reqVO.getContractPaperNumber());
            if (contract != null) {
                throw exception(CONTRACT_PAPER_NUMBER_EXISTS);
            }
        }

        // 合同主信息
        ContractMainDO contractMainDO = BeanUtils.toBean(reqVO, ContractMainDO.class);

        // ERP甲方公司编号
        contractMainDO.setErpPurchaseCompanyNumber(reqVO.getPurchaseCompanyNumber());
        // ERP甲方公司名称
        contractMainDO.setErpPurchaseCompanyName(reqVO.getPurchaseCompanyName());
        // ERP乙方公司编码
        contractMainDO.setErpSalesCompanyNumber(reqVO.getSalesCompanyNumber());
        // ERP乙方公司名称
        contractMainDO.setErpSalesCompanyName(reqVO.getSalesCompanyName());
        // 合同状态保存为草稿
        contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_DRAFT.getCode());
        // 生成系统合同编号
        contractMainDO.setSystemContractNumber(generateSystemContractNumber(reqVO.getBusinessType()));

        // 保存合同主信息
        contractMainMapper.insert(contractMainDO);

        // 合同主信息ID
        Long contractId = contractMainDO.getId();
        // 合同明细
        if (reqVO.getDetail() != null && !reqVO.getDetail().isEmpty()) {
            reqVO.getDetail().forEach(detail -> {
                // 合同明细DO
                ContractDetailDO detailDO = BeanUtils.toBean(detail, ContractDetailDO.class);
                // 设置合同主信息ID
                detailDO.setContractMainId(contractId);
                // 保存合同明细
                contractDetailMapper.insert(detailDO);

                // 合同明细ID
                Long detailDOId = detailDO.getId();
                // 交货计划
                if (detail.getPlans() != null && !detail.getPlans().isEmpty()) {
                    detail.getPlans().forEach(plan -> {
                        // 交货计划DO
                        ContractPlanDO planDO = BeanUtils.toBean(plan, ContractPlanDO.class);
                        // 合同明细主键
                        planDO.setContractDetailId(detailDOId);
                        // 保存交货计划
                        contractPlanMapper.insert(planDO);
                    });
                }
            });
        }

        // 价款结算条款
        if (reqVO.getFormulas() != null && !reqVO.getFormulas().isEmpty()) {
            reqVO.getFormulas().forEach(formula -> {
                // 价款结算条款DO
                ContractFormulaDO formulaDO = BeanUtils.toBean(formula, ContractFormulaDO.class);
                // 合同主键
                formulaDO.setContractId(contractId);
                // 保存价款结算条款
                contractFormulaMapper.insert(formulaDO);

                // 价款结算条款ID
                Long formulaDOId = formulaDO.getId();
                // 基础系数配置
                if (formula.getCoefficients() != null && !formula.getCoefficients().isEmpty()) {
                    formula.getCoefficients().forEach(coefficient -> {
                        // 基础系数配置DO
                        ContractCoefficientDO coefficientDO = BeanUtils.toBean(coefficient, ContractCoefficientDO.class);
                        // 条款主键
                        coefficientDO.setFormulaId(formulaDOId);
                        // 保存基础系数配置
                        contractCoefficientMapper.insert(coefficientDO);
                    });
                }
                // 品位等级价配置
                if (formula.getGrades() != null && !formula.getGrades().isEmpty()) {
                    formula.getGrades().forEach(grade -> {
                        // 品位等级价配置DO
                        ContractGradeDO gradeDO = BeanUtils.toBean(grade, ContractGradeDO.class);
                        // 条款主键
                        gradeDO.setFormulaId(formulaDOId);
                        // 保存品位等级价配置
                        contractGradeMapper.insert(gradeDO);
                    });
                }
                // 调整价配置
                if (formula.getDeducts() != null && !formula.getDeducts().isEmpty()) {
                    formula.getDeducts().forEach(deduct -> {
                        // 调整价配置DO
                        ContractDeductDO deductDO = BeanUtils.toBean(deduct, ContractDeductDO.class);
                        // 条款主键
                        deductDO.setFormulaId(formulaDOId);
                        // 保存品位等级价配置
                        contractDeductMapper.insert(deductDO);
                    });
                }
                // 市场价配置
                if (formula.getPrices() != null && !formula.getPrices().isEmpty()) {
                    formula.getPrices().forEach(price -> {
                        // 市场价配置DO
                        ContractPriceDO priceDO = BeanUtils.toBean(price, ContractPriceDO.class);
                        // 条款主键
                        priceDO.setFormulaId(formulaDOId);
                        // 保存市场价配置
                        contractPriceMapper.insert(priceDO);
                    });
                }
            });
        }

        // 参数降级规则
        if (reqVO.getDemotes() != null && !reqVO.getDemotes().isEmpty()) {
            reqVO.getDemotes().forEach(demote -> {
                // 参数降级规则DO
                ContractDemoteDO demoteDO = BeanUtils.toBean(demote, ContractDemoteDO.class);
                // 设置合同主键
                demoteDO.setContractId(contractId);
                // 保存参数降级规则
                contractDemoteMapper.insert(demoteDO);
            });
        }

        // 品位不计价规则
        if (reqVO.getNots() != null && !reqVO.getNots().isEmpty()) {
            reqVO.getNots().forEach(not -> {
                // 品位不计价规则DO
                ContractNotDO notDO = BeanUtils.toBean(not, ContractNotDO.class);
                // 条款主键
                notDO.setContractId(contractId);
                // 保存品位不计价规则
                contractNotMapper.insert(notDO);
            });
        }

        // 合同动态表单及条款
        // 更新关联主表
        TmplInscBsnRelSaveReqVO tmplInscBsnRelSaveReqVO = new TmplInscBsnRelSaveReqVO();
        tmplInscBsnRelSaveReqVO.setId(reqVO.getBusinessId());
        tmplInscBsnRelSaveReqVO.setBsnId(contractId);
        tmplInscBsnRelService.updateTmplInscBsnRel(tmplInscBsnRelSaveReqVO);
        // 保存动态字段
        List<TmplInscDatBsnSaveReqVO> dynamicsFields = reqVO.getDynamicsFields();
        if (dynamicsFields != null && !dynamicsFields.isEmpty()) {
//            dynamicsFields.forEach(dynamicsField -> {
//                dynamicsField.setBsnId(reqVO.getBusinessId().toString());
//                tmplInscDatBsnService.createTmplInscDatBsn(dynamicsField);
//            });
            tmplInscDatBsnService.updateTmplInscDatBsnBatch(dynamicsFields);
        }
        // 保存动态条款
        List<TmplInscItmBsnSaveReqVO> dynamicsItems = reqVO.getDynamicsItems();
        if (dynamicsItems != null && !dynamicsItems.isEmpty()) {
//            dynamicsItems.forEach(dynamicsItem -> {
//                dynamicsItem.setBsnId(reqVO.getBusinessId().toString());
//                tmplInscItmBsnService.createTmplInscItmBsn(dynamicsItem);
//            });
            tmplInscItmBsnService.updateTmplInscItmBsnBatch(dynamicsItems);
        }
//插入收发货规则
        if (reqVO.getContractReceiveSends() != null && !reqVO.getContractReceiveSends().isEmpty()) {
            reqVO.getContractReceiveSends().forEach(contractReceiveSend -> {
                contractReceiveSend.setContractId(contractId);
                contractReceiveSendService.createContractReceiveSend(contractReceiveSend);
            });
        }
        //插入资金拆分表
        if (reqVO.getAmountSplit() != null && !reqVO.getAmountSplit().isEmpty()) {
            reqVO.getAmountSplit().forEach(amountDismantle -> {
                amountDismantle.setContractId(contractId);
                amountDismantleService.createAmountDismantle(amountDismantle);
            });
        }

        return contractId;
    }

    @Override
    public ContractRespVO get(Long id) {

        // 返回结果
        ContractRespVO respVO = new ContractRespVO();

        // 查询并设置合同主信息
        ContractMainDO contractMainDO = contractMainMapper.selectById(id);
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }
        BeanUtils.copyProperties(contractMainDO, respVO);

        // 查询并设置合同明细
        List<ContractDetailDO> detailDOS = contractDetailMapper
                .selectList(TableFieldConstants.BSE_CTRT_DTL_CTRT_MAIN_ID, contractMainDO.getId());
        if (detailDOS != null && !detailDOS.isEmpty()) {
            respVO.setDetail(BeanUtils.toBean(detailDOS, DetailRespVO.class));
            respVO.getDetail().forEach(detail -> {

                // 查询并设置交货计划
                List<ContractPlanDO> planDOS = contractPlanMapper
                        .selectList(TableFieldConstants.BSE_CTRT_PLN_CTRT_DTL_ID, detail.getId());
                if (planDOS != null && !planDOS.isEmpty()) {
                    detail.setPlans(BeanUtils.toBean(planDOS, PlanRespVO.class));
                }
            });
        }

        // 查询并设置价款结算条款
        List<ContractFormulaDO> formulaDOS = contractFormulaMapper
                .selectList(TableFieldConstants.BSE_CTRT_FMU_CTRT_ID, contractMainDO.getId());
        if (formulaDOS != null && !formulaDOS.isEmpty()) {
            respVO.setFormulas(BeanUtils.toBean(formulaDOS, FormulaRespVO.class));

            respVO.getFormulas().forEach(formula -> {

                // 查询并设置基础系数配置
                List<ContractCoefficientDO> coefficientDOS = contractCoefficientMapper
                        .selectList(TableFieldConstants.BSE_CTRT_COEF_FMU_ID, formula.getId());
                if (coefficientDOS != null && !coefficientDOS.isEmpty()) {
                    formula.setCoefficients(BeanUtils.toBean(coefficientDOS, CoefficientRespVO.class));
                }
                // 查询并设置品位等级价配置
                List<ContractGradeDO> gradeDOS = contractGradeMapper
                        .selectList(TableFieldConstants.BSE_CTRT_GRD_FMU_ID, formula.getId());
                if (gradeDOS != null && !gradeDOS.isEmpty()) {
                    formula.setGrades(BeanUtils.toBean(gradeDOS, GradeRespVO.class));
                }
                // 查询并设置调整价配置
                List<ContractDeductDO> deductDOS = contractDeductMapper
                        .selectList(TableFieldConstants.BSE_CTRT_DDCT_FMU_ID, formula.getId());
                if (deductDOS != null && !deductDOS.isEmpty()) {
                    formula.setDeducts(BeanUtils.toBean(deductDOS, DeductRespVO.class));
                }
                // 查询并设置市场价配置
                List<ContractPriceDO> priceDOS = contractPriceMapper
                        .selectList(TableFieldConstants.BSE_CTRT_PRC_FMU_ID, formula.getId());
                if (priceDOS != null && !priceDOS.isEmpty()) {
                    formula.setPrices(BeanUtils.toBean(priceDOS, PriceRespVO.class));
                }
            });
        }

        // 查询并设置参数降级规则
        List<ContractDemoteDO> demoteDOS = contractDemoteMapper
                .selectList(TableFieldConstants.BSE_CTRT_DMOT_CTRT_ID, contractMainDO.getId());
        if (demoteDOS != null && !demoteDOS.isEmpty()) {
            respVO.setDemotes(BeanUtils.toBean(demoteDOS, DemoteRespVO.class));
        }

        // 查询并设置品位不计价规则
        List<ContractNotDO> notDOS = contractNotMapper
                .selectList(TableFieldConstants.BSE_CTRT_NT_CTRT_ID, contractMainDO.getId());
        if (notDOS != null && !notDOS.isEmpty()) {
            respVO.setNots(BeanUtils.toBean(notDOS, NotRespVO.class));
        }

        // 查询合同动态字段及条款
        if (contractMainDO.getBusinessId() != null) {
            TmplInscBsnRelRespVO tmplInscBsnRel = tmplInscBsnRelService.getTmplInscBsnRel(contractMainDO.getBusinessId());
            if (tmplInscBsnRel != null) {
                // 设置合同动态字段
                respVO.setDynamicsFields(tmplInscBsnRel.getTmplInscDatBsnRespVOS());
                // 设置合同动态条款
                respVO.setDynamicsItems(tmplInscBsnRel.getTmplInscItmBsnRespVOS());
            }
        }
        //收发货
        List<ContractReceiveSendRespVO> contractReceiveSendListByContractId = contractReceiveSendService.getContractReceiveSendListByContractId(contractMainDO.getId());
        if (contractReceiveSendListByContractId != null && !contractReceiveSendListByContractId.isEmpty()) {
            respVO.setContractReceiveSends(contractReceiveSendListByContractId);
        }
        //金额拆分
        List<AmountDismantleDO> amountDismantleListByContractId = amountDismantleService.getAmountDismantleListByContractId(contractMainDO.getId());
        if (amountDismantleListByContractId != null && !amountDismantleListByContractId.isEmpty()) {
            respVO.setAmountSplit(BeanUtils.toBean(amountDismantleListByContractId, AmountDismantleRespVO.class));
        }

        return respVO;
    }

    @Override
    public ContractRespVO getBySystemContractNumber(String systemContractNumber) {
        // 返回结果
        ContractRespVO respVO = new ContractRespVO();

        // 查询并设置合同主信息
        ContractMainDO contractMainDO = contractMainMapper.selectOne(TableFieldConstants.BSE_CTRT_MAIN_SYS_CTRT_NUM, systemContractNumber);
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }
        BeanUtils.copyProperties(contractMainDO, respVO);

        // 查询并设置合同明细
        List<ContractDetailDO> detailDOS = contractDetailMapper
                .selectList(TableFieldConstants.BSE_CTRT_DTL_CTRT_MAIN_ID, contractMainDO.getId());
        if (detailDOS != null && !detailDOS.isEmpty()) {
            respVO.setDetail(BeanUtils.toBean(detailDOS, DetailRespVO.class));
            respVO.getDetail().forEach(detail -> {

                // 查询并设置交货计划
                List<ContractPlanDO> planDOS = contractPlanMapper
                        .selectList(TableFieldConstants.BSE_CTRT_PLN_CTRT_DTL_ID, detail.getId());
                if (planDOS != null && !planDOS.isEmpty()) {
                    detail.setPlans(BeanUtils.toBean(planDOS, PlanRespVO.class));
                }
            });
        }

        // 查询并设置价款结算条款
        List<ContractFormulaDO> formulaDOS = contractFormulaMapper
                .selectList(TableFieldConstants.BSE_CTRT_FMU_CTRT_ID, contractMainDO.getId());
        if (formulaDOS != null && !formulaDOS.isEmpty()) {
            respVO.setFormulas(BeanUtils.toBean(formulaDOS, FormulaRespVO.class));

            respVO.getFormulas().forEach(formula -> {

                // 查询并设置基础系数配置
                List<ContractCoefficientDO> coefficientDOS = contractCoefficientMapper
                        .selectList(TableFieldConstants.BSE_CTRT_COEF_FMU_ID, formula.getId());
                if (coefficientDOS != null && !coefficientDOS.isEmpty()) {
                    formula.setCoefficients(BeanUtils.toBean(coefficientDOS, CoefficientRespVO.class));
                }
                // 查询并设置品位等级价配置
                List<ContractGradeDO> gradeDOS = contractGradeMapper
                        .selectList(TableFieldConstants.BSE_CTRT_GRD_FMU_ID, formula.getId());
                if (gradeDOS != null && !gradeDOS.isEmpty()) {
                    formula.setGrades(BeanUtils.toBean(gradeDOS, GradeRespVO.class));
                }
                // 查询并设置调整价配置
                List<ContractDeductDO> deductDOS = contractDeductMapper
                        .selectList(TableFieldConstants.BSE_CTRT_DDCT_FMU_ID, formula.getId());
                if (deductDOS != null && !deductDOS.isEmpty()) {
                    formula.setDeducts(BeanUtils.toBean(deductDOS, DeductRespVO.class));
                }
                // 查询并设置市场价配置
                List<ContractPriceDO> priceDOS = contractPriceMapper
                        .selectList(TableFieldConstants.BSE_CTRT_PRC_FMU_ID, formula.getId());
                if (priceDOS != null && !priceDOS.isEmpty()) {
                    formula.setPrices(BeanUtils.toBean(priceDOS, PriceRespVO.class));
                }
            });
        }

        // 查询并设置参数降级规则
        List<ContractDemoteDO> demoteDOS = contractDemoteMapper
                .selectList(TableFieldConstants.BSE_CTRT_DMOT_CTRT_ID, contractMainDO.getId());
        if (demoteDOS != null && !demoteDOS.isEmpty()) {
            respVO.setDemotes(BeanUtils.toBean(demoteDOS, DemoteRespVO.class));
        }

        // 查询并设置品位不计价规则
        List<ContractNotDO> notDOS = contractNotMapper
                .selectList(TableFieldConstants.BSE_CTRT_NT_CTRT_ID, contractMainDO.getId());
        if (notDOS != null && !notDOS.isEmpty()) {
            respVO.setNots(BeanUtils.toBean(notDOS, NotRespVO.class));
        }

        // 查询合同动态字段及条款
        if (contractMainDO.getBusinessId() != null) {
            TmplInscBsnRelRespVO tmplInscBsnRel = tmplInscBsnRelService.getTmplInscBsnRel(contractMainDO.getBusinessId());
            if (tmplInscBsnRel != null) {
                // 设置合同动态字段
                respVO.setDynamicsFields(tmplInscBsnRel.getTmplInscDatBsnRespVOS());
                // 设置合同动态条款
                respVO.setDynamicsItems(tmplInscBsnRel.getTmplInscItmBsnRespVOS());
            }
        }

        return respVO;
    }

    @Override
    public List<ContractRespVO> getListUpNotRelation(Long id) {

        // 查询合同信息
        ContractMainDO contractMainDO = contractMainMapper.selectById(id);
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 收支性质
        String direction = contractMainDO.getDirection();
        // 甲方公司编号
        String purchaseCompanyNumber = contractMainDO.getPurchaseCompanyNumber();
        // 乙方公司编号
        String salesCompanyNumber = contractMainDO.getSalesCompanyNumber();

        // 已关联的上游合同id集合
        List<SystemRelativityDO> systemRelativityDOS = systemRelativityMapper.selectList();
        LinkedHashSet<String> relationIds = new LinkedHashSet<>();
        if (systemRelativityDOS != null && !systemRelativityDOS.isEmpty()) {
            systemRelativityDOS.forEach(systemRelativityDO -> {
                relationIds.add(systemRelativityDO.getUpId());
            });
        }

        // 返回结果集
        List<ContractRespVO> result = new ArrayList<>();
        if (DictEnum.ERP_RCV_DLVY_INCOME.getCode().equals(direction)) { // 收入
            // 如果“收支性质”字段为收入，用“甲方公司编号”字段筛选“合同主信息”表中字段等于“乙方公司编号”的数据
            if (StringUtils.isEmpty(purchaseCompanyNumber)) {
                // 甲方公司编号不存在
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_PRCH_CPN_NUM_LABEL);
            }
            // 查询条件
            LambdaQueryWrapperX<ContractMainDO> conditon = new LambdaQueryWrapperX<>();
            conditon.eq(ContractMainDO::getSalesCompanyNumber, purchaseCompanyNumber);
            if (!relationIds.isEmpty()) {
                conditon.notIn(ContractMainDO::getId, relationIds);
            }

            // 查询
            List<ContractMainDO> contractMainDOS = contractMainMapper.selectList(conditon);
            result = BeanUtils.toBean(contractMainDOS, ContractRespVO.class);
        } else if (DictEnum.ERP_RCV_DLVY_EXPENSES.getCode().equals(direction)) { // 支出
            // 如果“收支性质”字段为支出，用“乙方公司编号”字段筛选“合同主信息”表中字段等于“甲方公司编号”的数据
            if (StringUtils.isEmpty(salesCompanyNumber)) {
                // 乙方公司编号不存在
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_SALE_CPN_NUM_LABEL);
            }

            // 查询条件
            LambdaQueryWrapperX<ContractMainDO> conditon = new LambdaQueryWrapperX<>();
            conditon.eq(ContractMainDO::getPurchaseCompanyNumber, salesCompanyNumber);
            if (!relationIds.isEmpty()) {
                conditon.notIn(ContractMainDO::getId, relationIds);
            }

            // 查询
            List<ContractMainDO> contractMainDOS = contractMainMapper.selectList(conditon);
            result = BeanUtils.toBean(contractMainDOS, ContractRespVO.class);
        } else {
            // 不存在的收支类型或收支类型为空
            throw exception(CONTRACT_ERP_RCV_DLVY_NOT_EXISTS);
        }

        return result;
    }

    @Override
    public List<ContractRespVO> getListDownNotRelation(Long id) {

        // 查询合同信息
        ContractMainDO contractMainDO = contractMainMapper.selectById(id);
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 收支性质
        String direction = contractMainDO.getDirection();
        // 甲方公司编号
        String purchaseCompanyNumber = contractMainDO.getPurchaseCompanyNumber();
        // 乙方公司编号
        String salesCompanyNumber = contractMainDO.getSalesCompanyNumber();

        // 已关联的上游合同id集合
        List<SystemRelativityDO> systemRelativityDOS = systemRelativityMapper.selectList();
        LinkedHashSet<String> relationIds = new LinkedHashSet<>();
        if (systemRelativityDOS != null && !systemRelativityDOS.isEmpty()) {
            systemRelativityDOS.forEach(systemRelativityDO -> {
                relationIds.add(systemRelativityDO.getDownId());
            });
        }

        // 返回结果集
        List<ContractRespVO> result = new ArrayList<>();
        if (DictEnum.ERP_RCV_DLVY_INCOME.getCode().equals(direction)) { // 收入
            // 如果“收支性质”字段为收入，用“甲方公司编号”字段筛选“合同主信息”表中字段等于“乙方公司编号”的数据
            if (StringUtils.isEmpty(purchaseCompanyNumber)) {
                // 甲方公司编号不存在
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_PRCH_CPN_NUM_LABEL);
            }
            // 查询条件
            LambdaQueryWrapperX<ContractMainDO> conditon = new LambdaQueryWrapperX<>();
            conditon.eq(ContractMainDO::getSalesCompanyNumber, purchaseCompanyNumber);
            if (!relationIds.isEmpty()) {
                conditon.notIn(ContractMainDO::getId, relationIds);
            }

            // 查询
            List<ContractMainDO> contractMainDOS = contractMainMapper.selectList(conditon);
            result = BeanUtils.toBean(contractMainDOS, ContractRespVO.class);
        } else if (DictEnum.ERP_RCV_DLVY_EXPENSES.getCode().equals(direction)) { // 支出
            // 如果“收支性质”字段为支出，用“乙方公司编号”字段筛选“合同主信息”表中字段等于“甲方公司编号”的数据
            if (StringUtils.isEmpty(salesCompanyNumber)) {
                // 乙方公司编号不存在
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_SALE_CPN_NUM_LABEL);
            }

            // 查询条件
            LambdaQueryWrapperX<ContractMainDO> conditon = new LambdaQueryWrapperX<>();
            conditon.eq(ContractMainDO::getPurchaseCompanyNumber, salesCompanyNumber);
            if (!relationIds.isEmpty()) {
                conditon.notIn(ContractMainDO::getId, relationIds);
            }

            // 查询
            List<ContractMainDO> contractMainDOS = contractMainMapper.selectList(conditon);
            result = BeanUtils.toBean(contractMainDOS, ContractRespVO.class);
        } else {
            // 不存在的收支类型或收支类型为空
            throw exception(CONTRACT_ERP_RCV_DLVY_NOT_EXISTS);
        }

        return result;
    }

    @Override
    public ContractRespVO getUpRelation(Long id) {

        // 查询合同信息
        if (contractMainMapper.selectById(id) == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 查询关联表
        SystemRelativityDO systemRelativityDO = systemRelativityMapper.selectOne(TableFieldConstants.BSE_SYS_REL_DOWN_ID, id.toString());
        if (systemRelativityDO == null) {
            return null;
        }

        // 上游合同ID
        String upId = systemRelativityDO.getUpId();

        // 获取上游合同信息
        ContractMainDO contractMainDO = contractMainMapper.selectById(upId);
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        return BeanUtils.toBean(contractMainDO, ContractRespVO.class);
    }

    @Override
    public ContractRespVO getDownRelation(Long id) {

        // 查询合同信息
        if (contractMainMapper.selectById(id) == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 查询关联表
        SystemRelativityDO systemRelativityDO = systemRelativityMapper.selectOne(TableFieldConstants.BSE_SYS_REL_UP_ID, id.toString());
        if (systemRelativityDO == null) {
            return null;
        }

        // 下游合同ID
        String upId = systemRelativityDO.getUpId();

        // 获取下游合同信息
        ContractMainDO contractMainDO = contractMainMapper.selectById(upId);
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        return BeanUtils.toBean(contractMainDO, ContractRespVO.class);
    }

    @Transactional
    @Override
    public Boolean update(ContractSaveReqVO reqVO) {

        // 校验合同主键是否存在
        Long id = reqVO.getId();
        if (id == null) {
            throw exception(CONTRACT_ID_NOT_EXISTS);
        }

        // 查询合同是否存在
        ContractMainDO oldContractMainDO = contractMainMapper.selectById(id);
        if (oldContractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 合同状态校验
        if (!(DictEnum.BSE_CTRT_STS_DRAFT.getCode().equals(oldContractMainDO.getStatus())
                || DictEnum.BSE_CTRT_STS_REJECTED.getCode().equals(oldContractMainDO.getStatus())
                || DictEnum.BSE_CTRT_STS_WAIT_PUSH.getCode().equals(oldContractMainDO.getStatus())
                || DictEnum.BSE_CTRT_STS_PUSH_ERROR.getCode().equals(oldContractMainDO.getStatus())
                || DictEnum.BSE_CTRT_STS_IN_PROGRESS.getCode().equals(oldContractMainDO.getStatus()))) {

            throw exception(CONTRACT_STATUS_NOT_UPDATE,
                    DictEnum.getByCodeAndType(oldContractMainDO.getStatus(), DictTypeConstants.BSE_CTRT_STS).getLabel());
        }

        // 校验合同名称是否重复
        ContractMainDO contract = contractMainMapper.selectOne(new QueryWrapper<ContractMainDO>()
                .eq(TableFieldConstants.BSE_CTRT_MAIN_CTRT_NAME, reqVO.getContractName())
                .ne(TableFieldConstants.ID, id));
        if (contract != null) {
            throw exception(CONTRACT_NAME_EXISTS);
        }

        if (StringUtils.isNotEmpty(reqVO.getContractPaperNumber())) {
            // 校验合同编号是否存在
            contract = contractMainMapper.selectOne(new QueryWrapper<ContractMainDO>()
                    .eq(TableFieldConstants.BSE_CTRT_MAIN_CTRT_PPR_NUM, reqVO.getContractPaperNumber())
                    .ne(TableFieldConstants.ID, id));
            if (contract != null) {
                throw exception(CONTRACT_PAPER_NUMBER_EXISTS);
            }
        }

        // 请求更新的合同信息
        ContractMainDO newContractMainDO = BeanUtils.toBean(reqVO, ContractMainDO.class);

        // ERP甲方公司编号
        newContractMainDO.setErpPurchaseCompanyNumber(reqVO.getPurchaseCompanyNumber());
        // ERP甲方公司名称
        newContractMainDO.setErpPurchaseCompanyName(reqVO.getPurchaseCompanyName());
        // ERP乙方公司编码
        newContractMainDO.setErpSalesCompanyNumber(reqVO.getSalesCompanyNumber());
        // ERP乙方公司名称
        newContractMainDO.setErpSalesCompanyName(reqVO.getSalesCompanyName());

        // 删除关联信息
        // 查询合同明细
        List<ContractDetailDO> detailDOS = contractDetailMapper
                .selectList(TableFieldConstants.BSE_CTRT_DTL_CTRT_MAIN_ID, id);
        if (detailDOS != null && !detailDOS.isEmpty()) {
            detailDOS.forEach(detailDO -> {
                Long detailDOId = detailDO.getId();

                // 删除交货计划
                contractPlanMapper.delete(TableFieldConstants.BSE_CTRT_PLN_CTRT_DTL_ID, detailDOId.toString());
            });

            // 删除合同明细
            contractDetailMapper.delete(TableFieldConstants.BSE_CTRT_DTL_CTRT_MAIN_ID, id.toString());
        }

        // 查询价款结算条款
        List<ContractFormulaDO> formulaDOS = contractFormulaMapper
                .selectList(TableFieldConstants.BSE_CTRT_FMU_CTRT_ID, id);
        if (formulaDOS != null && !formulaDOS.isEmpty()) {
            formulaDOS.forEach(formulaDO -> {

                // 价款结算条款ID
                Long formulaDOId = formulaDO.getId();

                // 删除基础系数配置
                contractCoefficientMapper.delete(TableFieldConstants.BSE_CTRT_COEF_FMU_ID, formulaDOId.toString());
                // 删除品位等级价配置
                contractGradeMapper.delete(TableFieldConstants.BSE_CTRT_GRD_FMU_ID, formulaDOId.toString());
                // 删除调整价配置
                contractDeductMapper.delete(TableFieldConstants.BSE_CTRT_DDCT_FMU_ID, formulaDOId.toString());
                // 删除市场价配置
                contractPriceMapper.delete(TableFieldConstants.BSE_CTRT_PRC_FMU_ID, formulaDOId.toString());
            });

            // 删除价款结算条款
            contractFormulaMapper.delete(TableFieldConstants.BSE_CTRT_FMU_CTRT_ID, id.toString());
        }

        // 删除参数降级规则
        contractDemoteMapper.delete(TableFieldConstants.BSE_CTRT_DMOT_CTRT_ID, id.toString());

        // 删除品位不计价规则
        contractNotMapper.delete(TableFieldConstants.BSE_CTRT_NT_CTRT_ID, id.toString());

        // 重新插入关联信息
        if (reqVO.getDetail() != null && !reqVO.getDetail().isEmpty()) {
            reqVO.getDetail().forEach(detail -> {
                // 合同明细DO
                ContractDetailDO detailDO = BeanUtils.toBean(detail, ContractDetailDO.class);
                // 设置合同主信息ID
                detailDO.setContractMainId(id);
                // 主键
                detailDO.setId(null);
                // 保存合同明细
                contractDetailMapper.insert(detailDO);

                // 合同明细ID
                Long detailDOId = detailDO.getId();
                // 交货计划
                if (detail.getPlans() != null && !detail.getPlans().isEmpty()) {
                    detail.getPlans().forEach(plan -> {
                        // 交货计划DO
                        ContractPlanDO planDO = BeanUtils.toBean(plan, ContractPlanDO.class);
                        // 合同明细主键
                        planDO.setContractDetailId(detailDOId);
                        // 主键
                        planDO.setId(null);
                        // 保存交货计划
                        contractPlanMapper.insert(planDO);
                    });
                }
            });
        }

        // 价款结算条款
        if (reqVO.getFormulas() != null && !reqVO.getFormulas().isEmpty()) {
            reqVO.getFormulas().forEach(formula -> {
                // 价款结算条款DO
                ContractFormulaDO formulaDO = BeanUtils.toBean(formula, ContractFormulaDO.class);
                // 合同主键
                formulaDO.setContractId(id);
                // 主键
                formulaDO.setId(null);
                // 保存价款结算条款
                contractFormulaMapper.insert(formulaDO);

                // 价款结算条款ID
                Long formulaDOId = formulaDO.getId();
                // 基础系数配置
                if (formula.getCoefficients() != null && !formula.getCoefficients().isEmpty()) {
                    formula.getCoefficients().forEach(coefficient -> {
                        // 基础系数配置DO
                        ContractCoefficientDO coefficientDO = BeanUtils.toBean(coefficient, ContractCoefficientDO.class);
                        // 条款主键
                        coefficientDO.setFormulaId(formulaDOId);
                        // 主键
                        coefficientDO.setId(null);
                        // 保存基础系数配置
                        contractCoefficientMapper.insert(coefficientDO);
                    });
                }
                // 品位等级价配置
                if (formula.getGrades() != null && !formula.getGrades().isEmpty()) {
                    formula.getGrades().forEach(grade -> {
                        // 品位等级价配置DO
                        ContractGradeDO gradeDO = BeanUtils.toBean(grade, ContractGradeDO.class);
                        // 条款主键
                        gradeDO.setFormulaId(formulaDOId);
                        // 主键
                        gradeDO.setId(null);
                        // 保存品位等级价配置
                        contractGradeMapper.insert(gradeDO);
                    });
                }
                // 调整价配置
                if (formula.getDeducts() != null && !formula.getDeducts().isEmpty()) {
                    formula.getDeducts().forEach(deduct -> {
                        // 调整价配置DO
                        ContractDeductDO deductDO = BeanUtils.toBean(deduct, ContractDeductDO.class);
                        // 条款主键
                        deductDO.setFormulaId(formulaDOId);
                        // 主键
                        deductDO.setId(null);
                        // 保存品位等级价配置
                        contractDeductMapper.insert(deductDO);
                    });
                }
                // 市场价配置
                if (formula.getPrices() != null && !formula.getPrices().isEmpty()) {
                    formula.getPrices().forEach(price -> {
                        // 市场价配置DO
                        ContractPriceDO priceDO = BeanUtils.toBean(price, ContractPriceDO.class);
                        // 条款主键
                        priceDO.setFormulaId(formulaDOId);
                        // 主键
                        priceDO.setId(null);
                        // 保存市场价配置
                        contractPriceMapper.insert(priceDO);
                    });
                }
            });
        }

        // 参数降级规则
        if (reqVO.getDemotes() != null && !reqVO.getDemotes().isEmpty()) {
            reqVO.getDemotes().forEach(demote -> {
                // 参数降级规则DO
                ContractDemoteDO demoteDO = BeanUtils.toBean(demote, ContractDemoteDO.class);
                // 设置合同主键
                demoteDO.setContractId(id);
                // 主键
                demoteDO.setId(null);
                // 保存参数降级规则
                contractDemoteMapper.insert(demoteDO);
            });
        }

        // 品位不计价规则
        if (reqVO.getNots() != null && !reqVO.getNots().isEmpty()) {
            reqVO.getNots().forEach(not -> {
                // 品位不计价规则DO
                ContractNotDO notDO = BeanUtils.toBean(not, ContractNotDO.class);
                // 条款主键
                notDO.setContractId(id);
                // 主键
                notDO.setId(null);
                // 保存品位不计价规则
                contractNotMapper.insert(notDO);
            });
        }

        // 更新合同动态字段
        if (reqVO.getDynamicsFields() != null && !reqVO.getDynamicsFields().isEmpty()) {
            reqVO.getDynamicsFields().forEach(field -> {
                tmplInscDatBsnService.updateTmplInscDatBsn(field);
            });
        }
        // 更新合同动态表单
        if (reqVO.getDynamicsItems() != null && !reqVO.getDynamicsItems().isEmpty()) {
            reqVO.getDynamicsItems().forEach(item -> {
                tmplInscItmBsnService.updateTmplInscItmBsn(item);
            });
        }

        // 合同状态更新
        if (DictEnum.BSE_CTRT_STS_PUSH_ERROR.getCode().equals(oldContractMainDO.getStatus())) {
            // “推送失败”的状态编辑后状态变为“待推送”
            newContractMainDO.setStatus(DictEnum.BSE_CTRT_STS_WAIT_PUSH.getCode());
        }

        // 更新合同主信息
        Long instanceId = newContractMainDO.getInstanceId();
        newContractMainDO.setInstanceId(null);
        contractMainMapper.update(newContractMainDO, new LambdaUpdateWrapper<>(ContractMainDO.class)
                .set(ContractMainDO::getInstanceId, instanceId)
                .eq(ContractMainDO::getId, newContractMainDO.getId()));

        if (DictEnum.BSE_CTRT_STS_IN_PROGRESS.getCode().equals(newContractMainDO.getStatus())) {
            // 执行中合同重新提交erp
            submitErp(newContractMainDO.getId());
        }
        //更新收发货规则
        if (reqVO.getContractReceiveSends() != null && !reqVO.getContractReceiveSends().isEmpty()) {
            //通过合同id删除收发货规则
            List<ContractReceiveSendRespVO> contractReceiveSendListByContract = contractReceiveSendService.getContractReceiveSendListByContractId(id);
            if (!contractReceiveSendListByContract.isEmpty()) {
                contractReceiveSendService.deleteContractReceiveSendListByIds(contractReceiveSendListByContract.stream().map(ContractReceiveSendRespVO::getId).toList());
            }
            //重新插入收发货规则
            reqVO.getContractReceiveSends().forEach(item -> {
                item.setContractId(id);
                item.setId(null);
                contractReceiveSendService.createContractReceiveSend(item);
            });
        }
        //更新资金拆分表(直接先删除后面再插入)
        if (reqVO.getAmountSplit() != null && !reqVO.getAmountSplit().isEmpty()) {
            List<AmountDismantleDO> amountDismantleList = amountDismantleService.getAmountDismantleListByContractId(id);
            if (!amountDismantleList.isEmpty()) {
                amountDismantleService.deleteAmountDismantleListByIds(amountDismantleList.stream().map(AmountDismantleDO::getId).toList());
            }
            reqVO.getAmountSplit().forEach(item -> {
                item.setContractId(id);
                item.setId(null);
                amountDismantleService.createAmountDismantle(item);
            });
        }
        return true;
    }

    @Override
    public List<JSONObject> delete(List<Long> ids) {

        // 执行结果
        List<JSONObject> result = new ArrayList<>();

        ids.forEach(id -> {

            // 查询合同是否存在
            ContractMainDO contractMainDO = contractMainMapper.selectById(id);
            if (contractMainDO == null) {
                result.add(new JSONObject().putOnce("deleted", false).putOnce("msg", id.toString() + ":" + CONTRACT_NOT_EXISTS));
            }

            // 合同状态校验
            if (!(DictEnum.BSE_CTRT_STS_DRAFT.getCode().equals(contractMainDO.getStatus())
                    || DictEnum.BSE_CTRT_STS_REJECTED.getCode().equals(contractMainDO.getStatus()))) {
                String msg = id.toString()
                        + ":"
                        + CONTRACT_STATUS_NOT_DELETE.getMsg()
                        .replace("{}", DictEnum.getByCodeAndType(contractMainDO.getStatus(), DictTypeConstants.BSE_CTRT_STS).getLabel());
                result.add(new JSONObject().putOnce("deleted", false).putOnce("msg", msg));
            }

            // 删除关联信息
            // 查询合同明细
            List<ContractDetailDO> detailDOS = contractDetailMapper
                    .selectList(TableFieldConstants.BSE_CTRT_DTL_CTRT_MAIN_ID, id);
            if (detailDOS != null && !detailDOS.isEmpty()) {
                detailDOS.forEach(detailDO -> {
                    Long detailDOId = detailDO.getId();

                    // 删除交货计划
                    contractPlanMapper.delete(TableFieldConstants.BSE_CTRT_PLN_CTRT_DTL_ID, detailDOId.toString());
                });

                // 删除合同明细
                contractDetailMapper.delete(TableFieldConstants.BSE_CTRT_DTL_CTRT_MAIN_ID, id.toString());
            }

            // 查询价款结算条款
            List<ContractFormulaDO> formulaDOS = contractFormulaMapper
                    .selectList(TableFieldConstants.BSE_CTRT_FMU_CTRT_ID, id);
            if (formulaDOS != null && !formulaDOS.isEmpty()) {
                formulaDOS.forEach(formulaDO -> {

                    // 价款结算条款ID
                    Long formulaDOId = formulaDO.getId();

                    // 删除基础系数配置
                    contractCoefficientMapper.delete(TableFieldConstants.BSE_CTRT_COEF_FMU_ID, formulaDOId.toString());
                    // 删除品位等级价配置
                    contractGradeMapper.delete(TableFieldConstants.BSE_CTRT_GRD_FMU_ID, formulaDOId.toString());
                    // 删除调整价配置
                    contractDeductMapper.delete(TableFieldConstants.BSE_CTRT_DDCT_FMU_ID, formulaDOId.toString());
                    // 删除市场价配置
                    contractPriceMapper.delete(TableFieldConstants.BSE_CTRT_PRC_FMU_ID, formulaDOId.toString());
                });

                // 删除价款结算条款
                contractFormulaMapper.delete(TableFieldConstants.BSE_CTRT_FMU_CTRT_ID, id.toString());
            }

            // 删除参数降级规则
            contractDemoteMapper.delete(TableFieldConstants.BSE_CTRT_DMOT_CTRT_ID, id.toString());

            // 删除品位不计价规则
            contractNotMapper.delete(TableFieldConstants.BSE_CTRT_NT_CTRT_ID, id.toString());

            // 更新合同状态
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_DELETED.getCode());
            contractMainMapper.updateById(contractMainDO);
            // 删除合同数据
            contractMainMapper.deleteById(id);

            result.add(new JSONObject().putOnce("deleted", true).putOnce("msg", id.toString()));
        });

        return result;
    }

    @Override
    public Boolean submitApproval(Long id) {

        // 判断主键
        if (ObjectUtils.isEmpty(id)) {
            throw exception(CONTRACT_ID_NOT_EXISTS);
        }

        // 查询合同是否存在
        ContractMainDO contractMainDO = contractMainMapper.selectById(id);
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 合同状态校验
        if (!(DictEnum.BSE_CTRT_STS_DRAFT.getCode().equals(contractMainDO.getStatus())
                || DictEnum.BSE_CTRT_STS_REJECTED.getCode().equals(contractMainDO.getStatus()))) {

            throw exception(CONTRACT_STATUS_NOT_SUBMIT_APPROVAL,
                    DictEnum.getByCodeAndType(contractMainDO.getStatus(), DictTypeConstants.BSE_CTRT_STS).getLabel());
        }

        // 合同内容校验
        verifyContract(get(id));

        // 查询登陆用户
        AdminUserRespDTO adminUserRespDTO = adminUserApi
                .getUser(SecurityFrameworkUtils.getLoginUserId()).getData();

        if (StringUtils.isNotBlank(contractMainDO.getProcessInstanceId())) {

            // 获取流程当前审批的任务节点
            List<BpmTaskRespDTO> taskList = bpmTaskApi.getTaskListByProcessInstanceId(contractMainDO.getProcessInstanceId()).getData();
            if (CollectionUtils.isNotEmpty(taskList)) {
                BpmTaskRespDTO bpmTaskDto = taskList.get(taskList.size() - 1);
                BpmApprovalDetailReqDTO badrDto = new BpmApprovalDetailReqDTO();
                badrDto.setProcessInstanceId(contractMainDO.getProcessInstanceId()); // 流程实例id
                badrDto.setTaskId(bpmTaskDto.getId()); // 当前审核任务节点id
                BpmApprovalDetailRespDTO approvalDetail = bpmProcessInstanceApi.getApprovalDetail(SecurityFrameworkUtils.getLoginUserId(), badrDto).getData();

                if (BpmProcessInstanceStatusEnum.REJECT.getStatus().equals(approvalDetail.getStatus())) {
                    // 如果状态是驳回状态,需要重新创建一个流程实例
                    BpmProcessInstanceCreateReqDTO pidtoNew = new BpmProcessInstanceCreateReqDTO();
                    pidtoNew.setProcessDefinitionKey(ProcessConstants.CONTRACT_APPROVAL_PROCESS);
                    pidtoNew.setBusinessKey(String.valueOf(id));
                    String data = bpmProcessInstanceApi.createProcessInstance(adminUserRespDTO.getId(), pidtoNew).getData();
                    if (StringUtils.isNotBlank(data)) {
                        // 获取流程当前审批的任务节点
                        List<BpmTaskRespDTO> taskListNew = bpmTaskApi.getTaskListByProcessInstanceId(data).getData();
                        contractMainDO.setProcessInstanceId(data);
                        if (CollectionUtils.isNotEmpty(taskListNew)) {
                            BpmTaskRespDTO undoTask = taskListNew.get(taskListNew.size() - 1);
                            contractMainDO.setTaskNodeId(undoTask.getId());
                        }
                        contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_UNDER_REVIEW.getCode());
                        contractMainMapper.updateById(contractMainDO);
                        return true;
                    }
                }
            }
        } else {

            // 未进入审批流程的合同，创建审批流程
            BpmProcessInstanceCreateReqDTO pidto = new BpmProcessInstanceCreateReqDTO();
            pidto.setProcessDefinitionKey(ProcessConstants.CONTRACT_APPROVAL_PROCESS);
            pidto.setBusinessKey(String.valueOf(id));
            String data = bpmProcessInstanceApi.createProcessInstance(adminUserRespDTO.getId(), pidto).getData();
            if (StringUtils.isNotBlank(data)) {

                // 获取流程当前审批的任务节点，更新合同审批状态
                List<BpmTaskRespDTO> taskList = bpmTaskApi.getTaskListByProcessInstanceId(data).getData();
                contractMainDO.setProcessInstanceId(data);
                if (CollectionUtils.isNotEmpty(taskList)) {
                    BpmTaskRespDTO undoTask = taskList.get(taskList.size() - 1);
                    contractMainDO.setTaskNodeId(undoTask.getId());
                }
                contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_UNDER_REVIEW.getCode());
                contractMainMapper.updateById(contractMainDO);
                return true;
            }
        }

        return false;
    }

    @Override
    public Boolean approval(ApprovalReqVO reqVO) {

        // 合同主键ID
        Long id = reqVO.getId();

        // 判断主键
        if (ObjectUtils.isEmpty(id)) {
            throw exception(CONTRACT_ID_NOT_EXISTS);
        }

        // 查询合同是否存在
        ContractMainDO contractMainDO = contractMainMapper.selectById(id);
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 合同状态校验
        if (!DictEnum.BSE_CTRT_STS_UNDER_REVIEW.getCode().equals(contractMainDO.getStatus())) {

            throw exception(CONTRACT_STATUS_NOT_APPROVAL,
                    DictEnum.getByCodeAndType(contractMainDO.getStatus(), DictTypeConstants.BSE_CTRT_STS).getLabel());
        }

        // 获取当前流程正在审批的任务节点
        List<BpmTaskRespDTO> taskList = bpmTaskApi.getTaskListByProcessInstanceId(contractMainDO.getProcessInstanceId()).getData();
        BpmTaskRespDTO undoTask = taskList.get(taskList.size() - 1);

        // 判断是否流程已经通过、驳回
        BpmApprovalDetailReqDTO badrDto = new BpmApprovalDetailReqDTO();
        badrDto.setProcessInstanceId(contractMainDO.getProcessInstanceId()); // 流程实例id
        badrDto.setTaskId(undoTask.getId()); // 当前审核任务节点id
        BpmApprovalDetailRespDTO approvalDetail = bpmProcessInstanceApi.getApprovalDetail(SecurityFrameworkUtils.getLoginUserId(), badrDto).getData();

        // 需要调用bpm 审核接口更新审批中的状态
        if (DictEnum.BSE_CTRT_STS_WAIT_PUSH.getCode().equals(reqVO.getStatus()) && ObjectUtils.isNotEmpty(undoTask)) {
            if (approvalDetail.getStatus().equals(BpmProcessInstanceStatusEnum.RUNNING.getStatus())) {
                BpmTaskApproveReqDTO btarDto = new BpmTaskApproveReqDTO();
                btarDto.setId(undoTask.getId());
                btarDto.setReason(reqVO.getReviewOpinion());
                bpmProcessInstanceApi.approveTask(btarDto);
            }
        } else if (DictEnum.BSE_CTRT_STS_REJECTED.getCode().equals(reqVO.getStatus()) && ObjectUtils.isNotEmpty(undoTask)) {
            if (approvalDetail.getStatus().equals(BpmProcessInstanceStatusEnum.RUNNING.getStatus())) {
                BpmTaskRejectReqDTO btrrDto = new BpmTaskRejectReqDTO();
                btrrDto.setId(undoTask.getId());
                btrrDto.setReason(reqVO.getReviewOpinion());
                bpmProcessInstanceApi.rejectTask(btrrDto);
            }
        }

        // 获取当前流程正在审批的任务节点
        taskList = bpmTaskApi.getTaskListByProcessInstanceId(contractMainDO.getProcessInstanceId()).getData();
        undoTask = taskList.get(taskList.size() - 1);

        // 判断是否流程已经通过、驳回
        badrDto = new BpmApprovalDetailReqDTO();
        badrDto.setProcessInstanceId(contractMainDO.getProcessInstanceId()); // 流程实例id
        badrDto.setTaskId(undoTask.getId()); // 当前审核任务节点id
        approvalDetail = bpmProcessInstanceApi.getApprovalDetail(SecurityFrameworkUtils.getLoginUserId(), badrDto).getData();

        // 更新合同状态,状态需要根据流程的状态进行判断
        contractMainDO.setReviewOpinion(reqVO.getReviewOpinion());
        if (approvalDetail.getStatus().equals(BpmProcessInstanceStatusEnum.NOT_START.getStatus())) {
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_UNDER_REVIEW.getCode());
        } else if (approvalDetail.getStatus().equals(BpmProcessInstanceStatusEnum.RUNNING.getStatus())) {
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_UNDER_REVIEW.getCode());
        } else if (approvalDetail.getStatus().equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_WAIT_PUSH.getCode());
        } else if (approvalDetail.getStatus().equals(BpmProcessInstanceStatusEnum.REJECT.getStatus())) {
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_REJECTED.getCode());
        } else if (approvalDetail.getStatus().equals(BpmProcessInstanceStatusEnum.CANCEL.getStatus())) {
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_REJECTED.getCode());
        }

        if (ObjectUtils.isNotEmpty(undoTask)) {
            contractMainDO.setTaskNodeId(undoTask.getId());
        }
        contractMainMapper.updateById(contractMainDO);

        return true;
    }

    @Override
    public PageResult<NotRespVO> getNots(NotsQueryReqVO queryReqVO) {

        // 查合同ID集合
        List<Long> contractIds = new ArrayList<>();
        if (StringUtils.isNotEmpty(queryReqVO.getContractName())
                || StringUtils.isNotEmpty(queryReqVO.getContractPaperNumber())) {
            contractIds = getContractIds(queryReqVO.getContractName(), queryReqVO.getContractPaperNumber());

            // 未查询到相关合同
            if (CollectionUtils.isEmpty(contractIds)) {
                return new PageResult<>();
            }
        }

        // 分页查询
        IPage<NotRespVO> ipage = contractNotMapper.selectNots(
                new Page<NotRespVO>().setCurrent(queryReqVO.getPageNo()).setSize(queryReqVO.getPageSize()),
                contractIds,
                queryReqVO.getMaterialName(),
                queryReqVO.getMaterialNumber(),
                queryReqVO.getElementAbbreviation()
        );

        // 分页返回
        return new PageResult<NotRespVO>().setTotal(ipage.getTotal()).setList(ipage.getRecords());
    }

    @Override
    public PageResult<DemoteRespVO> getDemotes(DemotesQueryReqVO queryReqVO) {

        // 查合同ID集合
        List<Long> contractIds = new ArrayList<>();
        if (StringUtils.isNotEmpty(queryReqVO.getContractName()) || StringUtils.isNotEmpty(queryReqVO.getContractPaperNumber())) {
            contractIds = getContractIds(queryReqVO.getContractName(), queryReqVO.getContractPaperNumber());

            // 未查询到相关合同
            if (CollectionUtils.isEmpty(contractIds)) {
                return new PageResult<>();
            }
        }

        // 分页查询
        IPage<DemoteRespVO> ipage = contractDemoteMapper.selectDemotes(
                new Page<>().setCurrent(queryReqVO.getPageNo()).setSize(queryReqVO.getPageSize()),
                contractIds,
                queryReqVO.getMaterialName(),
                queryReqVO.getMaterialNumber(),
                queryReqVO.getElementAbbreviation()
        );

        // 分页返回
        return new PageResult<DemoteRespVO>().setTotal(ipage.getTotal()).setList(ipage.getRecords());
    }

    @Override
    public PageResult<FormulaRespVO> getFormulas(FormulasQueryReqVO queryReqVO) {

        // 查合同ID集合
        List<Long> contractIds = new ArrayList<>();
        if (StringUtils.isNotEmpty(queryReqVO.getContractName()) || StringUtils.isNotEmpty(queryReqVO.getContractPaperNumber())) {
            contractIds = getContractIds(queryReqVO.getContractName(), queryReqVO.getContractPaperNumber());

            // 未查询到相关合同
            if (CollectionUtils.isEmpty(contractIds)) {
                return new PageResult<>();
            }
        }

        // 分页查询
        IPage<FormulaRespVO> ipage = contractFormulaMapper.selectFormulas(
                new Page<>().setCurrent(queryReqVO.getPageNo()).setSize(queryReqVO.getPageSize()),
                contractIds,
                queryReqVO.getFormulaType(),
                queryReqVO.getMaterialName(),
                queryReqVO.getMaterialNumber(),
                queryReqVO.getElementAbbreviation()
        );

        // 分页返回结果
        PageResult<FormulaRespVO> results = new PageResult<FormulaRespVO>().setTotal(ipage.getTotal()).setList(ipage.getRecords());
        if (results.getTotal() > 0) {
            results.getList().forEach(respVO -> {
                // 基础系数配置
                List<ContractCoefficientDO> coefficientDOS = contractCoefficientMapper.selectList("FMU_ID", respVO.getId());
                respVO.setCoefficients(BeanUtils.toBean(coefficientDOS, CoefficientRespVO.class));
                // 品位等级价配置
                List<ContractGradeDO> gradeDOS = contractGradeMapper.selectList("FMU_ID", respVO.getId());
                respVO.setGrades(BeanUtils.toBean(gradeDOS, GradeRespVO.class));
                // 调整价配置
                List<ContractDeductDO> deductDOS = contractDeductMapper.selectList("FMU_ID", respVO.getId());
                respVO.setDeducts(BeanUtils.toBean(deductDOS, DeductRespVO.class));
                // 市场价配置
                List<ContractPriceDO> priceDOS = contractPriceMapper.selectList("FMU_ID", respVO.getId());
                respVO.setPrices(BeanUtils.toBean(priceDOS, PriceRespVO.class));
            });
        }

        return results;
    }

    @Override
    public ContractRespDTO getFormulasByPaperNumber(String contractPaperNumber) {

        // 通过合同编号查询合同信息
        ContractMainDO contractMainDO = contractMainMapper
                .selectOne(TableFieldConstants.BSE_CTRT_MAIN_CTRT_PPR_NUM, contractPaperNumber);

        // 合同不存在
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 合同ID
        Long contractId = contractMainDO.getId();

        // 返回结果
        ContractRespDTO respDTO = new ContractRespDTO();
        BeanUtils.copyProperties(contractMainDO, respDTO);

        // 查询并设置合同明细
        List<ContractDetailDO> detailDOS = contractDetailMapper
                .selectList(TableFieldConstants.BSE_CTRT_DTL_CTRT_MAIN_ID, contractMainDO.getId());
        if (detailDOS != null && !detailDOS.isEmpty()) {
            respDTO.setDetail(BeanUtils.toBean(detailDOS, DetailRespDTO.class));
            respDTO.getDetail().forEach(detail -> {

                // 查询并设置交货计划
                List<ContractPlanDO> planDOS = contractPlanMapper
                        .selectList(TableFieldConstants.BSE_CTRT_PLN_CTRT_DTL_ID, detail.getId());
                if (planDOS != null && !planDOS.isEmpty()) {
                    detail.setPlans(BeanUtils.toBean(planDOS, PlanRespDTO.class));
                }
            });
        }

        // 查询并设置价款结算条款
        List<ContractFormulaDO> formulaDOS = contractFormulaMapper
                .selectList(TableFieldConstants.BSE_CTRT_FMU_CTRT_ID, contractId);
        if (formulaDOS != null && !formulaDOS.isEmpty()) {
            respDTO.setFormulas(BeanUtils.toBean(formulaDOS, FormulaRespDTO.class));

            respDTO.getFormulas().forEach(formula -> {

                // 查询并设置基础系数配置
                List<ContractCoefficientDO> coefficientDOS = contractCoefficientMapper
                        .selectList(TableFieldConstants.BSE_CTRT_COEF_FMU_ID, formula.getId());
                if (coefficientDOS != null && !coefficientDOS.isEmpty()) {
                    formula.setCoefficients(BeanUtils.toBean(coefficientDOS, CoefficientRespDTO.class));
                }
                // 查询并设置品位等级价配置
                List<ContractGradeDO> gradeDOS = contractGradeMapper
                        .selectList(TableFieldConstants.BSE_CTRT_GRD_FMU_ID, formula.getId());
                if (gradeDOS != null && !gradeDOS.isEmpty()) {
                    formula.setGrades(BeanUtils.toBean(gradeDOS, GradeRespDTO.class));
                }
                // 查询并设置调整价配置
                List<ContractDeductDO> deductDOS = contractDeductMapper
                        .selectList(TableFieldConstants.BSE_CTRT_DDCT_FMU_ID, formula.getId());
                if (deductDOS != null && !deductDOS.isEmpty()) {
                    formula.setDeducts(BeanUtils.toBean(deductDOS, DeductRespDTO.class));
                }
                // 查询并设置市场价配置
                List<ContractPriceDO> priceDOS = contractPriceMapper
                        .selectList(TableFieldConstants.BSE_CTRT_PRC_FMU_ID, formula.getId());
                if (priceDOS != null && !priceDOS.isEmpty()) {
                    formula.setPrices(BeanUtils.toBean(priceDOS, PriceRespDTO.class));
                }
            });
        }

        // 查询并设置参数降级规则
        List<ContractDemoteDO> demoteDOS = contractDemoteMapper
                .selectList(TableFieldConstants.BSE_CTRT_DMOT_CTRT_ID, contractMainDO.getId());
        if (demoteDOS != null && !demoteDOS.isEmpty()) {
            respDTO.setDemotes(BeanUtils.toBean(demoteDOS, DemoteRespDTO.class));
        }

        // 查询并设置品位不计价规则
        List<ContractNotDO> notDOS = contractNotMapper
                .selectList(TableFieldConstants.BSE_CTRT_NT_CTRT_ID, contractMainDO.getId());
        if (notDOS != null && !notDOS.isEmpty()) {
            respDTO.setNots(BeanUtils.toBean(notDOS, NotRespDTO.class));
        }
        //收发货
        List<ContractReceiveSendRespVO> contractReceiveSendListByContractId = contractReceiveSendService.getContractReceiveSendListByContractId(contractMainDO.getId());
        if (contractReceiveSendListByContractId != null && !contractReceiveSendListByContractId.isEmpty()) {
            respDTO.setContractReceiveSends(BeanUtils.toBean(contractReceiveSendListByContractId, ContractReceiveSendRespDTO.class));
        }
        //金额拆分
        List<AmountDismantleDO> amountDismantleListByContractId = amountDismantleService.getAmountDismantleListByContractId(contractMainDO.getId());
        if (amountDismantleListByContractId != null && !amountDismantleListByContractId.isEmpty()) {
            respDTO.setAmountSplits(BeanUtils.toBean(amountDismantleListByContractId, AmountSplitRespDTO.class));
        }
        return respDTO;
    }


    @Override
    public ContractRespDTO getFormulasBySysNumber(String contractSysNumber) {

        // 通过合同编号查询合同信息
        ContractMainDO contractMainDO = contractMainMapper
                .selectOne(ContractMainDO::getSystemContractNumber, contractSysNumber);

        // 合同不存在
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 合同ID
        Long contractId = contractMainDO.getId();

        // 返回结果
        ContractRespDTO respDTO = new ContractRespDTO();
        BeanUtils.copyProperties(contractMainDO, respDTO);

        // 查询并设置合同明细
        List<ContractDetailDO> detailDOS = contractDetailMapper
                .selectList(TableFieldConstants.BSE_CTRT_DTL_CTRT_MAIN_ID, contractMainDO.getId());
        if (detailDOS != null && !detailDOS.isEmpty()) {
            respDTO.setDetail(BeanUtils.toBean(detailDOS, DetailRespDTO.class));
            respDTO.getDetail().forEach(detail -> {

                // 查询并设置交货计划
                List<ContractPlanDO> planDOS = contractPlanMapper
                        .selectList(TableFieldConstants.BSE_CTRT_PLN_CTRT_DTL_ID, detail.getId());
                if (planDOS != null && !planDOS.isEmpty()) {
                    detail.setPlans(BeanUtils.toBean(planDOS, PlanRespDTO.class));
                }
            });
        }

        // 查询并设置价款结算条款
        List<ContractFormulaDO> formulaDOS = contractFormulaMapper
                .selectList(TableFieldConstants.BSE_CTRT_FMU_CTRT_ID, contractId);
        if (formulaDOS != null && !formulaDOS.isEmpty()) {
            respDTO.setFormulas(BeanUtils.toBean(formulaDOS, FormulaRespDTO.class));

            respDTO.getFormulas().forEach(formula -> {

                // 查询并设置基础系数配置
                List<ContractCoefficientDO> coefficientDOS = contractCoefficientMapper
                        .selectList(TableFieldConstants.BSE_CTRT_COEF_FMU_ID, formula.getId());
                if (coefficientDOS != null && !coefficientDOS.isEmpty()) {
                    formula.setCoefficients(BeanUtils.toBean(coefficientDOS, CoefficientRespDTO.class));
                }
                // 查询并设置品位等级价配置
                List<ContractGradeDO> gradeDOS = contractGradeMapper
                        .selectList(TableFieldConstants.BSE_CTRT_GRD_FMU_ID, formula.getId());
                if (gradeDOS != null && !gradeDOS.isEmpty()) {
                    formula.setGrades(BeanUtils.toBean(gradeDOS, GradeRespDTO.class));
                }
                // 查询并设置调整价配置
                List<ContractDeductDO> deductDOS = contractDeductMapper
                        .selectList(TableFieldConstants.BSE_CTRT_DDCT_FMU_ID, formula.getId());
                if (deductDOS != null && !deductDOS.isEmpty()) {
                    formula.setDeducts(BeanUtils.toBean(deductDOS, DeductRespDTO.class));
                }
                // 查询并设置市场价配置
                List<ContractPriceDO> priceDOS = contractPriceMapper
                        .selectList(TableFieldConstants.BSE_CTRT_PRC_FMU_ID, formula.getId());
                if (priceDOS != null && !priceDOS.isEmpty()) {
                    formula.setPrices(BeanUtils.toBean(priceDOS, PriceRespDTO.class));
                }
            });
        }

        // 查询并设置参数降级规则
        List<ContractDemoteDO> demoteDOS = contractDemoteMapper
                .selectList(TableFieldConstants.BSE_CTRT_DMOT_CTRT_ID, contractMainDO.getId());
        if (demoteDOS != null && !demoteDOS.isEmpty()) {
            respDTO.setDemotes(BeanUtils.toBean(demoteDOS, DemoteRespDTO.class));
        }

        // 查询并设置品位不计价规则
        List<ContractNotDO> notDOS = contractNotMapper
                .selectList(TableFieldConstants.BSE_CTRT_NT_CTRT_ID, contractMainDO.getId());
        if (notDOS != null && !notDOS.isEmpty()) {
            respDTO.setNots(BeanUtils.toBean(notDOS, NotRespDTO.class));
        }
        //收发货
        List<ContractReceiveSendRespVO> contractReceiveSendListByContractId = contractReceiveSendService.getContractReceiveSendListByContractId(contractMainDO.getId());
        if (contractReceiveSendListByContractId != null && !contractReceiveSendListByContractId.isEmpty()) {
            respDTO.setContractReceiveSends(BeanUtils.toBean(contractReceiveSendListByContractId, ContractReceiveSendRespDTO.class));
        }
        //金额拆分
        List<AmountDismantleDO> amountDismantleListByContractId = amountDismantleService.getAmountDismantleListByContractId(contractMainDO.getId());
        if (amountDismantleListByContractId != null && !amountDismantleListByContractId.isEmpty()) {
            respDTO.setAmountSplits(BeanUtils.toBean(amountDismantleListByContractId, AmountSplitRespDTO.class));
        }

        return respDTO;
    }


    @Override
    public JSONObject submitErp(Long id) {

        JSONObject result = new JSONObject();

        // 查询合同信息
        ContractMainDO contractMainDO = contractMainMapper.selectById(id);

        // 合同数据不存在
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 合同状态校验
        if (!(DictEnum.BSE_CTRT_STS_WAIT_PUSH.getCode().equals(contractMainDO.getStatus())
                || DictEnum.BSE_CTRT_STS_VOID.getCode().equals(contractMainDO.getStatus())
                || DictEnum.BSE_CTRT_STS_TERMINATED.getCode().equals(contractMainDO.getStatus())
                || DictEnum.BSE_CTRT_STS_PUSH_ERROR.getCode().equals(contractMainDO.getStatus())
        )) {

            throw exception(CONTRACT_STATUS_NOT_SUBMIT_ERP,
                    DictEnum.getByCodeAndType(contractMainDO.getStatus(), DictTypeConstants.BSE_CTRT_STS).getLabel());
        }

        // 生成ERP合同映射表
        ErpContractSaveReqVO erpContractVO = getErpContract(contractMainDO); //TODO ERP暂时返回成功
        //ErpContractSaveReqVO erpContractVO = new ErpContractSaveReqVO();

        // 调用ERP模块
        JSONObject erpResult = sendToErp(erpContractVO);
        log.info("合同提交ERP结果：{}", erpResult);
        result.putOnce("success", erpResult.getBool("success"));

        // 更新合同状态
        if (erpResult.getBool("success")) {
            if (DictEnum.BSE_CTRT_STS_WAIT_PUSH.getCode().equals(contractMainDO.getStatus())) {
                // 待推送的合同设置为执行中
                contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_IN_PROGRESS.getCode());
            }
            contractMainDO.setErpStatus(DictEnum.ERP_REQ_STS_FIND.getCode());
            contractMainDO.setCause("");
            contractMainMapper.updateById(contractMainDO);

            result.putOnce("data", erpResult.getStr("data"));
        } else {
            if (DictEnum.BSE_CTRT_STS_VOID.getCode().equals(contractMainDO.getStatus())
                    || DictEnum.BSE_CTRT_STS_TERMINATED.getCode().equals(contractMainDO.getStatus())) {
                // 作废和已完结订单退回执行中
                contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_TERMINATED.getCode());
            } else {
                // 待推送的合同设置为推送失败
                contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_PUSH_ERROR.getCode());
            }
            contractMainDO.setErpStatus(DictEnum.ERP_REQ_STS_RLBK.getCode());
            contractMainDO.setCause(erpResult.getStr("errMsg"));
            contractMainMapper.updateById(contractMainDO);

            result.putOnce("data", erpResult.getStr("errMsg"));
        }

        return result;
    }

    @Override
    public Boolean relation(RelationReqVo reqVo) {
        SystemRelativityDO saveDO = new SystemRelativityDO();
        saveDO.setStatus(DictEnum.BSE_SYS_REL_TP_CONTRACT.getCode());
        saveDO.setUpId(reqVo.getUpId());
        saveDO.setDownId(reqVo.getDownId());
        int insert = systemRelativityMapper.insert(saveDO);
        return insert > 0;
    }

    @Override
    public RelationRespVO getRelation(Long id) {

        // 返回结果
        RelationRespVO resp = new RelationRespVO();

        // 获得上游合同关联
        SystemRelativityDO upSystemRelativityDO = systemRelativityMapper
                .selectOne(new LambdaQueryWrapperX<SystemRelativityDO>()
                        .eq(SystemRelativityDO::getDownId, id)
                );

        // 获得下游合同关联
        SystemRelativityDO downSystemRelativityDO = systemRelativityMapper
                .selectOne(new LambdaQueryWrapperX<SystemRelativityDO>()
                        .eq(SystemRelativityDO::getUpId, id)
                );

        // 上游合同ID
        if (upSystemRelativityDO != null) resp.setUpId(upSystemRelativityDO.getId());
        // 下游合同ID
        if (downSystemRelativityDO != null) resp.setDownId(downSystemRelativityDO.getId());

        return resp;
    }

    @Override
    public ResponseEntity<ByteArrayResource> download(List<Long> ids) {
        try {

            // 返回的压缩包
            ByteArrayOutputStream zipsByte = new ByteArrayOutputStream();
            ZipOutputStream zips = new ZipOutputStream(zipsByte);

            // 遍历合同ID集合
            ids.forEach(id -> {
                try {
                    // 查询合同信息
                    ContractMainDO contractMainDO = contractMainMapper.selectById(id);

                    // 单个合同文件压缩
                    ByteArrayOutputStream zipByte = new ByteArrayOutputStream();
                    ZipOutputStream zip = new ZipOutputStream(zipByte);

                    // 关联的模版附件查询
                    TmplInscBsnRelDO tmplInscBsnRelDO = tmplInscBsnRelMapper.selectOne("BSN_ID", id);
                    if (tmplInscBsnRelDO != null) {
                        if (StringUtils.isNotEmpty(tmplInscBsnRelDO.getCntt())) {
                            JSONObject cntt = new JSONObject(tmplInscBsnRelDO.getCntt());
                            CommonResult<FileRespDTO> fileRespResult = fileApi
                                    .getFile(cntt.getLong("id"));

                            zip.putNextEntry(new ZipEntry(System.currentTimeMillis() + fileRespResult.getData().getName()));
                            zip.write(fileRespResult.getData().getContent());
                            zip.closeEntry();
                        }
                    }

                    // 上传模板附件
                    if (StringUtils.isNotBlank(contractMainDO.getFileObject())) {
                        JSONArray fileObjects = new JSONArray(contractMainDO.getFileObject());
                        for (int i = 0; i < fileObjects.size(); i++) {
                            JSONObject file = fileObjects.getJSONObject(i);
                            CommonResult<FileRespDTO> fileRespResult = fileApi
                                    .getFile(file.getLong("id"));

                            zip.putNextEntry(new ZipEntry(System.currentTimeMillis() + fileRespResult.getData().getName()));
                            zip.write(fileRespResult.getData().getContent());
                            zip.closeEntry();
                        }
                    }

                    // 合同其它附件
                    if (StringUtils.isNotBlank(contractMainDO.getFileObjectOther())) {
                        JSONArray fileObjectOthers = new JSONArray(contractMainDO.getFileObjectOther());
                        for (int i = 0; i < fileObjectOthers.size(); i++) {
                            JSONObject file = fileObjectOthers.getJSONObject(i);
                            CommonResult<FileRespDTO> fileRespResult = fileApi
                                    .getFile(file.getLong("id"));

                            zip.putNextEntry(new ZipEntry(System.currentTimeMillis() + fileRespResult.getData().getName()));
                            zip.write(fileRespResult.getData().getContent());
                            zip.closeEntry();
                        }
                    }

                    zip.finish();
                    String zipName = String.format("%s（%s）相关文件.zip", contractMainDO.getContractName(), contractMainDO.getSystemContractNumber());
                    zips.putNextEntry(new ZipEntry(zipName));
                    zips.write(zipByte.toByteArray());
                    zips.closeEntry();
                } catch (Exception e) {
                    log.info("添加压缩包异常：" + e.getMessage());
                }
            });

            zips.finish();
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=contract-file-" + System.currentTimeMillis() + ".zip")
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(new ByteArrayResource(zipsByte.toByteArray()));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    @Override
    public Boolean archive(List<Long> ids) {

        // 遍历合同ID
        ids.forEach(id -> {

            // 查询合同是否存在
            ContractMainDO contractMainDO = contractMainMapper.selectById(id);
            if (contractMainDO == null) {
                throw exception(CONTRACT_NOT_EXISTS);
            }

            // 合同状态校验
            if (!DictEnum.BSE_CTRT_STS_TERMINATED.getCode().equals(contractMainDO.getStatus())) {
                throw exception(CONTRACT_STATUS_NOT_ARCHIVE,
                        DictEnum.getByCodeAndType(contractMainDO.getStatus(), DictTypeConstants.BSE_CTRT_STS).getLabel());
            }

            // 设置归档状态
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_ARCHIVED.getCode());

            // 更新合同
            contractMainMapper.updateById(contractMainDO);
        });

        return true;
    }

    @Override
    public Boolean cancel(List<Long> ids) {

        // 遍历合同ID
        ids.forEach(id -> {

            // 查询合同是否存在
            ContractMainDO contractMainDO = contractMainMapper.selectById(id);
            if (contractMainDO == null) {
                throw exception(CONTRACT_NOT_EXISTS);
            }

            // 合同状态校验
            if (!DictEnum.BSE_CTRT_STS_IN_PROGRESS.getCode().equals(contractMainDO.getStatus())) {
                throw exception(CONTRACT_STATUS_NOT_CANCEL,
                        DictEnum.getByCodeAndType(contractMainDO.getStatus(), DictTypeConstants.BSE_CTRT_STS).getLabel());
            }

            // 设置作废状态
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_VOID.getCode());

            // 更新合同
            contractMainMapper.updateById(contractMainDO);

            // 重新提交erp
            submitErp(id);
        });

        return true;
    }

    @Override
    public Boolean complete(List<Long> ids) {

        // 遍历合同ID
        ids.forEach(id -> {

            // 查询合同是否存在
            ContractMainDO contractMainDO = contractMainMapper.selectById(id);
            if (contractMainDO == null) {
                throw exception(CONTRACT_NOT_EXISTS);
            }

            // 合同状态校验
            if (!DictEnum.BSE_CTRT_STS_IN_PROGRESS.getCode().equals(contractMainDO.getStatus())) {
                throw exception(CONTRACT_STATUS_NOT_ARCHIVE,
                        DictEnum.getByCodeAndType(contractMainDO.getStatus(), DictTypeConstants.BSE_CTRT_STS).getLabel());
            }

            // 设置完结状态
            contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_TERMINATED.getCode());

            // 更新合同
            contractMainMapper.updateById(contractMainDO);

            // 重新提交erp
            submitErp(id);
        });

        return true;
    }

    @Override
    public JSONObject sendToErp(ErpContractSaveReqVO erpContractVO) {
        JSONObject erpResult = new JSONObject();

        // TODO 暂时返回成功
//        erpResult.putOnce("success", true);
//        erpResult.putOnce("data", "success");
        log.info("ERP请求参数：{}", erpContractVO);
        Map<String, String> result = erpContractService.submitErp(erpContractVO);

        if ("E".equals(result.get("flag"))) {
            erpResult.putOnce("success", false);
            erpResult.putOnce("errMsg", result.get("resStr") + ":" + result.get("E_RESP"));
        } else {
            erpResult.putOnce("success", true);
            erpResult.putOnce("data", result);
        }

        return erpResult;
    }

    /**
     * 通过009ERP接口查询合同信息，判定合同映射表操作标识
     *
     * @param contractMainDO 合同主信息
     * @return 操作标识
     */
    private String getOperationId(ContractMainDO contractMainDO) {
        String operationId = null;

        // 1、先调用009ERP接口查询合同信息
        ErpContractPageReqVO pageReqVO = new ErpContractPageReqVO();
        // BUKRS 合同签订主体公司代码 收支方向判断，如果为“支出”，传“ERP甲方公司编码”，反之传“ERP乙方公司编码”
        // PARTNER 对方客商编号 收支方向判断，如果为“支出”，传“ERP乙方公司编码”，反之传“ERP甲方公司编码”
        // INEDR 1-借(销售合同)，2-贷(采购合同) 收支方向判断，如果为“支出”，传“2”，反之传“1”
        if (DictEnum.ERP_RCV_DLVY_EXPENSES.getCode().equals(contractMainDO.getDirection())) {
            pageReqVO.setContractSignNumber(contractMainDO.getErpPurchaseCompanyNumber());
            pageReqVO.setSupplierNumber(contractMainDO.getErpSalesCompanyNumber());
            pageReqVO.setContractCategory("2");
        } else if (DictEnum.ERP_RCV_DLVY_INCOME.getCode().equals(contractMainDO.getDirection())) {
            pageReqVO.setContractSignNumber(contractMainDO.getErpSalesCompanyNumber());
            pageReqVO.setSupplierNumber(contractMainDO.getErpPurchaseCompanyNumber());
            pageReqVO.setContractCategory("1");
        }
        // ZHTBH 合同编号 合同编号:CTRT_PPR_NUM
        pageReqVO.setContractTypeNumber(contractMainDO.getContractPaperNumber());
        // ZHTMC 合同名称 合同名称:CTRT_NAME
        pageReqVO.setContractName(contractMainDO.getContractName());

        // 查询
        PageResult<ErpContractDO> erpContractPage = erpContractService.getErpContractPage(pageReqVO);
        if (erpContractPage.getTotal() > 0) {
            // 2、如果009接口返回值中“合同编号”字段存在值，并且与传入的相同，则OPTN_ID值为“1”
            operationId = "1";
        } else {
            // 3、如果009接口返回值中“合同编号”字段不存在值，根据合同主键查询映射表中是否存在没有删除的数据，如果有，值为“1”，如果没有，值为“0”
            ErpContractDO erpContract = erpContractService.getErpContractByPaperNumber(contractMainDO.getContractPaperNumber());
            if (erpContract != null) {
                operationId = "1";
            } else {
                operationId = "0";
            }
        }

        return operationId;
    }

    @Override
    public ErpContractSaveReqVO getErpContract(ContractMainDO contractMainDO) {

        ErpContractSaveReqVO erpContractVO = new ErpContractSaveReqVO();
        // 合同主信息表主键:BSE_CTRT_MAIN
        erpContractVO.setContractMainId(contractMainDO.getId());
        // 操作标识:OPTN_ID
        erpContractVO.setOperationId(getOperationId(contractMainDO));
        // 合同编号:CTRT_PPR_NUM
        erpContractVO.setContractPaperNumber(contractMainDO.getContractPaperNumber());
        // 合同名称:CTRT_NAME
        erpContractVO.setContractName(contractMainDO.getContractName());
        // 合同类型编号:CTRT_TP_NUM
        erpContractVO.setContractTypeNumber(contractMainDO.getConstructionTypeNumber());
        // 合同类型名称:CTRT_TP_NAME
        erpContractVO.setContractTypeName(contractMainDO.getConstructionTypeName());
        // 合同类别:CTRT_CTGR
        erpContractVO.setContractCategory(contractMainDO.getCategory());
        // 是否虚拟合同:IS_VRTL_CTRT
        erpContractVO.setIsVirtualContract(contractMainDO.getContractVirtual());
        // 客商编号:SPLR_NUM 根据合同主表的收支方向判断，如果为“支出”，值为“ERP乙方公司编码”，反之为“ERP甲方公司编码”
        // 客商名称:SPLR_NAME 根据合同主表的收支方向判断，如果为“支出”，值为“ERP乙方公司名称”，反之为“ERP甲方公司名称”
        if (DictEnum.ERP_RCV_DLVY_EXPENSES.getCode().equals(contractMainDO.getDirection())) {
            erpContractVO.setSupplierNumber(contractMainDO.getErpSalesCompanyNumber());
            erpContractVO.setSupplierName(contractMainDO.getErpSalesCompanyName());
        } else if (DictEnum.ERP_RCV_DLVY_INCOME.getCode().equals(contractMainDO.getDirection())) {
            erpContractVO.setSupplierNumber(contractMainDO.getErpPurchaseCompanyNumber());
            erpContractVO.setSupplierName(contractMainDO.getErpPurchaseCompanyName());
        }
        // 代理方:AGT
        erpContractVO.setAgent(contractMainDO.getAgent());
        // 合同实施主体编号:CTRT_IMPL_NUM 根据合同主表的收支方向判断，如果为“支出”，值为“ERP甲方公司编码”，反之为“ERP乙方公司编码”
        // 合同签订主体编号:CTRT_SGN_NUM 根据合同主表的收支方向判断，如果为“支出”，值为“ERP甲方公司名称”，反之为“ERP乙方公司名称”
        if (DictEnum.ERP_RCV_DLVY_EXPENSES.getCode().equals(contractMainDO.getDirection())) {
            erpContractVO.setContractImplementNumber(contractMainDO.getErpPurchaseCompanyNumber());
            erpContractVO.setContractSignNumber(contractMainDO.getErpPurchaseCompanyNumber());
        } else if (DictEnum.ERP_RCV_DLVY_INCOME.getCode().equals(contractMainDO.getDirection())) {
            erpContractVO.setContractImplementNumber(contractMainDO.getErpSalesCompanyNumber());
            erpContractVO.setContractSignNumber(contractMainDO.getErpSalesCompanyNumber());
        }
        // 合同签订日期:SGN_DT
        if (contractMainDO.getSignDate() != null) {
            erpContractVO.setSignDate(contractMainDO.getSignDate().toLocalDate());
        }
        // 合同起始日期:STRT_DT
        if (contractMainDO.getStartDate() != null) {
            erpContractVO.setStartDate(contractMainDO.getStartDate().toLocalDate());
        }
        // 合同终止日期:STOP_DT
        if (contractMainDO.getEndDate() != null) {
            erpContractVO.setStopDate(contractMainDO.getEndDate().toLocalDate());
        }
        // 币种编号:CUR
        erpContractVO.setCurrency(contractMainDO.getCurrency());
        // 合同总金额(原币-含税):SRC_AMT
        erpContractVO.setSourceAmount(contractMainDO.getCooAmount());
        // 合同总金额(本位币-含税):BSC_AMT
        erpContractVO.setBasicAmount(contractMainDO.getBasicAmount());
        // 变更后合同总金额(原币-含税):CHG_SRC_AMT
        erpContractVO.setChangeSourceAmount(contractMainDO.getChangeCooAmount());
        // 变更后合同总金额(本位币-含税):CHG_BSC_AMT
        erpContractVO.setChangeBasicAmount(contractMainDO.getChangeBasicAmount());
        // 合同状态编号:STS_NUM 参照060接口
        // 合同状态名称:STS_NAME 参照060接口
        if (DictEnum.BSE_CTRT_STS_VOID.getCode().equals(contractMainDO.getStatus())) { // 作废
            erpContractVO.setStatusNumber(DictEnum.SUBMIT_ERP_CTRT_STS_CA.getCode());
            erpContractVO.setStatusName(DictEnum.SUBMIT_ERP_CTRT_STS_CA.getLabel());
        } else if (DictEnum.BSE_CTRT_STS_TERMINATED.getCode().equals(contractMainDO.getStatus())) { // 完结
            erpContractVO.setStatusNumber(DictEnum.SUBMIT_ERP_CTRT_STS_ZXWB.getCode());
            erpContractVO.setStatusName(DictEnum.SUBMIT_ERP_CTRT_STS_ZXWB.getLabel());
        } else { // 其它所有状态
            erpContractVO.setStatusNumber(DictEnum.SUBMIT_ERP_CTRT_STS_EF.getCode());
            erpContractVO.setStatusName(DictEnum.SUBMIT_ERP_CTRT_STS_EF.getLabel());
        }
        // 是否有预付款:IS_PPYM
        erpContractVO.setIsPrepayment(contractMainDO.getHasPrepayment());
        // 预付款比例:PPYM_RTIO
        erpContractVO.setPrepaymentRatio(contractMainDO.getPrepaymentRatio());
        // 预付款金额:PPYM_AMT
        erpContractVO.setPrepaymentAmount(contractMainDO.getPrepaymentAmount());
        // 履约保证金-变更前(原币):SRC_BFR_BND
        erpContractVO.setSourceBeforeBond(contractMainDO.getChangeCooAmountDeposit());
        // 履约保证金-变更前(本位币）:BSC_BFR_BND
        erpContractVO.setBasicBeforeBond(contractMainDO.getChangeBasicAmountDeposit());
        // 履约保证金-变更后(原币）:SRC_AFT_BND
        erpContractVO.setSourceAfterBond(contractMainDO.getChangeCooAmountDeposit());
        // 履约保证金-变更后(本位币）:BSC_AFT_BND
        erpContractVO.setBasicAfterBond(contractMainDO.getChangeBasicAmountDeposit());
        // 是否含质保金:IS_QUA_AMT
        erpContractVO.setIsQualityassuranceAmount(contractMainDO.getHasQualityAmount());
        // 质保金比例:QUA_RTIO
        erpContractVO.setQualityassuranceRatio(contractMainDO.getQualityRatio());
        // 质保金金额:QUA_AMT
        erpContractVO.setQualityassuranceAmount(contractMainDO.getQualityAmount());
        // 是否内部企业:IS_INTL
        erpContractVO.setIsInternal(contractMainDO.getIsInternal());
        // 收支性质:NTR
        erpContractVO.setNature(contractMainDO.getDirection());
        // 备注信息:RMK
        erpContractVO.setRemark(contractMainDO.getRemark());
        // 是否框架合同:IS_FMWK
        erpContractVO.setIsFramework(contractMainDO.getIsFramework());
        // 境内/境外:IS_DOM
        erpContractVO.setIsDomestic(contractMainDO.getIsDomestic());
        // 达到收款条件金额:PYEE_CND_AMT
        erpContractVO.setPayeeConditionAmount(contractMainDO.getPayeeConditionAmount());
        // 建筑服务发生地:ARCH_SVC_PLCE
        erpContractVO.setArchitectureService‌Place(contractMainDO.getArchitectureServicePlace());

        // 公司编号
        erpContractVO.setCompanyId(contractMainDO.getCompanyId());
        // 公司名称
        erpContractVO.setCompanyName(contractMainDO.getCompanyName());
        // 部门编号
        erpContractVO.setDeptId(contractMainDO.getDeptId());
        // 部门名称
        erpContractVO.setDeptName(contractMainDO.getDeptName());
        // 岗位编号
        erpContractVO.setPostId(contractMainDO.getPostId());
        // 创建者
        erpContractVO.setCreatorName(contractMainDO.getCreatorName());
        // 更新者
        erpContractVO.setUpdaterName(contractMainDO.getUpdaterName());

        return erpContractVO;
    }

    @Override
    public TransactionInfoRespVO transactionInfoByPaperNumber(String contractPaperNumber) {

        // 通过合同编号查询合同信息
        ContractMainDO contractMainDO = contractMainMapper
                .selectOne(TableFieldConstants.BSE_CTRT_MAIN_CTRT_PPR_NUM, contractPaperNumber);

        // 合同不存在
        if (contractMainDO == null) {
            throw exception(CONTRACT_NOT_EXISTS);
        }

        // 交易信息
        TransactionInfoRespVO infoRespVO = new TransactionInfoRespVO();

        if (DictEnum.ERP_RCV_DLVY_INCOME.getCode().equals(contractMainDO.getDirection())) { // 收入
            // 收支性质为收入，公司信息为乙方信息，客商信息为甲方信息
            infoRespVO.setCompanyNumber(contractMainDO.getSalesCompanyNumber());
            infoRespVO.setCompanyName(contractMainDO.getSalesCompanyName());
            infoRespVO.setCompanyAccountName(contractMainDO.getSalesAccountName());
            infoRespVO.setCompanyBankAccount(contractMainDO.getSalesBankAccount());
            infoRespVO.setCompanyAccountNumber(contractMainDO.getSalesAccountNumber());
            infoRespVO.setCompanyTaxNumber(contractMainDO.getSalesTaxNumber());
            infoRespVO.setSupplierNumber(contractMainDO.getPurchaseCompanyNumber());
            infoRespVO.setSupplierName(contractMainDO.getPurchaseCompanyName());
            infoRespVO.setSupplierAccountName(contractMainDO.getPurchaseAccountName());
            infoRespVO.setSupplierBankAccount(contractMainDO.getPurchaseBankAccount());
            infoRespVO.setSupplierAccountNumber(contractMainDO.getPurchaseAccountNumber());
            infoRespVO.setSupplierTaxNumber(contractMainDO.getPurchaseTaxNumber());
        } else { // 支出
            // 收支性质为支出，公司信息为甲方信息，客商信息为乙方信息
            infoRespVO.setCompanyNumber(contractMainDO.getPurchaseCompanyNumber());
            infoRespVO.setCompanyName(contractMainDO.getPurchaseCompanyName());
            infoRespVO.setCompanyAccountName(contractMainDO.getPurchaseAccountName());
            infoRespVO.setCompanyBankAccount(contractMainDO.getPurchaseBankAccount());
            infoRespVO.setCompanyAccountNumber(contractMainDO.getPurchaseAccountNumber());
            infoRespVO.setCompanyTaxNumber(contractMainDO.getPurchaseTaxNumber());
            infoRespVO.setSupplierNumber(contractMainDO.getSalesCompanyNumber());
            infoRespVO.setSupplierName(contractMainDO.getSalesCompanyName());
            infoRespVO.setSupplierAccountName(contractMainDO.getSalesAccountName());
            infoRespVO.setSupplierBankAccount(contractMainDO.getSalesBankAccount());
            infoRespVO.setSupplierAccountNumber(contractMainDO.getSalesAccountNumber());
            infoRespVO.setSupplierTaxNumber(contractMainDO.getSalesTaxNumber());
        }
        return infoRespVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CompanyDataPermissionIgnore
    @DeptDataPermissionIgnore
    public void relationContract(RelationContractVO relationContractVO) {
        //查询当前订单是否已经绑定订单了
        ContractMainDO contractMainDO = contractMainMapper.selectById(relationContractVO.getContractId());
        if (contractMainDO != null && contractMainDO.getRelatedContractId() != null) {
            ContractMainDO updateObj = contractMainMapper.selectById(contractMainDO.getRelatedContractId());
            updateObj.setRelatedContractId(null);
            contractMainMapper.updateById(updateObj);
        }
        contractMainDO.setRelatedContractId(relationContractVO.getRelationContractId());
        contractMainMapper.updateById(contractMainDO);// 绑定合同订单
        ContractMainDO relationContract = contractMainMapper.selectById(relationContractVO.getRelationContractId());
        if (relationContract != null) {
            // 绑定合同订单
            relationContract.setRelatedContractId(relationContractVO.getContractId());
            contractMainMapper.updateById(relationContract);
        }else {
            throw exception(CONTRACT_NOT_EXISTS);
        }

    }

    /**
     * 校验合同内容
     *
     * @param contract 合同数据
     */
    private void verifyContract(ContractRespVO contract) {

        /* 合同基本信息 */
        // 甲方公司编号不能为空
        if (StringUtils.isBlank(contract.getPurchaseCompanyNumber())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_PRCH_CPN_NUM_LABEL);
        }
        // 甲方公司名称不能为空
        if (StringUtils.isBlank(contract.getPurchaseCompanyName())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_PRCH_CPN_NAME_LABEL);
        }
        // 甲方地址不能为空
        if (StringUtils.isBlank(contract.getPurchaseAddress())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_PRCH_ADR_LABEL);
        }
        // 甲方法定代表人能为空
        if (StringUtils.isBlank(contract.getPurchaseLeader())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_PRCH_LDR_LABEL);
        }
        // 乙方公司编号不能为空
        if (StringUtils.isBlank(contract.getSalesCompanyNumber())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_SALE_CPN_NUM_LABEL);
        }
        // 乙方公司名称不能为空
        if (StringUtils.isBlank(contract.getSalesCompanyName())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_SALE_CPN_NAME_LABEL);
        }
        // 乙方地址不能为空
        if (StringUtils.isBlank(contract.getSalesAddress())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_SALE_ADR_LABEL);
        }
        // 乙方法定代表人能为空
        if (StringUtils.isBlank(contract.getSalesPurchaseLeader())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_SALE_PRCH_LDR_LABEL);
        }
        // 合同名称不能为空
        if (StringUtils.isBlank(contract.getContractName())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_CTRT_NAME_LABEL);
        }
        // 合同编号不能为空
        if (StringUtils.isBlank(contract.getContractPaperNumber())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_CTRT_PPR_NUM_LABEL);
        }
        // 类别不能为空
        if (StringUtils.isBlank(contract.getCategory())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_CTGR_LABEL);
        }
        // 收支性质不能为空
        if (StringUtils.isBlank(contract.getDirection())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_DRCT_LABEL);
        }
        // 签署日期不能为空
        if (contract.getSignDate() == null) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_SGN_DT_LABEL);
        }
        // 开始日期不能为空
        if (contract.getStartDate() == null) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_STRT_DT_LABEL);
        }
        // 结束日期不能为空
        if (contract.getEndDate() == null) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_END_DT_LABEL);
        }
        // 签署地不能为空
        if (StringUtils.isBlank(contract.getSignPlace())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_SGN_PLCE_LABEL);
        }

        /* 金额信息 */
        // 币种不能为空
        if (StringUtils.isBlank(contract.getCurrency())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_CUR_LABEL);
        }
        // 本币金额不能为空
        if (contract.getBasicAmount() == null) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_BSC_AMT_LABEL);
        }
        // 原币金额不能为空
        if (contract.getCooAmount() == null) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_COO_AMT_LABEL);
        }
        // 是否有履约保证金不能为空
        if (StringUtils.isBlank(contract.getHasDeposit())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_HS_DPST_LABEL);
        }
        // 是否有履约保证金为是的情况
        if (DictEnum.ERP_CTRT_YN_YES.getCode().equals(contract.getHasDeposit())) {
            // 原币履约保证金不能为空
            if (contract.getCooAmountDeposit() == null) {
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_COO_AMT_DPST_LABEL);
            }
            // 本币履约保证金不能为空
            if (contract.getBasicAmountDeposit() == null) {
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_BSC_AMT_DPST_LABEL);
            }
        }
        // 是否有预付款不能为空
        if (StringUtils.isBlank(contract.getHasPrepayment())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_HS_PPYM_LABEL);
        }
        // 是否有预付款为是的情况
        if (DictEnum.ERP_CTRT_YN_YES.getCode().equals(contract.getHasPrepayment())) {
            // 预付款比例不能为空
            if (contract.getPrepaymentRatio() == null) {
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_PPYM_RTIO_LABEL);
            }
            // 预付款金额不能为空
            if (contract.getPrepaymentAmount() == null) {
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_PPYM_AMT_LABEL);
            }
        }
        // 是否有质保金不能为空
        if (StringUtils.isBlank(contract.getHasQualityAmount())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_HS_QLT_AMT_LABEL);
        }
        // 是否有质保金为是的情况
        if (DictEnum.ERP_CTRT_YN_YES.getCode().equals(contract.getHasPrepayment())) {
            // 质保金比例不能为空
            if (contract.getQualityRatio() == null) {
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_QLT_RTIO_LABEL);
            }
            // 质保金金额不能为空
            if (contract.getQualityAmount() == null) {
                throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_QLT_AMT_LABEL);
            }
        }
        // 是否先款后货不能为空
        if (StringUtils.isBlank(contract.getHasPayable())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_HS_PYBL_LABEL);
        }

        /* 物料信息 */
        if (contract.getDetail() != null && !contract.getDetail().isEmpty()) {
            contract.getDetail().forEach(detail -> {
                // 物料名称不能为空
                if (StringUtils.isBlank(detail.getMaterialName())) {
                    throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_DTL_MTRL_NAME_LABEL);
                }
                // 数量不能为空
                if (detail.getQuantity() == null) {
                    throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_DTL_QTY_LABEL);
                }
                // 计量单位不能为空
                if (StringUtils.isBlank(detail.getUnit())) {
                    throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_DTL_UNT_LABEL);
                }
            });
        }

        /* 扩展信息 */
        // 是否框架合同不能为空
        if (StringUtils.isBlank(contract.getIsFramework())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_IS_FMWK_LABEL);
        }
        // 境内/境外不能为空
        if (StringUtils.isBlank(contract.getIsDomestic())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_IS_DOM_LABEL);
        }
        // 施工类型编号不能为空
        if (StringUtils.isBlank(contract.getConstructionTypeNumber())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_CON_TP_NUM_LABEL);
        }
        // 施工类型名称不能为空
        if (StringUtils.isBlank(contract.getConstructionTypeName())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_CON_TP_NAME_LABEL);
        }
        // 代理方不能为空
        if (StringUtils.isBlank(contract.getAgent())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_AGT_LABEL);
        }
        // 是否虚拟合同不能为空
        if (StringUtils.isBlank(contract.getContractVirtual())) {
            throw exception(CONTRACT_DATA_NOT_EXISTS, TableFieldConstants.BSE_CTRT_MAIN_CTRT_VRTL_LABEL);
        }
    }

    @Override
    public String generateSystemContractNumber(String category) {

        // 单据名称（拼音）
        String documentName = "XTHT";
        // 公司编码
        String companyId = CompanyContextHolder.getCompanyId() != null ? CompanyContextHolder.getCompanyId().toString() : "";
        // 年月日
        String yearMounth8Bit = LocalDate.now()
                .format(DateTimeFormatter.ofPattern(DateConstants.DATE_FORMAT_YEAR_MONTH_DAY_8_BIT));
        // 查询最大编号
        String numPrefix = documentName + "-" + category + "-" + companyId + "-" + yearMounth8Bit;
        QueryWrapper<ContractMainDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("SYS_CTRT_NUM", numPrefix);
        queryWrapper.orderByDesc("SYS_CTRT_NUM");
        queryWrapper.last("limit 1");
        ContractMainDO contract = contractMainMapper.selectOne(queryWrapper);
        // 获取最大的6位编号+1作为生成的编号
        String num = null;
        if (contract == null) {
            num = "000001";
        } else {
            String[] systemContractNumberSplit = contract.getSystemContractNumber().split("-");
            int numInt = Integer.parseInt(systemContractNumberSplit[systemContractNumberSplit.length - 1]) + 1;
            if (numInt > 999999) {
                throw exception(CONTRACT_NUM_TRANSFINITE);
            }
            num = String.format("%06d", numInt);
        }
        return numPrefix + "-" + num;
    }

    /**
     * 获取合同ID集合
     *
     * @param contractName        合同名称
     * @param contractPaperNumber 合同编号
     * @return 合同ID集合
     */
    private List<Long> getContractIds(String contractName, String contractPaperNumber) {
        List<Long> contractIds = new ArrayList<>();
        List<ContractMainDO> contractMainDOS = contractMainMapper.selectList(new LambdaQueryWrapperX<ContractMainDO>()
                .likeIfPresent(ContractMainDO::getContractName, contractName)
                .likeIfPresent(ContractMainDO::getContractPaperNumber, contractPaperNumber));
        if (CollectionUtils.isNotEmpty(contractMainDOS)) {
            contractIds = contractMainDOS.stream()
                    .map(contractMainDO -> contractMainDO.getId())
                    .collect(Collectors.toList());
        }
        return contractIds;
    }
}
