From 39f6fca28e3f78abe48f08e474ec011abb990b36 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期三, 09 九月 2026 10:39:21 +0800
Subject: [PATCH] update

---
 backend/src/test/java/com/tourguide/modules/order/service/TourOrderServiceTest.java |  125 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 120 insertions(+), 5 deletions(-)

diff --git a/backend/src/test/java/com/tourguide/modules/order/service/TourOrderServiceTest.java b/backend/src/test/java/com/tourguide/modules/order/service/TourOrderServiceTest.java
index d34cb6b..cc021c9 100644
--- a/backend/src/test/java/com/tourguide/modules/order/service/TourOrderServiceTest.java
+++ b/backend/src/test/java/com/tourguide/modules/order/service/TourOrderServiceTest.java
@@ -1,45 +1,60 @@
 package com.tourguide.modules.order.service;
 
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.tourguide.common.exception.BusinessException;
 import com.tourguide.modules.order.domain.OrderStatus;
 import com.tourguide.modules.order.domain.RefundStatus;
+import com.tourguide.modules.order.dto.TourOrderResponse;
 import com.tourguide.modules.order.entity.TourOrder;
 import com.tourguide.modules.order.mapper.TourOrderMapper;
 import com.tourguide.modules.review.mapper.OrderReviewMapper;
+import com.tourguide.modules.review.entity.OrderReview;
 import com.tourguide.modules.system.service.GuideNotificationService;
+import org.apache.ibatis.builder.MapperBuilderAssistant;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
 
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.mockito.ArgumentMatchers.any;
 
 class TourOrderServiceTest {
     private TourOrderMapper orderMapper;
     private TourOrderService orderService;
+    private OrderRefundService refundService;
+    private GuideNotificationService notificationService;
+    private static boolean tableInfoInitialized;
+    private static boolean reviewTableInfoInitialized;
 
     @BeforeEach
     void setUp() {
         orderMapper = mock(TourOrderMapper.class);
+        refundService = mock(OrderRefundService.class);
+        notificationService = mock(GuideNotificationService.class);
         orderService = new TourOrderService(orderMapper, mock(OrderReviewMapper.class),
-                mock(GuideNotificationService.class));
+                notificationService, refundService);
     }
 
     @Test
     void shouldRefundRequestedAmount() {
         TourOrder order = refundableOrder();
         when(orderMapper.selectForUpdate(1L)).thenReturn(order);
+        when(refundService.requestRefund(order, new BigDecimal("100.00"))).thenReturn(true);
 
         orderService.refund(1L, new BigDecimal("100.00"));
 
-        assertThat(order.getRefundAmount()).isEqualByComparingTo("100.00");
-        assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.REFUNDED.getCode());
-        assertThat(order.getStatus()).isEqualTo(OrderStatus.REFUNDED.getCode());
-        verify(orderMapper).updateById(order);
+        verify(refundService).requestRefund(order, new BigDecimal("100.00"));
     }
 
     @Test
@@ -52,6 +67,105 @@
                 .hasMessage("退款金额不能超过当前可退金额");
     }
 
+    @Test
+    void shouldAllowFollowUpRefundForPartialOrder() {
+        TourOrder order = refundableOrder();
+        order.setStatus(OrderStatus.CANCELLED.getCode());
+        order.setRefundStatus(RefundStatus.PARTIAL.getCode());
+        order.setRefundedAmount(new BigDecimal("100.00"));
+        when(orderMapper.selectForUpdate(1L)).thenReturn(order);
+        when(refundService.requestRefund(order, new BigDecimal("56.00"))).thenReturn(true);
+
+        TourOrderResponse response = orderService.refund(1L, new BigDecimal("56.00"));
+
+        assertThat(response.getRefundableAmount()).isEqualByComparingTo("56.00");
+        verify(refundService).requestRefund(order, new BigDecimal("56.00"));
+    }
+
+    @Test
+    void shouldRejectFollowUpRefundAboveRemainingAmount() {
+        TourOrder order = refundableOrder();
+        order.setStatus(OrderStatus.CANCELLED.getCode());
+        order.setRefundStatus(RefundStatus.PARTIAL.getCode());
+        order.setRefundedAmount(new BigDecimal("100.00"));
+        when(orderMapper.selectForUpdate(1L)).thenReturn(order);
+
+        assertThatThrownBy(() -> orderService.refund(1L, new BigDecimal("56.01")))
+                .isInstanceOf(BusinessException.class)
+                .hasMessage("退款金额不能超过当前可退金额");
+    }
+
+    @Test
+    void shouldReportProviderFailureInsteadOfSuccess() {
+        TourOrder order = refundableOrder();
+        when(orderMapper.selectForUpdate(1L)).thenReturn(order);
+        when(refundService.requestRefund(order, new BigDecimal("100.00"))).thenReturn(false);
+
+        assertThatThrownBy(() -> orderService.refund(1L, new BigDecimal("100.00")))
+                .isInstanceOf(BusinessException.class)
+                .hasMessage("支付渠道退款失败,请稍后重试");
+    }
+
+    @Test
+    void notificationFailureShouldNotFailAcceptedRefund() {
+        TourOrder order = refundableOrder();
+        order.setStatus(OrderStatus.PENDING_MEETING.getCode());
+        order.setGuideId(42L);
+        when(orderMapper.selectForUpdate(1L)).thenReturn(order);
+        when(refundService.requestRefund(order, new BigDecimal("100.00"))).thenReturn(true);
+        doThrow(new IllegalStateException("notification unavailable"))
+                .when(notificationService).notifyOrderCancelled(order);
+
+        TourOrderResponse response = orderService.refund(1L, new BigDecimal("100.00"));
+
+        assertThat(response).isNotNull();
+        verify(notificationService).notifyOrderCancelled(order);
+    }
+
+    @Test
+    void shouldFilterOrdersByGuideId() {
+        initializeTableInfo();
+        when(orderMapper.selectPage(any(Page.class), any())).thenAnswer(invocation -> invocation.getArgument(0));
+
+        orderService.page(1, 10, null, null, 42L, null, null, null, null);
+
+        ArgumentCaptor<LambdaQueryWrapper<TourOrder>> queryCaptor = ArgumentCaptor.forClass(LambdaQueryWrapper.class);
+        verify(orderMapper).selectPage(any(Page.class), queryCaptor.capture());
+        queryCaptor.getValue().getSqlSegment();
+        assertThat(queryCaptor.getValue().getParamNameValuePairs().values()).contains(42L);
+    }
+
+    @Test
+    void detailShouldOnlyTreatVisibleReviewAsReviewed() {
+        initializeTableInfo();
+        initializeReviewTableInfo();
+        OrderReviewMapper reviewMapper = mock(OrderReviewMapper.class);
+        orderService = new TourOrderService(orderMapper, reviewMapper, notificationService, refundService);
+        TourOrder order = new TourOrder();
+        order.setId(1L);
+        when(orderMapper.selectById(1L)).thenReturn(order);
+
+        orderService.detail(1L);
+
+        ArgumentCaptor<LambdaQueryWrapper<OrderReview>> queryCaptor = ArgumentCaptor.forClass(LambdaQueryWrapper.class);
+        verify(reviewMapper).selectOne(queryCaptor.capture());
+        assertThat(queryCaptor.getValue().getSqlSegment()).contains("status");
+    }
+
+    private static void initializeTableInfo() {
+        if (!tableInfoInitialized) {
+            TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), TourOrder.class);
+            tableInfoInitialized = true;
+        }
+    }
+
+    private static void initializeReviewTableInfo() {
+        if (!reviewTableInfoInitialized) {
+            TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), OrderReview.class);
+            reviewTableInfoInitialized = true;
+        }
+    }
+
     private TourOrder refundableOrder() {
         TourOrder order = new TourOrder();
         order.setId(1L);
@@ -60,6 +174,7 @@
         order.setRefundStatus(RefundStatus.NONE.getCode());
         order.setAmount(new BigDecimal("256.10"));
         order.setPaymentAmount(new BigDecimal("156.00"));
+        order.setPaymentTime(LocalDateTime.now());
         order.setPaymentMethod("WECHAT");
         return order;
     }

--
Gitblit v1.7.1