Sfoglia il codice sorgente

feat: 闪送用户端与骑手端支持按订单编号查询订单详情

qmj 20 ore fa
parent
commit
abe1706131

+ 7 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryRiderController.java

@@ -48,6 +48,13 @@ public class FlashDeliveryRiderController extends BaseController {
         return success(service.riderDetail(userId(token), id));
     }
 
+    /** 按订单编号查询订单详情;脱敏与归属校验和数字 ID 查询一致。 */
+    @GetMapping("/orders/byOrderNo")
+    @Auth
+    public AjaxResult detailByOrderNo(@RequestHeader String token, @RequestParam String orderNo) {
+        return success(service.riderDetailByOrderNo(userId(token), orderNo));
+    }
+
     /** 原子抢单;同一订单只能由一个骑手成功接取。 */
     @PostMapping("/orders/{id}/accept")
     @Auth

+ 7 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryUserController.java

@@ -68,6 +68,13 @@ public class FlashDeliveryUserController extends BaseController {
         return success(service.userDetail(userId(token), id));
     }
 
+    /** 按订单编号查询本人订单详情;App 点击推送消息打开订单详情时使用。 */
+    @GetMapping("/orders/byOrderNo")
+    @Auth
+    public AjaxResult detailByOrderNo(@RequestHeader String token, @RequestParam String orderNo) {
+        return success(service.userDetailByOrderNo(userId(token), orderNo));
+    }
+
     /** 修改取送信息的预报价,不写订单;沿用该订单计价快照。 */
     @PostMapping("/orders/{id}/address/quote")
     @Auth

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

@@ -247,7 +247,15 @@ public class FlashDeliveryApplicationService {
 
     /** 查询本人订单详情,仅寄件人和匹配到的收件人可见。 */
     public FlashDeliveryOrderDetailView userDetail(Long userId, Long orderId) {
-        FlashDeliveryOrder order = requireOrder(orderId);
+        return userDetail(userId, requireOrder(orderId));
+    }
+
+    /** 按订单编号查询本人订单详情;App 点击推送消息打开订单详情时使用。 */
+    public FlashDeliveryOrderDetailView userDetailByOrderNo(Long userId, String orderNo) {
+        return userDetail(userId, requireOrderByNo(orderNo));
+    }
+
+    private FlashDeliveryOrderDetailView userDetail(Long userId, FlashDeliveryOrder order) {
         if (!isParticipant(userId, order)) throw fail("flash.delivery.order.not.found");
         return participantDetail(order, true, false);
     }
@@ -475,8 +483,16 @@ public class FlashDeliveryApplicationService {
 
     /** 骑手任务详情:抢单前返回脱敏视图(隐藏联系人、电话、坐标和 PIN);接单后仅中单骑手可见完整信息。 */
     public FlashDeliveryOrderDetailView riderDetail(Long riderId, Long orderId) {
+        return riderDetail(riderId, requireOrder(orderId));
+    }
+
+    /** 按订单编号查询骑手视角订单详情;脱敏与归属校验和数字 ID 查询一致。 */
+    public FlashDeliveryOrderDetailView riderDetailByOrderNo(Long riderId, String orderNo) {
+        return riderDetail(riderId, requireOrderByNo(orderNo));
+    }
+
+    private FlashDeliveryOrderDetailView riderDetail(Long riderId, FlashDeliveryOrder order) {
         InfoUser rider = requireRider(riderId);
-        FlashDeliveryOrder order = requireOrder(orderId);
         if (WAITING_ACCEPTANCE.equals(order.getStatus()) && order.getRiderId() == null) {
             // 未开通闪送或车型不匹配时按订单不存在处理,避免泄露待抢任务信息。
             if (!Boolean.TRUE.equals(order.getIsDisplay()) || !isAvailableAt(order, new Date())
@@ -1166,6 +1182,15 @@ public class FlashDeliveryApplicationService {
         return order;
     }
 
+    /** 按订单编号加载订单;编号为空或不存在时按订单不存在处理。 */
+    private FlashDeliveryOrder requireOrderByNo(String orderNo) {
+        if (orderNo == null || orderNo.isBlank()) throw fail("flash.delivery.order.not.found");
+        FlashDeliveryOrder order = orderMapper.selectOne(new QueryWrapper<FlashDeliveryOrder>()
+                .eq("order_no", orderNo.trim()).last("limit 1"));
+        if (order == null) throw fail("flash.delivery.order.not.found");
+        return order;
+    }
+
     /** 写入状态变更审计日志。 */
     private void writeLog(Long orderId, String from, String to, String operatorType,
                           Long operatorId, String reason, Date now) {

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/OrderPushBodyDto.java

@@ -13,7 +13,7 @@ public class OrderPushBodyDto {
     private String state;
     //0:语音提醒新订单
     private int type=-1;
-    //1 外卖订单 2 充值订单
+    //1 外卖订单 2 充值订单  3 闪送订单
     private int pushType=1;
 
     private String title;

+ 16 - 0
ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryControllerContractTest.java

@@ -179,6 +179,22 @@ class FlashDeliveryControllerContractTest {
         verify(service).rateRider(7L, 10L, request);
     }
 
+    @Test
+    void detailByOrderNoEndpointsDelegateToService() {
+        FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);
+        FlashDeliveryOrderDetailView detail = new FlashDeliveryOrderDetailView();
+        when(service.userDetailByOrderNo(7L, "FL-1")).thenReturn(detail);
+        when(service.riderDetailByOrderNo(8L, "FL-1")).thenReturn(detail);
+
+        AjaxResult userResult = new FlashDeliveryUserController(service)
+                .detailByOrderNo(JwtUtil.token("7", "user"), "FL-1");
+        AjaxResult riderResult = new FlashDeliveryRiderController(service)
+                .detailByOrderNo(JwtUtil.token("8", "rider"), "FL-1");
+
+        assertSame(detail, userResult.get(AjaxResult.DATA_TAG));
+        assertSame(detail, riderResult.get(AjaxResult.DATA_TAG));
+    }
+
     @Test
     void addressConfirmationReturnsLatestQuoteForAnotherUserConfirmation() {
         FlashDeliveryApplicationService service = mock(FlashDeliveryApplicationService.class);

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

@@ -51,6 +51,7 @@ import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.ACCEPTED;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -731,6 +732,64 @@ class FlashDeliveryApplicationServiceTest {
         assertEquals(4.5, view.getRider().getStar());
     }
 
+    @Test
+    void userDetailByOrderNoReturnsParticipantDetail() {
+        Fixture fixture = new Fixture();
+        FlashDeliveryOrder order = order(10L, "COMPLETED");
+        order.setRiderId(8L);
+        order.setRiderStars(4.5);
+        when(fixture.orderMapper.selectOne(any(Wrapper.class))).thenReturn(order);
+        InfoUser rider = new InfoUser();
+        rider.setUserId(8L);
+        when(fixture.userMapper.selectInfoUserByUserId(8L)).thenReturn(rider);
+        when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
+
+        var view = fixture.service.userDetailByOrderNo(7L, "FL-20260813-021");
+
+        assertEquals(10L, view.getId());
+        assertEquals(4.5, view.getRiderStars());
+    }
+
+    @Test
+    void userDetailByOrderNoRejectsNonParticipantAndUnknownOrderNo() {
+        Fixture fixture = new Fixture();
+        FlashDeliveryOrder order = order(10L, "COMPLETED");
+        order.setReceiverUserId(null);
+        when(fixture.orderMapper.selectOne(any(Wrapper.class))).thenReturn(order);
+        assertThrows(ServiceException.class,
+                () -> fixture.service.userDetailByOrderNo(88L, "FL-20260813-021"));
+
+        when(fixture.orderMapper.selectOne(any(Wrapper.class))).thenReturn(null);
+        assertThrows(ServiceException.class,
+                () -> fixture.service.userDetailByOrderNo(7L, "FL-UNKNOWN"));
+    }
+
+    @Test
+    void riderDetailByOrderNoReturnsAssignedOrderDetail() {
+        Fixture fixture = new Fixture();
+        rider(fixture, 8L);
+        FlashDeliveryOrder order = order(10L, "ACCEPTED");
+        order.setRiderId(8L);
+        when(fixture.orderMapper.selectOne(any(Wrapper.class))).thenReturn(order);
+        when(fixture.userMapper.selectInfoUserByUserId(7L)).thenReturn(new InfoUser());
+        when(fixture.imageMapper.selectList(any(Wrapper.class))).thenReturn(List.of());
+
+        var view = fixture.service.riderDetailByOrderNo(8L, "FL-20260813-021");
+
+        assertEquals(10L, view.getId());
+        assertNotNull(view.getUser());
+    }
+
+    @Test
+    void riderDetailByOrderNoRejectsUnknownOrderNo() {
+        Fixture fixture = new Fixture();
+        rider(fixture, 8L);
+        when(fixture.orderMapper.selectOne(any(Wrapper.class))).thenReturn(null);
+
+        assertThrows(ServiceException.class,
+                () -> fixture.service.riderDetailByOrderNo(8L, "FL-UNKNOWN"));
+    }
+
     @Test
     void orderWithoutCreationTimeReceiverBindingIsNotClaimedLater() {
         Fixture fixture = new Fixture();