| | |
| | | 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; |
| | | |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void saveEstimatedDelivery(EstimatedDeliverySaveDTO request) { |
| | | // 查询已有规则 type=2, fieldA=1, cityId, deleted=0 |
| | | 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, "1") |
| | | .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); |
| | | |
| | | Date now = new Date(); |
| | | if (existing != null) { |
| | | // 更新 |
| | | existing.setFieldB(request.getStartDistance()); |
| | | existing.setFieldC(request.getStartTime()); |
| | | existing.setFieldD(request.getContinueDistance()); |
| | | existing.setFieldE(request.getContinueTime()); |
| | | 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("1"); |
| | | rule.setFieldB(request.getStartDistance()); |
| | | rule.setFieldC(request.getStartTime()); |
| | | rule.setFieldD(request.getContinueDistance()); |
| | | rule.setFieldE(request.getContinueTime()); |
| | | 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); |
| | |
| | | pricingRuleMapper.insert(rule); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public EstimatedDeliveryVO getEstimatedDelivery(Integer cityId) { |
| | | public List<EstimatedDeliveryVO> getEstimatedDelivery(Integer cityId) { |
| | | QueryWrapper<PricingRule> qw = new QueryWrapper<>(); |
| | | qw.lambda() |
| | | .eq(PricingRule::getType, Constants.TWO) |
| | | .eq(PricingRule::getFieldA, "1") |
| | | .in(PricingRule::getFieldA, "1", "2") |
| | | .eq(PricingRule::getCityId, cityId) |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .last("limit 1"); |
| | | PricingRule rule = pricingRuleMapper.selectOne(qw); |
| | | .orderByAsc(PricingRule::getFieldA); |
| | | List<PricingRule> rules = pricingRuleMapper.selectList(qw); |
| | | |
| | | // 将已有规则按fieldA分组 |
| | | Map<String, PricingRule> ruleMap = new HashMap<>(); |
| | | for (PricingRule rule : rules) { |
| | | ruleMap.put(rule.getFieldA(), rule); |
| | | } |
| | | |
| | | // 固定返回2条:fieldA=1(标速达), fieldA=2(极速达),无数据时返回空对象 |
| | | List<EstimatedDeliveryVO> voList = new ArrayList<>(); |
| | | for (int fieldA = 1; fieldA <= 2; fieldA++) { |
| | | EstimatedDeliveryVO vo = new EstimatedDeliveryVO(); |
| | | 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.setContinueDistance(rule.getFieldD()); |
| | | vo.setContinueTime(rule.getFieldE()); |
| | | } |
| | | return vo; |
| | | 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 |