rk
2 天以前 3aef471b170a703b501ddb4d9d2a12791d07ff28
server/services/src/main/java/com/doumee/service/business/impl/PricingRuleServiceImpl.java
@@ -34,6 +34,8 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
@@ -379,66 +381,113 @@
    }
    @Override
    public Integer createEstimatedDelivery(EstimatedDeliverySaveDTO request) {
        PricingRule rule = new PricingRule();
        rule.setType(Constants.TWO);
        rule.setCityId(request.getCityId());
        rule.setFieldA(request.getDistance());
        rule.setFieldB(request.getDuration());
        rule.setDeleted(Constants.ZERO);
        rule.setCreateTime(new Date());
        rule.setUpdateTime(new Date());
        pricingRuleMapper.insert(rule);
        return rule.getId();
    @Transactional(rollbackFor = Exception.class)
    public void saveEstimatedDelivery(EstimatedDeliverySaveDTO request) {
        if (request.getItems() == null || request.getItems().isEmpty()) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "时效配置列表不能为空");
        }
        Date now = new Date();
        for (EstimatedDeliverySaveDTO.EstimatedDeliveryItem item : request.getItems()) {
            // 查询已有规则 type=2, fieldA, cityId, deleted=0
            QueryWrapper<PricingRule> qw = new QueryWrapper<>();
            qw.lambda()
                    .eq(PricingRule::getType, Constants.TWO)
                    .eq(PricingRule::getFieldA, String.valueOf(item.getFieldA()))
                    .eq(PricingRule::getCityId, request.getCityId())
                    .eq(PricingRule::getDeleted, Constants.ZERO)
                    .last("limit 1");
            PricingRule existing = pricingRuleMapper.selectOne(qw);
            if (existing != null) {
                existing.setFieldB(item.getStartDistance());
                existing.setFieldC(item.getStartTime());
                existing.setFieldD(item.getContinueDistance());
                existing.setFieldE(item.getContinueTime());
                existing.setUpdateTime(now);
                pricingRuleMapper.updateById(existing);
            } else {
                PricingRule rule = new PricingRule();
                rule.setType(Constants.TWO);
                rule.setFieldA(String.valueOf(item.getFieldA()));
                rule.setFieldB(item.getStartDistance());
                rule.setFieldC(item.getStartTime());
                rule.setFieldD(item.getContinueDistance());
                rule.setFieldE(item.getContinueTime());
                rule.setCityId(request.getCityId());
                rule.setDeleted(Constants.ZERO);
                rule.setCreateTime(now);
                rule.setUpdateTime(now);
                pricingRuleMapper.insert(rule);
            }
        }
    }
    @Override
    public void updateEstimatedDelivery(EstimatedDeliverySaveDTO request) {
        if (request.getId() == null) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "主键不能为空");
        }
        PricingRule existing = pricingRuleMapper.selectById(request.getId());
        if (Objects.isNull(existing) || !Constants.equalsInteger(existing.getType(), Constants.TWO)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        existing.setFieldA(request.getDistance());
        existing.setFieldB(request.getDuration());
        existing.setCityId(request.getCityId());
        existing.setUpdateTime(new Date());
        pricingRuleMapper.updateById(existing);
    }
    @Override
    public void deleteEstimatedDelivery(Integer id) {
        PricingRule existing = pricingRuleMapper.selectById(id);
        if (Objects.isNull(existing) || !Constants.equalsInteger(existing.getType(), Constants.TWO)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        existing.setDeleted(Constants.ONE);
        existing.setUpdateTime(new Date());
        pricingRuleMapper.updateById(existing);
    }
    @Override
    public List<EstimatedDeliveryVO> listEstimatedDelivery(Integer cityId) {
    public List<EstimatedDeliveryVO> getEstimatedDelivery(Integer cityId) {
        QueryWrapper<PricingRule> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(PricingRule::getType, Constants.TWO)
                .in(PricingRule::getFieldA, "1", "2")
                .eq(PricingRule::getCityId, cityId)
                .eq(PricingRule::getDeleted, Constants.ZERO)
                .orderByAsc(PricingRule::getFieldA);
        List<PricingRule> rules = pricingRuleMapper.selectList(qw);
        if (CollectionUtils.isEmpty(rules)) {
            return new ArrayList<>();
        // 将已有规则按fieldA分组
        Map<String, PricingRule> ruleMap = new HashMap<>();
        for (PricingRule rule : rules) {
            ruleMap.put(rule.getFieldA(), rule);
        }
        return rules.stream().map(rule -> {
        // 固定返回2条:fieldA=1(标速达), fieldA=2(极速达),无数据时返回空对象
        List<EstimatedDeliveryVO> voList = new ArrayList<>();
        for (int fieldA = 1; fieldA <= 2; fieldA++) {
            EstimatedDeliveryVO vo = new EstimatedDeliveryVO();
            vo.setPricingRuleId(rule.getId());
            vo.setCityId(rule.getCityId());
            vo.setDistance(rule.getFieldA());
            vo.setDuration(rule.getFieldB());
            return vo;
        }).collect(Collectors.toList());
            vo.setCityId(cityId);
            vo.setFieldA(fieldA);
            PricingRule rule = ruleMap.get(String.valueOf(fieldA));
            if (rule != null) {
                vo.setPricingRuleId(rule.getId());
                vo.setStartDistance(rule.getFieldB());
                vo.setStartTime(rule.getFieldC());
                vo.setContinueDistance(rule.getFieldD());
                vo.setContinueTime(rule.getFieldE());
            }
            voList.add(vo);
        }
        return voList;
    }
    @Override
    public BigDecimal calculateEstimatedTime(Integer cityId, Integer fieldA, BigDecimal distance) {
        if (cityId == null || fieldA == null || distance == null) {
            return null;
        }
        QueryWrapper<PricingRule> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(PricingRule::getType, Constants.TWO)
                .eq(PricingRule::getFieldA, String.valueOf(fieldA))
                .eq(PricingRule::getCityId, cityId)
                .eq(PricingRule::getDeleted, Constants.ZERO)
                .last("limit 1");
        PricingRule rule = pricingRuleMapper.selectOne(qw);
        if (rule == null) {
            return null;
        }
        // fieldB=起送里程, fieldC=起送时长, fieldD=续送里程, fieldE=续送时长
        BigDecimal startDistance = new BigDecimal(rule.getFieldB());
        BigDecimal startTime = new BigDecimal(rule.getFieldC());
        BigDecimal continueDistance = new BigDecimal(rule.getFieldD());
        BigDecimal continueTime = new BigDecimal(rule.getFieldE());
        // 距离 <= 起送里程 → 直接返回起送时长
        if (distance.compareTo(startDistance) <= 0) {
            return startTime;
        }
        // 超出部分:向上取整 * 续送时长 + 起送时长
        BigDecimal extraDistance = distance.subtract(startDistance);
        BigDecimal extraCount = extraDistance.divide(continueDistance, 0, RoundingMode.CEILING);
        return startTime.add(extraCount.multiply(continueTime));
    }
    @Override