# Next14DaysServiceImpl.java

    package cloud.wconnect.rateshop.service.revenue.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.UpdateLog;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.commonlib.util.NumberUtil;
    import cloud.wconnect.commonlib.util.UpdateLogUtil;
    import cloud.wconnect.rateshop.cons.rateshop.RateTypeEnum;
    import cloud.wconnect.rateshop.entity.rateshop.Hotel;
    import cloud.wconnect.rateshop.entity.rateshop.Setting;
    import cloud.wconnect.rateshop.entity.revenue.HistoryBARRateNextNDays;
    import cloud.wconnect.rateshop.entity.revenue.HistoryRateNextNDays;
    import cloud.wconnect.rateshop.entity.revenue.HistoryRateNextNDaysManual;
    import cloud.wconnect.rateshop.entity.revenue.LatestRateManual;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.LatestHotelPriceDTO;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.RateConfigDTO;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.filterrate.RateQuery;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.filterrate.RateValue;
    import cloud.wconnect.rateshop.pojo.dto.revenue.*;
    import cloud.wconnect.rateshop.pojo.query.rateshop.LatestHotelPriceQuery;
    import cloud.wconnect.rateshop.pojo.query.revenue.Next14DaysRateQuery;
    import cloud.wconnect.rateshop.service.rateshop.ILatestBARRateService;
    import cloud.wconnect.rateshop.service.rateshop.ILatestRateService;
    import cloud.wconnect.rateshop.service.revenue.*;
    import cloud.wconnect.rateshop.util.rateshop.FilterRateUtil;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.math.BigDecimal;
    import java.time.LocalDate;
    import java.time.format.DateTimeFormatter;
    import java.util.*;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    /**
     * 查询未来14天房价的业务层
     *
     * @author lichen
     * @date 2024/5/16
     */
    @Service
    @DS("rate_shop")
    public class Next14DaysServiceImpl implements INext14DaysService {

        @Autowired
        private ILatestBARRateService latestBARRateService;
        @Autowired
        private ILatestRateService latestRateService;
        @Autowired
        private ILatestRateManualService latestRateManualService;
        @Autowired
        private UpdateLogUtil updateLogUtil;
        @Autowired
        private IHistoryRateNextNDaysManualService historyRateNextNDaysManualService;
        @Autowired
        private IHistoryRateNextNDaysService historyRateNextNDaysService;
        @Autowired
        private IHistoryBARRateNextNDaysService historyBARRateNextNDaysService;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private IRevenueHurdlePointService revenueHurdlePointService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IRevenueHurdlePointFutureService revenueHurdlePointFutureService;

        /**
         * 查询历史及当前日期的 指定酒店未来14天的房价
         *
         * @param date                原点日期（yyyy-MM-dd）
         * @param hotel               酒店
         * @param propertyDTO         当前资产DTO
         * @param setting             资产的setting
         * @param next14DaysRateQuery 查询条件（数据源、平台）
         * @return java.util.List<cloud.wconnect.rateshop.pojo.dto.revenue.Next14DaysRateDTO>
         * @author lichen
         * @date 2024/5/16
         */
        @Override
        public List<Next14DaysRateDTO> listHistoryDateNext14DaysRate(String date, Hotel hotel, PropertyDTO propertyDTO, Setting setting, Next14DaysRateQuery next14DaysRateQuery) {
            //销售地区
            String pos = setting.getPos();
            //币种ID
            Integer currencyId = setting.getCurrencyId();
            //yyyyMMdd
            Integer targetDate = Integer.valueOf(date.replace("-", ""));
            //资产配置的房价参数
            List<RateConfigDTO> rateConfigDTOS = JsonUtils.convertStringToList(objectMapper, setting.getRateConfig(), RateConfigDTO.class);
            Set<Integer> rateTypes = rateConfigDTOS.stream().map(RateConfigDTO::getRateType).collect(Collectors.toSet());

            //查询采集的BAR房价
            Map<Long, List<DayHotelPriceDTO>> checkInDate2BARRateList = Collections.emptyMap();
            if (rateTypes.contains(RateTypeEnum.BEST_AVAILABLE_RATE.getRateType())) {
                HistoryBARRateNextNDays next14DaysBARRate = historyBARRateNextNDaysService.getNext14DaysRate(propertyDTO.getTenantId(), propertyDTO.getId(), hotel.getId(), targetDate, currencyId, pos);
                if (Objects.nonNull(next14DaysBARRate)) {
                    //指定原点日期，未来14日的房价
                    checkInDate2BARRateList = filterRate(next14DaysBARRate.getData(), next14DaysRateQuery.getDatasourceIdByBAR(), next14DaysRateQuery.getPlatformIdByBAR(),
                            rateConfigDTOS, RateTypeEnum.BEST_AVAILABLE_RATE.getRateType())
                            .stream().collect(Collectors.groupingBy(DayHotelPriceDTO::getCheckInDate));
                }
            }

            //查询采集的早鸟价
            Map<Long, List<DayHotelPriceDTO>> checkInDate2RateList = Collections.emptyMap();
            if (rateTypes.contains(RateTypeEnum.EARLY_BIRD_RATE.getRateType())) {
                HistoryRateNextNDays next14DaysRate = historyRateNextNDaysService.getNext14DaysRate(propertyDTO.getTenantId(), propertyDTO.getId(), hotel.getId(), targetDate, currencyId, pos);
                if (Objects.nonNull(next14DaysRate)) {
                    //指定原点日期，未来14日的房价
                    checkInDate2RateList = filterRate(next14DaysRate.getData(), next14DaysRateQuery.getDatasourceIdByEBR(), next14DaysRateQuery.getPlatformIdByEBR(),
                            rateConfigDTOS, RateTypeEnum.EARLY_BIRD_RATE.getRateType())
                            .stream().collect(Collectors.groupingBy(DayHotelPriceDTO::getCheckInDate));
                }
            }

            //未来14天手动维护的房价
            Map<Integer, List<HistoryRateNextNDaysManual>> checkInDate2HistoryRateNextNDaysManualList = historyRateNextNDaysManualService.list(
                            hotel.getId(), setting.getCurrencyId(), targetDate, propertyDTO.getId(), pos)
                    .stream().collect(Collectors.groupingBy(HistoryRateNextNDaysManual::getCheckInDate));

            ArrayList<Next14DaysRateDTO> next14DaysRateDTOS = Lists.newArrayListWithCapacity(14);
            LocalDate startLocalDate = LocalDate.parse(date, DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYY_MM_DD));
            LocalDate endLocalDate = startLocalDate.plusDays(13);
            for (LocalDate localDate = startLocalDate; !localDate.isAfter(endLocalDate); localDate = localDate.plusDays(1)) {
                //当前的入住日期
                String checkInDate = localDate.format(DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYY_MM_DD));

                Long checkInDateLong = Long.valueOf(checkInDate.replace("-", ""));

                //指定日期的房价集合
                ArrayList<Next14DaysRatesDTO> rates = Lists.newArrayListWithCapacity(2);

                //手动维护的房价集合
                List<Next14DaysRatesDTO> next14DaysRatesDTOSByManual = this.convertByHistoryRateNextNDaysManual(
                        checkInDate2HistoryRateNextNDaysManualList.get(Integer.valueOf(checkInDateLong.toString())),
                        setting.getContainTaxFlag());

                if (CollectionUtils.isNotEmpty(next14DaysRatesDTOSByManual)) {
                    rates.addAll(next14DaysRatesDTOSByManual);
                }

                List<Integer> rateTypelist = next14DaysRatesDTOSByManual.stream().map(Next14DaysRatesDTO::getRateType).toList();
                if (!rateTypelist.contains(RateTypeEnum.BEST_AVAILABLE_RATE.getRateType())) {
                    //指定日期的最低BAR房价
                    DayHotelPriceDTO lowestBARPrice = getPriceOrderByQueryDateAndRate(checkInDate2BARRateList.get(checkInDateLong), setting.getContainTaxFlag());
                    if (Objects.nonNull(lowestBARPrice)) {
                        rates.add(convertByAutoDayHotelPriceDTO(lowestBARPrice, setting.getContainTaxFlag(), RateTypeEnum.BEST_AVAILABLE_RATE.getRateType()));
                    }
                }
                if (!rateTypelist.contains(RateTypeEnum.EARLY_BIRD_RATE.getRateType())) {
                    //指定日期的最低早鸟房价
                    DayHotelPriceDTO lowestPrice = getPriceOrderByQueryDateAndRate(checkInDate2RateList.get(checkInDateLong), setting.getContainTaxFlag());
                    if (Objects.nonNull(lowestPrice)) {
                        rates.add(convertByAutoDayHotelPriceDTO(lowestPrice, setting.getContainTaxFlag(), RateTypeEnum.EARLY_BIRD_RATE.getRateType()));
                    }
                }
                next14DaysRateDTOS.add(new Next14DaysRateDTO(hotel.getSymbol(), checkInDate, rates));
            }
            return next14DaysRateDTOS;
        }

        /**
         * 根据queryDate和rate排序获取最低房价
         *
         * @param hotelPriceDTOS 指定日期的房价集合
         * @param containTaxFlag 含税标识
         * @return cloud.wconnect.rateshop.entity.rateshop.LatestRate
         * @author lichen
         * @date 2025/8/12
         */
        private DayHotelPriceDTO getPriceOrderByQueryDateAndRate(List<DayHotelPriceDTO> hotelPriceDTOS, Integer containTaxFlag) {
            if (CollectionUtils.isEmpty(hotelPriceDTOS)) return null;

            //指定日期非空的价格集合
            List<DayHotelPriceDTO> rateListByCheckInDateByNotNull = hotelPriceDTOS.stream().filter(item -> {
                if (containTaxFlag.equals(Setting.BEFORE_TAX_RATE)) {//税前价格
                    return Objects.nonNull(item.getPrice());
                } else {//税后价格
                    return Objects.nonNull(item.getAfterTaxPrice());
                }
            }).toList();
            if (CollectionUtils.isNotEmpty(rateListByCheckInDateByNotNull)) {
                //按照查询时刻（yyyyMMddHH）分组
                Map<Integer, List<DayHotelPriceDTO>> queryHour2LatestRate = rateListByCheckInDateByNotNull.stream().collect(Collectors.groupingBy(item -> {
                    Long queryDate = item.getQueryDate();
                    return Integer.valueOf(DateTimeUtils.timestampToStr(queryDate, BaseConstant.DATE_FORMAT_YYYYMMDDHH, ""));
                }));
                //查询时刻集合
                ArrayList<Integer> queryHourList = new ArrayList<>(queryHour2LatestRate.keySet());
                queryHourList.sort(Comparator.reverseOrder());
                //获取最大时刻的房价集合
                List<DayHotelPriceDTO> latestRatesByMaxQueryHour = queryHour2LatestRate.get(queryHourList.get(0));

                //所有的房价都是0才表示当天是Sold out
                boolean isSoldOut = latestRatesByMaxQueryHour.stream().allMatch(item -> {
                    if (containTaxFlag.equals(Setting.BEFORE_TAX_RATE)) {
                        return item.getPrice().compareTo(BigDecimal.ZERO) == 0;
                    } else {
                        return item.getAfterTaxPrice().compareTo(BigDecimal.ZERO) == 0;
                    }
                });
                DayHotelPriceDTO result;
                if (isSoldOut) {
                    //取任意一条数据即可
                    result = latestRatesByMaxQueryHour.get(0);
                } else {
                    //取房价最低的数据
                    Optional<DayHotelPriceDTO> optional = latestRatesByMaxQueryHour.stream()
                            .filter(item -> {
                                if (containTaxFlag.equals(Setting.BEFORE_TAX_RATE)) {
                                    return item.getPrice().compareTo(BigDecimal.ZERO) > 0;
                                } else {
                                    return item.getAfterTaxPrice().compareTo(BigDecimal.ZERO) > 0;
                                }
                            })
                            .min(Comparator.comparing(item -> {
                                if (containTaxFlag.equals(Setting.BEFORE_TAX_RATE)) {
                                    return item.getPrice();
                                } else {
                                    return item.getAfterTaxPrice();
                                }
                            }));
                    result = optional.orElse(null);
                }
                return result;
            }
            return null;
        }

        /**
         * 根据数据源、平台筛选房价数据
         *
         * @param rateJson            房价json数据
         * @param datasourceIdByQuery 筛选的数据源ID
         * @param platformIdByQuery   筛选的平台ID
         * @param rateConfigDTOS      房价配置参数
         * @param rateType            房价类型
         * @return java.util.List<cloud.wconnect.rateshop.pojo.dto.revenue.DayHotelPriceDTO>
         * @author lichen
         * @date 2024/5/16
         */
        private List<DayHotelPriceDTO> filterRate(String rateJson, Integer datasourceIdByQuery, Integer platformIdByQuery, List<RateConfigDTO> rateConfigDTOS, int rateType) {
            //查询对象
            RateQuery rateQuery = RateQuery.builder()
                    .datasourceId(datasourceIdByQuery)
                    .platformId(platformIdByQuery)
                    .roomIds(Collections.emptyList())
                    .build();
            //指定条件下的房价集合
            return JsonUtils.convertStringToList(objectMapper, rateJson, DayHotelPriceDTO.class).stream()
                    .filter(rate -> {
                        RateValue rateValue = beanMapper.map(rate, RateValue.class);
                        return FilterRateUtil.isMatchByQueryCondition(rateValue, rateQuery, rateConfigDTOS, rateType);
                    }).toList();
        }

        /**
         * 查询未来日期的 指定酒店未来14天的房价
         *
         * @param date                原点日期（yyyy-MM-dd）
         * @param hotel               酒店
         * @param propertyDTO         当前资产DTO
         * @param setting             资产的setting
         * @param next14DaysRateQuery 查询条件（数据源、平台）
         * @return java.util.List<cloud.wconnect.rateshop.pojo.dto.revenue.Next14DaysRateDTO>
         * @author lichen
         * @date 2024/5/16
         */
        @Override
        public List<Next14DaysRateDTO> listFutureDateNext14DaysRate(String date, Hotel hotel, PropertyDTO propertyDTO, Setting setting, Next14DaysRateQuery next14DaysRateQuery) {
            //销售地区
            String pos = setting.getPos();
            //资产配置的房价参数
            List<RateConfigDTO> rateConfigDTOS = JsonUtils.convertStringToList(objectMapper, setting.getRateConfig(), RateConfigDTO.class);
            //资产配置的房价类型
            Set<Integer> rateTypes = rateConfigDTOS.stream().map(RateConfigDTO::getRateType).collect(Collectors.toSet());

            //13天后的日期
            LocalDate after13LocalDate = LocalDate.parse(date, DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYY_MM_DD))
                    .plusDays(13);

            //未来14天数据的区间范围
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYYMMDD);
            Long startDate = Long.valueOf(date.replace("-", ""));
            Long endDate = Long.valueOf(after13LocalDate.format(dateTimeFormatter));

            //查询未来14天的最低的BAR房价
            Map<String, LatestHotelPriceDTO> checkInDate2LatestBARRates = Collections.emptyMap();
            if (rateTypes.contains(RateTypeEnum.BEST_AVAILABLE_RATE.getRateType())) {
                LatestHotelPriceQuery latestHotelBARPriceQuery = LatestHotelPriceQuery.builder()
                        .fromDate(startDate)
                        .toDate(endDate)
                        .datasourceId(next14DaysRateQuery.getDatasourceIdByBAR())
                        .platformId(next14DaysRateQuery.getPlatformIdByBAR())
                        .roomIds(Collections.emptyList())
                        .build();
                List<LatestHotelPriceDTO> latestHotelPriceDTOS = latestBARRateService.listLowestBARHotelPrice(Collections.singletonList(hotel.getId()),
                        setting.getCurrencyId(), setting.getContainTaxFlag(), latestHotelBARPriceQuery, rateConfigDTOS, pos);
                checkInDate2LatestBARRates = latestHotelPriceDTOS.stream().collect(Collectors.toMap(LatestHotelPriceDTO::getDate, Function.identity()));
            }

            //查询未来14天最低的早鸟价
            Map<String, LatestHotelPriceDTO> checkInDate2LatestRates = Collections.emptyMap();
            if (rateTypes.contains(RateTypeEnum.EARLY_BIRD_RATE.getRateType())) {
                LatestHotelPriceQuery latestHotelEBRPriceQuery = LatestHotelPriceQuery.builder()
                        .fromDate(startDate)
                        .toDate(endDate)
                        .datasourceId(next14DaysRateQuery.getDatasourceIdByEBR())
                        .platformId(next14DaysRateQuery.getPlatformIdByEBR())
                        .roomIds(Collections.emptyList())
                        .build();
                List<LatestHotelPriceDTO> latestHotelPriceDTOS = latestRateService.listLowestEBRHotelPrice(Collections.singletonList(hotel.getId()),
                        setting.getCurrencyId(), setting.getContainTaxFlag(), latestHotelEBRPriceQuery, rateConfigDTOS, pos);
                checkInDate2LatestRates = latestHotelPriceDTOS.stream().collect(Collectors.toMap(LatestHotelPriceDTO::getDate, Function.identity()));
            }

            //查询手动编辑的房价
            List<LatestRateManual> latestRateManuals = latestRateManualService.list(hotel.getId(), setting.getCurrencyId(),
                    Integer.valueOf(startDate.toString()), Integer.valueOf(endDate.toString()), propertyDTO.getId(), pos);
            Map<Integer, List<LatestRateManual>> checkInDate2LatestRateManuals = latestRateManuals.stream().collect(Collectors.groupingBy(LatestRateManual::getCheckInDate));

            ArrayList<Next14DaysRateDTO> next14DaysRateDTOS = Lists.newArrayListWithCapacity(14);
            LocalDate startLocalDate = LocalDate.parse(date, DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYY_MM_DD));
            LocalDate endLocalDate = startLocalDate.plusDays(13);
            for (LocalDate localDate = startLocalDate; !localDate.isAfter(endLocalDate); localDate = localDate.plusDays(1)) {
                //当前的入住日期
                String checkInDate = localDate.format(DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYY_MM_DD));

                //指定日期的房价集合
                ArrayList<Next14DaysRatesDTO> rates = Lists.newArrayListWithCapacity(2);

                //指定日期下手动维护的房价
                List<Next14DaysRatesDTO> next14DaysRatesDTOSByManual = this.convertByLatestRateManual(
                        checkInDate2LatestRateManuals.get(Integer.valueOf(checkInDate.replace("-", ""))),
                        setting.getContainTaxFlag());

                if (CollectionUtils.isNotEmpty(next14DaysRatesDTOSByManual)) {
                    rates.addAll(next14DaysRatesDTOSByManual);
                }

                //指定查询条件指定日期下的最低BAR房价
                LatestHotelPriceDTO latestHotelPriceDTOByBAR = checkInDate2LatestBARRates.get(checkInDate);
                //指定查询条件指定日期下最低的早鸟价
                LatestHotelPriceDTO latestHotelPriceDTO = checkInDate2LatestRates.get(checkInDate);

                List<Integer> rateTypeList = next14DaysRatesDTOSByManual.stream().map(Next14DaysRatesDTO::getRateType).toList();
                //手动维护的BAR房价为空时，添加自动导入的BAR房价
                if (!rateTypeList.contains(RateTypeEnum.BEST_AVAILABLE_RATE.getRateType()) && Objects.nonNull(latestHotelPriceDTOByBAR)) {
                    //自动导入的BAR房价
                    rates.add(this.convertByAutoLatestHotelPriceDTO(latestHotelPriceDTOByBAR));
                }
                //手动维护的早鸟价为空时，添加自动导入的早鸟价
                if (!rateTypeList.contains(RateTypeEnum.EARLY_BIRD_RATE.getRateType()) && Objects.nonNull(latestHotelPriceDTO)) {
                    //自动导入的早鸟价
                    rates.add(this.convertByAutoLatestHotelPriceDTO(latestHotelPriceDTO));
                }
                next14DaysRateDTOS.add(new Next14DaysRateDTO(hotel.getSymbol(), checkInDate, rates));
            }
            return next14DaysRateDTOS;
        }

        /**
         * 修改未来14天的数据(HurdlePoint和rate)
         *
         * @param propertyDTO                  资产
         * @param date                         指定日期（YYYY-MM-DD)
         * @param updateHurdlerPointAndRateDTO 修改内容
         * @param userId                       操作人
         * @param properties                   当前操作人所属资产
         * @return void
         * @author lichen
         * @date 2024/5/17
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void updateHistoryDateNext14DaysData(PropertyDTO propertyDTO, String date, UpdateHurdlerPointAndRateDTO updateHurdlerPointAndRateDTO, int userId, List<Integer> properties) {
            List<UpdateHurdlerPointDTO> hurdlePoints = updateHurdlerPointAndRateDTO.getHurdlePoint();
            if (CollectionUtils.isNotEmpty(hurdlePoints)) {
                revenueHurdlePointService.updateHurdlePoint(propertyDTO, date, hurdlePoints, userId);
            }

            List<UpdateRateDTO> roomRates = updateHurdlerPointAndRateDTO.getRoomRate();
            if (CollectionUtils.isNotEmpty(roomRates)) {
                //修改history_rate_next_n_days_manual
                historyRateNextNDaysManualService.updateRates(propertyDTO, date, roomRates, updateHurdlerPointAndRateDTO.getSyncOtherProperty(), userId, properties);
            }
        }

        /**
         * 修改未来日期-未来14天的数据(HurdlePoint和rate)
         *
         * @param propertyDTO                  资产
         * @param date                         指定日期（YYYY-MM-DD)
         * @param updateHurdlerPointAndRateDTO 修改内容
         * @param userId                       操作人
         * @param properties                   当前操作人所属资产
         * @return void
         * @author lichen
         * @date 2025/01/03
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void updateFutureDateNext14DaysData(PropertyDTO propertyDTO, String date, UpdateHurdlerPointAndRateDTO updateHurdlerPointAndRateDTO, int userId, List<Integer> properties) {
            List<UpdateHurdlerPointDTO> hurdlePoints = updateHurdlerPointAndRateDTO.getHurdlePoint();
            if (CollectionUtils.isNotEmpty(hurdlePoints)) {
                revenueHurdlePointFutureService.updateHurdlePoint(propertyDTO, hurdlePoints, userId);
            }

            List<UpdateRateDTO> roomRates = updateHurdlerPointAndRateDTO.getRoomRate();
            if (CollectionUtils.isNotEmpty(roomRates)) {
                //修改latest_rate_manual
                latestRateManualService.updateRates(propertyDTO, roomRates, updateHurdlerPointAndRateDTO.getSyncOtherProperty(), userId, properties);
            }
        }

        /**
         * 手动维护的房价转化成 未来14天房价DTO
         *
         * @param latestRateManuals 手动维护的房价
         * @param containTaxFlag    含税标识 1: 税前 2：税后
         * @return cloud.wconnect.rateshop.pojo.dto.revenue.Next14DaysRatesDTO
         * @author lichen
         * @date 2024/5/16
         */
        private List<Next14DaysRatesDTO> convertByLatestRateManual(List<LatestRateManual> latestRateManuals, int containTaxFlag) {
            if (CollectionUtils.isEmpty(latestRateManuals)) return Collections.emptyList();

            ArrayList<Next14DaysRatesDTO> next14DaysRatesDTOS = Lists.newArrayListWithCapacity(latestRateManuals.size());
            for (LatestRateManual latestRateManual : latestRateManuals) {
                //房价
                String price = Setting.BEFORE_TAX_RATE == containTaxFlag ? latestRateManual.getRate() : latestRateManual.getAfterTaxRate();
                if (StringUtils.isNotBlank(price)) {
                    UpdateLog lastUpdateLog = updateLogUtil.getLast(latestRateManual.getUpdateLog());
                    //手动编辑的房价支持录入符号，所以此处先判断是否BigDecimal
                    BigDecimal priceBigDecimal = NumberUtil.isBigDecimal(price) ? new BigDecimal(price) : null;

                    next14DaysRatesDTOS.add(new Next14DaysRatesDTO().setPlatformId(latestRateManual.getPlatformId())
                            .setPrice(price).setPriceBigDecimal(priceBigDecimal)
                            .setDatasourceId(0)
                            .setOperatorId(lastUpdateLog.getUid())
                            .setUpdateDate(lastUpdateLog.getTimestamp())
                            .setRateType(latestRateManual.getRateType()));
                }
            }
            return next14DaysRatesDTOS;
        }

        /**
         * 自动导入房价转换成 未来14天房价DTO
         *
         * @param latestHotelPriceDTO 最低房价
         * @return cloud.wconnect.rateshop.pojo.dto.revenue.Next14DaysRatesDTO
         * @author lichen
         * @date 2025/8/12
         */
        private Next14DaysRatesDTO convertByAutoLatestHotelPriceDTO(LatestHotelPriceDTO latestHotelPriceDTO) {
            Next14DaysRatesDTO next14DaysRatesDTO = new Next14DaysRatesDTO();
            next14DaysRatesDTO.setPlatformId(latestHotelPriceDTO.getPlatformId());
            next14DaysRatesDTO.setPriceBigDecimal(latestHotelPriceDTO.getPrice());
            next14DaysRatesDTO.setPrice(Objects.nonNull(latestHotelPriceDTO.getPrice()) ? latestHotelPriceDTO.getPrice().toString() : null);
            next14DaysRatesDTO.setDatasourceId(latestHotelPriceDTO.getDatasourceId());
            next14DaysRatesDTO.setOperatorId(0);
            next14DaysRatesDTO.setUpdateDate(latestHotelPriceDTO.getUpdateTime());
            next14DaysRatesDTO.setRateType(latestHotelPriceDTO.getRateType());
            return next14DaysRatesDTO;
        }

        /**
         * 自动导入的带版本房价 转换成未来14天房价的DTO
         *
         * @param dayHotelPriceDTO 房价
         * @param containTaxFlag   含税标识
         * @param rateType         房价类型
         * @return java.util.ArrayList<cloud.wconnect.rateshop.pojo.dto.revenue.Next14DaysRatesDTO>
         * @author lichen
         * @date 2024/5/16
         */
        private Next14DaysRatesDTO convertByAutoDayHotelPriceDTO(DayHotelPriceDTO dayHotelPriceDTO, Integer containTaxFlag, Integer rateType) {
            BigDecimal price;
            if (containTaxFlag.equals(Setting.BEFORE_TAX_RATE)) {
                price = dayHotelPriceDTO.getPrice();
            } else {
                price = dayHotelPriceDTO.getAfterTaxPrice();
            }

            Next14DaysRatesDTO next14DaysRatesDTO = new Next14DaysRatesDTO();
            next14DaysRatesDTO.setPlatformId(dayHotelPriceDTO.getPlatformId());
            next14DaysRatesDTO.setPriceBigDecimal(price);
            next14DaysRatesDTO.setPrice(Objects.nonNull(price) ? price.toString() : null);
            next14DaysRatesDTO.setDatasourceId(dayHotelPriceDTO.getDatasourceId());
            next14DaysRatesDTO.setOperatorId(0);
            next14DaysRatesDTO.setUpdateDate(dayHotelPriceDTO.getQueryDate());
            next14DaysRatesDTO.setRateType(rateType);
            return next14DaysRatesDTO;
        }

        /**
         * 手动维护的带版本的房价 转化成未来14天房价的DTO
         *
         * @param historyRateNextNDaysManuals 手动维护的带版本的房价集合
         * @param containTaxFlag              含税标识 1: 税前 2：税后
         * @return java.util.List<cloud.wconnect.rateshop.pojo.dto.revenue.Next14DaysRatesDTO>
         * @author lichen
         * @date 2024/5/16
         */
        private List<Next14DaysRatesDTO> convertByHistoryRateNextNDaysManual(List<HistoryRateNextNDaysManual> historyRateNextNDaysManuals, Integer containTaxFlag) {
            if (CollectionUtils.isEmpty(historyRateNextNDaysManuals)) return Collections.emptyList();

            ArrayList<Next14DaysRatesDTO> next14DaysRatesDTOS = Lists.newArrayListWithCapacity(historyRateNextNDaysManuals.size());
            for (HistoryRateNextNDaysManual historyRateNextNDaysManual : historyRateNextNDaysManuals) {
                //房价
                String price = Setting.BEFORE_TAX_RATE == containTaxFlag ? historyRateNextNDaysManual.getRate() : historyRateNextNDaysManual.getAfterTaxRate();
                if (StringUtils.isNotBlank(price)) {
                    UpdateLog lastUpdateLog = updateLogUtil.getLast(historyRateNextNDaysManual.getUpdateLog());
                    //手动编辑的房价支持录入符号，所以此处先判断是否BigDecimal
                    BigDecimal priceBigDecimal = NumberUtil.isBigDecimal(price) ? new BigDecimal(price) : null;

                    next14DaysRatesDTOS.add(new Next14DaysRatesDTO().setPlatformId(historyRateNextNDaysManual.getPlatformId())
                            .setPrice(price).setPriceBigDecimal(priceBigDecimal)
                            .setDatasourceId(0)
                            .setOperatorId(lastUpdateLog.getUid())
                            .setUpdateDate(lastUpdateLog.getTimestamp())
                            .setRateType(historyRateNextNDaysManual.getRateType()));
                }
            }
            return next14DaysRatesDTOS;
        }
    }