# RevenueTransientGroupFutureServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.SystemPlatformEnum;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.internationalization.InternationalizationNumberDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.rateshop.entity.revenue.RevenueTransientGroupFuture;
    import cloud.wconnect.rateshop.mapper.revenue.RevenueTransientGroupFutureMapper;
    import cloud.wconnect.rateshop.pojo.bo.revenue.TransientGroupAdrBO;
    import cloud.wconnect.rateshop.pojo.bo.revenue.TransientGroupBO;
    import cloud.wconnect.rateshop.pojo.dto.revenue.TransientAndGroupDTO;
    import cloud.wconnect.rateshop.service.revenue.IRevenueTransientGroupFutureService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

    import java.math.RoundingMode;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.stream.Collectors;

    /**
     * <p>
     *  服务实现类
     * </p>
     *
     * @author yyt
     * @since 2024-05-08
     */
    @Service
    @DS("rate_shop")
    public class RevenueTransientGroupFutureServiceImpl extends ServiceImpl<RevenueTransientGroupFutureMapper, RevenueTransientGroupFuture> implements IRevenueTransientGroupFutureService {

        @Autowired
        private BeanMapper beanMapper;

        /**
         * 获取 Transient And Group
         *
         * @param propertyDTO 资产
         * @param targetDate  目标日期
         * @return Transient And Group
         * @author yyt
         * @date 2024/5/11
         */
        @Override
        public List<TransientAndGroupDTO> listTransientAndGroupDTO(PropertyDTO propertyDTO, Long targetDate) {
            // 查询当前日期对应的未来 14 天的数据
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYYMMDD);
            Integer propertyId = propertyDTO.getId();
            ZonedDateTime currentDay = DateTimeUtils.toZonedDateTime(targetDate, propertyDTO.getTimezone());
            ZonedDateTime nextDayDate = currentDay.plusDays(13);
            // 按照日期进行分组
            Map<Integer, RevenueTransientGroupFuture> transientGroupByDate = list(new QueryWrapper<RevenueTransientGroupFuture>().lambda()
                    .eq(RevenueTransientGroupFuture::getPropertyId, propertyId)
                    .between(RevenueTransientGroupFuture::getTargetDate, Integer.parseInt(currentDay.format(dateTimeFormatter)),
                            Integer.parseInt(nextDayDate.format(dateTimeFormatter))))
                    .stream().collect(Collectors.toMap(RevenueTransientGroupFuture::getTargetDate, v -> v));

            List<TransientAndGroupDTO> transientAndGroupDTOList = Lists.newArrayListWithExpectedSize(14);
            for (ZonedDateTime date = currentDay; !date.isAfter(nextDayDate); date = date.plusDays(1)) {
                Integer dateFormatter = Integer.parseInt(date.format(dateTimeFormatter));
                RevenueTransientGroupFuture transientGroup = transientGroupByDate.getOrDefault(dateFormatter,
                        new RevenueTransientGroupFuture().setTargetDate(dateFormatter));
                TransientAndGroupDTO transientAndGroupDTO = beanMapper.map(transientGroup, TransientAndGroupDTO.class);
                transientAndGroupDTO.setTargetDate(date.toEpochSecond());
                transientAndGroupDTOList.add(transientAndGroupDTO);
            }
            return transientAndGroupDTOList;
        }

        /**
         * 保存 Transient And Group
         *
         * @param propertyDTO        资产
         * @param date               目标日期
         * @param transientAndGroups 修改内容
         * @param userId             操作人
         * @author yyt
         * @date 2023/10/28
         */
        @Override
        public void save(PropertyDTO propertyDTO, Long date, List<TransientAndGroupDTO> transientAndGroups, int userId) {
            Integer propertyId = propertyDTO.getId();
            long now = DateTimeUtils.nowTimestamp();
            String timezone = propertyDTO.getTimezone();
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYYMMDD);
            baseMapper.saveOrUpdateBatch(transientAndGroups.stream().map(item ->
                    new RevenueTransientGroupFuture().setPropertyId(propertyId)
                            .setTargetDate(Integer.parseInt(DateTimeUtils.toZonedDateTime(item.getTargetDate(), timezone).format(dateTimeFormatter)))
                            .setOccPercent(item.getOccPercent()).setAdr(item.getAdr()).setTransientRoomNum(item.getTransientRoomNum())
                            .setTransientAdr(item.getTransientAdr()).setGroupRoomNum(item.getGroupRoomNum()).setGroupAdr(item.getGroupAdr())
                            .setUpdatedBy(userId).setUpdatedTime(now)
            ).sorted(Comparator.comparing(RevenueTransientGroupFuture::getTargetDate)).collect(Collectors.toList()));
        }

        /**
         * 保存 Transient And Group
         *
         * @param propertyDTO     资产
         * @param transientGroups Transient And Groups
         * @param userId          操作人
         * @author yyt
         * @date 2024/5/20
         */
        @Override
        public void saveTransientGroupFutureBO(PropertyDTO propertyDTO, List<TransientGroupBO> transientGroups, int userId) {
            if (CollectionUtils.isEmpty(transientGroups)) return;

            Integer propertyId = propertyDTO.getId();
            long now = DateTimeUtils.nowTimestamp();
            InternationalizationNumberDTO number = propertyDTO.getInternationalization().getNumber();
            int dataPrecision = BaseConstant.DATA_PRECISION;
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(number.getCalculationRule());

            String pmsType = propertyDTO.getPmsType();

            List<RevenueTransientGroupFuture> transientGroupFutureList = transientGroups.stream().map(item -> {
                RevenueTransientGroupFuture transientGroupFuture = new RevenueTransientGroupFuture().setPropertyId(propertyId)
                        .setTargetDate(Integer.parseInt(item.getTargetDate().replaceAll("-", "")))
                        .setOccPercent(Objects.isNull(item.getOccPercent()) ? null
                                : item.getOccPercent().setScale(dataPrecision, roundingMode))
                        .setAdr(Objects.isNull(item.getAdr()) ? null : item.getAdr().setScale(dataPrecision, roundingMode))
                        .setTransientRoomNum(item.getTransientRoomNum())
                        .setGroupRoomNum(item.getGroupRoomNum())
                        .setRoomsAvailable(item.getRoomsAvailable())
                        .setUpdatedBy(userId).setUpdatedTime(now);

                if (pmsType.equals(SystemPlatformEnum.SHI_JI.getDesc())) {
                    transientGroupFuture.setTransientAdr(Objects.isNull(item.getTransientAdr()) ? null
                                    : item.getTransientAdr().setScale(dataPrecision, roundingMode))
                            .setGroupAdr(Objects.isNull(item.getGroupAdr()) ? null : item.getGroupAdr().setScale(dataPrecision, roundingMode));
                }

                return transientGroupFuture;
            }).sorted(Comparator.comparing(RevenueTransientGroupFuture::getTargetDate)).collect(Collectors.toList());

            baseMapper.saveOrUpdateBatchForOcc(transientGroupFutureList);

            if (pmsType.equals(SystemPlatformEnum.SHI_JI.getDesc())) {
                baseMapper.saveOrUpdateBatchForAdr(transientGroupFutureList);
            }
        }

        /**
         * 保存 Transient Group Adr Future
         *
         * @param property           资产
         * @param transientGroupAdrs Transient Group Adrs 集合
         * @param userId             操作人
         * @author yyt
         * @date 2024/5/21
         */
        @Override
        public void saveTransientGroupAdrBO(PropertyDTO property, List<TransientGroupAdrBO> transientGroupAdrs, int userId) {
            if (CollectionUtils.isEmpty(transientGroupAdrs)) return;

            Integer propertyId = property.getId();
            long now = DateTimeUtils.nowTimestamp();
            InternationalizationNumberDTO number = property.getInternationalization().getNumber();
            int dataPrecision = BaseConstant.DATA_PRECISION;
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(number.getCalculationRule());

            List<RevenueTransientGroupFuture> transientGroupFutures = transientGroupAdrs.stream().map(item ->
                    new RevenueTransientGroupFuture().setPropertyId(propertyId)
                            .setTargetDate(Integer.parseInt(StringUtils.replace(item.getTargetDate(), "-", "")))
                            .setTransientAdr(Objects.isNull(item.getTransientAdr()) ? null
                                    : item.getTransientAdr().setScale(dataPrecision, roundingMode))
                            .setGroupAdr(Objects.isNull(item.getGroupAdr()) ? null : item.getGroupAdr().setScale(dataPrecision, roundingMode))
                            .setUpdatedBy(userId).setUpdatedTime(now)
            ).sorted(Comparator.comparing(RevenueTransientGroupFuture::getTargetDate)).collect(Collectors.toList());

            baseMapper.saveOrUpdateBatchForAdr(transientGroupFutures);
        }

    }