RiderLevelServiceImpl.java 4.4 KB
package com.diligrp.rider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.diligrp.rider.common.exception.BizException;
import com.diligrp.rider.entity.RiderLevel;
import com.diligrp.rider.entity.Rider;
import com.diligrp.rider.mapper.RiderLevelMapper;
import com.diligrp.rider.mapper.RiderMapper;
import com.diligrp.rider.service.RiderLevelService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;

@Service
@RequiredArgsConstructor
public class RiderLevelServiceImpl implements RiderLevelService {

    private final RiderMapper riderMapper;
    private final RiderLevelMapper riderLevelMapper;

    @Override
    public RiderLevel getLevelByRider(Long riderId) {
        Rider rider = riderMapper.selectById(riderId);
        if (rider == null) throw new BizException("骑手信息不存在");

        RiderLevel level = null;
        if (rider.getLevelId() != null && rider.getLevelId() > 0) {
            level = riderLevelMapper.selectById(rider.getLevelId());
        }
        if (level == null) {
            // 取该城市默认等级
            level = riderLevelMapper.selectOne(new LambdaQueryWrapper<RiderLevel>()
                    .eq(RiderLevel::getCityId, rider.getCityId())
                    .eq(RiderLevel::getIsDefault, 1)
                    .last("LIMIT 1"));
        }
        return level;
    }

    @Override
    public BigDecimal calcIncome(Long riderId, int orderType, BigDecimal deliveryFee, long distance) {
        RiderLevel level = getLevelByRider(riderId);
        if (level == null) return BigDecimal.ZERO;

        // 外卖配送(type=6)按跑腿类规则计算
        // 办事类(type=5)按办事类规则计算,其余统一按跑腿类
        if (orderType == 5) {
            return calcWorkIncome(level, deliveryFee);
        }
        return calcRunIncome(level, deliveryFee, distance);
    }

    private BigDecimal calcRunIncome(RiderLevel level, BigDecimal deliveryFee, long distance) {
        int mode = level.getRunFeeMode() == null ? 1 : level.getRunFeeMode();
        switch (mode) {
            case 1: // 固定金额
                return level.getRunFixMoney() == null ? BigDecimal.ZERO : level.getRunFixMoney();
            case 2: // 按比例
                if (level.getRunRate() == null || deliveryFee == null) return BigDecimal.ZERO;
                return deliveryFee.multiply(level.getRunRate())
                        .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
            case 3: // 按距离
                return calcDistanceIncome(level, distance);
            default:
                return BigDecimal.ZERO;
        }
    }

    private BigDecimal calcDistanceIncome(RiderLevel level, long distanceMeters) {
        if (level.getDistanceBasic() == null || level.getDistanceBasicMoney() == null) {
            return BigDecimal.ZERO;
        }
        BigDecimal income = level.getDistanceBasicMoney();
        long basicMeters = level.getDistanceBasic();
        if (distanceMeters > basicMeters && level.getDistanceMoreMoney() != null) {
            // 超出部分按每公里计费
            long extraMeters = distanceMeters - basicMeters;
            BigDecimal extraKm = BigDecimal.valueOf(extraMeters).divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
            income = income.add(extraKm.multiply(level.getDistanceMoreMoney()));
        }
        // 上限
        if (level.getDistanceMaxMoney() != null && level.getDistanceMaxMoney().compareTo(BigDecimal.ZERO) > 0) {
            if (income.compareTo(level.getDistanceMaxMoney()) > 0) {
                income = level.getDistanceMaxMoney();
            }
        }
        return income.setScale(2, RoundingMode.HALF_UP);
    }

    private BigDecimal calcWorkIncome(RiderLevel level, BigDecimal deliveryFee) {
        int mode = level.getWorkFeeMode() == null ? 1 : level.getWorkFeeMode();
        switch (mode) {
            case 1:
                return level.getWorkFixMoney() == null ? BigDecimal.ZERO : level.getWorkFixMoney();
            case 2:
                if (level.getWorkRate() == null || deliveryFee == null) return BigDecimal.ZERO;
                return deliveryFee.multiply(level.getWorkRate())
                        .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
            default:
                return BigDecimal.ZERO;
        }
    }
}