소스 검색

feat: 闪送订单详情返回骑手平均评分,无评价默认4.5

qmj 7 시간 전
부모
커밋
9a5c3916ec

+ 12 - 2
ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationService.java

@@ -876,6 +876,12 @@ public class FlashDeliveryApplicationService {
         return urls;
     }
 
+    /** 骑手闪送平均分;尚无评价时按平台骑手展示惯例回退 4.5。 */
+    private Double riderAverageStars(Long riderId) {
+        Double average = orderMapper.selectRiderAverageStars(riderId);
+        return average == null ? 4.5 : average;
+    }
+
     /** 组装用户或骑手视角详情;hideSensitiveFields 为 true 时按抢单前脱敏返回。 */
     private FlashDeliveryOrderDetailView participantDetail(FlashDeliveryOrder order,
                                                            boolean userView,
@@ -884,9 +890,13 @@ public class FlashDeliveryApplicationService {
         if (userView) {
             view.setOrderVersion(order.getVersion());
             view.setDeliveryPinCode(Boolean.TRUE.equals(order.getPinRequired()) ? order.getDeliveryPinCode() : null);
-            // 接单后直接返回骑手完整用户资料,不做字段加工
+            // 接单后直接返回骑手完整用户资料;star 填充该骑手的闪送平均分供前端展示
             if (order.getRiderId() != null) {
-                view.setRider(userMapper.selectInfoUserByUserId(order.getRiderId()));
+                InfoUser rider = userMapper.selectInfoUserByUserId(order.getRiderId());
+                if (rider != null) {
+                    rider.setStar(riderAverageStars(order.getRiderId()));
+                }
+                view.setRider(rider);
             }
         } else if (!hideSensitiveFields) {
             // 接单后仅中单骑手可见寄件用户完整资料;抢单前脱敏视图不返回用户身份信息。

+ 35 - 0
ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationServiceTest.java

@@ -696,6 +696,41 @@ class FlashDeliveryApplicationServiceTest {
         assertEquals(4.5, view.getRiderStars());
     }
 
+    @Test
+    void userDetailRiderCarriesFlashAverageStars() {
+        Fixture fixture = new Fixture();
+        FlashDeliveryOrder order = order(10L, "ACCEPTED");
+        order.setRiderId(8L);
+        when(fixture.orderMapper.selectById(10L)).thenReturn(order);
+        InfoUser rider = new InfoUser();
+        rider.setUserId(8L);
+        rider.setNickName("闪送骑手");
+        when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
+        when(fixture.orderMapper.selectRiderAverageStars(8L)).thenReturn(4.8);
+        when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
+
+        var view = fixture.service.userDetail(7L, 10L);
+
+        assertEquals(4.8, view.getRider().getStar());
+    }
+
+    @Test
+    void userDetailRiderFallsBackToDefaultStarsWithoutRatings() {
+        Fixture fixture = new Fixture();
+        FlashDeliveryOrder order = order(10L, "ACCEPTED");
+        order.setRiderId(8L);
+        when(fixture.orderMapper.selectById(10L)).thenReturn(order);
+        InfoUser rider = new InfoUser();
+        rider.setUserId(8L);
+        when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
+        when(fixture.orderMapper.selectRiderAverageStars(8L)).thenReturn(null);
+        when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
+
+        var view = fixture.service.userDetail(7L, 10L);
+
+        assertEquals(4.5, view.getRider().getStar());
+    }
+
     @Test
     void orderWithoutCreationTimeReceiverBindingIsNotClaimedLater() {
         Fixture fixture = new Fixture();

+ 3 - 0
ruoyi-system/src/main/java/com/ruoyi/system/mapper/flash/FlashDeliveryOrderMapper.java

@@ -67,6 +67,9 @@ public interface FlashDeliveryOrderMapper extends BaseMapper<FlashDeliveryOrder>
     List<FlashDeliveryOrder> selectScheduledAvailabilityCandidates(@Param("now") Date now,
                                                                    @Param("limit") int limit);
 
+    /** 骑手闪送平均分:仅统计已评价订单;无人评价时返回 null 由服务层回退默认分。 */
+    Double selectRiderAverageStars(@Param("riderId") Long riderId);
+
     /** 原子开放预约单;并发任务、取消或抢单已先完成时返回 0。 */
     int openScheduledForRiders(@Param("id") Long id, @Param("now") Date now);
 }

+ 6 - 0
ruoyi-system/src/main/resources/mapper/flash/FlashDeliveryOrderMapper.xml

@@ -148,6 +148,12 @@
           and rider_id is not null and rider_stars is null
     </update>
 
+    <!-- 骑手闪送平均分只统计闪送订单内的评价,与外卖评分体系互不影响。 -->
+    <select id="selectRiderAverageStars" resultType="java.lang.Double">
+        select round(avg(rider_stars), 1) from flash_delivery_order
+        where rider_id = #{riderId} and rider_stars is not null
+    </select>
+
     <!-- 平台/系统完成同样使用预期状态条件,防止与用户确认并发重复成功。 -->
     <update id="transitionByStatus">
         update flash_delivery_order

+ 17 - 0
ruoyi-system/src/test/java/com/ruoyi/system/mapper/flash/FlashDeliveryMapperXmlTest.java

@@ -133,4 +133,21 @@ class FlashDeliveryMapperXmlTest {
         assertTrue(xml.contains("version = version + 1"));
         assertTrue(xml.contains("receiver_user_id = #{userId}"));
     }
+
+    @Test
+    void riderAverageStarsAggregatesRatedFlashOrdersOnly() throws Exception {
+        String resource = "mapper/flash/FlashDeliveryOrderMapper.xml";
+        Configuration configuration = new Configuration();
+        configuration.getTypeAliasRegistry().registerAlias("FlashDeliveryOrder", FlashDeliveryOrder.class);
+        try (InputStream input = getClass().getClassLoader().getResourceAsStream(resource)) {
+            new XMLMapperBuilder(input, configuration, resource, configuration.getSqlFragments()).parse();
+        }
+        var statement = configuration.getMappedStatement(
+                "com.ruoyi.system.mapper.flash.FlashDeliveryOrderMapper.selectRiderAverageStars");
+        String text = statement.getBoundSql(java.util.Map.of("riderId", 8L)).getSql()
+                .replaceAll("\\s+", " ").toLowerCase();
+        assertTrue(text.contains("avg(rider_stars)"));
+        assertTrue(text.contains("rider_id = ?"));
+        assertTrue(text.contains("rider_stars is not null"));
+    }
 }

+ 1 - 0
specs/028-flash-delivery-push/tasks.md

@@ -140,6 +140,7 @@ description: "Task list for feature 028-flash-delivery-push"
 - [x] T028 [US5] 后端 i18n 6 份资源新增 `flash.delivery.rating.stars.invalid` / `flash.delivery.rating.not.allowed` / `flash.delivery.rating.already`;`updatesql/sql.md` 登记 `flash_delivery_order.rider_stars` 列(不直接执行)
 - [x] T029 [US5] 平台 PC 端 `foodie-admin-vue` `views/flashDelivery/orders/OrderDetail.vue` 骑手信息区显示评分(NULL 显示未评价),4 份语言文件(`src/api/language/language.*.js`)`flashDelivery` 命名空间新增 key
 - [x] T030 [US5] 回归:定向测试全绿 + `mvn -pl ruoyi-admin -am test` 维持基线(仅存量已知失败 `createRejectsUnsupportedPayType`);用户端 App 前端调新接口与五星默认选中由 App 侧另行处理(Bug #659 前端部分)
+- [x] T031 [US5] 用户端详情 `GET /orders/{id}` 的 `rider` 用户资料带闪送平均分:新增 `selectRiderAverageStars`(`AVG(rider_stars)` 仅统计闪送评价,与外卖分互不影响),无评价回退 4.5 默认展示(与外卖骑手 `setQsStar` 惯例一致);TDD 含 service 两个用例与 XML 聚合语句断言
 
 ---