# WeeklyMonthlyRevenueInternalServiceImpl.java

    package cloud.wconnect.rateshop.service.weeklymonthlyrevenue.internal.impl;

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.redis.PropertyBusinessDateRedisService;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.rateshop.cons.weeklymonthlyrevenue.MonthlyRevenueImportCategoryCons;
    import cloud.wconnect.rateshop.entity.weeklymonthlyrevenue.WeeklyMonthlyRevenueSegment;
    import cloud.wconnect.rateshop.entity.weeklymonthlyrevenue.WeeklyMonthlyRevenueVersionData;
    import cloud.wconnect.rateshop.pojo.bo.weeklymonthlyrevenue.WMRevenueCancellationSummaryBO;
    import cloud.wconnect.rateshop.pojo.bo.weeklymonthlyrevenue.WMRevenueGroupPickupBO;
    import cloud.wconnect.rateshop.pojo.dto.weeklymonthlyrevenue.internal.MonthlyRevenueInternalDTO;
    import cloud.wconnect.rateshop.pojo.dto.weeklymonthlyrevenue.internal.grouppickup.MonthlyRevenueGrcValueInternalDTO;
    import cloud.wconnect.rateshop.pojo.dto.weeklymonthlyrevenue.versiondata.WMRevenueVersionDataDTO;
    import cloud.wconnect.rateshop.service.weeklymonthlyrevenue.IWeeklyMonthlyRevenueReportService;
    import cloud.wconnect.rateshop.service.weeklymonthlyrevenue.IWeeklyMonthlyRevenueSegmentService;
    import cloud.wconnect.rateshop.service.weeklymonthlyrevenue.IWeeklyMonthlyRevenueVersionDataService;
    import cloud.wconnect.rateshop.service.weeklymonthlyrevenue.internal.IWeeklyMonthlyRevenueInternalService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Maps;
    import jakarta.annotation.Resource;
    import org.springframework.stereotype.Service;

    import java.time.LocalDate;
    import java.time.ZoneId;
    import java.util.*;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    /**
     * <p>
     * Weekly Monthly Revenue Internal Service
     * </p>
     *
     * @author zc
     * @since 2024-10-17
     */
    @Service
    @DS("rate_shop")
    public class WeeklyMonthlyRevenueInternalServiceImpl implements IWeeklyMonthlyRevenueInternalService {
        @Resource
        private IWeeklyMonthlyRevenueSegmentService segmentService;
        @Resource
        private IWeeklyMonthlyRevenueVersionDataService versionDataService;
        @Resource
        private IWeeklyMonthlyRevenueReportService reportService;
        @Resource
        private PropertyI18nRedisService propertyI18nRedisService;
        @Resource
        private ObjectMapper objectMapper;
        @Resource
        private PropertyBusinessDateRedisService propertyBusinessDateRedisService;

        /**
         * 获取指定日期范围的数据
         *
         * @param propertyId  资产 id
         * @param versionDate 版本日期(yyyyMMdd)
         * @param startDate   开始日期(yyyyMMdd)
         * @param endDate     结束日期(yyyyMMdd)
         * @return MonthlyRevenueInternalDTO 集合
         * @author zc
         * @date 2025/5/23
         */
        @Override
        public List<MonthlyRevenueInternalDTO> listByDateRange(int propertyId, long versionDate, long startDate, long endDate) {
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            if (Objects.isNull(propertyDTO)) {
                return Collections.emptyList();
            }
            if (startDate > endDate) {
                return Collections.emptyList();
            }
            LocalDate nowLocalDate = LocalDate.now(ZoneId.of(propertyDTO.getTimezone()));
            long nowDate = Long.parseLong(DateTimeUtils.localDateToStr(nowLocalDate, BaseConstant.DATE_FORMAT_YYYYMMDD));
            long yesterday = Long.parseLong(DateTimeUtils.localDateToStr(nowLocalDate.minusDays(1),
                    BaseConstant.DATE_FORMAT_YYYYMMDD));

            Map<Long, WeeklyMonthlyRevenueSegment> date2HistorySegment = Maps.newHashMap();
            Map<Long, WeeklyMonthlyRevenueVersionData> date2VersionDate = Maps.newHashMap();

            // 查询的开始日期小于当前日期时，表示需要查询历史数据；反之则只需要查询未来数据
            if (startDate < nowDate) {
                date2HistorySegment = segmentService.listByDateRange(propertyId, startDate, yesterday).stream()
                        .collect(Collectors.toMap(WeeklyMonthlyRevenueSegment::getTheDate, Function.identity()));
                // 查询的结束日期大于昨天日期时，表示需要查询未来数据
                if (endDate > yesterday) {
                    date2VersionDate = versionDataService.listByDateRange(propertyId, nowDate, endDate).stream()
                            .collect(Collectors.toMap(WeeklyMonthlyRevenueVersionData::getDate, Function.identity()));
                }
            } else {
                date2VersionDate = versionDataService.listByDateRange(propertyId, startDate, endDate).stream()
                        .collect(Collectors.toMap(WeeklyMonthlyRevenueVersionData::getDate, Function.identity()));
            }

            LocalDate startLocalDate = DateTimeUtils.strToLocalDate(String.valueOf(startDate), BaseConstant.DATE_FORMAT_YYYYMMDD);
            LocalDate endLocalDate = DateTimeUtils.strToLocalDate(String.valueOf(endDate), BaseConstant.DATE_FORMAT_YYYYMMDD);

            List<MonthlyRevenueInternalDTO> resultList = Lists.newArrayList();
            for (LocalDate indexLocalDate = startLocalDate; !indexLocalDate.isAfter(endLocalDate);
                 indexLocalDate = indexLocalDate.plusDays(1)) {
                long indexDate = Long.parseLong(DateTimeUtils.localDateToStr(indexLocalDate, BaseConstant.DATE_FORMAT_YYYYMMDD));

                MonthlyRevenueInternalDTO internalDTO = new MonthlyRevenueInternalDTO();
                internalDTO.setDate(indexDate);
                if (indexDate < nowDate) {
                    WeeklyMonthlyRevenueSegment segment = date2HistorySegment.get(indexDate);
                    if (Objects.isNull(segment)) {
                        continue;
                    }
                    internalDTO.setTransientSold(segment.getTransientSold());
                    internalDTO.setTransientRevenue(segment.getTransientRevenue());
                    internalDTO.setGroupSold(segment.getGroupSold());
                    internalDTO.setGroupRevenue(segment.getGroupRevenue());
                    internalDTO.setContractSold(segment.getContractSold());
                    internalDTO.setContractRevenue(segment.getContractRevenue());
                } else {
                    WeeklyMonthlyRevenueVersionData versionData = date2VersionDate.get(indexDate);
                    if (Objects.isNull(versionData)) {
                        continue;
                    }
                    List<WMRevenueVersionDataDTO> versionDataDTOList = JsonUtils.convertStringToList(objectMapper,
                            versionData.getVersionData(), WMRevenueVersionDataDTO.class);
                    WMRevenueVersionDataDTO versionDataDTO = versionDataDTOList.stream()
                            .filter(item -> item.getVersion() == versionDate)
                            .findFirst().orElse(null);
                    if (Objects.isNull(versionDataDTO)) {
                        continue;
                    }
                    internalDTO.setTransientSold(versionDataDTO.getTransients().getSold());
                    internalDTO.setTransientRevenue(versionDataDTO.getTransients().getRevenue());
                    internalDTO.setGroupSold(versionDataDTO.getGroup().getSold());
                    internalDTO.setGroupRevenue(versionDataDTO.getGroup().getRevenue());
                    internalDTO.setContractSold(versionDataDTO.getContract().getSold());
                    internalDTO.setContractRevenue(versionDataDTO.getContract().getRevenue());
                }
                resultList.add(internalDTO);
            }
            return resultList;
        }

        /**
         * 保存 Group Contracted
         *
         * @param propertyDTO 资产
         * @param list        数据
         * @author zc
         * @date 2025/7/10
         */
        @Override
        public void saveGroupContractedRooms(PropertyDTO propertyDTO, List<MonthlyRevenueGrcValueInternalDTO> list) {
            List<WMRevenueGroupPickupBO> boList = list.stream().map(item -> {
                String theDay = DateTimeUtils.localDateToStr(DateTimeUtils.strToLocalDate(item.getDate().toString(),
                        BaseConstant.DATE_FORMAT_YYYYMMDD), BaseConstant.DATE_FORMAT_YYYY_MM_DD);
                WMRevenueGroupPickupBO bo = new WMRevenueGroupPickupBO();
                bo.setTheDay(theDay);
                bo.setOrigin(item.getValue());
                return bo;
            }).toList();

            //获取有效的营业日期
            Long effectiveBusinessDate = propertyBusinessDateRedisService.getEffectiveBusinessDate(propertyDTO.getId(), propertyDTO.getTimezone());
            if(Objects.nonNull(effectiveBusinessDate)){
                reportService.handleGroupPickup(propertyDTO, boList, MonthlyRevenueImportCategoryCons.ALL, effectiveBusinessDate, 0);
            }
        }

        /**
         * 保存 Group Cancelled
         *
         * @param propertyDTO 资产
         * @param list        数据
         * @author zc
         * @date 2025/7/10
         */
        @Override
        public void saveGroupCancelledRooms(PropertyDTO propertyDTO, List<MonthlyRevenueGrcValueInternalDTO> list) {
            List<WMRevenueCancellationSummaryBO> boList = list.stream().map(item -> {
                String theDay = DateTimeUtils.localDateToStr(DateTimeUtils.strToLocalDate(item.getDate().toString(),
                        BaseConstant.DATE_FORMAT_YYYYMMDD), BaseConstant.DATE_FORMAT_YYYY_MM_DD);
                WMRevenueCancellationSummaryBO bo = new WMRevenueCancellationSummaryBO();
                bo.setTheDay(theDay);
                bo.setRoomsNights(item.getValue());
                return bo;
            }).toList();
            reportService.handleCancellationSummary(propertyDTO, boList, 0);
        }
    }