| | |
| | | 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.entity.TourOrderRefund; |
| | | import com.tourguide.modules.order.mapper.TourOrderMapper; |
| | | import com.tourguide.modules.order.mapper.TourOrderRefundMapper; |
| | | import com.tourguide.modules.order.payment.PaymentRefundGateway; |
| | | import com.tourguide.modules.finance.service.GuideBalanceSettlementService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | |
| | | private final TourOrderMapper orderMapper; |
| | | private final PaymentRefundGateway paymentRefundGateway; |
| | | private final TourOrderRefundMapper refundMapper; |
| | | private final GuideBalanceSettlementService balanceSettlementService; |
| | | |
| | | public OrderRefundService(TourOrderMapper orderMapper, PaymentRefundGateway paymentRefundGateway) { |
| | | this(orderMapper, paymentRefundGateway, null, null); |
| | | } |
| | | |
| | | public OrderRefundService(TourOrderMapper orderMapper, PaymentRefundGateway paymentRefundGateway, |
| | | TourOrderRefundMapper refundMapper) { |
| | | this(orderMapper, paymentRefundGateway, refundMapper, null); |
| | | } |
| | | |
| | | @Autowired |
| | | public OrderRefundService(TourOrderMapper orderMapper, PaymentRefundGateway paymentRefundGateway, |
| | | TourOrderRefundMapper refundMapper, |
| | | GuideBalanceSettlementService balanceSettlementService) { |
| | | this.orderMapper = orderMapper; |
| | | this.paymentRefundGateway = paymentRefundGateway; |
| | | this.refundMapper = refundMapper; |
| | | this.balanceSettlementService = balanceSettlementService; |
| | | } |
| | | |
| | | public boolean requestRefund(TourOrder order) { |
| | |
| | | order.setRefundStatus(RefundStatus.REFUNDING.getCode()); |
| | | order.setRefundAmount(refundAmount); |
| | | order.setRefundMethod(order.getPaymentMethod()); |
| | | TourOrderRefund refundRecord = createRefundRecord(order, refundAmount); |
| | | if (PaymentMethod.TEMPORARY_BYPASS.matches(order.getPaymentMethod())) { |
| | | if (order.getCancelledAt() == null) order.setCancelledAt(LocalDateTime.now()); |
| | | completeLocalRefund(order, refundAmount); |
| | | order.setRefundTime(LocalDateTime.now()); |
| | | LocalDateTime refundTime = LocalDateTime.now(); |
| | | order.setRefundTime(refundTime); |
| | | // 明细状态描述当前这一笔退款;订单状态则描述累计退款进度。 |
| | | updateRefundRecord(refundRecord, RefundStatus.REFUNDED.getCode(), refundTime); |
| | | orderMapper.updateById(order); |
| | | return true; |
| | | } |
| | |
| | | return true; |
| | | } catch (RuntimeException exception) { |
| | | order.setRefundStatus(RefundStatus.REFUND_FAILED.getCode()); |
| | | updateRefundRecord(refundRecord, RefundStatus.REFUND_FAILED.getCode(), null); |
| | | orderMapper.updateById(order); |
| | | log.error("Order refund request failed, orderId={}, orderNo={}, refundOrderNo={}", |
| | | order.getId(), order.getOrderNo(), order.getRefundOrderNo(), exception); |
| | |
| | | } |
| | | |
| | | private void completeLocalRefund(TourOrder order, BigDecimal refundAmount) { |
| | | BigDecimal refundedAmount = RefundAmountCalculator.refundedAmount(order).add(refundAmount); |
| | | BigDecimal previousRefundedAmount = RefundAmountCalculator.refundedAmount(order); |
| | | BigDecimal refundedAmount = previousRefundedAmount.add(refundAmount); |
| | | order.setRefundedAmount(refundedAmount); |
| | | if (refundedAmount.compareTo(RefundAmountCalculator.paidAmount(order)) >= 0) { |
| | | order.setRefundStatus(RefundStatus.REFUNDED.getCode()); |
| | |
| | | order.setRefundStatus(RefundStatus.PARTIAL.getCode()); |
| | | order.setStatus(OrderStatus.CANCELLED.getCode()); |
| | | } |
| | | reverseSettledEarning(order, previousRefundedAmount, refundedAmount); |
| | | } |
| | | |
| | | private void reverseSettledEarning(TourOrder order, BigDecimal previousRefundedAmount, |
| | | BigDecimal currentRefundedAmount) { |
| | | if (balanceSettlementService != null) { |
| | | balanceSettlementService.reverseRefund(order, previousRefundedAmount, currentRefundedAmount); |
| | | } |
| | | } |
| | | |
| | | private TourOrderRefund createRefundRecord(TourOrder order, BigDecimal refundAmount) { |
| | | if (refundMapper == null || order.getId() == null) return null; |
| | | TourOrderRefund refund = new TourOrderRefund(); |
| | | refund.setOrderId(order.getId()); |
| | | refund.setRefundOrderNo(order.getRefundOrderNo()); |
| | | refund.setRefundAmount(refundAmount); |
| | | refund.setRefundStatus(RefundStatus.REFUNDING.getCode()); |
| | | refund.setRefundMethod(order.getRefundMethod()); |
| | | refundMapper.insert(refund); |
| | | return refund; |
| | | } |
| | | |
| | | private void updateRefundRecord(TourOrderRefund refund, String status, LocalDateTime refundTime) { |
| | | if (refundMapper == null || refund == null) return; |
| | | refund.setRefundStatus(status); |
| | | refund.setRefundTime(refundTime); |
| | | refundMapper.updateById(refund); |
| | | } |
| | | } |