From 4f6f15b818704079ff2e4e4719b798f48d68a335 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期五, 11 九月 2026 13:52:19 +0800
Subject: [PATCH] update

---
 backend/src/main/java/com/tourguide/modules/finance/service/GuideBalanceSettlementService.java |   42 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 41 insertions(+), 1 deletions(-)

diff --git a/backend/src/main/java/com/tourguide/modules/finance/service/GuideBalanceSettlementService.java b/backend/src/main/java/com/tourguide/modules/finance/service/GuideBalanceSettlementService.java
index f8a0a66..6c92169 100644
--- a/backend/src/main/java/com/tourguide/modules/finance/service/GuideBalanceSettlementService.java
+++ b/backend/src/main/java/com/tourguide/modules/finance/service/GuideBalanceSettlementService.java
@@ -2,6 +2,7 @@
 
 import com.tourguide.common.exception.BusinessException;
 import com.tourguide.modules.order.domain.OrderStatus;
+import com.tourguide.modules.order.domain.RefundAmountCalculator;
 import com.tourguide.modules.order.domain.RefundStatus;
 import com.tourguide.modules.order.entity.TourOrder;
 import com.tourguide.modules.order.mapper.TourOrderMapper;
@@ -9,6 +10,7 @@
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDateTime;
 
 /** 将到期且未分账的订单收益幂等计入导游余额。 */
@@ -28,7 +30,7 @@
         TourOrder order = orderMapper.selectForUpdate(orderId);
         if (!canSettle(order, settledAt)) return false;
 
-        BigDecimal earning = order.getGuideEarningAmount();
+        BigDecimal earning = effectiveEarning(order);
         if (earning.signum() > 0) {
             if (order.getCommissionTeamId() != null) {
                 balanceService.creditTeam(order.getCommissionTeamId(), earning);
@@ -43,6 +45,27 @@
         return true;
     }
 
+    /** 退款成功后冲正已入账收益;按累计退款差额计算,保证部分退款幂等。 */
+    @Transactional
+    public void reverseRefund(TourOrder order, BigDecimal previousRefundedAmount,
+                              BigDecimal currentRefundedAmount) {
+        if (order == null || order.getSettledAt() == null
+                || order.getGuideEarningAmount() == null) return;
+        BigDecimal paidAmount = RefundAmountCalculator.paidAmount(order);
+        if (paidAmount.signum() <= 0) return;
+        BigDecimal previous = nonNegative(previousRefundedAmount);
+        BigDecimal current = nonNegative(currentRefundedAmount).min(paidAmount);
+        BigDecimal previousReversal = proratedEarning(order.getGuideEarningAmount(), previous, paidAmount);
+        BigDecimal currentReversal = proratedEarning(order.getGuideEarningAmount(), current, paidAmount);
+        BigDecimal reversal = currentReversal.subtract(previousReversal).setScale(2, RoundingMode.HALF_UP);
+        if (reversal.signum() <= 0) return;
+        if (order.getCommissionTeamId() != null) {
+            balanceService.debitTeamForRefund(order.getCommissionTeamId(), reversal);
+        } else if (order.getGuideId() != null) {
+            balanceService.debitForRefund(order.getGuideId(), reversal);
+        }
+    }
+
     private boolean canSettle(TourOrder order, LocalDateTime now) {
         return order != null
                 && OrderStatus.COMPLETED.matches(order.getStatus())
@@ -54,4 +77,21 @@
                 && order.getGuideEarningAmount().signum() >= 0
                 && !RefundStatus.REFUNDED.matches(order.getRefundStatus());
     }
+
+    private BigDecimal effectiveEarning(TourOrder order) {
+        BigDecimal earning = order.getGuideEarningAmount();
+        BigDecimal paidAmount = RefundAmountCalculator.paidAmount(order);
+        if (paidAmount.signum() <= 0) return earning;
+        BigDecimal refunded = RefundAmountCalculator.refundedAmount(order).min(paidAmount);
+        return earning.multiply(paidAmount.subtract(refunded))
+                .divide(paidAmount, 2, RoundingMode.HALF_UP);
+    }
+
+    private BigDecimal proratedEarning(BigDecimal earning, BigDecimal refunded, BigDecimal paidAmount) {
+        return earning.multiply(refunded).divide(paidAmount, 2, RoundingMode.HALF_UP);
+    }
+
+    private BigDecimal nonNegative(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO : value.max(BigDecimal.ZERO);
+    }
 }

--
Gitblit v1.7.1