# HotelKpiMetricsSettingTargetServiceImpl.java

    package cloud.wconnect.workperformance.service.hotelkpi.impl.old;

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.commonlib.util.YearMonthUtils;
    import cloud.wconnect.workperformance.cons.hotelkpi.old.HotelKpiDateTypeCons;
    import cloud.wconnect.workperformance.cons.hotelkpi.old.HotelKpiSettingCons;
    import cloud.wconnect.workperformance.cons.hotelkpi.old.HotelKpiValueCategoryCons;
    import cloud.wconnect.workperformance.entity.hotelkpi.old.HotelKpiMetricsSetting;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.old.setting.target.HotelKpiMetricsSettingConstantTargetDTO;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.old.setting.target.HotelKpiMetricsSettingIndependentTargetDTO;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.old.setting.target.HotelKpiMetricsSettingTargetDTO;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.old.setting.target.HotelKpiMetricsSettingTargetValueDTO;
    import cloud.wconnect.workperformance.service.hotelkpi.old.IHotelKpiMetricsSettingService;
    import cloud.wconnect.workperformance.service.hotelkpi.old.IHotelKpiMetricsSettingTargetService;
    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.springframework.stereotype.Service;

    import jakarta.annotation.Resource;
    import java.time.LocalDate;
    import java.time.YearMonth;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    /**
     * <p>
     * Hotel KPI Target Setting 服务实现类
     * </p>
     *
     * @author zc
     * @since 2024-06-24
     */
    @Service("hotelKpiMetricsSettingTargetServiceImpl_old")
    @DS("work_performance")
    public class HotelKpiMetricsSettingTargetServiceImpl implements IHotelKpiMetricsSettingTargetService {
        @Resource
        private IHotelKpiMetricsSettingService metricsSettingService;
        @Resource
        private ObjectMapper objectMapper;

        private static final int VALUE_CATEGORY = HotelKpiValueCategoryCons.TARGET;

        /**
         * 根据日期范围获取周设置
         *
         * @param propertyId    资产 id
         * @param metricsTypes  指标类型
         * @param startDateLong 开始日期
         * @param endDateLong   结束日期
         * @return HotelKpiMetricsSettingTargetDTO 集合
         * @author zc
         * @date 2024/6/26
         */
        @Override
        public List<HotelKpiMetricsSettingTargetDTO> listWeeklySettingByDateRange(int propertyId, List<Integer> metricsTypes, long startDateLong, long endDateLong) {
            if (CollectionUtils.isEmpty(metricsTypes)) {
                return Collections.emptyList();
            }
            LocalDate startLocalDate = DateTimeUtils.strToLocalDate(String.valueOf(startDateLong), BaseConstant.DATE_FORMAT_YYYYMMDD);
            LocalDate endLocalDate = DateTimeUtils.strToLocalDate(String.valueOf(endDateLong), BaseConstant.DATE_FORMAT_YYYYMMDD);

            // 获取当前年的指标设置数据
            List<HotelKpiMetricsSetting> settingList = metricsSettingService.listByYearRangeAndMetricsTypes(propertyId,
                    metricsTypes, startLocalDate.getYear(), endLocalDate.getYear(), VALUE_CATEGORY);
            if (CollectionUtils.isEmpty(settingList)) {
                return Collections.emptyList();
            }
            Map<Long, List<HotelKpiMetricsSetting>> year2SettingList = settingList.stream().collect(Collectors.groupingBy(HotelKpiMetricsSetting::getYear));

            List<HotelKpiMetricsSettingTargetDTO> settingValueDTOList = Lists.newArrayList();
            for (LocalDate indexLocalDate = startLocalDate; !indexLocalDate.isAfter(endLocalDate); indexLocalDate = (indexLocalDate.getDayOfMonth() >= 22) ?
                    indexLocalDate.plusMonths(1).withDayOfMonth(1) : indexLocalDate.plusDays(7)) {
                List<HotelKpiMetricsSetting> settingListByYear = year2SettingList.get((long) indexLocalDate.getYear());
                if (CollectionUtils.isEmpty(settingListByYear)) {
                    continue;
                }
                for (HotelKpiMetricsSetting metricsSetting : settingListByYear) {
                    settingValueDTOList.add(convertToSettingValueDTO(HotelKpiDateTypeCons.WEEKLY, indexLocalDate, metricsSetting));
                }
            }
            return settingValueDTOList;
        }

        /**
         * 根据日期范围获取月设置
         *
         * @param propertyId    资产 id
         * @param metricsTypes  指标类型
         * @param startDateLong 开始日期
         * @param endDateLong   结束日期
         * @return HotelKpiMetricsSettingTargetDTO 集合
         * @author zc
         * @date 2024/6/27
         */
        @Override
        public List<HotelKpiMetricsSettingTargetDTO> listMonthlySettingByDateRange(int propertyId, List<Integer> metricsTypes, long startDateLong, long endDateLong) {
            if (CollectionUtils.isEmpty(metricsTypes)) {
                return Collections.emptyList();
            }
            LocalDate startLocalDate = YearMonthUtils.getYearMonth(String.valueOf(startDateLong)).atDay(1);
            LocalDate endLocalDate = YearMonthUtils.getYearMonth(String.valueOf(endDateLong)).atDay(1);

            List<HotelKpiMetricsSetting> settingList = metricsSettingService.listByYearRangeAndMetricsTypes(propertyId,
                    metricsTypes, startLocalDate.getYear(), endLocalDate.getYear(), VALUE_CATEGORY);
            if (CollectionUtils.isEmpty(settingList)) {
                return Collections.emptyList();
            }
            Map<Long, List<HotelKpiMetricsSetting>> year2SettingList = settingList.stream().collect(Collectors.groupingBy(HotelKpiMetricsSetting::getYear));

            List<HotelKpiMetricsSettingTargetDTO> settingValueDTOList = Lists.newArrayList();
            for (LocalDate indexLocalDate = startLocalDate; !indexLocalDate.isAfter(endLocalDate); indexLocalDate = indexLocalDate.plusMonths(1)) {
                List<HotelKpiMetricsSetting> settingListByYear = year2SettingList.get((long) indexLocalDate.getYear());
                if (CollectionUtils.isEmpty(settingListByYear)) {
                    continue;
                }
                for (HotelKpiMetricsSetting metricsSetting : settingListByYear) {
                    settingValueDTOList.add(convertToSettingValueDTO(HotelKpiDateTypeCons.MONTHLY, indexLocalDate, metricsSetting));
                }
            }
            return settingValueDTOList;
        }

        /**
         * 根据日期范围获取季设置
         *
         * @param propertyId    资产 id
         * @param metricsTypes  指标类型
         * @param startDateLong 开始日期
         * @param endDateLong   结束日期
         * @return HotelKpiMetricsSettingTargetDTO 集合
         * @author zc
         * @date 2024/6/27
         */
        @Override
        public List<HotelKpiMetricsSettingTargetDTO> listQuarterlySettingByDateRange(int propertyId, List<Integer> metricsTypes, long startDateLong, long endDateLong) {
            if (CollectionUtils.isEmpty(metricsTypes)) {
                return Collections.emptyList();
            }
            LocalDate startLocalDate = YearMonthUtils.getYearMonth(String.valueOf(startDateLong)).atDay(1);
            LocalDate endLocalDate = YearMonthUtils.getYearMonth(String.valueOf(endDateLong)).atDay(1);

            List<HotelKpiMetricsSetting> settingList = metricsSettingService.listByYearRangeAndMetricsTypes(propertyId,
                    metricsTypes, startLocalDate.getYear(), endLocalDate.getYear(), VALUE_CATEGORY);
            if (CollectionUtils.isEmpty(settingList)) {
                return Collections.emptyList();
            }
            Map<Long, List<HotelKpiMetricsSetting>> year2SettingList = settingList.stream().collect(Collectors.groupingBy(HotelKpiMetricsSetting::getYear));

            List<HotelKpiMetricsSettingTargetDTO> settingValueDTOList = Lists.newArrayList();
            for (LocalDate indexLocalDate = startLocalDate; !indexLocalDate.isAfter(endLocalDate); indexLocalDate = indexLocalDate.plusMonths(3)) {
                List<HotelKpiMetricsSetting> settingListByYear = year2SettingList.get((long) indexLocalDate.getYear());
                if (CollectionUtils.isEmpty(settingListByYear)) {
                    continue;
                }
                for (HotelKpiMetricsSetting metricsSetting : settingListByYear) {
                    settingValueDTOList.add(convertToSettingValueDTO(HotelKpiDateTypeCons.QUARTERLY, indexLocalDate, metricsSetting));
                }
            }
            return settingValueDTOList;
        }

        /**
         * 根据日期范围获取年设置
         *
         * @param propertyId    资产 id
         * @param metricsTypes  指标类型
         * @param startDateLong 开始日期
         * @param endDateLong   结束日期
         * @return HotelKpiMetricsSettingTargetDTO 集合
         * @author zc
         * @date 2024/6/27
         */
        @Override
        public List<HotelKpiMetricsSettingTargetDTO> listYearlySettingByDateRange(int propertyId, List<Integer> metricsTypes, long startDateLong, long endDateLong) {
            if (CollectionUtils.isEmpty(metricsTypes)) {
                return Collections.emptyList();
            }
            LocalDate startLocalDate = YearMonth.of((int) startDateLong, 1).atDay(1);
            LocalDate endLocalDate = YearMonth.of((int) endDateLong, 1).atDay(1);

            List<HotelKpiMetricsSetting> settingList = metricsSettingService.listByYearRangeAndMetricsTypes(propertyId,
                    metricsTypes, startLocalDate.getYear(), endLocalDate.getYear(), VALUE_CATEGORY);
            if (CollectionUtils.isEmpty(settingList)) {
                return Collections.emptyList();
            }
            Map<Long, List<HotelKpiMetricsSetting>> year2SettingList = settingList.stream().collect(Collectors.groupingBy(HotelKpiMetricsSetting::getYear));

            List<HotelKpiMetricsSettingTargetDTO> settingValueDTOList = Lists.newArrayList();
            for (LocalDate indexLocalDate = startLocalDate; !indexLocalDate.isAfter(endLocalDate); indexLocalDate = indexLocalDate.plusYears(1)) {
                List<HotelKpiMetricsSetting> settingListByYear = year2SettingList.get((long) indexLocalDate.getYear());
                if (CollectionUtils.isEmpty(settingListByYear)) {
                    continue;
                }
                for (HotelKpiMetricsSetting metricsSetting : settingListByYear) {
                    settingValueDTOList.add(convertToSettingValueDTO(HotelKpiDateTypeCons.YEARLY, indexLocalDate, metricsSetting));
                }
            }
            return settingValueDTOList;
        }

        /**
         * 转换设置值
         *
         * @param dateType  日期类型
         * @param localDate 当前日期
         * @param setting   设置
         * @return HotelKpiMetricsSettingTargetDTO
         * @author zc
         * @date 2024/6/26
         */
        private HotelKpiMetricsSettingTargetDTO convertToSettingValueDTO(int dateType, LocalDate localDate, HotelKpiMetricsSetting setting) {
            int category = setting.getSettingCategory();
            if (HotelKpiSettingCons.CONSTANT == category) {
                return extractionForConstantOrAccumulation(dateType, localDate, setting);
            } else if (HotelKpiSettingCons.ACCUMULATION == category) {
                return extractionForConstantOrAccumulation(dateType, localDate, setting);
            } else if (HotelKpiSettingCons.DYNAMIC == category) {
                return extractionForDynamic(dateType, localDate, setting);
            } else {
                return extractionForIndependent(dateType, localDate, setting);
            }
        }

        /**
         * 提取设置值 for Constant or Accumulation（恒定、累加）
         *
         * @param dateType  日期类型
         * @param localDate 日期
         * @param setting   设置值
         * @return HotelKpiMetricsSettingTargetDTO
         * @author zc
         * @date 2024/6/26
         */
        private HotelKpiMetricsSettingTargetDTO extractionForConstantOrAccumulation(int dateType, LocalDate localDate, HotelKpiMetricsSetting setting) {
            HotelKpiMetricsSettingConstantTargetDTO settingConstantDTO = JsonUtils.convertStringToObject(objectMapper,
                    setting.getDetail(), HotelKpiMetricsSettingConstantTargetDTO.class);
            HotelKpiMetricsSettingTargetValueDTO settingValueDTO;
            long date;
            if (HotelKpiDateTypeCons.WEEKLY == dateType) {
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD));
                settingValueDTO = settingConstantDTO.getWeek();
            } else if (HotelKpiDateTypeCons.MONTHLY == dateType) {
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMM));
                settingValueDTO = settingConstantDTO.getMonth();
            } else if (HotelKpiDateTypeCons.QUARTERLY == dateType) {
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMM));
                settingValueDTO = settingConstantDTO.getQuarter();
            } else {
                date = localDate.getYear();
                settingValueDTO = settingConstantDTO.getYear();
            }
            return HotelKpiMetricsSettingTargetDTO.builder()
                    .date(date)
                    .metricsType(setting.getMetricsType())
                    .index(setting.getIndex())
                    .settingCategory(setting.getSettingCategory())
                    .target(settingValueDTO.getTarget())
                    .cure(settingValueDTO.getCure())
                    .build();
        }

        /**
         * 提取设置值 for Dynamic（动态）
         *
         * @param setting 设置值
         * @return HotelKpiMetricsSettingTargetDTO
         * @author zc
         * @date 2024/6/28
         */
        private HotelKpiMetricsSettingTargetDTO extractionForDynamic(int dateType, LocalDate localDate, HotelKpiMetricsSetting setting) {
            HotelKpiMetricsSettingConstantTargetDTO settingConstantDTO = JsonUtils.convertStringToObject(objectMapper,
                    setting.getDetail(), HotelKpiMetricsSettingConstantTargetDTO.class);
            HotelKpiMetricsSettingTargetValueDTO settingValueDTO;
            long date;
            if (HotelKpiDateTypeCons.WEEKLY == dateType) {
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD));
                settingValueDTO = settingConstantDTO.getWeek();
            } else if (HotelKpiDateTypeCons.MONTHLY == dateType) {
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMM));
                settingValueDTO = settingConstantDTO.getMonth();
            } else if (HotelKpiDateTypeCons.QUARTERLY == dateType) {
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMM));
                settingValueDTO = settingConstantDTO.getQuarter();
            } else {
                date = localDate.getYear();
                settingValueDTO = settingConstantDTO.getYear();
            }
            return HotelKpiMetricsSettingTargetDTO.builder()
                    .date(date)
                    .metricsType(setting.getMetricsType())
                    .index(setting.getIndex())
                    .settingCategory(setting.getSettingCategory())
                    .cure(settingValueDTO.getCure())
                    .build();
        }

        /**
         * 提取设置值 for Independent（独立）
         *
         * @param dateType  日期类型
         * @param localDate 日期
         * @param setting   设置值
         * @return HotelKpiMetricsSettingTargetDTO
         * @author zc
         * @date 2024/6/26
         */
        private HotelKpiMetricsSettingTargetDTO extractionForIndependent(int dateType, LocalDate localDate, HotelKpiMetricsSetting setting) {
            HotelKpiMetricsSettingIndependentTargetDTO settingIndependentDTO = JsonUtils.convertStringToObject(objectMapper,
                    setting.getDetail(), HotelKpiMetricsSettingIndependentTargetDTO.class);
            int index;
            long date;
            List<HotelKpiMetricsSettingTargetValueDTO> settingValueDTOList;
            if (HotelKpiDateTypeCons.WEEKLY == dateType) {
                index = (localDate.getMonthValue() - 1) * 4 + (localDate.getDayOfMonth() / 7) + 1;
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMMDD));
                settingValueDTOList = settingIndependentDTO.getWeek();
            } else if (HotelKpiDateTypeCons.MONTHLY == dateType) {
                index = localDate.getMonthValue();
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMM));
                settingValueDTOList = settingIndependentDTO.getMonth();
            } else if (HotelKpiDateTypeCons.QUARTERLY == dateType) {
                index = (localDate.getMonthValue() - 1) / 3 + 1;
                date = Long.parseLong(DateTimeUtils.localDateToStr(localDate, BaseConstant.DATE_FORMAT_YYYYMM));
                settingValueDTOList = settingIndependentDTO.getQuarter();
            } else {
                index = 1;
                date = localDate.getYear();
                settingValueDTOList = settingIndependentDTO.getYear();
            }
            Map<Integer, HotelKpiMetricsSettingTargetValueDTO> index2Setting = settingValueDTOList.stream()
                    .collect(Collectors.toMap(HotelKpiMetricsSettingTargetValueDTO::getIndex, Function.identity()));

            HotelKpiMetricsSettingTargetValueDTO settingValueDTO = index2Setting.getOrDefault(index, new HotelKpiMetricsSettingTargetValueDTO());
            return HotelKpiMetricsSettingTargetDTO.builder()
                    .date(date)
                    .metricsType(setting.getMetricsType())
                    .index(setting.getIndex())
                    .settingCategory(setting.getSettingCategory())
                    .target(settingValueDTO.getTarget())
                    .cure(settingValueDTO.getCure())
                    .build();
        }
    }