# RevenueCustomersServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.internationalization.InternationalizationNumberDTO;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.commonlib.util.UpdateLogUtil;
    import cloud.wconnect.rateshop.entity.revenue.RevenueCustomers;
    import cloud.wconnect.rateshop.mapper.revenue.RevenueCustomersMapper;
    import cloud.wconnect.rateshop.pojo.dto.revenue.CustomersDTO;
    import cloud.wconnect.rateshop.service.revenue.IRevenueCustomersService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.util.Objects;

    /**
     * <p>
     * 客源收入 服务实现类
     * </p>
     *
     * @author yyt
     * @since 2024-04-09
     */
    @Service
    @DS("rate_shop")
    public class RevenueCustomersServiceImpl extends ServiceImpl<RevenueCustomersMapper, RevenueCustomers> implements IRevenueCustomersService {

        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private UpdateLogUtil updateLogUtil;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;

        /**
         * 获取 CustomersDTO
         *
         * @param propertyId 资产 id
         * @param date       指定日期（格式：yyyyMMdd）
         * @return CustomersDTO
         * @author yyt
         * @date 2024/4/9
         **/
        @Override
        public CustomersDTO getCustomersDTO(Integer propertyId, Integer date) {
            RevenueCustomers revenueCustomers = get(propertyId, date);
            if (Objects.isNull(revenueCustomers)) {
                return new CustomersDTO();
            }

            return beanMapper.map(revenueCustomers, CustomersDTO.class);
        }

        /**
         * 获取 customers
         *
         * @param propertyId 资产 id
         * @param date       指定日期（格式：yyyyMMdd）
         * @return customers
         * @author yyt
         * @date 2024/4/9
         **/
        private RevenueCustomers get(Integer propertyId, Integer date) {
            return getOne(new QueryWrapper<RevenueCustomers>().lambda()
                    .eq(RevenueCustomers::getPropertyId, propertyId)
                    .eq(RevenueCustomers::getTheDate, date));
        }

        /**
         * 保存 customers
         *
         * @param propertyId 资产 id
         * @param date       指定日期（格式：yyyyMMdd）
         * @param customers  customers
         * @param userId     操作人
         * @author yyt
         * @date 2024/4/9
         **/
        @Override
        public void saveOrUpdate(Integer propertyId, Integer date, CustomersDTO customers, int userId) {
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            InternationalizationNumberDTO number = propertyDTO.getInternationalization().getNumber();
            int dataPrecision = BaseConstant.DATA_PRECISION;
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(number.getCalculationRule());

            BigDecimal transientRevenue = customers.getTransientRevenue();
            transientRevenue = Objects.isNull(transientRevenue) ? null : transientRevenue.setScale(dataPrecision, roundingMode);
            Integer transientRooms = customers.getTransientRooms();

            BigDecimal groupRevenue = customers.getGroupRevenue();
            groupRevenue = Objects.isNull(groupRevenue) ? null : groupRevenue.setScale(dataPrecision, roundingMode);
            Integer groupRooms = customers.getGroupRooms();

            BigDecimal contractRevenue = customers.getContractRevenue();
            contractRevenue = Objects.isNull(contractRevenue) ? null : contractRevenue.setScale(dataPrecision, roundingMode);
            Integer contractRooms = customers.getContractRooms();

            RevenueCustomers existCustomers = get(propertyId, date);
            if (Objects.isNull(existCustomers)) {
                RevenueCustomers revenueCustomers = new RevenueCustomers()
                        .setPropertyId(propertyId).setTheDate(date)
                        .setTransientRevenue(transientRevenue)
                        .setTransientRooms(transientRooms)
                        .setTransientAdr(calculateAdr(transientRevenue, transientRooms, number))
                        .setGroupRevenue(groupRevenue)
                        .setGroupRooms(groupRooms)
                        .setGroupAdr(calculateAdr(groupRevenue, groupRooms, number))
                        .setContractRevenue(contractRevenue)
                        .setContractRooms(contractRooms)
                        .setContractAdr(calculateAdr(contractRevenue, contractRooms, number))
                        .setUpdateLog(updateLogUtil.get(userId));
                save(revenueCustomers);
            } else {
                update(new UpdateWrapper<RevenueCustomers>().lambda()
                        .set(RevenueCustomers::getTransientRevenue, transientRevenue)
                        .set(RevenueCustomers::getTransientRooms, transientRooms)
                        .set(RevenueCustomers::getTransientAdr, calculateAdr(transientRevenue, transientRooms, number))
                        .set(RevenueCustomers::getGroupRevenue, groupRevenue)
                        .set(RevenueCustomers::getGroupRooms, groupRooms)
                        .set(RevenueCustomers::getGroupAdr, calculateAdr(groupRevenue, groupRooms, number))
                        .set(RevenueCustomers::getContractRevenue, contractRevenue)
                        .set(RevenueCustomers::getContractRooms, contractRooms)
                        .set(RevenueCustomers::getContractAdr, calculateAdr(contractRevenue, contractRooms, number))
                        .set(RevenueCustomers::getUpdateLog, updateLogUtil.append(existCustomers.getUpdateLog(), userId))
                        .eq(RevenueCustomers::getPropertyId, propertyId).eq(RevenueCustomers::getTheDate, date));
            }
        }

        /**
         * 计算 adr
         *
         * @param revenue revenue
         * @param rooms   rooms
         * @param number  国际化配置
         * @return adr
         * @author yyt
         * @date 2024/5/24
         **/
        private BigDecimal calculateAdr(BigDecimal revenue, Integer rooms, InternationalizationNumberDTO number) {
            int calculatePrecision = BaseConstant.DATA_PRECISION;
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(number.getCalculationRule());

            if (Objects.nonNull(revenue) && Objects.nonNull(rooms) && rooms != BaseConstant.ZERO) {
                // adr = revenue / rooms
                return revenue.divide(BigDecimal.valueOf(rooms), calculatePrecision, roundingMode);
            }

            return null;
        }

    }