From 15defa991fcd30b9fa60bab17d2230b5929bf2a2 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期一, 14 九月 2026 17:20:20 +0800
Subject: [PATCH] update

---
 backend/src/test/java/com/tourguide/modules/order/service/OrderRefundServiceTest.java |   81 ++++++++++++++++++++++++++++++++++++++--
 1 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/backend/src/test/java/com/tourguide/modules/order/service/OrderRefundServiceTest.java b/backend/src/test/java/com/tourguide/modules/order/service/OrderRefundServiceTest.java
index c5d3ddf..8091f9d 100644
--- a/backend/src/test/java/com/tourguide/modules/order/service/OrderRefundServiceTest.java
+++ b/backend/src/test/java/com/tourguide/modules/order/service/OrderRefundServiceTest.java
@@ -1,17 +1,23 @@
 package com.tourguide.modules.order.service;
 
+import com.tourguide.modules.order.domain.OrderStatus;
 import com.tourguide.modules.order.domain.RefundStatus;
 import com.tourguide.modules.order.domain.PaymentMethod;
 import com.tourguide.modules.order.entity.TourOrder;
+import com.tourguide.modules.order.entity.TourOrderRefund;
 import com.tourguide.modules.order.mapper.TourOrderMapper;
+import com.tourguide.modules.order.mapper.TourOrderRefundMapper;
 import com.tourguide.modules.order.payment.PaymentRefundGateway;
 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.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -37,15 +43,18 @@
                 org.mockito.ArgumentMatchers.eq(new BigDecimal("36.00"))))
                 .thenAnswer(invocation -> order.getRefundOrderNo());
 
-        refundService.requestRefund(order);
-        refundService.requestRefund(order);
+        boolean accepted = refundService.requestRefund(order);
+        boolean duplicateAccepted = refundService.requestRefund(order);
 
+        assertThat(accepted).isTrue();
+        assertThat(duplicateAccepted).isTrue();
         assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.REFUNDING.getCode());
+        assertThat(order.getStatus()).isEqualTo(OrderStatus.CANCELLED.getCode());
         assertThat(order.getRefundOrderNo()).startsWith("RF").hasSize(32);
         assertThat(order.getRefundAmount()).isEqualByComparingTo("36.00");
         assertThat(order.getRefundMethod()).isEqualTo("WECHAT");
         verify(refundGateway, times(1)).refund(order, new BigDecimal("36.00"));
-        verify(orderMapper, times(1)).updateById(order);
+        verify(orderMapper, times(2)).updateById(order);
     }
 
     @Test
@@ -55,8 +64,9 @@
                 org.mockito.ArgumentMatchers.any(BigDecimal.class)))
                 .thenThrow(new IllegalStateException("gateway unavailable"));
 
-        refundService.requestRefund(order);
+        boolean accepted = refundService.requestRefund(order);
 
+        assertThat(accepted).isFalse();
         assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.REFUND_FAILED.getCode());
         verify(orderMapper, times(2)).updateById(order);
     }
@@ -81,11 +91,73 @@
         refundService.requestRefund(order);
 
         assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.REFUNDED.getCode());
+        assertThat(order.getStatus()).isEqualTo(OrderStatus.REFUNDED.getCode());
         assertThat(order.getRefundTime()).isNotNull();
         assertThat(order.getRefundMethod()).isEqualTo(PaymentMethod.TEMPORARY_BYPASS.getCode());
         verify(refundGateway, never()).refund(org.mockito.ArgumentMatchers.any(),
                 org.mockito.ArgumentMatchers.any());
         verify(orderMapper).updateById(order);
+    }
+
+    @Test
+    void adminRefundShouldSubmitRequestedAmount() {
+        TourOrder order = paidOrder();
+        when(refundGateway.refund(eq(order), eq(new BigDecimal("20.00"))))
+                .thenAnswer(invocation -> order.getRefundOrderNo());
+
+        boolean accepted = refundService.requestRefund(order, new BigDecimal("20.00"));
+
+        assertThat(accepted).isTrue();
+        assertThat(order.getRefundAmount()).isEqualByComparingTo("20.00");
+        verify(refundGateway).refund(order, new BigDecimal("20.00"));
+    }
+
+    @Test
+    void followUpRefundShouldOnlyUseRemainingAmount() {
+        TourOrder order = paidOrder();
+        order.setStatus(OrderStatus.CANCELLED.getCode());
+        order.setRefundStatus(RefundStatus.PARTIAL.getCode());
+        order.setRefundedAmount(new BigDecimal("20.00"));
+        when(refundGateway.refund(eq(order), eq(new BigDecimal("16.00"))))
+                .thenAnswer(invocation -> order.getRefundOrderNo());
+
+        boolean accepted = refundService.requestRefund(order, new BigDecimal("16.00"));
+
+        assertThat(accepted).isTrue();
+        assertThat(order.getRefundAmount()).isEqualByComparingTo("16.00");
+        assertThat(order.getRefundStatus()).isEqualTo(RefundStatus.REFUNDING.getCode());
+        verify(refundGateway).refund(order, new BigDecimal("16.00"));
+    }
+
+    @Test
+    void eachSuccessfulLocalRefundShouldCreateAnIndependentCompletedRecord() {
+        TourOrderRefundMapper refundMapper = mock(TourOrderRefundMapper.class);
+        refundService = new OrderRefundService(orderMapper, refundGateway, refundMapper);
+        TourOrder order = paidOrder();
+        order.setPaymentMethod(PaymentMethod.TEMPORARY_BYPASS.getCode());
+
+        assertThat(refundService.requestRefund(order, new BigDecimal("20.00"))).isTrue();
+        assertThat(refundService.requestRefund(order, new BigDecimal("16.00"))).isTrue();
+
+        ArgumentCaptor<TourOrderRefund> insertCaptor = ArgumentCaptor.forClass(TourOrderRefund.class);
+        verify(refundMapper, times(2)).insert(insertCaptor.capture());
+        assertThat(insertCaptor.getAllValues()).extracting(TourOrderRefund::getRefundAmount)
+                .containsExactly(new BigDecimal("20.00"), new BigDecimal("16.00"));
+        verify(refundMapper, times(2)).updateById(any(TourOrderRefund.class));
+        assertThat(insertCaptor.getAllValues()).extracting(TourOrderRefund::getRefundStatus)
+                .containsOnly(RefundStatus.REFUNDED.getCode());
+    }
+
+    @Test
+    void refundShouldRejectAmountAboveRemainingBalance() {
+        TourOrder order = paidOrder();
+        order.setRefundedAmount(new BigDecimal("20.00"));
+
+        boolean accepted = refundService.requestRefund(order, new BigDecimal("17.00"));
+
+        assertThat(accepted).isFalse();
+        verify(refundGateway, never()).refund(org.mockito.ArgumentMatchers.any(),
+                org.mockito.ArgumentMatchers.any());
     }
 
     private TourOrder paidOrder() {
@@ -97,6 +169,7 @@
         order.setAmount(new BigDecimal("40.00"));
         order.setPaymentAmount(new BigDecimal("36.00"));
         order.setPaymentTime(LocalDateTime.now());
+        order.setStatus(OrderStatus.COMPLETED.getCode());
         order.setRefundStatus(RefundStatus.NONE.getCode());
         return order;
     }

--
Gitblit v1.7.1