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/main/java/com/tourguide/modules/finance/service/GuideBalanceSettlementService.java | 64 ++++++++++++++++++++++++++++++-
1 files changed, 61 insertions(+), 3 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 215d7bd..72b9a9c 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,15 +30,46 @@
TourOrder order = orderMapper.selectForUpdate(orderId);
if (!canSettle(order, settledAt)) return false;
- BigDecimal earning = order.getGuideEarningAmount();
+ BigDecimal earning = effectiveEarning(order);
if (earning.signum() > 0) {
- balanceService.credit(order.getGuideId(), earning);
+ if (order.getCommissionTeamId() != null) {
+ balanceService.creditTeam(order.getCommissionTeamId(), earning);
+ } else {
+ balanceService.credit(order.getGuideId(), earning);
+ }
}
order.setSettledAt(settledAt);
if (orderMapper.updateById(order) != 1) {
throw new BusinessException(500, "订单分账状态更新失败");
}
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;
+ boolean debited;
+ if (order.getCommissionTeamId() != null) {
+ debited = balanceService.debitTeamForRefund(order.getCommissionTeamId(), reversal);
+ } else if (order.getGuideId() != null) {
+ debited = balanceService.debitForRefund(order.getGuideId(), reversal);
+ } else {
+ return;
+ }
+ if (!debited) {
+ throw new BusinessException(500, "退款后导游收益冲正失败");
+ }
}
private boolean canSettle(TourOrder order, LocalDateTime now) {
@@ -48,6 +81,31 @@
&& order.getGuideId() != null
&& order.getGuideEarningAmount() != null
&& order.getGuideEarningAmount().signum() >= 0
- && !RefundStatus.REFUNDED.matches(order.getRefundStatus());
+ && canSettleRefund(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);
+ }
+
+ private boolean canSettleRefund(String refundStatus) {
+ return refundStatus == null
+ || refundStatus.trim().isEmpty()
+ || RefundStatus.NONE.matches(refundStatus)
+ || RefundStatus.PARTIAL.matches(refundStatus)
+ || RefundStatus.REFUND_FAILED.matches(refundStatus);
}
}
--
Gitblit v1.7.1