Commit 215ff4299bb501545f968bf97d11553c4468edb0
1 parent
efa4fb8d
新增骑手持单上限功能,包括上限解析、校验及批量查询接口,并优化相关订单分配逻辑
Showing
10 changed files
with
155 additions
and
41 deletions
src/main/java/com/diligrp/rider/controller/AdminRiderController.java
| @@ -93,6 +93,15 @@ public class AdminRiderController { | @@ -93,6 +93,15 @@ public class AdminRiderController { | ||
| 93 | return Result.success(); | 93 | return Result.success(); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | + /** 设置个人持单上限:0=不限制 */ | ||
| 97 | + @PostMapping("/setHoldOrderLimit") | ||
| 98 | + public Result<Void> setHoldOrderLimit(@RequestParam Long riderId, | ||
| 99 | + @RequestParam int holdOrderLimit, | ||
| 100 | + HttpServletRequest request) { | ||
| 101 | + adminRiderService.setHoldOrderLimit(riderId, holdOrderLimit, resolveScopedCityId(request)); | ||
| 102 | + return Result.success(); | ||
| 103 | + } | ||
| 104 | + | ||
| 96 | /** 指派骑手接单 */ | 105 | /** 指派骑手接单 */ |
| 97 | @PostMapping("/order/designate") | 106 | @PostMapping("/order/designate") |
| 98 | public Result<Void> designate(@RequestParam Long orderId, | 107 | public Result<Void> designate(@RequestParam Long orderId, |
src/main/java/com/diligrp/rider/entity/Rider.java
| @@ -59,6 +59,9 @@ public class Rider { | @@ -59,6 +59,9 @@ public class Rider { | ||
| 59 | /** 是否休息:0=否 1=是 */ | 59 | /** 是否休息:0=否 1=是 */ |
| 60 | private Integer isRest; | 60 | private Integer isRest; |
| 61 | 61 | ||
| 62 | + /** 个人持单上限:0=不限制 */ | ||
| 63 | + private Integer holdOrderLimit; | ||
| 64 | + | ||
| 62 | /** 身份证号 */ | 65 | /** 身份证号 */ |
| 63 | private String idNo; | 66 | private String idNo; |
| 64 | 67 |
src/main/java/com/diligrp/rider/service/AdminRiderService.java
| @@ -22,6 +22,8 @@ public interface AdminRiderService { | @@ -22,6 +22,8 @@ public interface AdminRiderService { | ||
| 22 | void setEnableStatus(Long riderId, int status, Long cityId); | 22 | void setEnableStatus(Long riderId, int status, Long cityId); |
| 23 | /** 切换全职/兼职 */ | 23 | /** 切换全职/兼职 */ |
| 24 | void setType(Long riderId, int type, Long cityId); | 24 | void setType(Long riderId, int type, Long cityId); |
| 25 | + /** 设置个人持单上限 */ | ||
| 26 | + void setHoldOrderLimit(Long riderId, int holdOrderLimit, Long cityId); | ||
| 25 | /** 指派骑手接单 */ | 27 | /** 指派骑手接单 */ |
| 26 | void designate(Long orderId, Long riderId, Long cityId); | 28 | void designate(Long orderId, Long riderId, Long cityId); |
| 27 | /** 处理转单申请(1=通过 3=拒绝) */ | 29 | /** 处理转单申请(1=通过 3=拒绝) */ |
src/main/java/com/diligrp/rider/service/RiderHoldLimitService.java
0 → 100644
| 1 | +package com.diligrp.rider.service; | ||
| 2 | + | ||
| 3 | +import com.diligrp.rider.entity.Rider; | ||
| 4 | +import com.diligrp.rider.vo.DispatchRuleTemplateVO; | ||
| 5 | + | ||
| 6 | +import java.util.List; | ||
| 7 | +import java.util.Map; | ||
| 8 | + | ||
| 9 | +public interface RiderHoldLimitService { | ||
| 10 | + /** 当前持单量(status=3/4) */ | ||
| 11 | + int countCurrentLoad(Long riderId); | ||
| 12 | + | ||
| 13 | + /** 批量查询当前持单量(status=3/4) */ | ||
| 14 | + Map<Long, Integer> getCurrentLoadMap(List<Long> riderIds); | ||
| 15 | + | ||
| 16 | + /** 解析骑手个人持单上限,null 表示不限制 */ | ||
| 17 | + Integer resolveHoldOrderLimit(Rider rider); | ||
| 18 | + | ||
| 19 | + /** 解析抢单场景生效上限,null 表示不限制 */ | ||
| 20 | + Integer resolveGrabLimit(Rider rider, DispatchRuleTemplateVO rule); | ||
| 21 | + | ||
| 22 | + /** 校验骑手是否还能继续接单 */ | ||
| 23 | + void assertWithinLimit(Long riderId, Integer limit, String message); | ||
| 24 | +} |
src/main/java/com/diligrp/rider/service/impl/AdminRiderServiceImpl.java
| @@ -16,6 +16,7 @@ import com.diligrp.rider.entity.*; | @@ -16,6 +16,7 @@ import com.diligrp.rider.entity.*; | ||
| 16 | import com.diligrp.rider.mapper.*; | 16 | import com.diligrp.rider.mapper.*; |
| 17 | import com.diligrp.rider.service.AdminRiderService; | 17 | import com.diligrp.rider.service.AdminRiderService; |
| 18 | import com.diligrp.rider.service.DeliveryOrderService; | 18 | import com.diligrp.rider.service.DeliveryOrderService; |
| 19 | +import com.diligrp.rider.service.RiderHoldLimitService; | ||
| 19 | import com.diligrp.rider.vo.DeliveryOrderCreateVO; | 20 | import com.diligrp.rider.vo.DeliveryOrderCreateVO; |
| 20 | import lombok.RequiredArgsConstructor; | 21 | import lombok.RequiredArgsConstructor; |
| 21 | import org.springframework.stereotype.Service; | 22 | import org.springframework.stereotype.Service; |
| @@ -40,6 +41,7 @@ public class AdminRiderServiceImpl implements AdminRiderService { | @@ -40,6 +41,7 @@ public class AdminRiderServiceImpl implements AdminRiderService { | ||
| 40 | private final RiderBalanceMapper balanceMapper; | 41 | private final RiderBalanceMapper balanceMapper; |
| 41 | private final AdminScopeGuard adminScopeGuard; | 42 | private final AdminScopeGuard adminScopeGuard; |
| 42 | private final DeliveryOrderService deliveryOrderService; | 43 | private final DeliveryOrderService deliveryOrderService; |
| 44 | + private final RiderHoldLimitService riderHoldLimitService; | ||
| 43 | 45 | ||
| 44 | @Override | 46 | @Override |
| 45 | public void add(AdminRiderAddDTO dto, Long cityId) { | 47 | public void add(AdminRiderAddDTO dto, Long cityId) { |
| @@ -171,6 +173,17 @@ public class AdminRiderServiceImpl implements AdminRiderService { | @@ -171,6 +173,17 @@ public class AdminRiderServiceImpl implements AdminRiderService { | ||
| 171 | } | 173 | } |
| 172 | 174 | ||
| 173 | @Override | 175 | @Override |
| 176 | + public void setHoldOrderLimit(Long riderId, int holdOrderLimit, Long cityId) { | ||
| 177 | + if (holdOrderLimit < 0) throw new BizException("个人持单上限不能小于0"); | ||
| 178 | + Rider rider = riderMapper.selectById(riderId); | ||
| 179 | + if (rider == null) throw new BizException("骑手不存在"); | ||
| 180 | + adminScopeGuard.assertCityAccessible(cityId, rider.getCityId()); | ||
| 181 | + riderMapper.update(null, new LambdaUpdateWrapper<Rider>() | ||
| 182 | + .eq(Rider::getId, riderId) | ||
| 183 | + .set(Rider::getHoldOrderLimit, holdOrderLimit)); | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + @Override | ||
| 174 | @Transactional | 187 | @Transactional |
| 175 | public void designate(Long orderId, Long riderId, Long cityId) { | 188 | public void designate(Long orderId, Long riderId, Long cityId) { |
| 176 | Orders order = ordersMapper.selectById(orderId); | 189 | Orders order = ordersMapper.selectById(orderId); |
| @@ -187,6 +200,8 @@ public class AdminRiderServiceImpl implements AdminRiderService { | @@ -187,6 +200,8 @@ public class AdminRiderServiceImpl implements AdminRiderService { | ||
| 187 | if (order.getIsTrans() == 1 && riderId.equals(order.getOldRiderId())) { | 200 | if (order.getIsTrans() == 1 && riderId.equals(order.getOldRiderId())) { |
| 188 | throw new BizException("此订单为该骑手转单订单,无法指派给该骑手"); | 201 | throw new BizException("此订单为该骑手转单订单,无法指派给该骑手"); |
| 189 | } | 202 | } |
| 203 | + Integer holdOrderLimit = riderHoldLimitService.resolveHoldOrderLimit(rider); | ||
| 204 | + riderHoldLimitService.assertWithinLimit(riderId, holdOrderLimit, "该骑手当前持单量已达个人上限,无法指派"); | ||
| 190 | 205 | ||
| 191 | long now = System.currentTimeMillis() / 1000; | 206 | long now = System.currentTimeMillis() / 1000; |
| 192 | LambdaUpdateWrapper<Orders> wrapper = new LambdaUpdateWrapper<Orders>() | 207 | LambdaUpdateWrapper<Orders> wrapper = new LambdaUpdateWrapper<Orders>() |
src/main/java/com/diligrp/rider/service/impl/DispatchServiceImpl.java
| @@ -7,6 +7,7 @@ import com.diligrp.rider.entity.*; | @@ -7,6 +7,7 @@ import com.diligrp.rider.entity.*; | ||
| 7 | import com.diligrp.rider.mapper.*; | 7 | import com.diligrp.rider.mapper.*; |
| 8 | import com.diligrp.rider.service.DispatchRuleService; | 8 | import com.diligrp.rider.service.DispatchRuleService; |
| 9 | import com.diligrp.rider.service.DispatchService; | 9 | import com.diligrp.rider.service.DispatchService; |
| 10 | +import com.diligrp.rider.service.RiderHoldLimitService; | ||
| 10 | import com.diligrp.rider.service.WebhookService; | 11 | import com.diligrp.rider.service.WebhookService; |
| 11 | import com.diligrp.rider.util.GeoUtil; | 12 | import com.diligrp.rider.util.GeoUtil; |
| 12 | import com.diligrp.rider.vo.DispatchRuleTemplateVO; | 13 | import com.diligrp.rider.vo.DispatchRuleTemplateVO; |
| @@ -33,6 +34,7 @@ public class DispatchServiceImpl implements DispatchService { | @@ -33,6 +34,7 @@ public class DispatchServiceImpl implements DispatchService { | ||
| 33 | private final OrdersMapper ordersMapper; | 34 | private final OrdersMapper ordersMapper; |
| 34 | private final RiderOrderCountMapper countMapper; | 35 | private final RiderOrderCountMapper countMapper; |
| 35 | private final RiderOrderRefuseMapper refuseMapper; | 36 | private final RiderOrderRefuseMapper refuseMapper; |
| 37 | + private final RiderHoldLimitService riderHoldLimitService; | ||
| 36 | private final WebhookService webhookService; | 38 | private final WebhookService webhookService; |
| 37 | private final ObjectMapper objectMapper; | 39 | private final ObjectMapper objectMapper; |
| 38 | 40 | ||
| @@ -94,7 +96,7 @@ public class DispatchServiceImpl implements DispatchService { | @@ -94,7 +96,7 @@ public class DispatchServiceImpl implements DispatchService { | ||
| 94 | double orderTLng = parseDouble(order.getTLng()); | 96 | double orderTLng = parseDouble(order.getTLng()); |
| 95 | 97 | ||
| 96 | // 5. 预加载每个骑手的统计数据 | 98 | // 5. 预加载每个骑手的统计数据 |
| 97 | - Map<Long, Integer> currentLoadMap = getCurrentLoadMap(riderIds); | 99 | + Map<Long, Integer> currentLoadMap = riderHoldLimitService.getCurrentLoadMap(riderIds); |
| 98 | Map<Long, Integer> dailyCountMap = getDailyCountMap(riderIds); | 100 | Map<Long, Integer> dailyCountMap = getDailyCountMap(riderIds); |
| 99 | 101 | ||
| 100 | // 6. 对每个候选骑手评分 | 102 | // 6. 对每个候选骑手评分 |
| @@ -111,7 +113,8 @@ public class DispatchServiceImpl implements DispatchService { | @@ -111,7 +113,8 @@ public class DispatchServiceImpl implements DispatchService { | ||
| 111 | 113 | ||
| 112 | // 持单量检查(强制过滤) | 114 | // 持单量检查(强制过滤) |
| 113 | int currentLoad = currentLoadMap.getOrDefault(rider.getId(), 0); | 115 | int currentLoad = currentLoadMap.getOrDefault(rider.getId(), 0); |
| 114 | - if (rule.getGrabMaxPerRider() != null && currentLoad >= rule.getGrabMaxPerRider()) { | 116 | + Integer holdOrderLimit = riderHoldLimitService.resolveHoldOrderLimit(rider); |
| 117 | + if (holdOrderLimit != null && currentLoad >= holdOrderLimit) { | ||
| 115 | continue; // 持单已满,跳过 | 118 | continue; // 持单已满,跳过 |
| 116 | } | 119 | } |
| 117 | 120 | ||
| @@ -283,21 +286,6 @@ public class DispatchServiceImpl implements DispatchService { | @@ -283,21 +286,6 @@ public class DispatchServiceImpl implements DispatchService { | ||
| 283 | return map; | 286 | return map; |
| 284 | } | 287 | } |
| 285 | 288 | ||
| 286 | - /** 获取每个骑手当前持单量(status=3 或 4 的订单数) */ | ||
| 287 | - private Map<Long, Integer> getCurrentLoadMap(List<Long> riderIds) { | ||
| 288 | - Map<Long, Integer> map = new HashMap<>(); | ||
| 289 | - if (riderIds.isEmpty()) return map; | ||
| 290 | - List<Orders> inProgress = ordersMapper.selectList( | ||
| 291 | - new LambdaQueryWrapper<Orders>() | ||
| 292 | - .in(Orders::getRiderId, riderIds) | ||
| 293 | - .in(Orders::getStatus, List.of(3, 4)) | ||
| 294 | - .select(Orders::getRiderId)); | ||
| 295 | - for (Orders o : inProgress) { | ||
| 296 | - map.merge(o.getRiderId(), 1, Integer::sum); | ||
| 297 | - } | ||
| 298 | - return map; | ||
| 299 | - } | ||
| 300 | - | ||
| 301 | /** 获取每个骑手当日接单量 */ | 289 | /** 获取每个骑手当日接单量 */ |
| 302 | private Map<Long, Integer> getDailyCountMap(List<Long> riderIds) { | 290 | private Map<Long, Integer> getDailyCountMap(List<Long> riderIds) { |
| 303 | Map<Long, Integer> map = new HashMap<>(); | 291 | Map<Long, Integer> map = new HashMap<>(); |
src/main/java/com/diligrp/rider/service/impl/RiderHoldLimitServiceImpl.java
0 → 100644
| 1 | +package com.diligrp.rider.service.impl; | ||
| 2 | + | ||
| 3 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||
| 4 | +import com.diligrp.rider.common.exception.BizException; | ||
| 5 | +import com.diligrp.rider.entity.Orders; | ||
| 6 | +import com.diligrp.rider.entity.Rider; | ||
| 7 | +import com.diligrp.rider.mapper.OrdersMapper; | ||
| 8 | +import com.diligrp.rider.service.RiderHoldLimitService; | ||
| 9 | +import com.diligrp.rider.vo.DispatchRuleTemplateVO; | ||
| 10 | +import lombok.RequiredArgsConstructor; | ||
| 11 | +import org.springframework.stereotype.Service; | ||
| 12 | + | ||
| 13 | +import java.util.HashMap; | ||
| 14 | +import java.util.List; | ||
| 15 | +import java.util.Map; | ||
| 16 | + | ||
| 17 | +@Service | ||
| 18 | +@RequiredArgsConstructor | ||
| 19 | +public class RiderHoldLimitServiceImpl implements RiderHoldLimitService { | ||
| 20 | + | ||
| 21 | + private final OrdersMapper ordersMapper; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public int countCurrentLoad(Long riderId) { | ||
| 25 | + if (riderId == null || riderId < 1) { | ||
| 26 | + return 0; | ||
| 27 | + } | ||
| 28 | + return Math.toIntExact(ordersMapper.selectCount(new LambdaQueryWrapper<Orders>() | ||
| 29 | + .eq(Orders::getRiderId, riderId) | ||
| 30 | + .eq(Orders::getIsDel, 0) | ||
| 31 | + .in(Orders::getStatus, List.of(3, 4)))); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + @Override | ||
| 35 | + public Map<Long, Integer> getCurrentLoadMap(List<Long> riderIds) { | ||
| 36 | + Map<Long, Integer> map = new HashMap<>(); | ||
| 37 | + if (riderIds == null || riderIds.isEmpty()) { | ||
| 38 | + return map; | ||
| 39 | + } | ||
| 40 | + List<Orders> inProgress = ordersMapper.selectList(new LambdaQueryWrapper<Orders>() | ||
| 41 | + .in(Orders::getRiderId, riderIds) | ||
| 42 | + .eq(Orders::getIsDel, 0) | ||
| 43 | + .in(Orders::getStatus, List.of(3, 4)) | ||
| 44 | + .select(Orders::getRiderId)); | ||
| 45 | + for (Orders order : inProgress) { | ||
| 46 | + map.merge(order.getRiderId(), 1, Integer::sum); | ||
| 47 | + } | ||
| 48 | + return map; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + @Override | ||
| 52 | + public Integer resolveHoldOrderLimit(Rider rider) { | ||
| 53 | + if (rider == null || rider.getHoldOrderLimit() == null || rider.getHoldOrderLimit() <= 0) { | ||
| 54 | + return null; | ||
| 55 | + } | ||
| 56 | + return rider.getHoldOrderLimit(); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + @Override | ||
| 60 | + public Integer resolveGrabLimit(Rider rider, DispatchRuleTemplateVO rule) { | ||
| 61 | + Integer personalLimit = resolveHoldOrderLimit(rider); | ||
| 62 | + Integer templateLimit = null; | ||
| 63 | + if (rule != null && rule.getGrabEnabled() != null && rule.getGrabEnabled() == 1 | ||
| 64 | + && rule.getGrabMaxPerRider() != null && rule.getGrabMaxPerRider() > 0) { | ||
| 65 | + templateLimit = rule.getGrabMaxPerRider(); | ||
| 66 | + } | ||
| 67 | + if (personalLimit == null) { | ||
| 68 | + return templateLimit; | ||
| 69 | + } | ||
| 70 | + if (templateLimit == null) { | ||
| 71 | + return personalLimit; | ||
| 72 | + } | ||
| 73 | + return Math.min(personalLimit, templateLimit); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Override | ||
| 77 | + public void assertWithinLimit(Long riderId, Integer limit, String message) { | ||
| 78 | + if (limit == null) { | ||
| 79 | + return; | ||
| 80 | + } | ||
| 81 | + if (countCurrentLoad(riderId) >= limit) { | ||
| 82 | + throw new BizException(message); | ||
| 83 | + } | ||
| 84 | + } | ||
| 85 | +} |
src/main/java/com/diligrp/rider/service/impl/RiderLocationServiceImpl.java
| @@ -10,12 +10,11 @@ import com.diligrp.rider.mapper.OrdersMapper; | @@ -10,12 +10,11 @@ import com.diligrp.rider.mapper.OrdersMapper; | ||
| 10 | import com.diligrp.rider.mapper.RiderLocationMapper; | 10 | import com.diligrp.rider.mapper.RiderLocationMapper; |
| 11 | import com.diligrp.rider.mapper.RiderMapper; | 11 | import com.diligrp.rider.mapper.RiderMapper; |
| 12 | import com.diligrp.rider.service.CityService; | 12 | import com.diligrp.rider.service.CityService; |
| 13 | -import com.diligrp.rider.service.DispatchRuleService; | 13 | +import com.diligrp.rider.service.RiderHoldLimitService; |
| 14 | import com.diligrp.rider.service.RiderLocationService; | 14 | import com.diligrp.rider.service.RiderLocationService; |
| 15 | import com.diligrp.rider.util.GeoUtil; | 15 | import com.diligrp.rider.util.GeoUtil; |
| 16 | import com.diligrp.rider.vo.AdminRiderDashboardVO; | 16 | import com.diligrp.rider.vo.AdminRiderDashboardVO; |
| 17 | import com.diligrp.rider.vo.AdminRiderLocationVO; | 17 | import com.diligrp.rider.vo.AdminRiderLocationVO; |
| 18 | -import com.diligrp.rider.vo.DispatchRuleTemplateVO; | ||
| 19 | import com.diligrp.rider.vo.NearbyRiderVO; | 18 | import com.diligrp.rider.vo.NearbyRiderVO; |
| 20 | import com.diligrp.rider.websocket.LocationPushService; | 19 | import com.diligrp.rider.websocket.LocationPushService; |
| 21 | import lombok.RequiredArgsConstructor; | 20 | import lombok.RequiredArgsConstructor; |
| @@ -37,7 +36,7 @@ public class RiderLocationServiceImpl implements RiderLocationService { | @@ -37,7 +36,7 @@ public class RiderLocationServiceImpl implements RiderLocationService { | ||
| 37 | private final RiderMapper riderMapper; | 36 | private final RiderMapper riderMapper; |
| 38 | private final OrdersMapper ordersMapper; | 37 | private final OrdersMapper ordersMapper; |
| 39 | private final CityService cityService; | 38 | private final CityService cityService; |
| 40 | - private final DispatchRuleService dispatchRuleService; | 39 | + private final RiderHoldLimitService riderHoldLimitService; |
| 41 | private final LocationPushService locationPushService; | 40 | private final LocationPushService locationPushService; |
| 42 | 41 | ||
| 43 | /** | 42 | /** |
| @@ -146,9 +145,6 @@ public class RiderLocationServiceImpl implements RiderLocationService { | @@ -146,9 +145,6 @@ public class RiderLocationServiceImpl implements RiderLocationService { | ||
| 146 | return result; | 145 | return result; |
| 147 | } | 146 | } |
| 148 | 147 | ||
| 149 | - DispatchRuleTemplateVO rule = dispatchRuleService.getActiveRule(cityId); | ||
| 150 | - Integer maxHoldOrderCount = normalizeMaxHoldOrderCount(rule); | ||
| 151 | - | ||
| 152 | List<Rider> riders = riderMapper.selectList(new LambdaQueryWrapper<Rider>() | 148 | List<Rider> riders = riderMapper.selectList(new LambdaQueryWrapper<Rider>() |
| 153 | .eq(Rider::getCityId, cityId) | 149 | .eq(Rider::getCityId, cityId) |
| 154 | .orderByDesc(Rider::getId)); | 150 | .orderByDesc(Rider::getId)); |
| @@ -165,8 +161,8 @@ public class RiderLocationServiceImpl implements RiderLocationService { | @@ -165,8 +161,8 @@ public class RiderLocationServiceImpl implements RiderLocationService { | ||
| 165 | .in(Orders::getStatus, List.of(3, 4)) | 161 | .in(Orders::getStatus, List.of(3, 4)) |
| 166 | .in(Orders::getRiderId, riderIds) | 162 | .in(Orders::getRiderId, riderIds) |
| 167 | .eq(Orders::getIsDel, 0)); | 163 | .eq(Orders::getIsDel, 0)); |
| 168 | - log.debug("商铺骑手看板基础数据查询完成,cityId={} riderCount={} locationCount={} holdingOrderCount={} maxHoldOrderCount={}", | ||
| 169 | - cityId, riders.size(), locations.size(), holdingOrders.size(), maxHoldOrderCount); | 164 | + log.debug("商铺骑手看板基础数据查询完成,cityId={} riderCount={} locationCount={} holdingOrderCount={}", |
| 165 | + cityId, riders.size(), locations.size(), holdingOrders.size()); | ||
| 170 | 166 | ||
| 171 | java.util.Map<Long, RiderLocation> locationMap = new java.util.HashMap<>(); | 167 | java.util.Map<Long, RiderLocation> locationMap = new java.util.HashMap<>(); |
| 172 | for (RiderLocation location : locations) { | 168 | for (RiderLocation location : locations) { |
| @@ -191,6 +187,7 @@ public class RiderLocationServiceImpl implements RiderLocationService { | @@ -191,6 +187,7 @@ public class RiderLocationServiceImpl implements RiderLocationService { | ||
| 191 | vo.setStatus(buildRiderStatus(rider, locationMap.get(rider.getId()))); | 187 | vo.setStatus(buildRiderStatus(rider, locationMap.get(rider.getId()))); |
| 192 | 188 | ||
| 193 | int holdOrderCount = holdCountMap.getOrDefault(rider.getId(), 0); | 189 | int holdOrderCount = holdCountMap.getOrDefault(rider.getId(), 0); |
| 190 | + Integer maxHoldOrderCount = riderHoldLimitService.resolveHoldOrderLimit(rider); | ||
| 194 | vo.setHoldOrderCount(holdOrderCount); | 191 | vo.setHoldOrderCount(holdOrderCount); |
| 195 | vo.setMaxHoldOrderCount(maxHoldOrderCount); | 192 | vo.setMaxHoldOrderCount(maxHoldOrderCount); |
| 196 | vo.setLoadRate(calcLoadRate(holdOrderCount, maxHoldOrderCount)); | 193 | vo.setLoadRate(calcLoadRate(holdOrderCount, maxHoldOrderCount)); |
| @@ -290,13 +287,6 @@ public class RiderLocationServiceImpl implements RiderLocationService { | @@ -290,13 +287,6 @@ public class RiderLocationServiceImpl implements RiderLocationService { | ||
| 290 | return "在线"; | 287 | return "在线"; |
| 291 | } | 288 | } |
| 292 | 289 | ||
| 293 | - private Integer normalizeMaxHoldOrderCount(DispatchRuleTemplateVO rule) { | ||
| 294 | - if (rule == null || rule.getGrabMaxPerRider() == null || rule.getGrabMaxPerRider() <= 0) { | ||
| 295 | - return null; | ||
| 296 | - } | ||
| 297 | - return rule.getGrabMaxPerRider(); | ||
| 298 | - } | ||
| 299 | - | ||
| 300 | private Integer calcLoadRate(int holdOrderCount, Integer maxHoldOrderCount) { | 290 | private Integer calcLoadRate(int holdOrderCount, Integer maxHoldOrderCount) { |
| 301 | if (maxHoldOrderCount == null || maxHoldOrderCount <= 0) { | 291 | if (maxHoldOrderCount == null || maxHoldOrderCount <= 0) { |
| 302 | return null; | 292 | return null; |
src/main/java/com/diligrp/rider/service/impl/RiderOrderServiceImpl.java
| @@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.type.TypeReference; | @@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.type.TypeReference; | ||
| 8 | import com.fasterxml.jackson.databind.ObjectMapper; | 8 | import com.fasterxml.jackson.databind.ObjectMapper; |
| 9 | import com.diligrp.rider.common.exception.BizException; | 9 | import com.diligrp.rider.common.exception.BizException; |
| 10 | import com.diligrp.rider.service.DispatchRuleService; | 10 | import com.diligrp.rider.service.DispatchRuleService; |
| 11 | +import com.diligrp.rider.service.RiderHoldLimitService; | ||
| 11 | import com.diligrp.rider.service.RiderLevelService; | 12 | import com.diligrp.rider.service.RiderLevelService; |
| 12 | import com.diligrp.rider.service.RiderOrderService; | 13 | import com.diligrp.rider.service.RiderOrderService; |
| 13 | import com.diligrp.rider.service.WebhookService; | 14 | import com.diligrp.rider.service.WebhookService; |
| @@ -40,6 +41,7 @@ public class RiderOrderServiceImpl implements RiderOrderService { | @@ -40,6 +41,7 @@ public class RiderOrderServiceImpl implements RiderOrderService { | ||
| 40 | private final RiderMapper riderMapper; | 41 | private final RiderMapper riderMapper; |
| 41 | private final RiderLevelService riderLevelService; | 42 | private final RiderLevelService riderLevelService; |
| 42 | private final DispatchRuleService dispatchRuleService; | 43 | private final DispatchRuleService dispatchRuleService; |
| 44 | + private final RiderHoldLimitService riderHoldLimitService; | ||
| 43 | private final ObjectMapper objectMapper; | 45 | private final ObjectMapper objectMapper; |
| 44 | private final WebhookService webhookService; | 46 | private final WebhookService webhookService; |
| 45 | 47 | ||
| @@ -130,14 +132,8 @@ public class RiderOrderServiceImpl implements RiderOrderService { | @@ -130,14 +132,8 @@ public class RiderOrderServiceImpl implements RiderOrderService { | ||
| 130 | } | 132 | } |
| 131 | 133 | ||
| 132 | DispatchRuleTemplateVO rule = dispatchRuleService.getActiveRule(cityId); | 134 | DispatchRuleTemplateVO rule = dispatchRuleService.getActiveRule(cityId); |
| 133 | - if (rule != null && rule.getGrabMaxPerRider() != null && rule.getGrabMaxPerRider() > 0) { | ||
| 134 | - Long currentLoad = ordersMapper.selectCount(new LambdaQueryWrapper<Orders>() | ||
| 135 | - .eq(Orders::getRiderId, riderId) | ||
| 136 | - .in(Orders::getStatus, List.of(3, 4))); | ||
| 137 | - if (currentLoad >= rule.getGrabMaxPerRider()) { | ||
| 138 | - throw new BizException(1000, "当前持单量已达上限,无法继续抢单"); | ||
| 139 | - } | ||
| 140 | - } | 135 | + Integer grabLimit = riderHoldLimitService.resolveGrabLimit(rider, rule); |
| 136 | + riderHoldLimitService.assertWithinLimit(riderId, grabLimit, "当前持单量已达上限,无法继续抢单"); | ||
| 141 | if (order.getIsTrans() == 1 && riderId.equals(order.getOldRiderId())) { | 137 | if (order.getIsTrans() == 1 && riderId.equals(order.getOldRiderId())) { |
| 142 | throw new BizException(980, "抢单失败,不能抢自己转出的单"); | 138 | throw new BizException(980, "抢单失败,不能抢自己转出的单"); |
| 143 | } | 139 | } |
src/main/resources/schema.sql
| @@ -20,6 +20,7 @@ CREATE TABLE `rider` ( | @@ -20,6 +20,7 @@ CREATE TABLE `rider` ( | ||
| 20 | `status` TINYINT NOT NULL DEFAULT 1 COMMENT '账号状态:0=禁用 1=正常', | 20 | `status` TINYINT NOT NULL DEFAULT 1 COMMENT '账号状态:0=禁用 1=正常', |
| 21 | `balance` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '余额(兼职用)', | 21 | `balance` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '余额(兼职用)', |
| 22 | `is_rest` TINYINT NOT NULL DEFAULT 0 COMMENT '是否休息:0=否 1=是', | 22 | `is_rest` TINYINT NOT NULL DEFAULT 0 COMMENT '是否休息:0=否 1=是', |
| 23 | + `hold_order_limit` INT NOT NULL DEFAULT 0 COMMENT '个人持单上限,0=不限制', | ||
| 23 | `id_no` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '身份证号', | 24 | `id_no` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '身份证号', |
| 24 | `thumb` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '手持身份证照片', | 25 | `thumb` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '手持身份证照片', |
| 25 | `create_time` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '注册时间', | 26 | `create_time` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '注册时间', |
| @@ -500,7 +501,8 @@ ALTER TABLE `orders` ADD COLUMN `ext_store_id` BIGINT UNSIGNED NOT NULL DEFAULT | @@ -500,7 +501,8 @@ ALTER TABLE `orders` ADD COLUMN `ext_store_id` BIGINT UNSIGNED NOT NULL DEFAULT | ||
| 500 | ALTER TABLE `orders` ADD COLUMN `dispatch_time` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '系统派单时间' AFTER `trans_time`; | 501 | ALTER TABLE `orders` ADD COLUMN `dispatch_time` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '系统派单时间' AFTER `trans_time`; |
| 501 | ALTER TABLE `orders` ADD COLUMN `dispatch_rider_id` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '系统指派骑手ID' AFTER `dispatch_time`; | 502 | ALTER TABLE `orders` ADD COLUMN `dispatch_rider_id` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '系统指派骑手ID' AFTER `dispatch_time`; |
| 502 | 503 | ||
| 503 | --- rider 表补充评分统计字段 | 504 | +-- rider 表补充个人持单上限与评分统计字段 |
| 505 | +ALTER TABLE `rider` ADD COLUMN `hold_order_limit` INT NOT NULL DEFAULT 0 COMMENT '个人持单上限,0=不限制' AFTER `is_rest`; | ||
| 504 | ALTER TABLE `rider` ADD COLUMN `star_total` INT NOT NULL DEFAULT 0 COMMENT '评分总分' AFTER `thumb`; | 506 | ALTER TABLE `rider` ADD COLUMN `star_total` INT NOT NULL DEFAULT 0 COMMENT '评分总分' AFTER `thumb`; |
| 505 | ALTER TABLE `rider` ADD COLUMN `star_count` INT NOT NULL DEFAULT 0 COMMENT '评分次数' AFTER `star_total`; | 507 | ALTER TABLE `rider` ADD COLUMN `star_count` INT NOT NULL DEFAULT 0 COMMENT '评分次数' AFTER `star_total`; |
| 506 | 508 |