# CalculateIwcConsumer.java

    package cloud.wconnect.rateshop.consumer.iwc;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.FunctionIdConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.CommonService;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.rateshop.entity.rateshop.Iwc;
    import cloud.wconnect.rateshop.entity.rateshop.PropertyHotel;
    import cloud.wconnect.rateshop.entity.rateshop.Setting;
    import cloud.wconnect.rateshop.entity.rateshop.TrendSourceSetting;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.RateConfigDTO;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.sender.CalculateIwcContentByOTA;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.sender.CalculateIwcContentByPriceChange;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.sender.CalculateIwcMessage;
    import cloud.wconnect.rateshop.service.rateshop.IIwcService;
    import cloud.wconnect.rateshop.service.rateshop.IPropertyHotelService;
    import cloud.wconnect.rateshop.service.rateshop.ISettingService;
    import cloud.wconnect.rateshop.service.rateshop.ITrendSourceSettingService;
    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.collections4.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import software.amazon.awssdk.services.sqs.model.Message;

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Objects;

    /**
     * IWC计算的消费方
     *
     * @author lichen
     * @date 2025/4/3
     */
    @Slf4j
    @Component
    @DS("rate_shop")
    public class CalculateIwcConsumer {

        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private IIwcService iwcService;
        @Autowired
        private ISettingService settingService;
        @Autowired
        private ITrendSourceSettingService trendSourceSettingService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private IPropertyHotelService propertyHotelService;
        @Autowired
        private CommonService commonService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;

        /**
         * IWC计算
         *
         * @param message 消息内容
         * @return void
         * @author lichen
         * @date 2025/4/3
         */
        public void handleMessage(Message message) {
            //把消息内容转化成IWCCalculateMessage
            CalculateIwcMessage calculateIwcMessage = JsonUtils.convertStringToObject(objectMapper, message.body(), CalculateIwcMessage.class);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(calculateIwcMessage.getPropertyId());
            //校验资产是否开通rate shop功能
            if (!commonService.checkOpenFunction(propertyDTO, FunctionIdConstant.RATE_SHOP)) {
                log.warn("CalculateIwcConsumer.end... the property has not opened the rate shop function;property:{}", propertyDTO.getAbbr());
                return;
            }
            //资产的rate shop配置
            Setting setting = settingService.getByPropertyId(calculateIwcMessage.getPropertyId());
            if (Objects.isNull(setting)) return;

            if (calculateIwcMessage.getTriggerType() == CalculateIwcMessage.PRICE_CHANGE) {
                //价格变化（sold out，调涨）时，计算iwc值
                this.calculateIwcByPriceChange(calculateIwcMessage.getPropertyId(), setting, calculateIwcMessage.getContent());
            } else {
                //采集到OTA卖况时，计算iwc值
                this.calculateIwcByOTA(calculateIwcMessage.getPropertyId(), setting, calculateIwcMessage.getContent());
            }
        }

        /**
         * 价格变化（sold out，调涨）时，计算iwc值
         *
         * @param propertyId 资产ID
         * @param setting    资产的rate shop配置
         * @param content    需计算的IWC范围
         * @return void
         * @author lichen
         * @date 2025/4/3
         */
        private void calculateIwcByPriceChange(Integer propertyId, Setting setting, String content) {
            //查询资产配置的OTA 地址ID
            List<TrendSourceSetting> trendSourceSettings = trendSourceSettingService.listByPropertyId(propertyId);
            if (CollectionUtils.isEmpty(trendSourceSettings)) return;
            //目前只取第一个OTA地址，super admin只支持配置一个
            TrendSourceSetting trendSourceSetting = trendSourceSettings.get(0);

            CalculateIwcContentByPriceChange calculateIwcContentByPriceChange = JsonUtils.convertStringToObject(objectMapper, content, CalculateIwcContentByPriceChange.class);

            //组装待计算的iwc集合
            Iwc iwc = beanMapper.map(calculateIwcContentByPriceChange, Iwc.class);
            iwc.setPropertyId(propertyId);
            iwc.setTrendLocationId(trendSourceSetting.getLocationId());
            List<Iwc> waitCalculateIwcList = Collections.singletonList(iwc);

            //入住日期所在的年份
            String year = calculateIwcContentByPriceChange.getCheckInDate().toString().substring(0, 4);

            //计算IWC
            iwcService.calculateIwc(propertyId, trendSourceSetting.getLocationId(), waitCalculateIwcList, setting, year);
        }

        /**
         * 采集到OTA卖况时，计算IWC值
         *
         * @param propertyId 资产ID
         * @param setting    rate shop的配置
         * @param content    需计算的IWC范围
         * @return void
         * @author lichen
         * @date 2025/4/3
         */
        private void calculateIwcByOTA(Integer propertyId, Setting setting, String content) {
            //查询资产自身酒店
            PropertyHotel propertySelfHotel = propertyHotelService.getPropertySelfHotel(propertyId);
            Integer hotelId = propertySelfHotel.getHotelId();

            //房价参数配置
            List<RateConfigDTO> rateConfigDTOS = JsonUtils.convertStringToList(objectMapper, setting.getRateConfig(), RateConfigDTO.class);

            CalculateIwcContentByOTA calculateIwcContentByOTA = JsonUtils.convertStringToObject(objectMapper, content, CalculateIwcContentByOTA.class);
            Integer trendLocationId = calculateIwcContentByOTA.getTrendLocationId();

            //等待计算的iwc集合
            ArrayList<Iwc> waitCalculateIwcList = Lists.newArrayList();

            //组装key集合
            for (RateConfigDTO rateConfigDTO : rateConfigDTOS) {
                for (Integer platformId : rateConfigDTO.getPlatformIds()) {
                    for (Long checkInDate : calculateIwcContentByOTA.getCheckInDateList()) {
                        Iwc iwc = new Iwc().setPropertyId(propertyId)
                                .setTrendLocationId(trendLocationId)
                                .setHotelId(hotelId)
                                .setPos(setting.getPos())
                                .setCurrencyId(setting.getCurrencyId())
                                .setCheckInDate(checkInDate)
                                .setDatasourceId(rateConfigDTO.getDatasourceId())
                                .setPlatformId(platformId)
                                .setRateType(rateConfigDTO.getRateType())
                                .setContainTaxFlag(setting.getContainTaxFlag());
                        waitCalculateIwcList.add(iwc);
                    }
                }
            }
            //计算IWC
            iwcService.calculateIwc(propertyId, trendLocationId, waitCalculateIwcList, setting, calculateIwcContentByOTA.getYear());
        }

    }