package com.ruoyi.project.business.service.quotation.impl;

import static com.ruoyi.project.business.enums.AuditFlowEnum.QUOTATION;
import static com.ruoyi.project.business.enums.AuditStatusEnum.BARGAIN_APPROVAL3;
import static com.ruoyi.project.business.enums.AuditStatusEnum.BARGAIN_APPROVAL4;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ElevatorParamCodeConstants;
import com.ruoyi.common.enums.FileBuzType;
import com.ruoyi.common.enums.SerialNumberPrefix;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.framework.redis.RedisCache;
import com.ruoyi.project.business.domain.TbCountry;
import com.ruoyi.project.business.domain.TbFile;
import com.ruoyi.project.business.domain.TbSalesDiscount;
import com.ruoyi.project.business.domain.TcProject;
import com.ruoyi.project.business.domain.TpAreaBasicPrice;
import com.ruoyi.project.business.domain.TqBargainPrice;
import com.ruoyi.project.business.domain.TqPriceDetail;
import com.ruoyi.project.business.domain.TqQuotation;
import com.ruoyi.project.business.domain.TqSalespersonSetPrice;
import com.ruoyi.project.business.domain.TqSpecification;
import com.ruoyi.project.business.domain.TqSpecificationDetail;
import com.ruoyi.project.business.domain.TqSpecificationNonStandard;
import com.ruoyi.project.business.domain.bo.quotation.DescFileAddBO;
import com.ruoyi.project.business.domain.bo.quotation.ElevatorAddBO;
import com.ruoyi.project.business.domain.bo.quotation.ElevatorParamAddBO;
import com.ruoyi.project.business.domain.bo.quotation.NonStandardAddBO;
import com.ruoyi.project.business.domain.bo.quotation.QuotationAddBO;
import com.ruoyi.project.business.domain.bo.quotation.QuotationCopyBO;
import com.ruoyi.project.business.domain.bo.quotation.QuotationQueryBO;
import com.ruoyi.project.business.domain.flow.Flow;
import com.ruoyi.project.business.domain.flow.FlowAuditParam;
import com.ruoyi.project.business.domain.vo.quotation.QuotationDetailVO;
import com.ruoyi.project.business.domain.vo.quotation.QuotationExportVO;
import com.ruoyi.project.business.domain.vo.quotation.QuotationPriceVO;
import com.ruoyi.project.business.domain.vo.quotation.QuotationVO;
import com.ruoyi.project.business.domain.vo.quotation.QuotationVersionVO;
import com.ruoyi.project.business.domain.vo.selectParam.ProjectParam;
import com.ruoyi.project.business.dto.TaskGenerateParams;
import com.ruoyi.project.business.enums.AuditFlowEnum;
import com.ruoyi.project.business.enums.AuditStatusEnum;
import com.ruoyi.project.business.enums.DelFlagEnum;
import com.ruoyi.project.business.enums.NodeRoleEnum;
import com.ruoyi.project.business.enums.ParamTypeEnum;
import com.ruoyi.project.business.enums.QuotationStatusEnum;
import com.ruoyi.project.business.enums.SystemCheckResultEnum;
import com.ruoyi.project.business.mapper.TcProjectMapper;
import com.ruoyi.project.business.mapper.quotation.TqQuotationMapper;
import com.ruoyi.project.business.mapper.quotation.TqSpecificationMapper;
import com.ruoyi.project.business.mapper.quotation.TqSpecificationNonStandardMapper;
import com.ruoyi.project.business.service.ITbAreaService;
import com.ruoyi.project.business.service.ITbCountryService;
import com.ruoyi.project.business.service.ITbFileService;
import com.ruoyi.project.business.service.ITbSalesDiscountService;
import com.ruoyi.project.business.service.ITpAreaBasicPriceService;
import com.ruoyi.project.business.service.flow.IFlowService;
import com.ruoyi.project.business.service.quotation.ITqBargainPriceService;
import com.ruoyi.project.business.service.quotation.ITqPriceDetailService;
import com.ruoyi.project.business.service.quotation.ITqQuotationService;
import com.ruoyi.project.business.service.quotation.ITqSalespersonSetPriceService;
import com.ruoyi.project.business.service.quotation.ITqSpecificationDetailService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author ruoyi
 * @date 2024-05-10
 */
@Service
@Slf4j
public class TqQuotationServiceImpl extends ServiceImpl<TqQuotationMapper, TqQuotation> implements ITqQuotationService {

    public static final String ONE_HUNDRED = "100";

    @Resource
    private TqSpecificationMapper tqSpecificationMapper;

    @Resource
    private TcProjectMapper tcProjectMapper;

    @Resource
    private RedisCache redisCache;

    @Resource
    private ITqSpecificationDetailService iTqSpecificationDetailService;

    @Resource
    private IFlowService flowService;

    @Resource
    private ITqPriceDetailService priceDetailService;

    @Resource
    private ITpAreaBasicPriceService iTpAreaBasicPriceService;

    @Resource
    private ITbCountryService tbCountryService;

    @Resource
    private ITqBargainPriceService tqBargainPriceService;

    @Resource
    private ITqSalespersonSetPriceService tqSalespersonSetPriceService;

    @Resource
    private TqSpecificationNonStandardMapper tqSpecificationNonStandardMapper;

    @Resource
    private ITbFileService tbFileService;

    @Resource
    private ITbAreaService tbAreaService;

    @Resource
    private ITbSalesDiscountService tbSalesDiscountService;

    /**
     * 查询【请填写功能名称】
     *
     * @param id 【请填写功能名称】主键
     * @return 【请填写功能名称】
     */
    @Override
    public QuotationDetailVO selectTqQuotationById(Long id) {
        QuotationDetailVO quotationDetailVO = baseMapper.selectDetailById(id);
        ProjectParam tcProject = new ProjectParam();
        tcProject.setProjectId(quotationDetailVO.getProjectId());
        tcProject.setPermissionChar(SecurityUtils.getPermissionCharSea());
        List<TcProject> tcProjects = tcProjectMapper.selectTcProjectList(tcProject);
        if (CollUtil.isNotEmpty(tcProjects)) {
            BeanUtils.copyProperties(tcProjects.get(0), quotationDetailVO, "currencyId");
        }
        return quotationDetailVO;
    }

    /**
     * 查询【请填写功能名称】列表
     *
     * @param queryBO 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<QuotationVO> selectTqQuotationList(QuotationQueryBO queryBO) {
        Optional.ofNullable(queryBO.getCreateTime()).ifPresent(item -> {
            if (item.size() > 1) {
                item.set(1, DateUtil.endOfDay(item.get(1)));
            }
        });
        queryBO.setAreaIdList(tbAreaService.selectChildAreaIdsByAreaIds(SecurityUtils.getLoginUser().getAreaIdList()));
        List<QuotationVO> quotationVOS = baseMapper.selectTqQuotationList(queryBO);

        // 查询子项
        List<String> quotationNoList = quotationVOS.stream().map(QuotationVO::getQuotationNo)
            .collect(Collectors.toList());
        List<Long> quotatiionIdList = quotationVOS.stream().map(QuotationVO::getId)
            .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(quotationNoList) && queryBO.getIsGroupBy()) {
            QuotationQueryBO quotationQueryBO = new QuotationQueryBO();
            quotationQueryBO.setQuotationNoList(quotationNoList);
            quotationQueryBO.setExcludeQuotationIdList(quotatiionIdList);
            quotationQueryBO.setIsGroupBy(false);
            List<QuotationVO> childrenList = baseMapper.selectTqQuotationList(quotationQueryBO);
            if (CollUtil.isNotEmpty(childrenList)) {
                Map<String, List<QuotationVO>> childrenMap = childrenList.stream()
                    .collect(Collectors.groupingBy(QuotationVO::getQuotationNo));
                for (QuotationVO quotationVO : quotationVOS) {
                    quotationVO.setChildren(childrenMap.getOrDefault(quotationVO.getQuotationNo(),
                        Collections.emptyList()));
                }
            }
        }

        Map<Long, Flow> flowMap = flowService.getFlowMap(quotatiionIdList, QUOTATION);
        quotationVOS.forEach(quotationVO -> {
            quotationVO.setFlow(flowMap.get(quotationVO.getId()));
        });

        return quotationVOS;
    }

    /**
     * 新增【请填写功能名称】
     *
     * @param quotationAddBO 【请填写功能名称】
     * @return 结果
     */
    @Override
    @Transactional
    public void insertTqQuotation(QuotationAddBO quotationAddBO) {
        // 报价
        TqQuotation tqQuotation = new TqQuotation();
        tqQuotation.setQuotationNo(redisCache.generateSerialNumber(SerialNumberPrefix.BJ.getPrefix()));
        tqQuotation.setVersion(1L);
        tqQuotation.setAgentId(quotationAddBO.getAgentId());
        tqQuotation.setProjectId(quotationAddBO.getProjectId());
        tqQuotation.setCurrencyId(quotationAddBO.getCurrencyId());
        tqQuotation.setSubmitTime(new Date());
        // 数据权限字符
        tqQuotation.setPermissionChar("default");
        tqQuotation.setQuotationStatus(quotationAddBO.getQuotationStatus());
        tqQuotation.setDelFlag(DelFlagEnum.NORMAL.getValue());
        tqQuotation.setCreateBy(SecurityUtils.getStrUserId());
        tqQuotation.setCreateTime(DateUtils.getNowDate());
        tqQuotation.setUpdateBy(SecurityUtils.getStrUserId());
        tqQuotation.setUpdateTime(DateUtils.getNowDate());
        // 区域ID
        List<Long> areaIdList = baseMapper.getAreaIdByProjectId(quotationAddBO.getProjectId());
        if (CollUtil.isNotEmpty(areaIdList)) {
            tqQuotation.setAreaId(areaIdList.get(0));
        } else {
            throw new ServiceException(MessageUtils.message("quotation.unknown.area"));
        }

        baseMapper.insertTqQuotation(tqQuotation);
        Long quotationId = tqQuotation.getId();
        log.info("报价id [{}]", quotationId);

        insertSpecificationParam(quotationAddBO, quotationId);
        // 技术评审中时，启动审批流程（技术评审）
        if (QuotationStatusEnum.REVIEWING.getCode().equals(quotationAddBO.getQuotationStatus())) {
            flowService.generateTasks(
                new TaskGenerateParams(QUOTATION, tqQuotation, SecurityUtils.getUserId(),
                    tqQuotation.getQuotationNo()));
        }
    }

    // 新增电梯规则 和 参数
    private void insertSpecificationParam(QuotationAddBO quotationAddBO, Long quotationId) {
        BigDecimal quotationBasicPrice = BigDecimal.ZERO;
        BigDecimal quotationOptionalPrice = BigDecimal.ZERO;
        for (ElevatorAddBO elevator : quotationAddBO.getElevatorList()) {
            TqSpecification tqSpecification = new TqSpecification();
            tqSpecification.setQuotationId(quotationId);
            tqSpecification.setElevatorModelId(elevator.getElevatorModelId());
            tqSpecification.setElevatorNumber(elevator.getElevatorNumber());
            tqSpecification.setSpecification(elevator.getSpecification());
            tqSpecification.setQuotationStatus(quotationAddBO.getQuotationStatus());
            tqSpecification.setSystemCheckResult(SystemCheckResultEnum.OFF_STANDARD.getCode());
            tqSpecification.setDelFlag(DelFlagEnum.NORMAL.getValue());
            tqSpecification.setCreateBy(SecurityUtils.getStrUserId());
            if (Objects.nonNull(elevator.getCreateTime())) {
                tqSpecification.setCreateTime(elevator.getCreateTime());
            } else {
                tqSpecification.setCreateTime(DateUtils.getNowDate());
            }
            tqSpecification.setUpdateBy(SecurityUtils.getStrUserId());
            tqSpecification.setUpdateTime(DateUtils.getNowDate());
            // 计算电梯基础价格
            // Long basicPrice = calculateBasicPrice(elevator);
            // tqSpecification.setBasicPrice(BigDecimal.valueOf(basicPrice));
            tqSpecification.setBasicPrice(BigDecimal.valueOf(1000L));
            tqSpecification.setOptionalPrice(new BigDecimal("10000"));
            tqSpecification.setPrice(new BigDecimal("11000"));
            tqSpecificationMapper.insertTqSpecification(tqSpecification);
            // 统计报价的基础价格 选配价格
            quotationBasicPrice = quotationBasicPrice.add(
                tqSpecification.getBasicPrice().multiply(BigDecimal.valueOf(tqSpecification.getElevatorNumber())));
            quotationOptionalPrice = quotationOptionalPrice.add(
                tqSpecification.getOptionalPrice().multiply(BigDecimal.valueOf(tqSpecification.getElevatorNumber())));

            Long specificationId = tqSpecification.getId();
            log.info("规格id [{}]", specificationId);
            // TODO: 2024/5/22 价格明细假数据
            // 价格明细
            List<TqPriceDetail> priceDetailList = getPriceDetail(specificationId);
            priceDetailService.saveBatch(priceDetailList);

            // 非标记录表
            List<NonStandardAddBO> nonStandardList = elevator.getNonStandardList();
            if (CollUtil.isNotEmpty(nonStandardList)) {
                for (NonStandardAddBO nonStandardAddBO : nonStandardList) {
                    TqSpecificationNonStandard tqSpecificationNonStandard = new TqSpecificationNonStandard();
                    tqSpecificationNonStandard.setSpecificationId(specificationId);
                    tqSpecificationNonStandard.setNonStandardDesc(nonStandardAddBO.getNonStandardDesc());
                    tqSpecificationNonStandard.setSystemCheckResult(SystemCheckResultEnum.OFF_STANDARD.getCode());
                    tqSpecificationNonStandard.setDelFlag(DelFlagEnum.NORMAL.getValue());
                    tqSpecificationNonStandard.setCreateBy(SecurityUtils.getStrUserId());
                    tqSpecificationNonStandard.setCreateTime(DateUtils.getNowDate());
                    tqSpecificationNonStandard.setUpdateBy(SecurityUtils.getStrUserId());
                    tqSpecificationNonStandard.setUpdateTime(DateUtils.getNowDate());
                    tqSpecificationNonStandardMapper.insertTqSpecificationNonStandard(tqSpecificationNonStandard);
                    // 上传文件
                    List<DescFileAddBO> fileList = nonStandardAddBO.getFileList();
                    if (CollUtil.isNotEmpty(fileList)) {
                        List<TbFile> tbFileList = new ArrayList<>();
                        for (DescFileAddBO descFileAddBO : fileList) {
                            TbFile tbFile = new TbFile();
                            tbFile.setBusinessId(tqSpecificationNonStandard.getId());
                            tbFile.setBusinessType(FileBuzType.NON_STANDARD_DESC.getType());
                            tbFile.setRealFileName(descFileAddBO.getRealFileName());
                            tbFile.setServerFileName(descFileAddBO.getServerFileName());
                            tbFile.setFilePath(descFileAddBO.getFilePath());
                            tbFile.setDelFlag(DelFlagEnum.NORMAL.getValue());
                            tbFile.setCreateTime(DateUtils.getNowDate());
                            tbFile.setCreateBy(SecurityUtils.getStrUserId());
                            tbFile.setUpdateTime(DateUtils.getNowDate());
                            tbFile.setUpdateBy(SecurityUtils.getStrUserId());
                            tbFileList.add(tbFile);
                        }
                        tbFileService.saveBatch(tbFileList);
                    }
                }
            }

            // 过滤出来普通参数
            List<ElevatorParamAddBO> normalParamList = elevator.getParamList().stream()
                .filter(item -> ParamTypeEnum.NORMAL.getCode().equals(item.getParamType())).collect(
                    Collectors.toList());
            for (ElevatorParamAddBO paramAddBO : normalParamList) {
                TqSpecificationDetail tqSpecificationDetail = new TqSpecificationDetail();
                tqSpecificationDetail.setSpecificationId(specificationId);
                tqSpecificationDetail.setParaCode(paramAddBO.getParaCode());
                tqSpecificationDetail.setParaValue(paramAddBO.getParaValue());
                tqSpecificationDetail.setParaCategory(paramAddBO.getParaCategory());
                tqSpecificationDetail.setDelFlag(DelFlagEnum.NORMAL.getValue());
                tqSpecificationDetail.setCreateBy(SecurityUtils.getStrUserId());
                tqSpecificationDetail.setCreateTime(DateUtils.getNowDate());
                tqSpecificationDetail.setUpdateBy(SecurityUtils.getStrUserId());
                tqSpecificationDetail.setUpdateTime(DateUtils.getNowDate());
                iTqSpecificationDetailService.insertTqSpecificationDetail(tqSpecificationDetail);
            }
            // 过滤参数包参数
            List<ElevatorParamAddBO> parabarParamList = elevator.getParamList().stream()
                .filter(item -> ParamTypeEnum.BAR_PARAM.getCode().equals(item.getParamType())).collect(
                    Collectors.toList());
            for (ElevatorParamAddBO paramAddBO : parabarParamList) {
                TqSpecificationDetail tqSpecificationDetail = new TqSpecificationDetail();
                tqSpecificationDetail.setSpecificationId(specificationId);
                tqSpecificationDetail.setParaCode(paramAddBO.getParaCode());
                tqSpecificationDetail.setParaValue(paramAddBO.getParaValue());
                tqSpecificationDetail.setParabarId(paramAddBO.getParabarId());
                tqSpecificationDetail.setParabarDetailId(paramAddBO.getParabarDetailId());
                tqSpecificationDetail.setParaCategory(paramAddBO.getParaCategory());
                tqSpecificationDetail.setDelFlag(DelFlagEnum.NORMAL.getValue());
                tqSpecificationDetail.setCreateBy(SecurityUtils.getStrUserId());
                tqSpecificationDetail.setCreateTime(DateUtils.getNowDate());
                tqSpecificationDetail.setUpdateBy(SecurityUtils.getStrUserId());
                tqSpecificationDetail.setUpdateTime(DateUtils.getNowDate());
                iTqSpecificationDetailService.insertTqSpecificationDetail(tqSpecificationDetail);
            }
        }
        // 根据规格更新价格
        BigDecimal quotationPrice = quotationBasicPrice.add(quotationOptionalPrice);
        this.update(Wrappers.<TqQuotation>lambdaUpdate()
            .eq(TqQuotation::getId, quotationId)
            .set(TqQuotation::getBasicPrice, quotationBasicPrice)
            .set(TqQuotation::getOptionalPrice, quotationOptionalPrice)
            .set(TqQuotation::getPrice, quotationPrice)
        );
    }

    private List<TqPriceDetail> getPriceDetail(Long specificationId) {
        List<TqPriceDetail> tqPriceDetailList = new ArrayList<>();
        TqPriceDetail tqPriceDetail = new TqPriceDetail();
        tqPriceDetail.setSpecificationId(specificationId);
        tqPriceDetail.setMarkupKey("jiajiabianma1");
        tqPriceDetail.setMarkupName("加价名称1");
        tqPriceDetail.setRelatedParaInfo("额定载重：630KG 额定速度：1.73m/s");
        tqPriceDetail.setQuantity(3L);
        tqPriceDetail.setUnit("个");
        tqPriceDetail.setPrice(new BigDecimal("1000"));
        tqPriceDetail.setTotal(new BigDecimal("3000"));
        tqPriceDetail.setSystemCheckResult("00");
        tqPriceDetail.setDelFlag(DelFlagEnum.NORMAL.getValue());
        tqPriceDetail.setCreateBy(SecurityUtils.getStrUserId());
        tqPriceDetail.setCreateTime(DateUtils.getNowDate());
        tqPriceDetail.setUpdateBy(SecurityUtils.getStrUserId());
        tqPriceDetail.setUpdateTime(DateUtils.getNowDate());
        tqPriceDetailList.add(tqPriceDetail);

        TqPriceDetail tqPriceDetail11 = new TqPriceDetail();
        tqPriceDetail11.setSpecificationId(specificationId);
        tqPriceDetail11.setMarkupKey("jiajiabianma2");
        tqPriceDetail11.setMarkupName("加价名称2");
        tqPriceDetail11.setRelatedParaInfo("较壁材质：XXXXXXXXXXX");
        tqPriceDetail11.setQuantity(10L);
        tqPriceDetail11.setUnit("台");
        tqPriceDetail11.setSystemCheckResult("01");
        tqPriceDetail11.setNonStandardReason("系统不存在");
        tqPriceDetail11.setDelFlag(DelFlagEnum.NORMAL.getValue());
        tqPriceDetail11.setCreateBy(SecurityUtils.getStrUserId());
        tqPriceDetail11.setCreateTime(DateUtils.getNowDate());
        tqPriceDetail11.setUpdateBy(SecurityUtils.getStrUserId());
        tqPriceDetail11.setUpdateTime(DateUtils.getNowDate());
        tqPriceDetailList.add(tqPriceDetail11);

        return tqPriceDetailList;
    }

    private Long calculateBasicPrice(ElevatorAddBO elevator) {
        Long basicPrice;
        Map<String, String> paramMap = new HashMap<>();
        elevator.getParamList().forEach(item -> {
            paramMap.put(item.getParaCode(), item.getParaValue());
        });
        paramMap.put(ElevatorParamCodeConstants.RATED_LOAD_CAPACITY, "2500");
        paramMap.put(ElevatorParamCodeConstants.RATED_SPEED, "1.75");
        paramMap.put(ElevatorParamCodeConstants.STANDARD_DOOR_WIDTH, "1200");
        paramMap.put(ElevatorParamCodeConstants.STANDARD_DOOR_HEIGHT, "2100");
        paramMap.put(ElevatorParamCodeConstants.MAX_LIFTING_HEIGHT, "80");
        paramMap.put(ElevatorParamCodeConstants.FLOORS, "7");

        LambdaQueryWrapper<TpAreaBasicPrice> wrapper = Wrappers.<TpAreaBasicPrice>lambdaQuery()
            .eq(TpAreaBasicPrice::getElevatorModelId, elevator.getElevatorModelId())
            // 额定载重
            .eq(TpAreaBasicPrice::getRatedLoadCapacity,
                Long.valueOf(paramMap.get(ElevatorParamCodeConstants.RATED_LOAD_CAPACITY)))
            // 额定速度
            .eq(TpAreaBasicPrice::getRatedSpeed,
                new BigDecimal(paramMap.get(ElevatorParamCodeConstants.RATED_SPEED)))
            // 标准开门宽度
            .eq(TpAreaBasicPrice::getStandardDoorWidth,
                Long.valueOf(paramMap.get(ElevatorParamCodeConstants.STANDARD_DOOR_WIDTH)))
            // 标准开门高度
            .eq(TpAreaBasicPrice::getStandardDoorHeight,
                Long.valueOf(paramMap.get(ElevatorParamCodeConstants.STANDARD_DOOR_HEIGHT)))
            // 最大提升高度
            .eq(TpAreaBasicPrice::getMaxLiftingHeight,
                Long.valueOf(paramMap.get(ElevatorParamCodeConstants.MAX_LIFTING_HEIGHT)))
            // 删除标记
            .eq(TpAreaBasicPrice::getDelFlag, DelFlagEnum.NORMAL.getValue());
        List<TpAreaBasicPrice> list = iTpAreaBasicPriceService.list(wrapper);
        if (CollUtil.isEmpty(list)) {
            // 基础价格不能为空
            throw new ServiceException(MessageUtils.message("area.basic.price.is.empty"));
        } else {
            TpAreaBasicPrice tpAreaBasicPrice = list.get(0);
            // 根据层数加/减价
            basicPrice = tpAreaBasicPrice.getBasicPrice();
            Long actualFloors = Long.valueOf(paramMap.get(ElevatorParamCodeConstants.FLOORS));
            Long diffFloors = actualFloors - tpAreaBasicPrice.getStandardFloors();
            if (diffFloors > 0) {
                basicPrice += tpAreaBasicPrice.getAddOnefloorPrice() * diffFloors;
            } else if (diffFloors < 0) {
                basicPrice += tpAreaBasicPrice.getSubtractOnefloorPrice() * diffFloors;
            }
        }
        return basicPrice;
    }

    /**
     * 修改【请填写功能名称】
     *
     * @param quotationAddBO 【请填写功能名称】
     * @return 结果
     */
    @Override
    @Transactional
    public void updateTqQuotation(QuotationAddBO quotationAddBO) {
        Long quotationId = quotationAddBO.getQuotationId();
        // 报价更新状态
        TqQuotation tqQuotation = this.getById(quotationId);
        this.update(Wrappers.<TqQuotation>lambdaUpdate()
            .eq(TqQuotation::getId, quotationId)
            .set(TqQuotation::getQuotationStatus, quotationAddBO.getQuotationStatus()));
        // 电梯规格删除
        List<TqSpecification> tqSpecifications = tqSpecificationMapper.selectList(
            Wrappers.<TqSpecification>lambdaQuery()
                .eq(TqSpecification::getQuotationId, quotationId)
                .eq(TqSpecification::getDelFlag, DelFlagEnum.NORMAL.getValue()));
        List<Long> specificationIdList = tqSpecifications.stream().map(TqSpecification::getId)
            .collect(Collectors.toList());
        tqSpecificationMapper.deleteByQuotationId(quotationAddBO.getQuotationId());
        // 删除梯形参数,非标描述
        if (CollUtil.isNotEmpty(specificationIdList)) {
            // 梯形参数
            iTqSpecificationDetailService.update(Wrappers.<TqSpecificationDetail>lambdaUpdate()
                .in(TqSpecificationDetail::getSpecificationId, specificationIdList)
                .set(TqSpecificationDetail::getDelFlag, DelFlagEnum.DELETED.getValue()));
            // 非标描述
            tqSpecificationNonStandardMapper.update(null,
                Wrappers.<TqSpecificationNonStandard>lambdaUpdate()
                    .in(TqSpecificationNonStandard::getSpecificationId, specificationIdList)
                    .set(TqSpecificationNonStandard::getDelFlag, DelFlagEnum.DELETED.getValue()));
        }
        insertSpecificationParam(quotationAddBO, quotationId);
        // 技术评审中时，启动审批流程（技术评审）
        if (QuotationStatusEnum.REVIEWING.getCode().equals(quotationAddBO.getQuotationStatus())) {
            flowService.generateTasks(
                new TaskGenerateParams(QUOTATION, tqQuotation, SecurityUtils.getUserId(),
                    tqQuotation.getQuotationNo()));
        }
    }

    /**
     * 批量删除【请填写功能名称】
     *
     * @param ids 需要删除的【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteTqQuotationByIds(Long[] ids) {
        return baseMapper.deleteTqQuotationByIds(ids);
    }

    /**
     * 删除【请填写功能名称】信息
     *
     * @param id 【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteTqQuotationById(Long id) {
        return baseMapper.deleteTqQuotationById(id);
    }

    @Override
    @Transactional
    public void copyVersions(QuotationCopyBO copyBO) {
        List<TqQuotation> tqQuotations = baseMapper.selectBatchIds(copyBO.getIds());
        // 获取报价编号的最大版本号
        List<QuotationVersionVO> maxVersionById = baseMapper.getMaxVersionById(copyBO.getIds());
        Map<String, Long> quotationVersionMap = maxVersionById.stream()
            .collect(Collectors.toMap(QuotationVersionVO::getQuotationNo, QuotationVersionVO::getVersion, (a, b) -> a));
        // 报价复制版本
        for (TqQuotation tqQuotation : tqQuotations) {
            // 复制前报价ID
            Long oldQuotationId = tqQuotation.getId();
            // 复制报价
            tqQuotation.setVersion(quotationVersionMap.getOrDefault(tqQuotation.getQuotationNo(), 1L) + 1L);
            tqQuotation.setQuotationStatus(QuotationStatusEnum.DRAFT.getCode());
            tqQuotation.setPrice(null);
            tqQuotation.setFreightPrice(null);
            tqQuotation.setBasicPrice(null);
            tqQuotation.setOptionalPrice(null);
            tqQuotation.setCreateTime(DateUtils.getNowDate());
            tqQuotation.setCreateBy(SecurityUtils.getStrUserId());
            tqQuotation.setUpdateTime(DateUtils.getNowDate());
            tqQuotation.setUpdateBy(SecurityUtils.getStrUserId());
            baseMapper.insertTqQuotation(tqQuotation);
            // 复制后报价ID
            Long newQuotationId = tqQuotation.getId();
            // 复制电梯规格
            List<TqSpecification> tqSpecifications = tqSpecificationMapper.selectList(
                Wrappers.<TqSpecification>lambdaQuery()
                    .eq(TqSpecification::getQuotationId, oldQuotationId)
                    .eq(TqSpecification::getDelFlag, DelFlagEnum.NORMAL.getValue())
            );
            tqSpecifications.forEach(item -> {
                item.setQuotationId(newQuotationId);
                item.setQuotationStatus(QuotationStatusEnum.DRAFT.getCode());
                item.setCreateTime(DateUtils.getNowDate());
                item.setCreateBy(SecurityUtils.getStrUserId());
                item.setUpdateTime(DateUtils.getNowDate());
                item.setUpdateBy(SecurityUtils.getStrUserId());
            });
            // 电梯规格复制版本
            for (TqSpecification tqSpecification : tqSpecifications) {
                // 复制前规格ID
                Long oldSpecificationId = tqSpecification.getId();
                tqSpecificationMapper.insertTqSpecification(tqSpecification);
                // 复制后规格ID
                Long newSpecificationId = tqSpecification.getId();
                // 复制电梯规格参数
                List<TqSpecificationDetail> paramDetail = iTqSpecificationDetailService.list(
                    Wrappers.<TqSpecificationDetail>lambdaQuery()
                        .eq(TqSpecificationDetail::getSpecificationId, oldSpecificationId)
                        .eq(TqSpecificationDetail::getDelFlag, DelFlagEnum.NORMAL.getValue())
                );
                // 电梯规格参数复制版本
                paramDetail.forEach(item -> {
                    item.setSpecificationId(newSpecificationId);
                    item.setId(null);
                });
                iTqSpecificationDetailService.saveBatch(paramDetail);
                // 复制非标描述
                List<TqSpecificationNonStandard> nonStandardList = tqSpecificationNonStandardMapper.selectList(
                    Wrappers.<TqSpecificationNonStandard>lambdaQuery()
                        .eq(TqSpecificationNonStandard::getSpecificationId, oldSpecificationId)
                        .eq(TqSpecificationNonStandard::getDelFlag, DelFlagEnum.NORMAL.getValue())
                );
                for (TqSpecificationNonStandard tqSpecificationNonStandard : nonStandardList) {
                    // 复制前非标描述ID
                    Long oldNonStandardId = tqSpecificationNonStandard.getId();
                    tqSpecificationNonStandard.setSpecificationId(newSpecificationId);
                    tqSpecificationNonStandard.setBuyerPrice(null);
                    tqSpecificationNonStandard.setFloatPercent(null);
                    tqSpecificationNonStandard.setTreasurerPrice(null);
                    tqSpecificationNonStandard.setPrice(null);
                    tqSpecificationNonStandard.setTotal(null);
                    tqSpecificationNonStandard.setSpecificationId(newSpecificationId);
                    tqSpecificationNonStandard.setCreateTime(DateUtils.getNowDate());
                    tqSpecificationNonStandard.setCreateBy(SecurityUtils.getStrUserId());
                    tqSpecificationNonStandard.setUpdateTime(DateUtils.getNowDate());
                    tqSpecificationNonStandard.setUpdateBy(SecurityUtils.getStrUserId());
                    tqSpecificationNonStandardMapper.insertTqSpecificationNonStandard(tqSpecificationNonStandard);
                    // 复制后非标描述ID
                    Long newNonStandardId = tqSpecificationNonStandard.getId();
                    List<TbFile> tbFileList = tbFileService.list(Wrappers.<TbFile>lambdaQuery()
                        .eq(TbFile::getBusinessType, FileBuzType.NON_STANDARD_DESC.getType())
                        .eq(TbFile::getDelFlag, DelFlagEnum.NORMAL.getValue())
                        .eq(TbFile::getBusinessId, oldNonStandardId)
                    );
                    if (CollUtil.isNotEmpty(tbFileList)) {
                        tbFileList.forEach(item -> {
                            item.setId(null);
                            item.setBusinessId(newNonStandardId);
                        });
                        tbFileService.saveBatch(tbFileList);
                    }
                }
            }
        }
    }

    public List<QuotationVO> listByProjectId(Long projectId) {
        return baseMapper.listByProjectId(projectId);
    }

    @Override
    public List<QuotationExportVO> listExportVO(QuotationQueryBO queryBO) {
        queryBO.setIsGroupBy(false);
        List<QuotationExportVO> quotationExportVOList = new ArrayList<>();
        List<QuotationVO> quotationVOS = this.selectTqQuotationList(queryBO);
        Map<String, String> countryMap = getCountryMap(tbCountryService.getAllNationList());
        if (CollUtil.isNotEmpty(quotationVOS)) {
            for (QuotationVO item : quotationVOS) {
                QuotationExportVO quotationExportVO = new QuotationExportVO();
                quotationExportVO.setQuotationNo(item.getQuotationNo());
                quotationExportVO.setVersion(item.getVersion());
                quotationExportVO.setProjectName(item.getProjectName());
                quotationExportVO.setTypeName(DictUtils.getInternationalDictLabel("project_type", item.getType()));
                quotationExportVO.setSegmentedMarketName(
                    DictUtils.getInternationalDictLabel("project_market", item.getSegmentedMarket()));
                quotationExportVO.setCountry(countryMap.get(item.getCountryId()));
                quotationExportVO.setCity(item.getCity());
                quotationExportVO.setCurrencyName(
                    DictUtils.getInternationalDictLabel("currency_type", item.getCurrencyId().toString()));
                quotationExportVO.setElevatorMode(item.getElevatorModel());
                quotationExportVO.setNickName(item.getNickName());
                quotationExportVO.setFinalPrice(item.getFinalPrice());
                quotationExportVO.setAdditionalCost(item.getAdditionalFees());
                quotationExportVO.setSubmitTime(item.getSubmitTime());
                quotationExportVO.setQuotationStatusName(
                    DictUtils.getInternationalDictLabel("quotation_status", item.getQuotationStatus()));
                quotationExportVOList.add(quotationExportVO);
            }
        }
        return quotationExportVOList;
    }

    private Map<String, String> getCountryMap(List<TbCountry> allNationList) {
        Map<String, String> countryMap = new HashMap<>();
        String country = LocaleContextHolder.getLocale().getCountry();
        if (CollUtil.isNotEmpty(allNationList)) {
            for (TbCountry item : allNationList) {
                String countryName;
                switch (country) {
                    case Constants.US:
                        countryName = item.getCountryNameUS();
                        break;
                    case Constants.ES:
                        countryName = item.getCountryNameES();
                        break;
                    case Constants.RU:
                        countryName = item.getCountryNameRU();
                        break;
                    default:
                        countryName = item.getCountryName();
                        break;

                }
                countryMap.put(item.getCountryId().toString(), countryName);
            }
        }
        return countryMap;
    }

    @Override
    public void changeQuotationStatus(FlowAuditParam auditParam) {
        if (Objects.isNull(auditParam.getCurrentStatus()) ||
            AuditStatusEnum.INIT.getValue().equals(auditParam.getCurrentStatus())) {
            log.info("[{}] 未知节点状态", auditParam.getBusinessId());
            return;
        }
        String quotationStatus;
        JSONObject reviewResultJson = Optional.ofNullable(auditParam.getBusinessObj())
            .map(a -> a.getJSONObject("reviewResultJson")).orElse(new JSONObject());
        // 报价当前状态
        AuditStatusEnum auditStatusEnum = AuditStatusEnum.from(auditParam.getCurrentStatus());
        switch (auditStatusEnum) {
            // 技术评审中
            case TECH_REVIEW:
                // 技术评审通过
                for (Map.Entry<String, Object> entry : reviewResultJson.entrySet()) {
                    JSONArray from = JSONArray.from(entry.getValue());
                    for (int i = 0; i < from.size(); i++) {
                        JSONObject jsonObject = from.getJSONObject(i);
                        String solution = jsonObject.getString("solution");
                        Long id = jsonObject.getLong("id");
                        if (StringUtils.isNotBlank(solution)) {
                            if (Boolean.TRUE.equals(jsonObject.getBoolean("nonStandardDescFlag"))) {
                                tqSpecificationNonStandardMapper.update(null,
                                    Wrappers.<TqSpecificationNonStandard>lambdaUpdate()
                                        .eq(TqSpecificationNonStandard::getId, id)
                                        .set(TqSpecificationNonStandard::getSolution, solution)
                                );
                            } else {
                                priceDetailService.update(
                                    Wrappers.<TqPriceDetail>lambdaUpdate()
                                        .eq(TqPriceDetail::getId, id)
                                        .set(TqPriceDetail::getSolution, solution));
                            }
                        }
                    }
                }
                if (auditParam.isPass()) {
                    quotationStatus = QuotationStatusEnum.BUYER.getCode();
                } else {
                    quotationStatus = QuotationStatusEnum.REVIEW_REJECT.getCode();
                }
                // 技术评审通过
                // 更新报价
                this.update(Wrappers.<TqQuotation>lambdaUpdate()
                    .eq(TqQuotation::getId, auditParam.getBusinessId())
                    .set(TqQuotation::getQuotationStatus, quotationStatus));
                // 更新电梯规格
                tqSpecificationMapper.update(null, Wrappers.<TqSpecification>lambdaUpdate()
                    .eq(TqSpecification::getQuotationId, auditParam.getBusinessId())
                    .eq(TqSpecification::getSystemCheckResult, SystemCheckResultEnum.OFF_STANDARD.getCode())
                    .set(TqSpecification::getQuotationStatus, quotationStatus)
                );
                break;
            // 采购报价中
            case BUYER_INQUIRY:
                for (Map.Entry<String, Object> entry : reviewResultJson.entrySet()) {
                    JSONArray from = JSONArray.from(entry.getValue());
                    for (int i = 0; i < from.size(); i++) {
                        JSONObject jsonObject = from.getJSONObject(i);
                        String buyerPrice = jsonObject.getString("buyerPrice");
                        String quantity = jsonObject.getString("quantity");
                        Long id = jsonObject.getLong("id");
                        if (StringUtils.isNotBlank(buyerPrice)) {
                            if (StringUtils.isBlank(quantity)) {
                                quantity = BigDecimal.ONE.toPlainString();
                            }
                            BigDecimal total = new BigDecimal(quantity)
                                .multiply(new BigDecimal(buyerPrice))
                                .setScale(2, RoundingMode.HALF_UP);
                            if (Boolean.TRUE.equals(jsonObject.getBoolean("nonStandardDescFlag"))) {
                                tqSpecificationNonStandardMapper.update(null,
                                    Wrappers.<TqSpecificationNonStandard>lambdaUpdate()
                                        .eq(TqSpecificationNonStandard::getId, id)
                                        .set(TqSpecificationNonStandard::getBuyerPrice, buyerPrice)
                                        .set(TqSpecificationNonStandard::getTotal, total)
                                );
                            } else {
                                priceDetailService.update(Wrappers.<TqPriceDetail>lambdaUpdate()
                                    .eq(TqPriceDetail::getId, id)
                                    .set(TqPriceDetail::getBuyerPrice, buyerPrice)
                                    .set(TqPriceDetail::getTotal, total));
                            }
                        }
                    }
                }
                quotationStatus = QuotationStatusEnum.TREASURE.getCode();
                // 更新报价
                this.update(Wrappers.<TqQuotation>lambdaUpdate()
                    .eq(TqQuotation::getId, auditParam.getBusinessId())
                    .set(TqQuotation::getQuotationStatus, quotationStatus));
                // 更新电梯规格
                tqSpecificationMapper.update(null, Wrappers.<TqSpecification>lambdaUpdate()
                    .eq(TqSpecification::getQuotationId, auditParam.getBusinessId())
                    .eq(TqSpecification::getSystemCheckResult, SystemCheckResultEnum.OFF_STANDARD.getCode())
                    .set(TqSpecification::getQuotationStatus, quotationStatus)
                );
                break;
            // 财务报价中
            case TREASURE_INQUIRY:
                // 电梯规格的非标选配价格总和MAP    KEY:specificationId  VALUE:非标选配价格总和
                Map<Long, BigDecimal> specificationPriceMap = new HashMap<>();
                // 报价的非标选配价格总和
                BigDecimal quotationOptionalPrice = BigDecimal.ZERO;
                for (Map.Entry<String, Object> entry : reviewResultJson.entrySet()) {
                    JSONArray from = JSONArray.from(entry.getValue());
                    for (int i = 0; i < from.size(); i++) {
                        JSONObject jsonObject = from.getJSONObject(i);
                        String buyerPrice = jsonObject.getString("buyerPrice");
                        Long specificationId = jsonObject.getLong("specificationId");
                        String floatPercent = jsonObject.getString("floatPercent");
                        String quantity = jsonObject.getString("quantity");
                        String elevatorNumber = jsonObject.getString("elevatorNumber");
                        Long id = jsonObject.getLong("id");
                        if (StringUtils.isNotBlank(buyerPrice)) {
                            BigDecimal treasurePrice = new BigDecimal(buyerPrice).multiply(
                                (new BigDecimal(floatPercent).add(BigDecimal.valueOf(100L)))
                                    .divide(BigDecimal.valueOf(100L), 2, RoundingMode.HALF_UP)
                            ).setScale(2, RoundingMode.HALF_UP);

                            if (StringUtils.isBlank(quantity)) {
                                quantity = BigDecimal.ONE.toPlainString();
                            }

                            BigDecimal total = new BigDecimal(quantity)
                                .multiply(treasurePrice)
                                .setScale(2, RoundingMode.HALF_UP);

                            if (Boolean.TRUE.equals(jsonObject.getBoolean("nonStandardDescFlag"))) {
                                tqSpecificationNonStandardMapper.update(null,
                                    Wrappers.<TqSpecificationNonStandard>lambdaUpdate()
                                        .eq(TqSpecificationNonStandard::getId, id)
                                        .set(TqSpecificationNonStandard::getFloatPercent, floatPercent)
                                        .set(TqSpecificationNonStandard::getTreasurerPrice, treasurePrice)
                                        .set(TqSpecificationNonStandard::getPrice, treasurePrice)
                                        .set(TqSpecificationNonStandard::getTotal, total));
                            } else {
                                priceDetailService.update(Wrappers.<TqPriceDetail>lambdaUpdate()
                                    .eq(TqPriceDetail::getId, id)
                                    .set(TqPriceDetail::getFloatPercent, floatPercent)
                                    .set(TqPriceDetail::getTreasurerPrice, treasurePrice)
                                    .set(TqPriceDetail::getPrice, treasurePrice)
                                    .set(TqPriceDetail::getTotal, total));
                            }
                            quotationOptionalPrice = quotationOptionalPrice.add(
                                total.multiply(new BigDecimal(elevatorNumber)));
                            BigDecimal oneTotal = specificationPriceMap.getOrDefault(specificationId, BigDecimal.ZERO);
                            specificationPriceMap.put(specificationId, oneTotal.add(total));
                        }
                    }
                }
                // 更新电梯规格状态 及 选配价格
                for (Map.Entry<Long, BigDecimal> entry : specificationPriceMap.entrySet()) {
                    tqSpecificationMapper.updateAuditOptionalPrice(entry.getKey(), entry.getValue());
                }
                // 更新报价状态 及选配价格
                this.baseMapper.updateAuditOptionalPrice(auditParam.getBusinessId(), quotationOptionalPrice);
                break;
            // 销售确认
            case SALES_CONFIRM:
                quotationStatus = QuotationStatusEnum.ALREADY_BID.getCode();
                // 更新报价
                this.update(Wrappers.<TqQuotation>lambdaUpdate()
                    .eq(TqQuotation::getId, auditParam.getBusinessId())
                    .set(TqQuotation::getQuotationStatus, quotationStatus));
                // 更新电梯规格
                tqSpecificationMapper.update(null, Wrappers.<TqSpecification>lambdaUpdate()
                    .eq(TqSpecification::getQuotationId, auditParam.getBusinessId())
                    .eq(TqSpecification::getSystemCheckResult, SystemCheckResultEnum.OFF_STANDARD.getCode())
                    .set(TqSpecification::getQuotationStatus, quotationStatus));
                break;
            default:
                log.info("[报价] 未知状态 [{}]", auditParam.getCurrentStatus());
        }
    }

    @Override
    public void changeBargainStatus(FlowAuditParam auditParam) {
        if (AuditStatusEnum.INIT.getValue().equals(auditParam.getCurrentStatus())) {
            log.info("[{}] 未知节点状态", auditParam.getBusinessId());
            return;
        }
        Long bargainId = Optional.ofNullable(auditParam.getBusinessObj())
            .map(a -> a.getLong("bargainId")).orElse(0L);
        Long quotationId = Optional.ofNullable(auditParam.getBusinessObj())
            .map(a -> a.getLong("quotationId")).orElse(0L);
        String totalDiscountRate = Optional.ofNullable(auditParam.getBusinessObj())
            .map(a -> a.getString("discountRate")).orElse("");
        JSONArray tableList = Optional.ofNullable(auditParam.getBusinessObj())
            .map(a -> a.getJSONArray("tableList")).orElse(new JSONArray());

        // 报价当前状态
        AuditStatusEnum auditStatusEnum = AuditStatusEnum.from(auditParam.getCurrentStatus());
        NodeRoleEnum nodeRoleEnum = NodeRoleEnum.fromAuditStatusEnum(auditStatusEnum);
        TbSalesDiscount salesDiscount;
        switch (auditStatusEnum) {
            // 议价审批(销售)
            case BARGAIN_APPROVAL1:
                // 议价审批(区总)
            case BARGAIN_APPROVAL2:
                // 议价审批(销售VP)
            case BARGAIN_APPROVAL3:
                salesDiscount = getRoleDiscount(nodeRoleEnum.getRoleId());
                log.info("议价审批获取角色折扣率  [{}] 区间 [{}]  [{}]",
                    nodeRoleEnum.getName(), salesDiscount.getMinDiscount(), salesDiscount.getMaxDiscount());
                for (int i = 0; i < tableList.size(); i++) {
                    JSONObject row = tableList.getJSONObject(i);
                    Long specificationId = row.getLong("id");
                    BigDecimal basicPrice = row.getBigDecimal("basicPrice");
                    BigDecimal optionalPrice = row.getBigDecimal("optionalPrice");
                    BigDecimal discountRate = row.getBigDecimal("discountRate");
                    BigDecimal discountBasicPrice = basicPrice.multiply(
                        discountRate.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                    BigDecimal discountPrice = discountBasicPrice.add(optionalPrice);
                    // 新增议价定价表
                    TqSalespersonSetPrice tqSalespersonSetPrice = new TqSalespersonSetPrice();
                    tqSalespersonSetPrice.setBargainId(bargainId);
                    tqSalespersonSetPrice.setSpecificationId(specificationId);
                    tqSalespersonSetPrice.setBasicPrice(basicPrice);
                    tqSalespersonSetPrice.setOptionalPrice(optionalPrice);
                    tqSalespersonSetPrice.setDiscountRate(discountRate);
                    tqSalespersonSetPrice.setDiscountbasicPrice(discountBasicPrice);
                    tqSalespersonSetPrice.setDiscountPrice(discountPrice);
                    tqSalespersonSetPrice.setDelFlag(DelFlagEnum.NORMAL.getValue());
                    tqSalespersonSetPrice.setCreateBy(SecurityUtils.getStrUserId());
                    tqSalespersonSetPrice.setCreateTime(DateUtils.getNowDate());
                    tqSalespersonSetPrice.setUpdateBy(SecurityUtils.getStrUserId());
                    tqSalespersonSetPrice.setUpdateTime(DateUtils.getNowDate());
                    tqSalespersonSetPriceService.save(tqSalespersonSetPrice);
                }
                String quotationStatus = null;
                // 节点通过
                if (auditParam.isPass()) {
                    BigDecimal number = new BigDecimal(totalDiscountRate);
                    if (number.compareTo(salesDiscount.getMinDiscount()) >= 0
                        && number.compareTo(salesDiscount.getMaxDiscount()) <= 0) {
                        // 结束审批
                        this.bargainPass(quotationId);
                        quotationStatus = QuotationStatusEnum.BARGAIN_CONFIRM.getCode();
                    }
                } else {
                    // 节点驳回
                    quotationStatus = QuotationStatusEnum.BARGAIN_REJECT.getCode();

                }
                if (Objects.nonNull(quotationStatus)) {
                    // 更新报价
                    this.update(Wrappers.<TqQuotation>lambdaUpdate()
                        .eq(TqQuotation::getId, quotationId)
                        .set(TqQuotation::getQuotationStatus, quotationStatus));
                    // 更新电梯规格
                    tqSpecificationMapper.update(null, Wrappers.<TqSpecification>lambdaUpdate()
                        .eq(TqSpecification::getQuotationId, quotationId)
                        .set(TqSpecification::getQuotationStatus, quotationStatus));
                }
                break;
            // 议价审批(总经理) 101
            case BARGAIN_APPROVAL4:
                // 审批通过 且 流程结束
                if (auditParam.isPass() && auditParam.isFinish()) {
                    this.bargainPass(quotationId);
                }
                if (!auditParam.isPass()) {
                    // 驳回则追加vp审核及后续流程
                    flowService.insertCopy(auditParam,
                        Lists.newArrayList(BARGAIN_APPROVAL3.getValue(), BARGAIN_APPROVAL4.getValue()));
                }
                break;
        }
    }

    // 根据角色获取销售折扣
    private TbSalesDiscount getRoleDiscount(Long roleId) {
        List<TbSalesDiscount> list = tbSalesDiscountService.list(Wrappers.<TbSalesDiscount>lambdaQuery()
            .eq(TbSalesDiscount::getRoleId, roleId)
            .eq(TbSalesDiscount::getDelFlag, DelFlagEnum.NORMAL.getValue())
        );
        if (CollUtil.isEmpty(list)) {
            throw new ServiceException("请先设置销售折率");
        } else {
            return list.get(0);
        }
    }

    public void bargainPass(Long quotationId) {
        String quotationStatus = QuotationStatusEnum.BARGAIN_CONFIRM.getCode();
        // 更新报价
        this.update(Wrappers.<TqQuotation>lambdaUpdate()
            .eq(TqQuotation::getId, quotationId)
            .set(TqQuotation::getQuotationStatus, quotationStatus));
        // 更新电梯规格
        tqSpecificationMapper.update(null, Wrappers.<TqSpecification>lambdaUpdate()
            .eq(TqSpecification::getQuotationId, quotationId)
            .set(TqSpecification::getQuotationStatus, quotationStatus));
        FlowAuditParam param = new FlowAuditParam();
        param.setAuditFlow((long)AuditFlowEnum.BARGAIN.getValue());
        param.setBusinessId(quotationId);
        flowService.finish(param);
    }

    @Override
    public QuotationPriceVO getPriceInfo(Long quotationId) {
        QuotationPriceVO quotationPriceVO = new QuotationPriceVO();
        TqQuotation tqQuotation = this.getById(quotationId);
        // 基准价格合计
        quotationPriceVO.setBasicPrice(tqQuotation.getBasicPrice());
        // 选配价格合计
        quotationPriceVO.setOptionalPrice(tqQuotation.getOptionalPrice());
        // 价格合计
        quotationPriceVO.setPriceTotal(tqQuotation.getPrice());

        List<TqBargainPrice> list = tqBargainPriceService
            .list(Wrappers.<TqBargainPrice>lambdaQuery()
                .eq(TqBargainPrice::getQuotationId, quotationId).orderByDesc(TqBargainPrice::getId));
        if (CollUtil.isNotEmpty(list)) {
            TqBargainPrice tqBargainPrice = list.get(0);
            quotationPriceVO.setBargainId(tqBargainPrice.getId());
            // 希望价格
            quotationPriceVO.setExpectedPrice(tqBargainPrice.getBargainPrice());
            // 折率（希望价格）
            BigDecimal rate = quotationPriceVO.getExpectedPrice()
                .divide(quotationPriceVO.getPriceTotal(), 4, RoundingMode.HALF_UP);
            quotationPriceVO.setExpectedRate(rate.multiply(new BigDecimal(ONE_HUNDRED)).toPlainString());
            // 基价折率（希望价格）
            BigDecimal basicRate = (quotationPriceVO.getExpectedPrice().subtract(quotationPriceVO.getOptionalPrice()))
                .divide(quotationPriceVO.getBasicPrice(), 4, RoundingMode.HALF_UP);
            quotationPriceVO.setExpectedBasicRate(basicRate.multiply(new BigDecimal(ONE_HUNDRED)).toPlainString());
        } else {
            quotationPriceVO.setExpectedRate(ONE_HUNDRED);
            quotationPriceVO.setExpectedBasicRate(ONE_HUNDRED);
            quotationPriceVO.setExpectedPrice(quotationPriceVO.getPriceTotal());
        }
        return quotationPriceVO;
    }

    @Override
    public TbSalesDiscount getSalesDiscountByQuotationId(Long quotationId) {
        // NodeRoleEnum nodeRoleEnum = NodeRoleEnum.fromAuditStatusEnum(NodeRoleEnum.SALES1.);
        // Map<Long, Flow> flowMap = flowService.getFlowMap(Collections.singletonList(quotationId), QUOTATION);
        // Flow flow = flowMap.get(quotationId);
        // if (Objects.isNull(flow)){
        //
        // }
        return getRoleDiscount(NodeRoleEnum.SALES1.getRoleId());
    }
}
