# RoomRevenueServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.MoudleEventSubjectEnum;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.workperformance.pojo.bo.modelevent.monthlyreport.MonthlyReportEventDataBO;
    import cloud.wconnect.workperformance.pojo.bo.modelevent.monthlyreport.MonthlyReportEventValueBO;
    import cloud.wconnect.workperformance.pojo.bo.modelevent.monthlyreport.MonthlyReportEventBO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.commonlib.util.TransactionUtils;
    import cloud.wconnect.commonlib.util.YearMonthUtils;
    import cloud.wconnect.sns.http.processor.Sender;
    import cloud.wconnect.workperformance.cons.monthlyreport.AreaEnum;
    import cloud.wconnect.workperformance.entity.monthlyreport.*;
    import cloud.wconnect.workperformance.mapper.monthlyreport.ReportRemarkMapper;
    import cloud.wconnect.workperformance.mapper.monthlyreport.RoomRevenueMapper;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.parsereport.RoomRevenueByReportDTO;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.roomrevenue.RoomRevenueDTO;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.roomrevenue.RoomRevenueDetailDTO;
    import cloud.wconnect.workperformance.service.monthlyreport.*;
    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 com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.math.BigDecimal;
    import java.time.YearMonth;
    import java.util.*;
    import java.util.concurrent.Executor;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    /**
     * <p>
     * 月报Room Revenue区域表 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2023-09-01
     */
    @Service
    @DS("monthly_report")
    public class RoomRevenueServiceImpl extends ServiceImpl<RoomRevenueMapper, RoomRevenue> implements IRoomRevenueService, IHandlePropertySettingChange, IHandleAreaTypeConfigChange {

        @Lazy
        @Autowired
        private IMonthlyReportService monthlyReportService;
        @Autowired
        private IReportRemarkService reportRemarkService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IAreaTypeConfigService areaTypeConfigService;
        @Autowired
        private ReportRemarkMapper reportRemarkMapper;
        @Autowired
        private Executor executor;
        @Autowired
        @Qualifier("moduleEventSender")
        private Sender moduleEventSender;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private RoomRevenueMapper roomRevenueMapper;
        @Autowired
        private IMonthlyReportBudgetDatabaseService budgetDatabaseService;

        /**
         * 查询Room Revenue区域数据
         *
         * @param monthlyReport 月报
         * @param propertyDTO   资产DTO
         * @return 区域详情
         * @author lichen
         * @date 2023/9/1
         */
        @Override
        public RoomRevenueDetailDTO getRoomRevenue(MonthlyReport monthlyReport, PropertyDTO propertyDTO) {
            //查询备注
            String remark = reportRemarkService.listByReportIdAndAreaId(monthlyReport.getId(), AreaEnum.ROOM_REVENUE.getAreaId());

            List<RoomRevenueDTO> roomRevenueDtoList = list(new LambdaQueryWrapper<RoomRevenue>()
                    .eq(RoomRevenue::getReportId, monthlyReport.getId())
                    .eq(RoomRevenue::getPropertyId, propertyDTO.getId())
                    .orderByAsc(RoomRevenue::getCategoryId))
                    .stream().map(item -> beanMapper.map(item, RoomRevenueDTO.class)).toList();

            //校验是否历史月报
            Boolean isHistoryMonthlyReport = monthlyReportService.checkIsHistoryMonthlyReport(monthlyReport, propertyDTO);

            /**
             * 历史月报：按照区域表存储的数据，返回
             * 当前正在使用或未来的数据：按照最新的区域类型配置 组装返回对象
             */
            if (isHistoryMonthlyReport) {
                return new RoomRevenueDetailDTO(roomRevenueDtoList, remark);
            }

            Map<Integer, RoomRevenueDTO> categoryId2RevenueCompSetDTO = roomRevenueDtoList.stream()
                    .collect(Collectors.toMap(RoomRevenueDTO::getCategoryId, Function.identity()));
            //区域分类集合
            List<AreaTypeConfig> areaTypeConfigs = areaTypeConfigService.listByAreaId(propertyDTO.getId(), Lists.newArrayList(AreaEnum.ROOM_REVENUE.getAreaId()));

            List<RoomRevenueDTO> resultList = Lists.newArrayListWithCapacity(areaTypeConfigs.size());
            for (AreaTypeConfig areaTypeConfig : areaTypeConfigs) {
                RoomRevenueDTO roomRevenueDTO = categoryId2RevenueCompSetDTO.get(areaTypeConfig.getId());
                if (Objects.isNull(roomRevenueDTO)) {
                    resultList.add(RoomRevenueDTO.builder()
                            .categoryId(areaTypeConfig.getId())
                            .categoryName(areaTypeConfig.getName())
                            .contentType(areaTypeConfig.getContentType())
                            .build());
                } else {
                    resultList.add(roomRevenueDTO);
                }
            }
            return new RoomRevenueDetailDTO(resultList, remark);
        }

        /**
         * 保存Room Revenue区域数据
         *
         * @param monthlyReport        月报
         * @param propertyDTO          资产DTO
         * @param roomRevenueDetailDTO 区域信息
         * @param loginUserId          登录用户id
         * @return void
         * @author lichen
         * @date 2023/9/2
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void save(MonthlyReport monthlyReport, PropertyDTO propertyDTO, RoomRevenueDetailDTO roomRevenueDetailDTO, int loginUserId) {
            Integer tenantId = propertyDTO.getTenantId();
            Integer propertyId = propertyDTO.getId();

            remove(new LambdaQueryWrapper<RoomRevenue>()
                    .eq(RoomRevenue::getReportId, monthlyReport.getId())
                    .eq(RoomRevenue::getPropertyId, propertyId));

            //保存区域信息
            List<RoomRevenue> roomRevenues = beanMapper.mapList(roomRevenueDetailDTO.getList(), RoomRevenue.class, (dto, entity) -> {
                entity.setTenantId(tenantId);
                entity.setPropertyId(propertyId);
                entity.setReportId(monthlyReport.getId());
                entity.setUpdateId(loginUserId);
                entity.setUpdateTime(DateTimeUtils.nowTimestamp());
            });
            saveBatch(roomRevenues);

            //保存备注
            ReportRemark reportRemark = ReportRemark.builder()
                    .tenantId(tenantId)
                    .propertyId(propertyId)
                    .reportId(monthlyReport.getId())
                    .areaId(AreaEnum.ROOM_REVENUE.getAreaId())
                    .remark(roomRevenueDetailDTO.getRemark())
                    .build();
            reportRemarkMapper.saveOrUpdateByUnique(reportRemark);

            //发送事件
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                HashMap<Long, MonthlyReport> id2MonthlyReport = new HashMap<>();
                id2MonthlyReport.put(monthlyReport.getId(), monthlyReport);
                this.sendRoomRevenueSnsEvent(tenantId, propertyId, roomRevenues, id2MonthlyReport);
            });
        }

        /**
         * Room Revenue区域数据变化时，发送sns事件
         *
         * @param tenantId         租户id
         * @param propertyId       资产id
         * @param roomRevenues     Room Revenue区域数据
         * @param id2MonthlyReport 月报集合
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        public void sendRoomRevenueSnsEvent(Integer tenantId, Integer propertyId, List<RoomRevenue> roomRevenues, Map<Long, MonthlyReport> id2MonthlyReport) {
            Map<Long, List<RoomRevenue>> reportId2RoomRevenues = roomRevenues.stream().collect(Collectors.groupingBy(RoomRevenue::getReportId));

            List<MonthlyReportEventDataBO> monthlyReportEventDataBOS = Lists.newArrayListWithCapacity(id2MonthlyReport.size());
            id2MonthlyReport.forEach((reportId, monthlyReport) -> {
                //获取当前月的数据并转化成BO
                List<MonthlyReportEventValueBO> monthlyReportEventValueBOS = reportId2RoomRevenues.getOrDefault(reportId, Collections.emptyList())
                        .stream()
                        .map(item -> MonthlyReportEventValueBO.builder()
                                .categoryName(item.getCategoryName())
                                .target(item.getBudget())
                                .actual(item.getActual())
                                .ly(item.getLastYear())
                                .build())
                        .collect(Collectors.toList());

                //生成每个月的数据并添加到集合中
                long yearMonth = YearMonthUtils.parseYearMonthToLong(YearMonth.of(monthlyReport.getYear(), monthlyReport.getMonth()));
                monthlyReportEventDataBOS.add(MonthlyReportEventDataBO.builder()
                        .yearMonth(yearMonth)
                        .data(monthlyReportEventValueBOS)
                        .build());
            });
            MonthlyReportEventBO monthlyReportEventBO = new MonthlyReportEventBO(propertyId, monthlyReportEventDataBOS);
            moduleEventSender.publish(MoudleEventSubjectEnum.MONTHLY_REPORT_ROOM_REVENUE.getSubject(),
                    JsonUtils.convertObjToString(objectMapper, monthlyReportEventBO));
        }

        /**
         * 保存导入的数据
         *
         * @param tenantId                   租户id
         * @param propertyId                 资产id
         * @param monthlyReport              月报
         * @param userId                     用户id
         * @param roomRevenueByReportDTOList 区域数据
         * @param areaTypeConfigs            区域类型集合
         * @return void
         * @author lichen
         * @date 2023/9/7
         */
        @Override
        public void saveImportData(Integer tenantId, Integer propertyId, MonthlyReport monthlyReport, Integer userId,
                                   List<RoomRevenueByReportDTO> roomRevenueByReportDTOList, List<AreaTypeConfig> areaTypeConfigs) {
            Map<String, AreaTypeConfig> name2Category = areaTypeConfigs.stream().collect(Collectors.toMap(AreaTypeConfig::getName, Function.identity()));
            Set<String> categoryNames = name2Category.keySet();

            List<RoomRevenue> roomRevenues = roomRevenueByReportDTOList.stream()
                    .filter(item -> categoryNames.contains(item.getCategoryName()))
                    .map(item -> beanMapper.map(item, RoomRevenue.class, entity -> {
                        entity.setTenantId(tenantId);
                        entity.setPropertyId(propertyId);
                        entity.setReportId(monthlyReport.getId());
                        entity.setCategoryId(name2Category.get(item.getCategoryName()).getId());
                        entity.setContentType(name2Category.get(item.getCategoryName()).getContentType());
                        entity.setUpdateId(userId);
                        entity.setUpdateTime(DateTimeUtils.nowTimestamp());
                    })).toList();

            if (CollectionUtils.isNotEmpty(roomRevenues)) {
                roomRevenueMapper.saveOrUpdateByUnique(roomRevenues);
            }

            List<RoomRevenue> list = list(new LambdaQueryWrapper<RoomRevenue>()
                    .eq(RoomRevenue::getReportId, monthlyReport.getId())
                    .eq(RoomRevenue::getPropertyId, propertyId));
            //发送事件
            Map<Long, MonthlyReport> reportId2MonthlyReport = new HashMap<>();
            reportId2MonthlyReport.put(monthlyReport.getId(), monthlyReport);
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                this.sendRoomRevenueSnsEvent(tenantId, propertyId, list, reportId2MonthlyReport);
            });
        }

        /**
         * 删除区域数据
         *
         * @param propertyDTO    资产DTO
         * @param monthlyReports 月报集合
         * @return void
         * @author lichen
         * @date 2023/9/5
         */
        @Override
        public void delete(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports) {
            List<Long> reportIds = monthlyReports.stream().map(MonthlyReport::getId).toList();
            if (CollectionUtils.isEmpty(reportIds)) return;
            remove(new LambdaQueryWrapper<RoomRevenue>()
                    .in(RoomRevenue::getReportId, reportIds)
                    .eq(RoomRevenue::getPropertyId, propertyDTO.getId()));

            //查询月报数据
            Map<Long, MonthlyReport> reportId2MonthlyReport = monthlyReports.stream()
                    .collect(Collectors.toMap(MonthlyReport::getId, Function.identity()));

            //发送事件
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                this.sendRoomRevenueSnsEvent(propertyDTO.getTenantId(), propertyDTO.getId(), Collections.emptyList(), reportId2MonthlyReport);
            });
        }

        /**
         * 更新分类
         *
         * @param propertyDTO       资产DTO
         * @param monthlyReports    月报集合
         * @param areaTypeConfig    分类
         * @param oriAreaTypeConfig 修改前的 分类
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        public void updateCategory(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports, AreaTypeConfig areaTypeConfig, AreaTypeConfig oriAreaTypeConfig) {
            List<Long> monthlyReportIds = monthlyReports.stream().map(MonthlyReport::getId).collect(Collectors.toList());

            // 月报对应的月份集合
            Map<Long, YearMonth> monthlyReportId2YearMonth = monthlyReports.stream().collect(Collectors.toMap(
                    MonthlyReport::getId, monthlyReport -> YearMonth.of(monthlyReport.getYear(), monthlyReport.getMonth())));
            Map<YearMonth, Map<Integer, BigDecimal>> yearMonth2Type2Budget = new HashMap<>();
            if(Objects.nonNull(areaTypeConfig.getType())){
                List<YearMonth> yearMonths = monthlyReportId2YearMonth.values().stream().toList();
                // 获取指定type Budget Datebase功能的budget值
                yearMonth2Type2Budget = budgetDatabaseService.listMultiMonthBudget(propertyDTO.getId(), yearMonths,
                        Collections.singletonList(areaTypeConfig.getType()));
            }
            final Map<YearMonth, Map<Integer, BigDecimal>> finalYearMonth2Type2Budget = yearMonth2Type2Budget;

            //查询需要更新分类名称的数据
            List<RoomRevenue> roomRevenues = list(new LambdaQueryWrapper<RoomRevenue>()
                    .in(RoomRevenue::getReportId, monthlyReportIds)
                    .eq(RoomRevenue::getPropertyId, propertyDTO.getId())
                    .eq(RoomRevenue::getCategoryId, areaTypeConfig.getId()));
            if (CollectionUtils.isEmpty(roomRevenues)) return;

            long nowTimestamp = DateTimeUtils.nowTimestamp();
            roomRevenues.forEach(item -> {
                // 设置新的分类名称
                item.setCategoryName(areaTypeConfig.getName()).setContentType(areaTypeConfig.getContentType());
                // 更新人为0且type不为null时，重新初始化数据
                if (item.getUpdateId() == 0 && Objects.nonNull(areaTypeConfig.getType())) {
                    YearMonth yearMonth = monthlyReportId2YearMonth.get(item.getReportId());
                    BigDecimal budget = finalYearMonth2Type2Budget.getOrDefault(yearMonth, Collections.emptyMap()).get(areaTypeConfig.getType());
                    item.setBudget(budget);
                    item.setUpdateTime(nowTimestamp);
                }
            });
            //更新
            baseMapper.batchUpdateWithNull(roomRevenues);

            Map<Long, MonthlyReport> reportId2MonthlyReport = monthlyReports.stream().collect(Collectors.toMap(MonthlyReport::getId, Function.identity()));
            List<RoomRevenue> list = list(new LambdaQueryWrapper<RoomRevenue>()
                    .in(RoomRevenue::getReportId, monthlyReportIds)
                    .eq(RoomRevenue::getPropertyId, propertyDTO.getId()));
            //发送事件
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                this.sendRoomRevenueSnsEvent(propertyDTO.getTenantId(), propertyDTO.getId(), list, reportId2MonthlyReport);
            });
        }

        /**
         * 删除区域分类id对应的数据
         *
         * @param propertyDTO    资产DTO
         * @param monthlyReports 月报集合
         * @param categoryId     分类id
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        @Override
        public void deleteAreaDataByCategoryId(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports, Integer categoryId) {
            List<Long> monthlyReportIds = monthlyReports.stream().map(MonthlyReport::getId).collect(Collectors.toList());

            //查询需要刪除的分类数据
            List<RoomRevenue> roomRevenues = list(new LambdaQueryWrapper<RoomRevenue>()
                    .in(RoomRevenue::getReportId, monthlyReportIds)
                    .eq(RoomRevenue::getPropertyId, propertyDTO.getId())
                    .eq(RoomRevenue::getCategoryId, categoryId));
            if (CollectionUtils.isEmpty(roomRevenues)) return;

            //批量删除
            removeByIds(roomRevenues.stream().map(RoomRevenue::getId).toList());

            Map<Long, MonthlyReport> reportId2MonthlyReport = monthlyReports.stream().collect(Collectors.toMap(MonthlyReport::getId, Function.identity()));
            List<RoomRevenue> list = list(new LambdaQueryWrapper<RoomRevenue>()
                    .in(RoomRevenue::getReportId, monthlyReportIds)
                    .eq(RoomRevenue::getPropertyId, propertyDTO.getId()));
            //发送事件
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                this.sendRoomRevenueSnsEvent(propertyDTO.getTenantId(), propertyDTO.getId(), list, reportId2MonthlyReport);
            });
        }

        /**
         * 根据分类，新增区域数据
         *
         * @param propertyDTO    资产DTO
         * @param monthlyReports 月报集合
         * @param areaTypeConfig 区域分类
         * @return void
         * @author lichen
         * @date 2023/9/8
         */
        @Override
        public void insertAreaDataByCategory(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports, AreaTypeConfig areaTypeConfig) {
            Map<YearMonth, Map<Integer, BigDecimal>> yearMonth2Type2Budget = new HashMap<>();
            if(Objects.nonNull(areaTypeConfig.getType())){
                List<YearMonth> yearMonths = monthlyReports.stream()
                        .map(monthlyReport -> YearMonth.of(monthlyReport.getYear(), monthlyReport.getMonth())).toList();
                // 获取指定type Budget Datebase功能的budget值
                yearMonth2Type2Budget = budgetDatabaseService.listMultiMonthBudget(propertyDTO.getId(), yearMonths,
                        Collections.singletonList(areaTypeConfig.getType()));
            }
            final Map<YearMonth, Map<Integer, BigDecimal>> finalYearMonth2Type2Budget = yearMonth2Type2Budget;

            List<RoomRevenue> roomRevenues = monthlyReports.stream()
                    .map(monthlyReport -> {
                        RoomRevenue roomRevenue = RoomRevenue.builder()
                                .tenantId(propertyDTO.getTenantId())
                                .propertyId(propertyDTO.getId())
                                .reportId(monthlyReport.getId())
                                .categoryId(areaTypeConfig.getId())
                                .categoryName(areaTypeConfig.getName())
                                .contentType(areaTypeConfig.getContentType())
                                .updateId(0)
                                .updateTime(DateTimeUtils.nowTimestamp())
                                .build();
                        if(Objects.nonNull(areaTypeConfig.getType())){
                            YearMonth yearMonth = YearMonth.of(monthlyReport.getYear(), monthlyReport.getMonth());
                            //指定月份指定type的budget指标
                            BigDecimal budget = finalYearMonth2Type2Budget.getOrDefault(yearMonth, Collections.emptyMap()).getOrDefault(areaTypeConfig.getType(), null);
                            roomRevenue.setBudget(budget);
                        }
                        return roomRevenue;
                    })
                    .toList();
            saveBatch(roomRevenues);

            List<Long> monthlyReportIds = monthlyReports.stream().map(MonthlyReport::getId).toList();
            Map<Long, MonthlyReport> reportId2MonthlyReport = monthlyReports.stream().collect(Collectors.toMap(MonthlyReport::getId, Function.identity()));
            List<RoomRevenue> list = list(new LambdaQueryWrapper<RoomRevenue>()
                    .in(RoomRevenue::getReportId, monthlyReportIds)
                    .eq(RoomRevenue::getPropertyId, propertyDTO.getId()));
            //发送事件
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                this.sendRoomRevenueSnsEvent(propertyDTO.getTenantId(), propertyDTO.getId(), list, reportId2MonthlyReport);
            });
        }

        /**
         * 初始化区域数据
         *
         * @param propertyDTO            资产DTO
         * @param monthlyReports         月报集合
         * @param areaId2AreaTypeConfigs 区域分类集合
         * @return void
         * @author lichen
         * @date 2023/9/8
         */
        @Override
        public void init(PropertyDTO propertyDTO, List<MonthlyReport> monthlyReports,
                         Map<Integer, List<AreaTypeConfig>> areaId2AreaTypeConfigs) {
            //过滤出开通对应区域的月报
            List<MonthlyReport> openAreaMonthlyReports = monthlyReports.stream().filter(monthlyReport -> {
                List<Integer> openAreaIds = JsonUtils.convertStringToList(objectMapper, monthlyReport.getAreaIds(), Integer.class);
                return openAreaIds.contains(AreaEnum.ROOM_REVENUE.getAreaId());
            }).toList();

            if (CollectionUtils.isEmpty(openAreaMonthlyReports)) return;

            //获取分类集合
            List<AreaTypeConfig> areaTypeConfigs = areaId2AreaTypeConfigs.get(AreaEnum.ROOM_REVENUE.getAreaId());
            if (CollectionUtils.isEmpty(areaTypeConfigs)) return;

            // 指标类型集合
            List<Integer> typeList = areaTypeConfigs.stream().map(AreaTypeConfig::getType).filter(Objects::nonNull).toList();
            Map<YearMonth, Map<Integer, BigDecimal>> yearMonth2Type2Budget = new HashMap<>();
            if(CollectionUtils.isNotEmpty(typeList)){
                // 开通月报的月份集合
                List<YearMonth> yearMonths = openAreaMonthlyReports.stream()
                        .map(monthlyReport -> YearMonth.of(monthlyReport.getYear(), monthlyReport.getMonth())).toList();
                // 获取指定type Budget Datebase功能的budget值
                yearMonth2Type2Budget = budgetDatabaseService.listMultiMonthBudget(propertyDTO.getId(), yearMonths, typeList);
            }

            List<RoomRevenue> roomRevenues = Lists.newArrayListWithCapacity(areaTypeConfigs.size() * openAreaMonthlyReports.size());

            for (MonthlyReport openAreaMonthlyReport : openAreaMonthlyReports) {
                for (AreaTypeConfig areaTypeConfig : areaTypeConfigs) {
                    RoomRevenue roomRevenue = RoomRevenue.builder()
                            .tenantId(propertyDTO.getTenantId())
                            .propertyId(propertyDTO.getId())
                            .reportId(openAreaMonthlyReport.getId())
                            .categoryId(areaTypeConfig.getId())
                            .categoryName(areaTypeConfig.getName())
                            .contentType(areaTypeConfig.getContentType())
                            .updateId(0)
                            .updateTime(DateTimeUtils.nowTimestamp())
                            .build();
                    if(Objects.nonNull(areaTypeConfig.getType())){
                        // 获取指定月份的Budget
                        YearMonth yearMonth = YearMonth.of(openAreaMonthlyReport.getYear(), openAreaMonthlyReport.getMonth());
                        Map<Integer, BigDecimal> type2Budget = yearMonth2Type2Budget.getOrDefault(yearMonth, Collections.emptyMap());
                        roomRevenue.setBudget(type2Budget.get(areaTypeConfig.getType()));
                    }
                    roomRevenues.add(roomRevenue);
                }
            }
            saveBatch(roomRevenues);

            //发送事件
            TransactionUtils.afterCommitAsyncExecute(executor, () -> {
                Map<Long, MonthlyReport> reportId2MonthlyReport = openAreaMonthlyReports.stream().collect(Collectors.toMap(MonthlyReport::getId, Function.identity()));
                this.sendRoomRevenueSnsEvent(propertyDTO.getTenantId(), propertyDTO.getId(), roomRevenues, reportId2MonthlyReport);
            });
        }

    }