package com.tourguide.modules.order.service; import com.tourguide.common.exception.BusinessException; import com.tourguide.modules.operation.service.PlatformSettingsService; import com.tourguide.modules.order.entity.TourOrder; import com.tourguide.modules.user.entity.GuideTeam; import com.tourguide.modules.user.entity.GuideUser; import com.tourguide.modules.user.mapper.GuideTeamMapper; import com.tourguide.modules.user.service.GuideUserService; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; /** 接单时固化订单抽成规则和导游实际业绩。 */ @Service public class GuideOrderEarningSnapshotService { private static final BigDecimal ONE_HUNDRED = new BigDecimal("100"); private final GuideUserService guideUserService; private final GuideTeamMapper guideTeamMapper; private final PlatformSettingsService platformSettingsService; public GuideOrderEarningSnapshotService(GuideUserService guideUserService, GuideTeamMapper guideTeamMapper, PlatformSettingsService platformSettingsService) { this.guideUserService = guideUserService; this.guideTeamMapper = guideTeamMapper; this.platformSettingsService = platformSettingsService; } public void apply(TourOrder order, Long guideId) { apply(order, guideUserService.findEnabledById(guideId)); } public void apply(TourOrder order, GuideUser guide) { BigDecimal commissionRate; if (guide.getTeamId() == null) { order.setCommissionSource("PERSONAL"); order.setCommissionTeamId(null); commissionRate = platformSettingsService.getSettings().getCommissionRate(); } else { GuideTeam team = guideTeamMapper.selectById(guide.getTeamId()); if (team == null || team.getStatus() == null || team.getStatus() != 1) { throw new BusinessException(409, "导游所属讲解队不存在或已停用"); } order.setCommissionSource("TEAM"); order.setCommissionTeamId(team.getId()); commissionRate = team.getCommissionRatio(); } validateCommissionRate(commissionRate); order.setCommissionRate(commissionRate.setScale(2, RoundingMode.HALF_UP)); order.setGuideEarningAmount(calculateEarning(paymentAmount(order), commissionRate)); } BigDecimal calculateEarning(BigDecimal orderAmount, BigDecimal commissionRate) { BigDecimal guideRate = ONE_HUNDRED.subtract(commissionRate).movePointLeft(2); return orderAmount.multiply(guideRate).setScale(2, RoundingMode.HALF_UP); } private BigDecimal paymentAmount(TourOrder order) { BigDecimal amount = order.getPaymentAmount() == null ? order.getAmount() : order.getPaymentAmount(); if (amount == null || amount.signum() < 0) { throw new BusinessException(400, "订单实付金额不正确"); } return amount; } private void validateCommissionRate(BigDecimal commissionRate) { if (commissionRate == null || commissionRate.signum() < 0 || commissionRate.compareTo(ONE_HUNDRED) > 0) { throw new BusinessException(500, "导游抽成比例配置不正确"); } } }