# HotelKpiDailyServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.workperformance.entity.hotelkpi.HotelKpiDaily;
    import cloud.wconnect.workperformance.mapper.hotelkpi.HotelKpiDailyMapper;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.internal.crawl.value.v1.HotelKpiCrawlDailyDTO;
    import cloud.wconnect.workperformance.service.hotelkpi.IHotelKpiDailyService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import jakarta.annotation.Resource;
    import org.apache.commons.collections4.CollectionUtils;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.math.RoundingMode;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;

    /**
     * <p>
     * Hotel KPI 指标每日数值 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-03-21
     */
    @Service
    @DS("work_performance")
    public class HotelKpiDailyServiceImpl extends ServiceImpl<HotelKpiDailyMapper, HotelKpiDaily> implements IHotelKpiDailyService {
        @Resource
        private BeanMapper beanMapper;

        /**
         * 处理采集的数据-每日
         *
         * @param propertyDTO 资产
         * @param dailyDTO    采集数据DTO
         * @author zc
         * @date 2025/3/24
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void saveCrawlValueDaily(PropertyDTO propertyDTO, HotelKpiCrawlDailyDTO dailyDTO) {
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(propertyDTO
                    .getInternationalization().getNumber().getCalculationRule());
            List<HotelKpiDaily> dailyList = beanMapper.mapList(dailyDTO.getList(), HotelKpiDaily.class, (dto, item) -> {
                item.setPropertyId(propertyDTO.getId());
                item.setMetricsType(dailyDTO.getMetricsType());
                item.setDate(item.getDate());
                item.setValue(item.getValue().setScale(BaseConstant.DATA_PRECISION, roundingMode));
            });

            // 按唯一索引字段排序，避免死锁
            dailyList.sort(Comparator.comparing(HotelKpiDaily::getPropertyId)
                    .thenComparing(HotelKpiDaily::getDate)
                    .thenComparing(HotelKpiDaily::getMetricsType));

            baseMapper.insertOrUpdateBatchByUnique(dailyList);
        }

        /**
         * 获取指定日期范围内的数据
         *
         * @param propertyId 资产ID
         * @param startDate  开始日期（yyyyMMdd）
         * @param endDate    结束日期（yyyyMMdd）
         * @return 指定日期范围内的数据
         * @author zc
         * @date 2025/3/22
         */
        @Override
        public List<HotelKpiDaily> listByDateRange(int propertyId, List<Integer> metricsTypeList, long startDate, long endDate) {
            if (CollectionUtils.isEmpty(metricsTypeList)) {
                return Collections.emptyList();
            }
            return list(new LambdaQueryWrapper<HotelKpiDaily>()
                    .eq(HotelKpiDaily::getPropertyId, propertyId)
                    .between(HotelKpiDaily::getDate, startDate, endDate)
                    .in(HotelKpiDaily::getMetricsType, metricsTypeList));
        }
    }