# RateShopOccupancySummaryServiceTask.java

    package cloud.wconnect.rateshop.businesstask.rateshop;

    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.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.JsonUtils;
    import cloud.wconnect.rateshop.cons.BusinessEnum;
    import cloud.wconnect.rateshop.cons.EventSubjectEnum;
    import cloud.wconnect.rateshop.cons.rateshop.RateShopNotifyConfigTypeEnum;
    import cloud.wconnect.rateshop.entity.rateshop.RateShopScheduler;
    import cloud.wconnect.rateshop.service.rateshop.IRateShopSchedulerService;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections.MapUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    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.Map;
    import java.util.concurrent.TimeUnit;

    /**
     * 定时任务：检查 Occupancy Summary 报告 是否存在数据缺失
     *
     * @author yyt
     * @date 2026/3/10
     */
    @Slf4j
    @Component
    public class RateShopOccupancySummaryServiceTask {

        @Autowired
        private IRateShopSchedulerService rateShopSchedulerService;
        @Autowired
        private RateShopPackageNotifyDTOUtil rateShopPackageNotifyDTOUtil;
        @Autowired
        private CheckReportMissedService checkReportMissedService;
        @Autowired
        private PropertyInternalService propertyInternalService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private ObjectMapper objectMapper;

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

        /**
         * 业务名称
         */
        private final static String BUSINESS = BusinessEnum.RATE_SHOP.getBusiness();
        /**
         * subject
         */
        private final static String SUBJECT = EventSubjectEnum.OCCUPANCY_SUMMARY_YESTERDAY.getSubject();

        /**
         * 检查是否存在数据缺失
         *
         * @author yyt
         * @date 2026/3/10
         */
        @Async
        public void dataMissingCheck(RateShopScheduler scheduler) {
            log.info("OccupancySummaryServiceTask.dataMissingCheck start...");
            Integer propertyId = scheduler.getPropertyId();
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            if (!propertyDTO.getStatus()) {
                log.warn("OccupancySummaryServiceTask.dataMissingCheck end... the property is closed, no processing required");
                return;
            }

            //报告缺失日期
            Map<String, Long> dateRange = rateShopSchedulerService.getDateRange(propertyDTO, RateShopNotifyConfigTypeEnum.OCCUPANCY_SUMMARY_REPORT_MISSED.getType());
            if (MapUtils.isEmpty(dateRange)) {
                log.warn("OccupancySummaryServiceTask.checkReportMissing end... no date range");
                return;
            }
            String missDate = rateShopPackageNotifyDTOUtil.getDateRangeStr(propertyDTO, dateRange.get(JobParameterDTO.START_DATE), dateRange.get(JobParameterDTO.END_DATE));

            // 获取资产配置的 PMS 报告名称
            String reportName = propertyInternalService.getPmsReportConfig(propertyDTO.getId(),
                    propertyDTO.getPmsType(), PmsReportEnum.OCCUPANCY_SUMMARY.getSymbol()).getReportName();

            //阈值DTO
            JobParameterDTO jobParameterDTO = JsonUtils.convertStringToObject(objectMapper, scheduler.getParameters(), JobParameterDTO.class);
            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(rateShopPackageNotifyDTOUtil.getNotifyDTO(propertyDTO, missDate, reportName, scheduler.getCategory()))
                    .thresholdDTO(thresholdDTO)
                    .build();
            checkReportMissedService.doCheck(job);
            log.info("OccupancySummaryServiceTask.dataMissingCheck end");
        }

    }