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

import static com.ruoyi.common.constant.ElevatorParamCodeConstants.*;
import static com.ruoyi.project.business.enums.AuditFlowEnum.BARGAIN;
import static com.ruoyi.project.business.enums.AuditFlowEnum.QUOTATION;
import static com.ruoyi.project.business.service.quotation.impl.QuoteApprovalServiceImpl.ONE_HUNDRED;
import static java.util.Objects.nonNull;
import static org.apache.commons.lang3.StringUtils.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.FileBuzType;
import com.ruoyi.common.enums.SerialNumberPrefix;
import com.ruoyi.common.enums.ValueType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.office.doc.CommonDocUtils;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.redis.RedisCache;
import com.ruoyi.project.business.domain.TbCurrency;
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.TpElevatorModel;
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.TqSpecification;
import com.ruoyi.project.business.domain.TqSpecificationDetail;
import com.ruoyi.project.business.domain.TqSpecificationNonStandard;
import com.ruoyi.project.business.domain.bo.quotation.*;
import com.ruoyi.project.business.domain.*;
import com.ruoyi.project.business.domain.flow.Flow;
import com.ruoyi.project.business.domain.vo.MaterialImageVO;
import com.ruoyi.project.business.domain.vo.paramSelectItem.TpElevatorModelVo;
import com.ruoyi.project.business.domain.vo.quotation.*;
import com.ruoyi.project.business.domain.vo.selectParam.ProjectParam;
import com.ruoyi.project.business.dto.TaskGenerateParams;
import com.ruoyi.project.business.enums.*;
import com.ruoyi.project.business.mapper.*;
import com.ruoyi.project.business.mapper.quotation.TqQuotationMapper;
import com.ruoyi.project.business.mapper.quotation.TqSpecificationMapper;
import com.ruoyi.project.business.service.*;
import com.ruoyi.project.business.service.flow.IFlowService;
import com.ruoyi.project.business.service.quotation.IPriceCalcService;
import com.ruoyi.project.business.service.quotation.IQuoteApprovalService;
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.ITqSpecificationDetailService;
import com.ruoyi.project.business.service.quotation.ITqSpecificationNonStandardService;
import com.ruoyi.project.business.service.quotation.ITqSpecificationService;

import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.ruoyi.project.business.service.quotation.*;
import com.ruoyi.project.system.domain.SysDictData;
import fr.opensagres.xdocreport.document.images.FileImageProvider;
import fr.opensagres.xdocreport.template.formatter.NullImageBehaviour;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ruoyi.common.constant.ElevatorParamCodeConstants.*;
import static com.ruoyi.project.business.enums.AuditFlowEnum.BARGAIN;
import static com.ruoyi.project.business.enums.AuditFlowEnum.QUOTATION;
import static com.ruoyi.project.business.service.quotation.impl.QuoteApprovalServiceImpl.ONE_HUNDRED;
import static org.apache.commons.lang3.StringUtils.*;
import static com.ruoyi.common.utils.Tools.numberToLetter;
/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author ruoyi
 * @date 2024-05-10
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class TqQuotationServiceImpl extends ServiceImpl<TqQuotationMapper, TqQuotation> implements ITqQuotationService {

    public static final DecimalFormat formatter = new DecimalFormat("#,###");

    private final TqSpecificationMapper tqSpecificationMapper;

    private final ITqSpecificationService tqSpecificationService;

    private final TcProjectMapper tcProjectMapper;

    private final RedisCache redisCache;

    private final ITqSpecificationDetailService tqSpecificationDetailService;

    private final IFlowService flowService;

    private final IQuoteApprovalService quoteApprovalService;

    private final ITqSpecificationNonStandardService tqSpecificationNonStandardService;

    private final ITqPriceDetailService priceDetailService;

    private final ITqBargainPriceService tqBargainPriceService;

    private final ITbFileService tbFileService;

    private final ITcLeadService tcLeadService;

    private final ITpElevatorModelService tpElevatorModelService;

    private final IPriceCalcService priceCalcService;

    private final ITcAccountService tcAccountService;

    private final TbCurrencyMapper tbCurrencyMapper;

    private final TcAccountMapper tbAccountMapper;
    private final TbAgentMapper tbAgentMapper;
    private final TpParaSelectItemMapper tpParaSelectItemMapper;
    private final ITpParaLibraryService tpParaLibraryService;

    private final ITpParaSelectItemService tpParaSelectItemService;


    /**
     * 查询【请填写功能名称】
     *
     * @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.getPermissionCharIns());
        List<TcProject> tcProjects = tcProjectMapper.selectTcProjectList(tcProject);
        if (CollUtil.isNotEmpty(tcProjects)) {
            BeanUtils.copyProperties(tcProjects.get(0), quotationDetailVO, "currencyId", "updateTime", "discountFlag","createBy");
        }
        return quotationDetailVO;
    }

    /**
     * 查询【请填写功能名称】列表
     *
     * @param queryBO 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<QuotationVO> selectTqQuotationList(QuotationQueryBO queryBO) {
        SpecialCharacterEscaper.escapeSpecialCharacters(queryBO
            , QuotationQueryBO::getQuotationNo
            , QuotationQueryBO::getProjectName
            , QuotationQueryBO::getCity
            , QuotationQueryBO::getElevatorModel
            , QuotationQueryBO::getNickName
        );
        String permissionCharIns = SecurityUtils.getPermissionCharIns();
        // queryBO.setAreaIdList(tbAreaService.selectChildAreaIdsByAreaIds(SecurityUtils.getLoginUser().getAreaIdList()));
        queryBO.setPermissionChar(permissionCharIns);
        // 代理商销售经理的场合
        if (SecurityUtils.hasRole("agent_sales")) {
            queryBO.setLoginUserId(SecurityUtils.getUserId());
            queryBO.setPermission(SecurityUtils.getPermissionCharIns());
        }
        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);
            quotationQueryBO.setPermissionChar(permissionCharIns);
            // 代理商销售经理的场合
            if (SecurityUtils.hasRole("agent_sales")) {
                quotationQueryBO.setLoginUserId(SecurityUtils.getUserId());
                quotationQueryBO.setPermission(SecurityUtils.getPermissionCharIns());
            }
            List<QuotationVO> childrenList = baseMapper.selectTqQuotationList(quotationQueryBO);
            if (CollUtil.isNotEmpty(childrenList)) {
                // 获取审批节点信息
                List<Long> collect = childrenList.stream().map(QuotationVO::getId)
                    .collect(Collectors.toList());
                Map<Long, Flow> flowMap = flowService.getFlowMap(collect, Arrays.asList(QUOTATION, BARGAIN));
                childrenList.forEach(item -> {
                    item.setFlow(flowMap.get(item.getId()));
                    item.setQuotationStatusName(DictUtils.getInternationalDictLabel("quotation_status", item.getQuotationStatus()));
                });

                if (CollUtil.isNotEmpty(childrenList)) {
                    Map<String, List<QuotationVO>> childrenMap = childrenList.stream()
                        .collect(Collectors.groupingBy(QuotationVO::getQuotationNo));
                    for (QuotationVO quotationVO : quotationVOS) {
                        quotationVO.setSelectable(true);
                        quotationVO.setChildren(childrenMap.getOrDefault(quotationVO.getQuotationNo(),
                            Collections.emptyList()));
                    }
                }
            }
        }

        // 获取审批节点信息
        Map<Long, Flow> flowMap = flowService.getFlowMap(quotatiionIdList, Arrays.asList(QUOTATION, BARGAIN));
        quotationVOS.forEach(item -> {
            item.setFlow(flowMap.get(item.getId()));
            item.setQuotationStatusName(DictUtils.getInternationalDictLabel("quotation_status", item.getQuotationStatus()));
        });

        return quotationVOS;
    }

    /**
     * 新增【请填写功能名称】
     *
     * @param quotationAddBO 【请填写功能名称】
     * @return 结果
     */
    @Override
    @Transactional
    public void insertTqQuotation(QuotationAddBO quotationAddBO) {
        // 获取币种汇率
        List<TbCurrency> tbCurrencies = tbCurrencyMapper.selectList(Wrappers.<TbCurrency>lambdaQuery()
            .eq(TbCurrency::getCurrencyName, quotationAddBO.getCurrencyId())
            .le(TbCurrency::getEffectiveDate, DateUtils.getNowDate())
            .ge(TbCurrency::getExpirationDate, DateUtils.getNowDate())
            .eq(TbCurrency::getDelFlag, DelFlagEnum.NORMAL.getValue())
            .orderByDesc(TbCurrency::getCurrencyId));
        if (CollUtil.isNotEmpty(tbCurrencies)) {
            TbCurrency currency = tbCurrencies.get(0);
            quotationAddBO.setExchangeRate(currency.getExchangeRate());
        } else {
            throw new ServiceException(MessageUtils.message("quotation.currency.unknown"));
        }

        // 验证电梯是否属于关联项目
        List<Pair<Long, String>> collect = quotationAddBO.getElevatorList().stream()
            .map(item -> Pair.of(item.getElevatorModelId(), item.getElevatorModel()))
            .collect(Collectors.toList());
        TcProject tcProjects = tcProjectMapper.selectTcProjectByProjectId(quotationAddBO.getProjectId());
        if (nonNull(tcProjects)) {
            checkAreaElevatorCorrelation(tcProjects.getCountryId(), collect);
        } else {
            log.info("项目不存在 [{}]", quotationAddBO.getProjectId());
        }
        // 报价
        TqQuotation tqQuotation = new TqQuotation();
        //20240826修改采番

        //String quotationNo = redisCache.generateSerialNumber(SerialNumberPrefix.BJ.getPrefix());
        String quotationNo = redisCache.generateSerialNumberNew(SerialNumberPrefix.BJ.getPrefix(),tcProjects.getCountryAbbr());
        tqQuotation.setQuotationNo(quotationNo);
        tqQuotation.setQuotationVersion(quotationNo);
        tqQuotation.setVersion(1L);
        tqQuotation.setAgentId(quotationAddBO.getAgentId());
        tqQuotation.setExchangeRate(quotationAddBO.getExchangeRate());
        tqQuotation.setAgentDiscountRate(quotationAddBO.getAgentDiscountRate());
        tqQuotation.setCountryDiscountRate(quotationAddBO.getCountryDiscountRate());
        tqQuotation.setProjectId(quotationAddBO.getProjectId());
        tqQuotation.setCurrencyId(quotationAddBO.getCurrencyId());
        tqQuotation.setSubmitTime(new Date());
        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"));
        }
//        String permissionChar = tcAccountService.getPermissionChar(tqQuotation.getAreaId());
        // 数据权限字符
        tqQuotation.setPermissionChar(tcProjects.getPermissionChar());
        baseMapper.insertTqQuotation(tqQuotation);
        Long quotationId = tqQuotation.getId();
        log.info("报价id [{}]", quotationId);
        boolean quotationStandardFlag = insertSpecificationParam(quotationAddBO
            , quotationId
            , isNeedCalc(quotationAddBO.getQuotationStatus()));
        // 技术评审中时，启动审批流程（技术评审）
        if (QuotationStatusEnum.REVIEWING.getCode().equals(quotationAddBO.getQuotationStatus())) {
            if (quotationStandardFlag) {
                this.update(Wrappers.<TqQuotation>lambdaUpdate()
                    .eq(TqQuotation::getId, quotationId)
                    .set(TqQuotation::getQuotationStatus, QuotationStatusEnum.ALREADY_BID.getCode())
                );
                // 发送邮件通知
                QuotationUtil.sendMsgAsync(QuotationMsgEnum.STAND_QUOTATION,
                    Collections.singletonList(SecurityUtils.getUserId()),
                    quotationNo);
            } else {
                flowService.generateTasks(
                    new TaskGenerateParams(QUOTATION, tqQuotation, SecurityUtils.getUserId(),
                        tqQuotation.getQuotationNo()));
            }
            tcLeadService.convertQuotationFromProject(quotationAddBO.getProjectId(), quotationId);
        }
    }

    @Override
    public void checkAreaElevatorCorrelation(Long countryId, List<Pair<Long, String>> elevatorList) {
        TpElevatorModelVo tpElevatorModel = new TpElevatorModelVo();
        tpElevatorModel.setCountryId(countryId);
        tpElevatorModel.setUserId(SecurityUtils.getUserId());
        List<TpElevatorModel> tpElevatorModels = tpElevatorModelService.listNewAll(tpElevatorModel);
        List<Long> allocated = tpElevatorModels.stream().map(TpElevatorModel::getId).collect(Collectors.toList());
        Set<String> set = new HashSet<>();
        elevatorList.forEach(item -> {
            if (!allocated.contains(item.getKey())) {
                set.add(item.getValue());
            }
        });
        if (set.size() > 0) {
            throw new ServiceException(MessageUtils.message("area.elevator.mismatch",
                StringUtils.join(set, ",")));
        }
    }

    // 新增电梯规则 和 参数
    private boolean insertSpecificationParam(QuotationAddBO quotationAddBO, Long quotationId, boolean needCalc) {
        TbAgent agent = tbAgentMapper.selectById(quotationAddBO.getAgentId());
        Boolean discountFlag = false;
        String discountType = ValueType.VALUE.getCode();
        if (nonNull(agent)){
            discountFlag = nonNull(agent.getDiscountFlag()) ? agent.getDiscountFlag(): false;
            discountType = isNotBlank(agent.getDiscountType()) ? agent.getDiscountType(): ValueType.VALUE.getCode();
        }


        // 基础价格 （含国家折扣 代理商折扣 汇率）
        BigDecimal quotationBasicPrice = BigDecimal.ZERO;
        // 基础价格 （含汇率）
        BigDecimal quotationOriginalBasicPrice = BigDecimal.ZERO;
        // 选配价格 （含汇率）
        BigDecimal quotationOptionalPrice = BigDecimal.ZERO;
        BigDecimal quotationOriginalOptionalPrice = BigDecimal.ZERO;
        BigDecimal quotationPrice = BigDecimal.ZERO;
        boolean quotationStandardFlag = true;
        for (ElevatorAddBO elevator : quotationAddBO.getElevatorList()) {
            boolean elevatorStandardFlag = true;
            TqSpecification tqSpecification = new TqSpecification();
            tqSpecification.setQuotationId(quotationId);
            tqSpecification.setElevatorModelId(elevator.getElevatorModelId());
            tqSpecification.setElevatorNumber(elevator.getElevatorNumber());
            tqSpecification.setElevatorGroupCode(elevator.getElevatorGroupCode());
            tqSpecification.setElevatorCode(elevator.getElevatorCode());
            tqSpecification.setSpecification(elevator.getSpecification());
            tqSpecification.setQuotationStatus(quotationAddBO.getQuotationStatus());
            tqSpecification.setSystemCheckResult(SystemCheckResultEnum.OFF_STANDARD.getCode());
            tqSpecification.setDelFlag(DelFlagEnum.NORMAL.getValue());
            tqSpecification.setCreateBy(SecurityUtils.getStrUserId());
            if (nonNull(elevator.getCreateTime1())) {
                tqSpecification.setCreateTime(elevator.getCreateTime1());
            } else {
                tqSpecification.setCreateTime(DateUtils.getNowDate());
            }
            tqSpecification.setUpdateBy(SecurityUtils.getStrUserId());
            tqSpecification.setUpdateTime(DateUtils.getNowDate());
            Long basicPriceLong = 0L;
            List<TqPriceDetail> tqPriceDetailList = new ArrayList<>();
            BigDecimal agentDiscount = quotationAddBO.getAgentDiscountRate();
            if (needCalc) {
                // 初始化梯形计算参数
                QuotationUtil.initMap(elevator.getParamList());
                try {
                    // 计算电梯基础价格 &&  层站差价放到选配价格
                    basicPriceLong = priceCalcService.calculateBasicPrice(elevator, tqPriceDetailList);
                    log.info("基础价格 [{}]", basicPriceLong);
                } catch (Exception e) {
                    log.error("计算基价失败", e);
                    throw new ServiceException(
                        MessageUtils.message("elevator.basic.price.fail",
                            elevator.getElevatorModel(),
                            elevator.getSpecification()));
                }
                // 计算电梯选配价格 （以及价格明细）
                try {
                    priceCalcService.statisticsOptionalPrice(elevator, tqPriceDetailList);
                } catch (Exception e) {
                    log.error("计算加价项目失败", e);
                    throw new ServiceException(
                        MessageUtils.message("elevator.optional.price.fail",
                            elevator.getElevatorModel(),
                            elevator.getSpecification()));
                }

                if (ValueType.FORMULA.getCode().equals(discountType)) {
                    try {
                        // 计算电梯折率
                        agentDiscount = priceCalcService.calculateAgentDiscount(elevator, agent.getDiscountFormula());
                        log.info("电梯代理商折率 [{}]", agentDiscount);
                    } catch (Exception e) {
                        log.error("计算代理商折率失败", e);
                        throw new ServiceException(
                                MessageUtils.message("计算代理商折率失败",
                                        elevator.getElevatorModel(),
                                        elevator.getSpecification()));
                    }
                }
            }
            // 选配价格求和
            BigDecimal optionalPrice = tqPriceDetailList.stream()
                .filter(item -> !item.getMarkupName().equals(PriceCalcServiceImpl.BASIC_PRICE))
                .map(TqPriceDetail::getTotal)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            log.info("选配价格 [{}]", optionalPrice);
            BigDecimal decimalBasicPrice = BigDecimal.valueOf(basicPriceLong);

            BigDecimal defaultRate = quotationAddBO.getCountryDiscountRate().divide(new BigDecimal(ONE_HUNDRED));
            if (nonNull(agentDiscount)){
                defaultRate = defaultRate.multiply(agentDiscount).divide(new BigDecimal(ONE_HUNDRED));
            }
            BigDecimal finalRate = defaultRate.multiply(quotationAddBO.getExchangeRate());
            // 电梯单价乘最终折率
            BigDecimal basicPrice = decimalBasicPrice.multiply(finalRate).setScale(0, RoundingMode.HALF_UP);
            BigDecimal originalBasicPrice = decimalBasicPrice.multiply(quotationAddBO.getExchangeRate())
                .setScale(0, RoundingMode.HALF_UP);

            BigDecimal discountOptionalPrice = optionalPrice.multiply(finalRate).setScale(0, RoundingMode.HALF_UP);
            BigDecimal originalOptionalPrice = optionalPrice.multiply(quotationAddBO.getExchangeRate()).setScale(0, RoundingMode.HALF_UP);

            tqSpecification.setBasicPrice(basicPrice);
            tqSpecification.setOriginalBasicPrice(originalBasicPrice);
            tqSpecification.setOptionalPrice(discountFlag ? discountOptionalPrice: originalOptionalPrice);
            tqSpecification.setOriginalOptionalPrice(originalOptionalPrice);
            tqSpecification.setPrice(tqSpecification.getBasicPrice().add(tqSpecification.getOptionalPrice()));

            // 判断规则加价项目是否有非标
            if (tqPriceDetailList.stream().anyMatch(a ->
                a.getSystemCheckResult().equals(SystemCheckResultEnum.OFF_STANDARD.getCode()))
                || CollUtil.isNotEmpty(elevator.getNonStandardList())) {
                elevatorStandardFlag = false;
            } else {
                tqSpecification.setQuotationStatus(QuotationStatusEnum.ALREADY_BID.getCode());
                tqSpecification.setSystemCheckResult(SystemCheckResultEnum.STANDARD.getCode());
            }
            // 如果是草稿,规格状态改为草稿
            if (QuotationStatusEnum.DRAFT.getCode().equals(quotationAddBO.getQuotationStatus())) {
                tqSpecification.setQuotationStatus(QuotationStatusEnum.DRAFT.getCode());
            }

            tqSpecification.setDefaultRate(defaultRate.multiply(new BigDecimal(ONE_HUNDRED)));
            tqSpecification.setDiscountRate(tqSpecification.getDefaultRate());
            if (needCalc && discountFlag){
                // 如果是总价折率此处需要转为对应基价折率
                BigDecimal discountRate = tqSpecification.getPrice().subtract(tqSpecification.getOriginalOptionalPrice()).divide(tqSpecification.getOriginalBasicPrice(), 6, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(ONE_HUNDRED));
                tqSpecification.setDiscountRate(discountRate);
            }
            tqSpecificationService.insertTqSpecification(tqSpecification);
            // 统计报价的基础价格 选配价格
            BigDecimal count = BigDecimal.valueOf(tqSpecification.getElevatorNumber());

            quotationOriginalBasicPrice = quotationOriginalBasicPrice.add(tqSpecification.getOriginalBasicPrice().multiply(count));
            quotationBasicPrice = quotationBasicPrice.add(tqSpecification.getBasicPrice().multiply(count));
            quotationOptionalPrice = quotationOptionalPrice.add(tqSpecification.getOptionalPrice().multiply(count));
            quotationOriginalOptionalPrice = quotationOriginalOptionalPrice.add( tqSpecification.getOriginalOptionalPrice().multiply(count));
            quotationPrice = quotationPrice.add(tqSpecification.getPrice().multiply(count));

            Long specificationId = tqSpecification.getId();
            log.info("规格id [{}]", specificationId);
            // 保存价格明细
            if (CollUtil.isNotEmpty(tqPriceDetailList)) {
                tqPriceDetailList = tqPriceDetailList.stream().peek(item -> {
                    item.setSpecificationId(specificationId);
                }).collect(Collectors.toList());
                priceDetailService.saveBatch(tqPriceDetailList);
            }

            // 非标记录表
            List<NonStandardAddBO> nonStandardList = elevator.getNonStandardList();
            if (CollUtil.isNotEmpty(nonStandardList)) {
                elevatorStandardFlag = false;
                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.setQuotationFlagElectric(QuotationEnum.NO.getValue());
                    tqSpecificationNonStandard.setQuotationFlagMachine(QuotationEnum.NO.getValue());
                    tqSpecificationNonStandard.setCreateBy(SecurityUtils.getStrUserId());
                    tqSpecificationNonStandard.setCreateTime(DateUtils.getNowDate());
                    tqSpecificationNonStandard.setUpdateBy(SecurityUtils.getStrUserId());
                    tqSpecificationNonStandard.setUpdateTime(DateUtils.getNowDate());
                    tqSpecificationNonStandardService.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());
                tqSpecificationDetailService.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());
                tqSpecificationDetailService.insertTqSpecificationDetail(tqSpecificationDetail);
            }
            // 规格有一个非标，报价就是非标
            if (!elevatorStandardFlag) {
                quotationStandardFlag = false;
            }
        }
        this.update(Wrappers.<TqQuotation>lambdaUpdate()
            .eq(TqQuotation::getId, quotationId)
            .set(TqQuotation::getDiscountFlag, discountFlag)
            .set(TqQuotation::getBasicPrice, quotationBasicPrice)
            .set(TqQuotation::getOriginalBasicPrice, quotationOriginalBasicPrice)
            .set(TqQuotation::getOriginalOptionalPrice, quotationOriginalOptionalPrice)
            .set(TqQuotation::getOptionalPrice, quotationOptionalPrice)
            .set(TqQuotation::getPrice, quotationPrice)
        );
        return quotationStandardFlag;
    }

    /**
     * 修改【请填写功能名称】
     *
     * @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)
            .eq(TqQuotation::getQuotationStatus, QuotationStatusEnum.DRAFT.getCode())
            .set(TqQuotation::getQuotationStatus, quotationAddBO.getQuotationStatus())
            .set(TqQuotation::getUpdateBy, SecurityUtils.getStrUserId())
            .set(TqQuotation::getUpdateTime, DateUtils.getNowDate()));

        // 电梯规格删除
        List<TqSpecification> tqSpecifications = tqSpecificationService.list(
            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)) {
            // 梯形参数
            tqSpecificationDetailService.update(Wrappers.<TqSpecificationDetail>lambdaUpdate()
                .in(TqSpecificationDetail::getSpecificationId, specificationIdList)
                .set(TqSpecificationDetail::getDelFlag, DelFlagEnum.DELETED.getValue()));
            // 非标描述
            tqSpecificationNonStandardService.update(
                Wrappers.<TqSpecificationNonStandard>lambdaUpdate()
                    .in(TqSpecificationNonStandard::getSpecificationId, specificationIdList)
                    .set(TqSpecificationNonStandard::getDelFlag, DelFlagEnum.DELETED.getValue()));
            // 价格明细
            priceDetailService.update(
                Wrappers.<TqPriceDetail>lambdaUpdate()
                    .in(TqPriceDetail::getSpecificationId, specificationIdList)
                    .set(TqPriceDetail::getDelFlag, DelFlagEnum.DELETED.getValue())
            );
        }
        quotationAddBO.setExchangeRate(tqQuotation.getExchangeRate());
        quotationAddBO.setCountryDiscountRate(tqQuotation.getCountryDiscountRate());
        quotationAddBO.setAgentDiscountRate(tqQuotation.getAgentDiscountRate());
        boolean quotationStandardFlag = insertSpecificationParam(quotationAddBO
            , quotationId
            , isNeedCalc(quotationAddBO.getQuotationStatus()));
        // 技术评审中时，启动审批流程（技术评审）
        if (QuotationStatusEnum.REVIEWING.getCode().equals(quotationAddBO.getQuotationStatus())) {
            if (quotationStandardFlag) {
                this.update(Wrappers.<TqQuotation>lambdaUpdate()
                    .eq(TqQuotation::getId, quotationId)
                    .set(TqQuotation::getQuotationStatus, QuotationStatusEnum.ALREADY_BID.getCode())
                );
                // 发送邮件通知
                QuotationUtil.sendMsgAsync(QuotationMsgEnum.STAND_QUOTATION,
                    Collections.singletonList(SecurityUtils.getUserId()),
                    tqQuotation.getQuotationNo());
            } else {
                flowService.generateTasks(
                    new TaskGenerateParams(QUOTATION, tqQuotation, SecurityUtils.getUserId(),
                        tqQuotation.getQuotationNo()));
            }
            tcLeadService.convertQuotationFromProject(quotationAddBO.getProjectId(), quotationId);
        }
    }

    // 是否计算梯形价格(上线后放开注释)
    private boolean isNeedCalc(String quotationStatus) {
         return !QuotationStatusEnum.DRAFT.getCode().equals(quotationStatus);
    }

    /**
     * 批量删除【请填写功能名称】
     *
     * @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();
            // 复制报价
            Long nextVersion = quotationVersionMap.getOrDefault(tqQuotation.getQuotationNo(), 1L) + 1;
            //复制报价版本修改，添加新的字段数据记录
            String quotationVersion = numberToLetter(Integer.parseInt(nextVersion.toString()));
            tqQuotation.setQuotationVersion(tqQuotation.getQuotationNo() + quotationVersion);
            quotationVersionMap.put(tqQuotation.getQuotationNo(), nextVersion);
            tqQuotation.setVersion(nextVersion);
            tqQuotation.setQuotationStatus(QuotationStatusEnum.DRAFT.getCode());
            tqQuotation.setPrice(null);
//            String permissionChar = tcAccountService.getPermissionChar(tqQuotation.getAreaId());
//            tqQuotation.setPermissionChar(permissionChar);
            tqQuotation.setFreightPrice(null);
            tqQuotation.setBasicPrice(null);
            tqQuotation.setOptionalPrice(null);
            tqQuotation.setFinalPrice(null);
            tqQuotation.setFinalCurrencyPrice(null);
            tqQuotation.setSubmitTime(DateUtils.getNowDate());
            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 = tqSpecificationService.list(
                Wrappers.<TqSpecification>lambdaQuery()
                    .eq(TqSpecification::getQuotationId, oldQuotationId)
                    .eq(TqSpecification::getDelFlag, DelFlagEnum.NORMAL.getValue())
            );
            tqSpecifications.forEach(item -> {
                item.setQuotationId(newQuotationId);
                item.setPrice(null);
                item.setBasicPrice(null);
                item.setOptionalPrice(null);
                item.setFinalPrice(null);
                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();
                tqSpecificationService.insertTqSpecification(tqSpecification);
                // 复制后规格ID
                Long newSpecificationId = tqSpecification.getId();
                // 复制电梯规格参数
                List<TqSpecificationDetail> paramDetail = tqSpecificationDetailService.list(
                    Wrappers.<TqSpecificationDetail>lambdaQuery()
                        .eq(TqSpecificationDetail::getSpecificationId, oldSpecificationId)
                        .eq(TqSpecificationDetail::getDelFlag, DelFlagEnum.NORMAL.getValue())
                );
                // 电梯规格参数复制版本
                paramDetail.forEach(item -> {
                    item.setSpecificationId(newSpecificationId);
                    item.setId(null);
                });
                tqSpecificationDetailService.saveBatch(paramDetail);
                // 复制非标描述
                List<TqSpecificationNonStandard> nonStandardList = tqSpecificationNonStandardService.list(
                    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());
                    tqSpecificationNonStandardService.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<CivilQuotationVO> listByProjectId(Long projectId) {
        List<CivilQuotationVO> civilQuotationList = new ArrayList<>();
        List<QuotationVO> quotationVOS = baseMapper.listByProjectId(projectId);
        if (CollUtil.isNotEmpty(quotationVOS)) {
            String projectName = quotationVOS.get(0).getProjectName();
            Map<String, List<QuotationVO>> collect = quotationVOS.stream()
                .collect(Collectors.groupingBy(QuotationVO::getQuotationNo));
            for (Map.Entry<String, List<QuotationVO>> entry : collect.entrySet()) {
                List<Long> versionList = entry.getValue().stream().map(QuotationVO::getVersion)
                    .collect(Collectors.toList());
                civilQuotationList.add(new CivilQuotationVO(projectName, entry.getKey(), versionList));
            }
        }
        civilQuotationList.sort(Comparator.comparing(CivilQuotationVO::getQuotationNo));
        Collections.reverse(civilQuotationList);
        return civilQuotationList;
    }

    @Override
    public QuotationPriceVO getPriceInfo(Long quotationId) {
        QuotationPriceVO quotationPriceVO = new QuotationPriceVO();
        TqQuotation tqQuotation = this.getById(quotationId);

        if (Objects.isNull(tqQuotation.getOriginalBasicPrice())){
            return null;
        }

        List<SysDictData> dictDataList = DictUtils.getDictCache("currency_type");
        SysDictData sysDictData = dictDataList.stream().filter(item -> item.getDictValue().equals(tqQuotation.getCurrencyId().toString())).findAny().orElse(new SysDictData());
        quotationPriceVO.setCurrency(sysDictData.getRemark());

        quotationPriceVO.setOriginalBasicPrice(tqQuotation.getOriginalBasicPrice());
        quotationPriceVO.setOriginalOptionalPrice(nonNull(tqQuotation.getOriginalOptionalPrice()) ? tqQuotation.getOriginalOptionalPrice(): tqQuotation.getOptionalPrice());
        if (nonNull(quotationPriceVO.getOriginalBasicPrice())){
            quotationPriceVO.setOriginalPriceTotal(quotationPriceVO.getOriginalBasicPrice().add(quotationPriceVO.getOriginalOptionalPrice()));
        }

        // 基准价格合计tq_salesperson_set_price
        quotationPriceVO.setBasicPrice(tqQuotation.getBasicPrice());
        quotationPriceVO.setBasicPriceFormat(formatter.format(tqQuotation.getBasicPrice()));
        // 选配价格合计
        BigDecimal optionalPrice = tqQuotation.getOptionalPrice();
        quotationPriceVO.setOptionalPrice(optionalPrice);
        quotationPriceVO.setOptionalPriceFormat(formatter.format(optionalPrice));
        // 价格合计
        quotationPriceVO.setPriceTotal(tqQuotation.getPrice());
        quotationPriceVO.setPriceTotalFormat(formatter.format(tqQuotation.getPrice()));
        quotationPriceVO.setDiscountFlag(tqQuotation.getDiscountFlag());

        List<TqBargainPrice> list = tqBargainPriceService
            .list(Wrappers.<TqBargainPrice>lambdaQuery()
                .eq(TqBargainPrice::getQuotationId, quotationId).orderByDesc(TqBargainPrice::getId));

        BigDecimal priceTotal = quotationPriceVO.getPriceTotal();
        String priceTotalStr = formatter.format(priceTotal);

        if (CollUtil.isNotEmpty(list)) {
            TqBargainPrice tqBargainPrice = list.get(0);
            quotationPriceVO.setBargainId(tqBargainPrice.getId());
            // 希望价格
            quotationPriceVO.setExpectedPrice(tqBargainPrice.getBargainPrice());
            quotationPriceVO.setExpectedPriceFormat(formatter.format(tqBargainPrice.getBargainPrice()));
            quotationPriceVO.setBargainPriceList(list);
            // 折率（希望价格）
            String expectedRateStr = nonNull(tqBargainPrice.getDiscountRate()) ? tqBargainPrice.getDiscountRate().setScale(4, BigDecimal.ROUND_HALF_UP).toString(): BigDecimal.ZERO.toString();
            quotationPriceVO.setExpectedRate(expectedRateStr);
            quotationPriceVO.setExpectedBasicRate(expectedRateStr);
        } else {
            quotationPriceVO.setExpectedRate(ONE_HUNDRED);
            quotationPriceVO.setExpectedBasicRate(ONE_HUNDRED);
            quotationPriceVO.setExpectedPrice(priceTotal);
            quotationPriceVO.setExpectedPriceFormat(priceTotalStr);
        }
        return quotationPriceVO;
    }

    @Override
    public TbSalesDiscount getSalesDiscountByQuotationId(Long quotationId) {
        // 获取当前审批节点信息
        Map<Long, Flow> flowMap = flowService.getFlowMap(Collections.singletonList(quotationId),
            Arrays.asList(QUOTATION, BARGAIN));
        // 获取当前审批节点信息
        Flow flow = flowMap.get(quotationId);
        if (nonNull(flow) ) {
            NodeRoleEnum nodeRoleEnum = NodeRoleEnum.fromAuditStatusEnum(flow.getStatus());
            return quoteApprovalService.getRoleDiscount(nodeRoleEnum.getRoleId());
        }
        log.info("报价 [{}] 获取审批节点失败", quotationId);
        throw new ServiceException(MessageUtils.message("quotation.flow.undefined"));
    }

    @Override
    public TbSalesDiscount getSalesDiscountByFlow(Integer flowStatus) {
        if (Objects.isNull(flowStatus)) {
            throw new ServiceException(MessageUtils.message("quotation.flow.undefined"));
        }
        NodeRoleEnum nodeRoleEnum = NodeRoleEnum.fromAuditStatusEnum(flowStatus);
        return quoteApprovalService.getRoleDiscount(nodeRoleEnum.getRoleId());
    }

    @Override
    public PageInfo<QuotationApprovalVO> listApproval() {
        List<QuotationApprovalVO> quotationApprovalVOList = this.baseMapper
            .listPendingApproval(SecurityUtils.getStrUserId());
        PageInfo<QuotationApprovalVO> quotationApprovalVOPageInfo = new PageInfo<>(quotationApprovalVOList);
        quotationApprovalVOList = quotationApprovalVOPageInfo.getList().stream().peek(item -> {
            if (nonNull(item.getPrice())) {
                item.setPriceStr(formatter.format(item.getPrice().setScale(0, RoundingMode.HALF_UP)));
            }
            if (nonNull(item.getBargainPrice())) {
                item.setBargainPriceStr(formatter.format(item.getBargainPrice().setScale(0, RoundingMode.HALF_UP)));
            }
        }).collect(Collectors.toList());
        quotationApprovalVOPageInfo.setList(quotationApprovalVOList);
        return quotationApprovalVOPageInfo;
    }

    @Override
    public H5QuotationDetailVO detailApproval(Long id) {
        H5QuotationDetailVO quotationDetailVO = this.baseMapper.detailApproval(id);
        QuotationPriceVO priceInfo = this.getPriceInfo(id);
        List<H5ElevatorVO> elevatorList = tqSpecificationMapper.listSpecification(id, priceInfo.getBargainId());
        quotationDetailVO.setBargainId(priceInfo.getBargainId());
        // 接受价格
        BigDecimal acceptPrice = BigDecimal.ZERO;
        // 折前基价
        BigDecimal beforeBasicPrice = BigDecimal.ZERO;
        // 折后基价
        BigDecimal afterBasicPrice = BigDecimal.ZERO;
        for (H5ElevatorVO item : elevatorList) {
            item.setPriceStr(formatter.format(item.getPrice().setScale(0, RoundingMode.HALF_UP)));
            // 设置默认折扣率
            if (Objects.isNull(item.getDiscountRate())) {
                item.setDiscountRate(new BigDecimal(100));
            }
            beforeBasicPrice = beforeBasicPrice.add(item.getOriginalBasicPrice());
            BigDecimal discountRate = item.getDiscountRate().divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
            BigDecimal discountBasicPrice = discountRate.multiply(item.getOriginalBasicPrice());
            afterBasicPrice = afterBasicPrice.add(discountBasicPrice);
            item.setDiscountPrice(item.getOriginalOptionalPrice().add(discountBasicPrice));
            acceptPrice = acceptPrice.add(item.getDiscountPrice().multiply(new BigDecimal(item.getElevatorNumber())));
        }
        BigDecimal discountRate = (afterBasicPrice.divide(beforeBasicPrice, 6, RoundingMode.HALF_UP))
            .multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP);
        quotationDetailVO.setDiscountRate(discountRate);
        quotationDetailVO.setElevatorList(elevatorList);
        // 基准价格合计
        if (nonNull(priceInfo.getBasicPrice())) {
            quotationDetailVO.setBasicPriceTotal(priceInfo.getBasicPrice());
            quotationDetailVO.setBasicPriceTotalStr(
                formatter.format(priceInfo.getBasicPrice().setScale(0, RoundingMode.HALF_UP)));
        }
        if (nonNull(priceInfo.getOriginalBasicPrice())) {
            quotationDetailVO.setOriginBasicPrice(priceInfo.getOriginalBasicPrice());
            quotationDetailVO.setOriginBasicPriceStr(
                    formatter.format(priceInfo.getOriginalBasicPrice().setScale(0, RoundingMode.HALF_UP)));
        }
        // 选配价格合计
        if (nonNull(priceInfo.getOptionalPrice())) {
            quotationDetailVO.setOptionalPriceTotal(priceInfo.getOptionalPrice());
            quotationDetailVO.setOptionalPriceTotalStr(
                formatter.format(priceInfo.getOptionalPrice().setScale(0, RoundingMode.HALF_UP)));
        }
        // 为打折选配价格合计
        if (nonNull(priceInfo.getOriginalOptionalPrice())) {
            quotationDetailVO.setOriginOptionalPrice(priceInfo.getOriginalOptionalPrice());
            quotationDetailVO.setOriginOptionalPriceStr(
                    formatter.format(priceInfo.getOriginalOptionalPrice().setScale(0, RoundingMode.HALF_UP)));
        }
        // 价格合计
        if (nonNull(priceInfo.getPriceTotal())) {
            quotationDetailVO.setPriceTotal(priceInfo.getPriceTotal());
            quotationDetailVO.setPriceTotalStr(
                formatter.format(priceInfo.getPriceTotal().setScale(0, RoundingMode.HALF_UP)));
        }
        // 希望价格
        if (nonNull(priceInfo.getExpectedPrice())) {
            quotationDetailVO.setExpectedPrice(priceInfo.getExpectedPrice());
            quotationDetailVO.setExpectedPriceStr(
                formatter.format(priceInfo.getExpectedPrice().setScale(0, RoundingMode.HALF_UP)));
        }
        // 基价折率
        quotationDetailVO.setBasicPriceRate(priceInfo.getExpectedBasicRate());
        // 同意价格
        quotationDetailVO.setAcceptPrice(acceptPrice);
        quotationDetailVO.setAcceptPriceStr(formatter.format(acceptPrice.setScale(0, RoundingMode.HALF_UP)));
        // 销售
        String saler = quotationDetailVO.getSaler();
        String insensitiveSaler = saler;
        if (StringUtils.isNotBlank(saler) && saler.length() >= 2) {
            StringBuilder replacedString = new StringBuilder(saler.substring(0, 1));
            for (int i = 1; i < saler.length(); i++) {
                replacedString.append("*");
            }
            insensitiveSaler = replacedString.toString();
        }
        quotationDetailVO.setInsensitiveSaler(insensitiveSaler);
        return quotationDetailVO;
    }

    /**
     * 根据word模板导出
     * @param id
     */
    @Override
    public void export(Long id) {
        DecimalFormat format = new DecimalFormat("#,###.##");
        // 1. 获取基础数据
        TqQuotation tqQuotation = getById(id);
        if (Objects.isNull(tqQuotation)) {
            throw new ServiceException("数据不存在或已被删除");
        }
        List<SysDictData> currencyList = DictUtils.getDictCache("currency_type");

        SysDictData tbCurrency = currencyList.stream().filter(dictData -> dictData.getDictValue().equals(tqQuotation.getCurrencyId().toString())).findFirst().orElse(null);
        String currencyName = nonNull(tbCurrency) ? defaultIfBlank(tbCurrency.getRemark(), EMPTY) : EMPTY;
        TcProject tcProject  = tcProjectMapper.selectTcProjectByProjectId(tqQuotation.getProjectId());
        TcAccount tcAccount = tcAccountService.selectTcAccountByAccountId(tcProject.getAccountId());

        Map<String, String> paraNameMap = tpParaLibraryService.list().stream()
                .collect(Collectors.toMap(TpParaLibrary::getParaCode, item -> LocalUtils.localParaNameFun(Constants.US).apply(item)));
        List<TpParaSelectItem> itemList = tpParaSelectItemService.list();
        Map<String, String> paraItemNameMap = Maps.newHashMap();
        itemList.forEach(item -> paraItemNameMap.put(item.getValue(), LocalUtils.localParaItemNameFun(Constants.US).apply(item)));

        // 1.1 规格信息获取
        SpecificationQueryBO params = new SpecificationQueryBO();
        params.setQuotationId(id);
        List<SpecificationVO> specificationVOList = tqSpecificationService.selectTqSpecificationList(params);
        int index = 1;
        List<JSONObject> specifications = Lists.newArrayList();
        BigDecimal totalPrice = BigDecimal.ZERO;
        BigDecimal totalFreight = BigDecimal.ZERO;
        List<String> freightRemarks = Lists.newArrayList();
        Map<Long, JSONObject> dataMap = Maps.newHashMap();
        List<String> imageKeys = Lists.newArrayList();

        for (SpecificationVO item: specificationVOList){
            JSONObject data = new JSONObject();
            // 梯型参数
            Map<String, List<SpecificationParamVO>> paramMap = item.getParamList().stream()
                    .filter(para -> StringUtils.isNotBlank(para.getParaCode()))
                    .collect(Collectors.groupingBy(SpecificationParamVO::getParaCode));
            paramMap.keySet().forEach(key -> {
                List<SpecificationParamVO> list = paramMap.get(key);
                if (CollectionUtils.isNotEmpty(list)){
                    data.put(key, defaultIfBlank(list.get(0).getParaValue(), EMPTY));
                }
            });

            data.put("id", item.getId());
            data.put("noFix", "E" + StringUtils.padl(String.valueOf(index++), 2, '0'));
            data.put("no", data.get("noFix"));

            data.put("specification", item.getSpecification());
            data.put("qty", format.format(item.getElevatorNumber()));
            BigDecimal unitPrice = nonNull(item.getFinalPrice()) ? item.getFinalPrice() : item.getPrice();
            if (nonNull(unitPrice)){
                data.put("unitPrice", currencyName + format.format(unitPrice));
                BigDecimal itemTotal = unitPrice.multiply(new BigDecimal(item.getElevatorNumber()));
                data.put("totalPrice", currencyName + format.format(itemTotal));
                totalPrice = totalPrice.add(itemTotal);
            }

            totalFreight = totalFreight.add(nonNull(item.getLandShipFees()) ? item.getLandShipFees() : BigDecimal.ZERO);
            totalFreight = totalFreight.add(nonNull(item.getSeaShipFees()) ? item.getSeaShipFees() : BigDecimal.ZERO);
            freightRemarks.add(item.getFreightRemark());

            data.put("productType", item.getElevatorModel());
            String loadCapacity = data.getString(RATED_LOAD_CAPACITY);
            String persons = isNotBlank(loadCapacity) ? String.valueOf(Integer.parseInt(loadCapacity) / 75) : EMPTY;
            data.put("loadCapacity", loadCapacity + "kg(" + persons + " persons)");
            data.put("speed", data.getString(RATED_SPEED) + "m/s");
            data.put("numberOfFloors", data.getString(LANDS) + "floors");
            data.put("numberOfStops", data.getString(STOPS) + "stops");
            data.put("numberOfDoors", data.getString(DOORS) + "doors");
            data.put("floorDisplaying", "1~" + data.get(LANDS));
            data.put("mainFloor", "1");
            data.put("cabinSize", data.getString(CW) + "*" + data.getString(CD) + "*" + data.getString(CH) + "mm");
            data.put("doorSize", data.getString(OP) + "*" + data.getString(OPH) + "mm");
            data.put("shaftSize", data.getString(HW) + "*" + data.getString(HD) + "mm");
            data.put("pit", data.getString(PD) + "mm");
            data.put("oh", data.getString(OH) + "mm");
            data.put("tr", data.getString(TR) + "mm");

            Function<String, String> getInfo = key ->  {
                if (Objects.isNull(data.get(key)) || isBlank(data.getString(key))){
                    return null;
                }
                imageKeys.add(data.getString(key));
                return paraNameMap.get(key) + ": " + defaultIfBlank(paraItemNameMap.get(data.get(key)), EMPTY);
            };
            BiFunction<String, String, String> getMaterialInfoWithCode = (key, code)  ->  {
                if (Objects.isNull(data.get(key)) || isBlank(data.getString(key))){
                    return null;
                }
                String codeKey = defaultIfBlank(code, key+"_CODE");
                imageKeys.add(data.getString(key));
                imageKeys.add(data.getString(codeKey));
                return paraNameMap.get(key) + ": " + defaultIfBlank(data.getString(codeKey), EMPTY) + "," + defaultIfBlank(paraItemNameMap.get(data.getString(key)), EMPTY);
            };
            Function<String, String> getMaterialInfo = key -> getMaterialInfoWithCode.apply(key, null);

            // 1.2 材质信息
            // 1.2.1 轿厢
            String carType = data.getString(CAR_TYPE);
            data.put("carType", getInfo.apply(CAR_TYPE));
            if ("单一轿厢".equals(carType)){
                data.put("carDetail", getMaterialInfo.apply(CAR_WALL_MATERIAL));
            }else if ("组合轿厢".equals(carType)){
                data.put("carDetail", getMaterialInfo.apply(MIDDLE_LEFT_WALL));
                data.put("carDetail1", getMaterialInfo.apply(MIDDLE_RIGHT_WALL));
                data.put("carDetail2", getMaterialInfo.apply(LEFT_WALL_AUXILIARY_PANEL));
                data.put("carDetail3", getMaterialInfo.apply(RIGHT_WALL_AUXILIARY_PANEL));
                data.put("carDetail4", getMaterialInfo.apply(MIDDLE_REAR_WALL));
                data.put("carDetail5", getMaterialInfo.apply(REAR_WALL_AUXILIARY_PANEL));
                data.put("carDetail6", getMaterialInfo.apply(ANTERIOR_WALL));
            } else if ("观光轿厢".equals(carType)){
                data.put("carDetail", getMaterialInfo.apply(SIGHTSEEING_ELEVATOR_CAR_MATERIAL));
            }

            // 1.2.2 门
            data.put("typeOfDoor", getInfo.apply(DOOR_OPEN));
            data.put("carDoor", getMaterialInfo.apply(CABIN_DOOR_MATERIAL));
            data.put("landingDoor", getMaterialInfoWithCode.apply(GROUND_FLOOR_DOOR_MATERIAL, GROUND_FLOOR_DOOR_MATERIAL_CODE));
            data.put("landingDoor1", getMaterialInfoWithCode.apply(OTHER_FLOOR_DOOR_MATERIAL1, OTHER_FLOOR_DOOR_MATERIAL_CODE1));
            data.put("landingDoor2", getMaterialInfoWithCode.apply(OTHER_FLOOR_DOOR_MATERIAL2, OTHER_FLOOR_DOOR_MATERIAL_CODE2));
            data.put("landingDoor3", getMaterialInfoWithCode.apply(OTHER_FLOOR_DOOR_MATERIAL3, OTHER_FLOOR_DOOR_MATERIAL_CODE3));
            data.put("landingDoor4", getMaterialInfoWithCode.apply(OTHER_FLOOR_DOOR_MATERIAL4, OTHER_FLOOR_DOOR_MATERIAL_CODE4));

            // 1.2.3 扶手
            String handrail = data.getString(HANDRAIL_YES_NO);
            if ("Yes".equals(handrail)){
                data.put("handrailDetail", getMaterialInfoWithCode.apply(HANDRAIL_TYPE_LEFT, HANDRAIL_TYPE_CODE_LEFT));
                data.put("handrailDetail1", getMaterialInfoWithCode.apply(HANDRAIL_TYPE_RIGHT, HANDRAIL_TYPE_CODE_RIGHT));
                data.put("handrailDetail2", getMaterialInfoWithCode.apply(HANDRAIL_TYPE_REAR, HANDRAIL_TYPE_CODE_REAR));
                data.put("handrailDetail3", getMaterialInfoWithCode.apply(HANDRAIL_MATERIAL, HANDRAIL_MATERIAL_CODE));
            }

            // 1.2.4 吊顶
            data.put("ceiling", getInfo.apply(CEILING));
            data.put("ceilingType", getMaterialInfo.apply(CEILING_MATERIAL));
            // 1.2.5 地板
            data.put("flooringType", getMaterialInfo.apply(FLOORTYPE));

            // 1.2.6 操纵箱
            data.put("copDetail", getInfo.apply(CONTROL_BOX_TYPE));
            data.put("copDetail1", getMaterialInfo.apply(CONTROL_BOX_PANEL_MATERIAL));
            data.put("copDetail2", getInfo.apply(CONTROL_BOX_DISPLAY));
            data.put("copDetail3", getInfo.apply(AUXILIARY_CONTROL_BOX_TYPE));
            data.put("copDetail4", getMaterialInfo.apply(AUXILIARY_CONTROL_BOX_PANEL_MATERIAL));
            data.put("copDetail5", getInfo.apply(AUXILIARY_CONTROL_BOX_DISPLAY));

            // 1.2.7 外呼
            data.put("lopDetail", getInfo.apply(OUTBOUND_CALL_TYPE1));
            data.put("lopDetail1", getMaterialInfoWithCode.apply(OUTBOUND_CALL__PANEL_MATERIAL, OUTBOUND_CALL__PANEL_MATERIAL_CODE));
            data.put("lopDetail2", getInfo.apply(SUMMONING_DISPLAY1));

            data.put("lopDetail3", getInfo.apply(OUTBOUND_CALL_TYPE2));
            data.put("lopDetail4", getMaterialInfoWithCode.apply(OUTBOUND_CALL_PANEL_MATERIAL2, OUTBOUND_CALL_PANEL_MATERIAL_CODE2));
            data.put("lopDetail5", getInfo.apply(SUMMONING_DISPLAY2));

            data.put("lopDetail6", getInfo.apply(OUTBOUND_CALL_TYPE3));
            data.put("lopDetail7", getMaterialInfoWithCode.apply(OUTBOUND_CALL_PANEL_MATERIAL3, OUTBOUND_CALL_PANEL_MATERIAL_CODE3));
            data.put("lopDetail8", getInfo.apply(SUMMONING_DISPLAY3));

            data.put("lopDetail9", getInfo.apply(OUTBOUND_CALL_TYPE4));
            data.put("lopDetail10", getMaterialInfoWithCode.apply(OUTBOUND_CALL_PANEL_MATERIAL4, OUTBOUND_CALL_PANEL_MATERIAL_CODE4));
            data.put("lopDetail11", getInfo.apply(SUMMONING_DISPLAY4));

            data.put("lopDetail12", getInfo.apply(OUTBOUND_CALL_TYPE5));
            data.put("lopDetail13", getMaterialInfoWithCode.apply(OUTBOUND_CALL_PANEL_MATERIAL5, OUTBOUND_CALL_PANEL_MATERIAL_CODE5));
            data.put("lopDetail14", getInfo.apply(SUMMONING_DISPLAY5));

            // 1.2.8 镜子
            String mirror = data.getString(MIRROR_YES_NO);
            if ("Yes".equals(mirror)){
                data.put("mirrorDetail", getInfo.apply(MIRROR_TYPE_LEFT));
                data.put("mirrorDetail1", getInfo.apply(MIRROR_TYPE_RIGHT));
                data.put("mirrorDetail2", getInfo.apply(MIRROR_TYPE_REAR));
            }

            specifications.add(data);
            dataMap.put(item.getId(), data);
        }

        // 1.3 选配信息
        TqPriceDetail detailParams = new TqPriceDetail();
        List<Long> specificationIds = specificationVOList.stream().map(SpecificationVO::getId).collect(Collectors.toList());
        detailParams.setSpecificationIds(specificationIds);
        List<TqPriceDetail> priceDetailList = CollectionUtils.isNotEmpty(specificationIds) ?
                priceDetailService.selectTqPriceDetailList(detailParams): Lists.newArrayList();
        Map<Long, List<TqPriceDetail>> priceDetailMap = priceDetailList.stream()
                .filter(item -> nonNull(item.getTotal()) && item.getTotal().compareTo(BigDecimal.ZERO) > 0)
                .collect(Collectors.groupingBy(TqPriceDetail::getSpecificationId));
        Map<String, String> optionalsMap = Maps.newHashMap();
        priceDetailMap.entrySet().forEach(entry -> {
            JSONObject data = dataMap.get(entry.getKey());
            String no = data.getString("no");
            entry.getValue().forEach(item -> {
                if (isNotBlank(item.getExportParaCodes())){
                    Arrays.stream(item.getExportParaCodes().split(",")).forEach(code ->{
                        String str = paraItemNameMap.get(data.getString(code));
                        String key = paraNameMap.get(code) + ":" + (nonNull(str) ? str: data.getString(code));
                        String value = optionalsMap.get(key);
                        if (isNotBlank(value)){
                            value += "," + no;
                        } else {
                            value = no;
                        }
                        optionalsMap.put(key, value);
                    });
                }
            });
        });
        List<JSONObject> optionals = Lists.newArrayList();
        int i = 1;
        for (String key : optionalsMap.keySet()) {
            JSONObject data = new JSONObject();
            data.put("key", i++ + ". " + key);
            data.put("value", optionalsMap.get(key));
            optionals.add(data);
        }

        // 1.4 材质类型图片
        List<TpParaSelectItem> imageList = tpParaSelectItemMapper.selectImageListAll();
        Map<String, List<TpParaSelectItem>> imageMap = imageList.stream()
                .collect(Collectors.groupingBy(item -> item.getValue()));

        List<MaterialImageVO> images = new ArrayList<>();
        imageKeys.stream().distinct().forEach(key -> {
            if (CollectionUtils.isNotEmpty(imageMap.get(key))) {
                MaterialImageVO exist = images.size() > 0 ? images.get(images.size() - 1) : null;
                String code = paraItemNameMap.get(key);
                String path = RuoYiConfig.getProfile() + StringUtils.substringAfter(imageMap.get(key).get(0).getPrarSource(), Constants.RESOURCE_PREFIX);
                FileImageProvider file = new FileImageProvider(new File(path), true);
                file.setWidth(250f);
                file.setResize(true);
                if (nonNull(exist) && Objects.isNull(exist.getCodeRight())){
                    exist.setCodeRight(code);
                    exist.setPhotoRight(file);
                } else {
                    exist = new MaterialImageVO();
                    exist.setCodeLeft(code);
                    exist.setPhotoLeft(file);
                    images.add(exist);
                }
            }
        });
        // 1.5 预览图
        List<TbFile> previewList = tbFileService.selectTbFileListByBuzIdAndBuzType(id, FileBuzType.SPECIFICATION_CIVIL_IMG.getType());

        // 2. 转换数据格式
        // 2.1 基础信息
        Map<String, Object> map = Maps.newHashMap();
        map.put("quotationNo", tqQuotation.getQuotationNo());
        map.put("project", tcProject.getProjectName());
        map.put("to", tcAccount.getAccountName());
        map.put("contact", tcProject.getContact());
        map.put("email", tcProject.getEmail());
        map.put("date", DateUtils.parseDateToStr("yyyy-MM-dd", tqQuotation.getCreateTime()));
        // 2.2 规格信息
        map.put("specifications", specifications);
        // 2.3 规格统计信息
        String targetPort = "";
        if (isNotBlank(tqQuotation.getTargetPort())){
            targetPort = DictUtils.getInternationalDictLabel("target_port", tqQuotation.getTargetPort());
            //装船口岸需要字典
            map.put("targetPort", "- To " + targetPort);
        }
        if (isNotBlank(tqQuotation.getTradeType())){
            map.put("tradeType", "(" + DictUtils.getInternationalDictLabel("contract_trade_terms", tqQuotation.getTradeType()) + " " + targetPort + ")");
        }
        map.put("freightPrice", currencyName + format.format(totalFreight));
        map.put("freightRemarks", freightRemarks.stream().filter(StringUtils::isNotBlank).collect(Collectors.joining(",")));
        totalPrice = totalPrice.add(totalFreight);
        map.put("totalPrice", currencyName + format.format(totalPrice));
        // 2.4 选配信息
        if (optionals.size() > 0) {
            map.put("optionalTitle", "Optional Function");
        }
        map.put("optionals", optionals);
        // 2.5 材质图片
        map.put("images", images);
        // 2.6 预览图
        String path = CollectionUtils.isNotEmpty(previewList) ? RuoYiConfig.getProfile() + StringUtils.substringAfter(previewList.get(0).getFilePath(), Constants.RESOURCE_PREFIX): "/null";
        FileImageProvider file = new FileImageProvider(new File(path), true);
        file.setBehaviour(NullImageBehaviour.RemoveImageTemplate);
        file.setWidth(600f);
        file.setResize(true);
        map.put("preview", file);

        // 3. 填充模板并返回
        new CommonDocUtils()
                .loadFromClasspath("/wordTemplate/报价单.docx")
                .replaceData(map)
                .download();
    }

    public static void main(String[] args) {
        // 2.1 基础信息
        Map<String, Object> map = Maps.newHashMap();
        map.put("buyers","陈杰");
        // 3. 填充模板并返回
        new CommonDocUtils()
                .loadFromClasspath("/wordTemplate/国际部销售合同模版2024test.docx")
                .replaceData(map)
                .download();
    }


    @Override
    public List<QuotationVO> selectTqQuotationListAll(QuotationQueryBO queryBO) {
        SpecialCharacterEscaper.escapeSpecialCharacters(queryBO
                , QuotationQueryBO::getQuotationNo
                , QuotationQueryBO::getProjectName
                , QuotationQueryBO::getCity
                , QuotationQueryBO::getElevatorModel
                , QuotationQueryBO::getNickName
        );
        String permissionCharIns = SecurityUtils.getPermissionCharIns();
        queryBO.setPermissionChar(permissionCharIns);
        // 代理商销售经理的场合
        if (SecurityUtils.hasRole("agent_sales")) {
            queryBO.setLoginUserId(SecurityUtils.getUserId());
            queryBO.setPermission(SecurityUtils.getPermissionCharIns());
        }
        List<QuotationVO> quotationVOS = baseMapper.selectTqQuotationList(queryBO);

        Map<String, String> typeMap = DictI18nUtil.getI18nLabel("quotation_status");
        Map<String, String> currencyMap = DictI18nUtil.getI18nLabel("currency_type");
        //处理数据
        for(QuotationVO item : quotationVOS){
            //如果状态《6则价格全为-
            if(Integer.parseInt(item.getQuotationStatus())>=6){
                //如果FinalCurrencyPrice没有则使用price
                BigDecimal addfis = ObjectUtils.isEmpty(item.getAdditionalFees())?BigDecimal.ZERO:item.getAdditionalFees();
                item.setPrice(ObjectUtils.isEmpty(item.getPrice())?BigDecimal.ZERO:item.getPrice());
                if(ObjectUtils.isEmpty(item.getFinalCurrencyPrice())){
                    item.setFinalCurrencyPrice(item.getPrice());
                    item.setTotalPrice(item.getPrice().add(addfis));
                }else {
                    item.setTotalPrice(item.getFinalCurrencyPrice().add(addfis));
                }
            }else {
                item.setFinalPrice(null);
                item.setFinalCurrencyPrice(null);
                item.setTotalPrice(null);
            }

            //设置状态
            item.setQuotationStatusName(typeMap.get(item.getQuotationStatus()));
            //设置币种
            item.setCurrencyName(currencyMap.get(item.getCurrencyId().toString()));
            //设置日期
            item.setSubmitTimeStr(DateUtils.dateTime(item.getSubmitTime()));

        }
        return quotationVOS;
    }


    @Override
    public List<QuotationContractVo> getQuotation4Contract(QuotationContractBo quotationContractBo){
        return tqSpecificationMapper.getQuotation4Contract(quotationContractBo);
    }
}
