# HotelKpiInternalServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.service.PropertyInternalService;
    import cloud.wconnect.workperformance.cons.hotelkpi.HotelKpiDateTypeCons;
    import cloud.wconnect.workperformance.entity.hotelkpi.HotelKpiMetricsConfig;
    import cloud.wconnect.workperformance.entity.hotelkpi.HotelKpiStrWeek;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.budgetdb.*;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.internal.kpidata.*;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.internal.metrics.HotelKpiMetricsConfigInternalDTO;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.kpi.HotelKpiDTO;
    import cloud.wconnect.workperformance.pojo.query.hotelkpi.HotelKpiQuery;
    import cloud.wconnect.workperformance.service.hotelkpi.*;
    import cloud.wconnect.workperformance.service.hotelkpi.internal.IHotelKpiInternalService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import jakarta.annotation.Nullable;
    import jakarta.annotation.Resource;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.stereotype.Service;

    import java.math.BigDecimal;
    import java.time.DayOfWeek;
    import java.util.Collections;
    import java.util.List;

    /**
     * Internal Service
     *
     * @author zc
     * @date 2024/10/19
     */
    @Service
    @DS("work_performance")
    public class HotelKpiInternalServiceImpl implements IHotelKpiInternalService {
        @Resource
        private IHotelKpiWeeklyService weeklyService;
        @Resource
        private IHotelKpiService hotelKpiService;
        @Resource
        private IHotelKpiStrWeekService strWeekService;
        @Resource
        private IHotelKpiMetricsConfigService metricsConfigService;
        @Resource
        private IHotelKpiWeekStartDayService weekStartDayService;
        @Resource
        private IHotelKpiBudgetDatabaseService budgetDatabaseService;
        @Resource
        private PropertyInternalService propertyInternalService;
        @Resource
        private BeanMapper beanMapper;

        /**
         * 获取指定日期范围的周 KPI 数据
         *
         * @param propertyId         资产 id
         * @param startWeekFirstDate 开始周起始日期(yyyyMMdd)
         * @param endWeekFirstDate   结束周起始日期(yyyyMMdd)
         * @return HotelKpiInternalDTO 集合
         * @author zc
         * @date 2024/10/19
         */
        @Override
        public List<HotelKpiInternalDTO> listForWeekly(int propertyId, long startWeekFirstDate, long endWeekFirstDate) {
            PropertyDTO propertyDTO = propertyInternalService.getOne(propertyId);

            HotelKpiQuery query = new HotelKpiQuery();
            query.setDateType(HotelKpiDateTypeCons.WEEKLY);
            query.setStartDate(startWeekFirstDate);
            query.setEndDate(endWeekFirstDate);

            List<HotelKpiDTO> hotelKpiDTOList = weeklyService.listHotelKpi(propertyDTO, query);
            return hotelKpiDTOList.stream().map(dto -> {
                List<HotelKpiDetailInternalDTO> details = dto.getDetails().stream().map(detail -> {
                    List<HotelKpiItemInternalDTO> items = detail.getItems().stream().map(item -> {
                        List<HotelKpiMetricsInternalDTO> metrics = item.getMetrics().stream().map(metric ->
                                HotelKpiMetricsInternalDTO.builder()
                                        .metricsType(metric.getMetricsType())
                                        .title(metric.getTitle())
                                        .unit(metric.getUnit())
                                        .actual(HotelKpiMetricsValueInternalDTO.builder()
                                                .value(hotelKpiService.getEffectiveValue(metric.getActual()))
                                                .content(metric.getActual().getContent())
                                                .build())
                                        .target(HotelKpiMetricsValueInternalDTO.builder()
                                                .value(hotelKpiService.getEffectiveValue(metric.getTarget()))
                                                .content(metric.getTarget().getContent())
                                                .build())
                                        .cure(HotelKpiMetricsValueInternalDTO.builder()
                                                .value(hotelKpiService.getEffectiveValue(metric.getCure()))
                                                .content(metric.getCure().getContent())
                                                .build())
                                        .build()
                        ).toList();
                        return HotelKpiItemInternalDTO.builder()
                                .title(item.getTitle())
                                .metrics(metrics)
                                .build();
                    }).toList();
                    return HotelKpiDetailInternalDTO.builder()
                            .title(detail.getTitle())
                            .items(items)
                            .build();
                }).toList();
                return HotelKpiInternalDTO.builder()
                        .date(dto.getDate())
                        .details(details)
                        .build();
            }).toList();
        }

        /**
         * 获取所有指标配置
         *
         * @param propertyId 资产 id
         * @param version    版本
         * @return HotelKpiMetricsConfigInternalDTO 指标配置集合
         * @author zc
         * @date 2024/10/19
         */
        @Override
        public List<HotelKpiMetricsConfigInternalDTO> listAllMetrics(int propertyId, @Nullable Integer version) {
            List<HotelKpiMetricsConfig> metricsConfigList = metricsConfigService.listAll(propertyId, 0, false, version);
            if (CollectionUtils.isEmpty(metricsConfigList)) {
                return Collections.emptyList();
            }
            return beanMapper.mapList(metricsConfigList, HotelKpiMetricsConfigInternalDTO.class);
        }

        /**
         * 获取周起始日
         *
         * @param propertyId 资产 id
         * @return java.time.DayOfWeek
         * @author zc
         * @date 2025/2/28
         */
        @Override
        public DayOfWeek getWeekStartDay(int propertyId) {
            return weekStartDayService.getWeekStartDay(propertyId);
        }

        /**
         * 获取指定周期日期的 Str week 数据
         *
         * @param propertyId 资产 id
         * @param date       周期日期(yyyyMMdd)
         * @return HotelKpiStrWeek
         * @author zc
         * @date 2025/8/23
         */
        @Override
        public HotelKpiStrWeek getStrWeek(int propertyId, long date) {
            return strWeekService.getOne(new LambdaQueryWrapper<HotelKpiStrWeek>()
                    .eq(HotelKpiStrWeek::getPropertyId, propertyId)
                    .eq(HotelKpiStrWeek::getDate, date));
        }

        /**
         * 获取指定年的 Budget Database 数据
         *
         * @param propertyId 资产 id
         * @param year       年(yyyy)
         * @return HotelKpiBudgetDatabaseDTO
         * @author zc
         * @date 2025/8/28
         */
        @Override
        public HotelKpiBudgetDatabaseDTO getBudgetByYear(int propertyId, int year) {
            return budgetDatabaseService.getByYear(propertyId, year);
        }

        /**
         * 获取房间数销售预算
         *
         * @param budgetDTO 数据
         * @param startDate 开始时间(yyyyMM)
         * @param endDate   结束时间(yyyyMM)
         * @return 房间数销售预算
         * @author zc
         * @date 2025/11/10
         */
        @Override
        public Long getRoomsSoldBudget(HotelKpiBudgetDatabaseDTO budgetDTO, long startDate, long endDate) {
            return budgetDatabaseService.getRoomsSoldBudget(budgetDTO, startDate, endDate, null);
        }

        /**
         * 获取房间收入预算
         *
         * @param budgetDTO 数据
         * @param startDate 开始时间(yyyyMM)
         * @param endDate   结束时间(yyyyMM)
         * @return 房间收入预算
         * @author zc
         * @date 2025/11/10
         */
        @Override
        public BigDecimal getRoomRevenueBudget(HotelKpiBudgetDatabaseDTO budgetDTO, long startDate, long endDate) {
            return budgetDatabaseService.getRoomRevenueBudget(budgetDTO, startDate, endDate, null);
        }

        /**
         * 获取其他收入预算
         *
         * @param budgetDTO 数据
         * @param startDate 开始时间(yyyyMM)
         * @param endDate   结束时间(yyyyMM)
         * @return 其他收入预算
         * @author zc
         * @date 2025/11/10
         */
        @Override
        public BigDecimal getOtherRevenueBudget(HotelKpiBudgetDatabaseDTO budgetDTO, long startDate, long endDate) {
            return budgetDatabaseService.getOtherRevenueBudget(budgetDTO, startDate, endDate);
        }

        /**
         * 获取F&B收入预算
         *
         * @param budgetDTO 数据
         * @param startDate 开始时间(yyyyMM)
         * @param endDate   结束时间(yyyyMM)
         * @return F&B收入预算
         * @author zc
         * @date 2025/11/10
         */
        @Override
        public BigDecimal getFBRevenueBudget(HotelKpiBudgetDatabaseDTO budgetDTO, long startDate, long endDate) {
            return budgetDatabaseService.getFBRevenueBudget(budgetDTO, startDate, endDate, null);
        }
    }