# HotelKpiHistoryAndForecastTask.java

    package cloud.wconnect.workperformance.businesstask.hotelkpi;

    import cloud.wconnect.commonlib.businesstask.CheckReportMissedService;
    import cloud.wconnect.commonlib.businesstask.rule.MissedRuleByThreshold;
    import cloud.wconnect.commonlib.cons.PmsReportEnum;
    import cloud.wconnect.commonlib.pojo.dto.CheckReportMissedDTO;
    import cloud.wconnect.commonlib.pojo.dto.NotifyDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.ThresholdDTO;
    import cloud.wconnect.commonlib.pojo.dto.scheduler.JobParameterDTO;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.PropertyInternalService;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.cons.BusinessEnum;
    import cloud.wconnect.workperformance.cons.EventSubjectEnum;
    import cloud.wconnect.workperformance.cons.hotelkpi.HotelKpiNotifyTypeEnum;
    import cloud.wconnect.workperformance.entity.hotelkpi.HotelKpiScheduler;
    import cloud.wconnect.workperformance.service.hotelkpi.IHotelKpiReportService;
    import cloud.wconnect.workperformance.service.hotelkpi.IHotelKpiSendNotifyService;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import jakarta.annotation.Resource;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Component;

    import java.util.List;
    import java.util.concurrent.TimeUnit;

    /**
     * Task: history-and-forecast/service--30d-100d
     *
     * @author zc
     * @date 2024/07/11
     */
    @Slf4j
    @Component
    public class HotelKpiHistoryAndForecastTask {
        @Resource
        private IHotelKpiReportService reportService;
        @Resource
        private IHotelKpiSendNotifyService sendNotifyService;
        @Resource
        private CheckReportMissedService checkReportMissedService;
        @Resource
        private PropertyI18nRedisService propertyI18nRedisService;
        @Resource
        private PropertyInternalService propertyInternalService;
        @Resource
        private ObjectMapper objectMapper;

        @Value("${default.timezone}")
        private String defaultTimezone;

        private final static String BUSINESS = BusinessEnum.HOTEL_KPI.getBusiness();
        private final static String SUBJECT = EventSubjectEnum.HISTORY_AND_FORECAST_SERVICE_HISTORY_THIRTY_DAY_HUNDRED_DAY.getSubject();

        /**
         * 检查报告是否缺失
         *
         * @param schedulerJob 调度数据
         * @author zc
         * @date 2024/7/11
         */
        @Async
        public void dataMissingCheck(HotelKpiScheduler schedulerJob) {
            log.info("HotelKpiHistoryAndForecastTask.dataMissingCheck start...");

            int propertyId = schedulerJob.getPropertyId();
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            if (!propertyDTO.getStatus()) {
                return;
            }

            JobParameterDTO jobParameterDTO = JsonUtils.convertStringToObject(objectMapper,
                    schedulerJob.getParameters(), JobParameterDTO.class);

            // 获取资产配置的 PMS 报告名称
            String reportName = propertyInternalService.getPmsReportConfig(propertyId,
                    propertyDTO.getPmsType(), PmsReportEnum.HISTORY_AND_FORECAST.getSymbol()).getReportName();
            // 获取通知配置
            String missDateStr = getMissDate(propertyDTO, schedulerJob.getCategory());
            NotifyDTO notifyDTO = sendNotifyService.getNotifyDTO(propertyDTO, reportName, missDateStr,
                    HotelKpiNotifyTypeEnum.MISSING_REPORT_HISTORY_AND_FORECAST.getType());

            // 获取资产配置的阈值
            ThresholdDTO thresholdDTO = new ThresholdDTO(jobParameterDTO.getThreshold(), TimeUnit.MINUTES, defaultTimezone);

            // 封装 CheckReportMissedDTO 对象
            CheckReportMissedDTO job = CheckReportMissedDTO.builder()
                    .business(BUSINESS)
                    .subject(SUBJECT)
                    .ruleClazzList(List.of(MissedRuleByThreshold.class))
                    .propertyDTO(propertyDTO)
                    .notifyDTO(notifyDTO)
                    .thresholdDTO(thresholdDTO)
                    .build();
            checkReportMissedService.doCheck(job);

            log.info("HotelKpiHistoryAndForecastTask.dataMissingCheck end");
        }

        /**
         * 获取缺失日期
         *
         * @param propertyDTO 资产
         * @param category    分类
         * @return java.lang.String
         * @author zc
         * @date 2024/7/1
         */
        private String getMissDate(PropertyDTO propertyDTO, int category) {
            String language = propertyDTO.getLanguage();
            String pattern = propertyDTO.getInternationalization().getDateTime().getLongDate();

            List<Long> dateRange = reportService.getDateRange(propertyDTO.getTimezone(), category);

            String startDateStr = InternationalizationUtils.formatYearMonthDate(dateRange.get(0), pattern, language);
            String endDateStr = InternationalizationUtils.formatYearMonthDate(dateRange.get(1), pattern, language);
            return startDateStr + " ~ " + endDateStr;
        }
    }