# HotelKpiM3MonthServiceImpl.java

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

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.cons.S3BucketFunctionCons;
    import cloud.wconnect.workperformance.entity.hotelkpi.HotelKpiM3Month;
    import cloud.wconnect.workperformance.mapper.hotelkpi.HotelKpiM3MonthMapper;
    import cloud.wconnect.workperformance.pojo.bo.hotelkpi.m3.HotelKpiM3MonthlyReportTotalsBO;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.m3.HotelKpiM3MonthDTO;
    import cloud.wconnect.workperformance.pojo.dto.hotelkpi.m3.HotelKpiM3MonthValueDTO;
    import cloud.wconnect.workperformance.service.AmazonS3Service;
    import cloud.wconnect.workperformance.service.hotelkpi.IHotelKpiM3MonthService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import jakarta.annotation.Resource;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections4.CollectionUtils;
    import org.springframework.stereotype.Service;

    import java.io.IOException;
    import java.io.InputStream;
    import java.time.LocalDate;
    import java.util.Collections;
    import java.util.List;

    /**
     * <p>
     * Hotel KPI M3 Month Total 服务实现类
     * </p>
     *
     * @author zc
     * @since 2025-09-08
     */
    @Slf4j
    @Service
    @DS("work_performance")
    public class HotelKpiM3MonthServiceImpl extends ServiceImpl<HotelKpiM3MonthMapper, HotelKpiM3Month> implements IHotelKpiM3MonthService {

        @Resource
        private ObjectMapper objectMapper;
        @Resource
        private AmazonS3Service amazonS3Service;

        /**
         * 保存数据
         *
         * @param propertyDTO  资产数据
         * @param nowLocalDate 当前时间
         * @param bo           报告数据
         * @param path         报告文件路径
         * @return 数据日期
         * @author zc
         * @date 2025/9/8
         */
        @Override
        public long saveData(PropertyDTO propertyDTO, LocalDate nowLocalDate, HotelKpiM3MonthlyReportTotalsBO bo, String path) {
            // 上传报告，用于点击指标下载报告
            uploadReport(path);

            // 当前月导入上个月的数据，转换为上个月日期
            long month = Long.parseLong(DateTimeUtils.localDateToStr(nowLocalDate.minusMonths(1),
                    BaseConstant.DATE_FORMAT_YYYYMM));

            HotelKpiM3Month entity = new HotelKpiM3Month();
            entity.setPropertyId(propertyDTO.getId());
            entity.setDate(month);
            entity.setFileUrl(path);
            entity.setFbRevenue(JsonUtils.convertObjToString(objectMapper, bo.getFbRevenue()));
            entity.setBanquetRevenue(JsonUtils.convertObjToString(objectMapper, bo.getBanquetRevenue()));
            entity.setOtherRevenue(JsonUtils.convertObjToString(objectMapper, bo.getOtherRevenue()));

            baseMapper.insertOrUpdateByUnique(entity);

            return month;
        }

        /**
         * 根据日期范围获取数据
         *
         * @param propertyId 资产ID
         * @param startMonth 开始时间(yyyyMM)
         * @param endMonth   结束时间(yyyyMM)
         * @return HotelKpiM3MonthDTO 集合
         * @author zc
         * @date 2025/9/11
         */
        @Override
        public List<HotelKpiM3MonthDTO> listByDateRange(int propertyId, long startMonth, long endMonth) {
            List<HotelKpiM3Month> list = list(new LambdaQueryWrapper<HotelKpiM3Month>()
                    .eq(HotelKpiM3Month::getPropertyId, propertyId)
                    .between(HotelKpiM3Month::getDate, startMonth, endMonth));
            if (CollectionUtils.isEmpty(list)) {
                return Collections.emptyList();
            }
            return list.stream().map(item -> {
                HotelKpiM3MonthDTO dto = new HotelKpiM3MonthDTO();
                dto.setPropertyId(item.getPropertyId());
                dto.setMonth(item.getDate());
                dto.setFileUrl(item.getFileUrl());
                dto.setFbRevenue(JsonUtils.convertStringToObject(objectMapper, item.getFbRevenue(),
                        HotelKpiM3MonthValueDTO.class));
                dto.setBanquetRevenue(JsonUtils.convertStringToObject(objectMapper, item.getBanquetRevenue(),
                        HotelKpiM3MonthValueDTO.class));
                dto.setOtherRevenue(JsonUtils.convertStringToObject(objectMapper, item.getOtherRevenue(),
                        HotelKpiM3MonthValueDTO.class));
                return dto;
            }).toList();
        }

        /**
         * 上传报告，用于点击指标下载报告
         *
         * @param fileUrl S3 路径
         * @author zc
         * @date 2025/8/22
         */
        private void uploadReport(String fileUrl) {
            try (InputStream in = amazonS3Service.getFile(fileUrl)) {
                amazonS3Service.uploadFile(S3BucketFunctionCons.HOTEL_KPI, in, fileUrl);
            } catch (IOException e) {
                log.error("HotelKpiStrWeekServiceImpl Upload M3 Monthly report error. fileUrl: {}", fileUrl, e);
            }
        }
    }