# RevenueDailySummarySenderServiceImpl.java

    package cloud.wconnect.rateshop.service.revenue.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.MoudleEventSubjectEnum;
    import cloud.wconnect.commonlib.pojo.bo.revenue.DailySummaryBO;
    import cloud.wconnect.commonlib.pojo.bo.revenue.DailySummaryDataBO;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.rateshop.entity.revenue.RevenueDailySummary;
    import cloud.wconnect.rateshop.entity.revenue.RevenueDailySummaryManual;
    import cloud.wconnect.rateshop.mapper.revenue.RevenueDailySummaryManualMapper;
    import cloud.wconnect.rateshop.service.revenue.IRevenueDailySummaryManualService;
    import cloud.wconnect.rateshop.service.revenue.IRevenueDailySummarySenderService;
    import cloud.wconnect.rateshop.service.revenue.IRevenueDailySummaryService;
    import cloud.wconnect.sns.http.processor.Sender;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import lombok.extern.slf4j.Slf4j;
    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 software.amazon.awssdk.services.sns.model.PublishResponse;

    import java.math.BigDecimal;
    import java.util.*;
    import java.util.function.Function;
    import java.util.stream.Collectors;

    /**
     * Daily Summary Occ数据变更时发送Event事件
     *
     * @author lichen
     * @date 2024/10/18
     */
    @Service
    @DS("rate_shop")
    @Slf4j
    public class RevenueDailySummarySenderServiceImpl implements IRevenueDailySummarySenderService {

        @Qualifier("moduleEventSender")
        @Autowired
        private Sender snsSender;
        @Lazy
        @Autowired
        private IRevenueDailySummaryService revenueDailySummaryService;
        @Autowired
        private RevenueDailySummaryManualMapper revenueDailySummaryManualMapper;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IRevenueDailySummaryManualService revenueDailySummaryManualService;

        /**
         * 自动导入Occ时发送Event事件
         *
         * @param propertyId              资产id
         * @param revenueDailySummaryList 自动导入的Occ数据
         * @return void
         * @author lichen
         * @date 2024/10/18
         */
        @Override
        public void publishByAutoImport(Integer propertyId, List<RevenueDailySummary> revenueDailySummaryList) {
            if (CollectionUtils.isEmpty(revenueDailySummaryList)) return;

            //查询资产下指定日期的手动维护的Occ数据
            List<RevenueDailySummaryManual> queryCondition = beanMapper.mapList(revenueDailySummaryList, RevenueDailySummaryManual.class);
            List<RevenueDailySummaryManual> revenueDailySummaryManualList = revenueDailySummaryManualMapper.listByDateAndHour(propertyId, queryCondition);
            Map<String, RevenueDailySummaryManual> key2RevenueDailySummaryManual = revenueDailySummaryManualList.stream()
                    .collect(Collectors.toMap(RevenueDailySummaryManual::generateKey, Function.identity()));

            ArrayList<DailySummaryDataBO> dailySummaryDataBOList = Lists.newArrayListWithCapacity(revenueDailySummaryList.size());

            for (RevenueDailySummary revenueDailySummary : revenueDailySummaryList) {
                //生成唯一的key
                String key = revenueDailySummary.generateKey();
                //获取指定时刻手动维护的数据
                RevenueDailySummaryManual revenueDailySummaryManual = key2RevenueDailySummaryManual.get(key);

                //入住率
                BigDecimal occ = getOccByPriority(revenueDailySummary, revenueDailySummaryManual);
                //售卖房间数
                Integer totalRoomsSold = getTotalRoomsSoldByPriority(revenueDailySummary, revenueDailySummaryManual);

                dailySummaryDataBOList.add(new DailySummaryDataBO(revenueDailySummary.getTheDate(), revenueDailySummary.getTheHour(), occ, totalRoomsSold));
            }

            DailySummaryBO dailySummaryBO = new DailySummaryBO(propertyId, dailySummaryDataBOList);
            //发送消息
            String msg = JsonUtils.convertObjToString(objectMapper, dailySummaryBO);
            PublishResponse response = snsSender.publish(MoudleEventSubjectEnum.DAILY_REVENUE_DAILY_SUMMARY.getSubject(), msg);
            log.info("Revenue Daily Summary send daily-revenue-daily-summary,msgId:{}, body:{}", response.messageId(), msg);
        }

        /**
         * 手动维护Occ时发送Event事件
         *
         * @param propertyId 资产id
         * @param theDate    日期，时间戳
         * @param theHour    小时数
         * @return void
         * @author lichen
         * @date 2024/10/18
         */
        @Override
        public void publishByManualSave(Integer propertyId, Long theDate, Integer theHour) {
            //查询指定时刻自动导入的Daily Summary信息
            RevenueDailySummary revenueDailySummary = revenueDailySummaryService.getByPropertyIdAndDateAndHour(propertyId, theDate, theHour);
            //查询手动维护的Daily Summary信息
            RevenueDailySummaryManual revenueDailySummaryManual = revenueDailySummaryManualService.get(propertyId, theDate, theHour);

            //入住率
            BigDecimal occ = getOccByPriority(revenueDailySummary, revenueDailySummaryManual);
            //售卖房间数
            Integer totalRoomsSold = getTotalRoomsSoldByPriority(revenueDailySummary, revenueDailySummaryManual);

            DailySummaryDataBO dailySummaryDataBO = new DailySummaryDataBO(theDate, theHour, occ, totalRoomsSold);
            DailySummaryBO dailySummaryBO = new DailySummaryBO(propertyId, Collections.singletonList(dailySummaryDataBO));
            //发送消息
            String msg = JsonUtils.convertObjToString(objectMapper, dailySummaryBO);
            PublishResponse response = snsSender.publish(MoudleEventSubjectEnum.DAILY_REVENUE_DAILY_SUMMARY.getSubject(), msg);
            log.info("Revenue Daily Summary send daily-revenue-daily-summary,msgId:{}, body:{}", response.messageId(), msg);
        }

        /**
         * 根据优先级获取occ，手动维护的优先级大于自动导入的
         *
         * @param revenueDailySummary       自动导入的
         * @param revenueDailySummaryManual 手动维护的
         * @return java.math.BigDecimal
         * @author lichen
         * @date 2024/10/22
         */
        private BigDecimal getOccByPriority(RevenueDailySummary revenueDailySummary, RevenueDailySummaryManual revenueDailySummaryManual) {
            //优先级说明：手动维护 > 报告导入

            //手动维护的Occ
            if (Objects.nonNull(revenueDailySummaryManual) && Objects.nonNull(revenueDailySummaryManual.getOcc())) {
                return revenueDailySummaryManual.getOcc();
            }
            //报告导入的occ
            if (Objects.nonNull(revenueDailySummary)) {
                return revenueDailySummary.getOcc();
            }
            return null;
        }

        /**
         * 根据优先级获取totalRoomsSold，手动维护的优先级大于自动导入的
         *
         * @param revenueDailySummary       自动导入的
         * @param revenueDailySummaryManual 手动维护的
         * @return java.math.BigDecimal
         * @author lichen
         * @date 2024/10/22
         */
        private Integer getTotalRoomsSoldByPriority(RevenueDailySummary revenueDailySummary, RevenueDailySummaryManual revenueDailySummaryManual) {
            //优先级说明：手动维护 > 报告导入

            //手动维护的TotalRoomsSold
            if (Objects.nonNull(revenueDailySummaryManual) && Objects.nonNull(revenueDailySummaryManual.getTotalRoomsSold())) {
                return revenueDailySummaryManual.getTotalRoomsSold();
            }
            //报告导入的TotalRoomsSold
            if (Objects.nonNull(revenueDailySummary)) {
                return revenueDailySummary.getTotalRoomsSold();
            }
            return null;
        }

    }