package com.tourguide.modules.finance.service; import com.tourguide.common.exception.BusinessException; import com.tourguide.modules.user.mapper.GuideUserMapper; import com.tourguide.modules.user.mapper.GuideTeamMapper; import com.tourguide.modules.user.entity.GuideTeam; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; /** 统一读取和原子变更导游可提现余额。 */ @Service public class GuideWithdrawableBalanceService { private final GuideUserMapper guideUserMapper; private final GuideTeamMapper guideTeamMapper; public GuideWithdrawableBalanceService(GuideUserMapper guideUserMapper, GuideTeamMapper guideTeamMapper) { this.guideUserMapper = guideUserMapper; this.guideTeamMapper = guideTeamMapper; } public BigDecimal getAvailableAmount(Long guideId) { return money(guideUserMapper.selectBalance(guideId)); } public boolean debit(Long guideId, BigDecimal amount) { BigDecimal value = money(amount); return value.signum() > 0 && guideUserMapper.decreaseBalance(guideId, value) == 1; } /** 退款冲正只扣除当前余额,余额不足时保留为零,避免退款回调因余额竞争失败。 */ public boolean debitForRefund(Long guideId, BigDecimal amount) { BigDecimal value = money(amount); return value.signum() > 0 && guideUserMapper.decreaseBalanceForRefund(guideId, value) == 1; } public void credit(Long guideId, BigDecimal amount) { BigDecimal value = money(amount); if (value.signum() == 0) return; if (value.signum() < 0 || guideUserMapper.increaseBalance(guideId, value) != 1) { throw new BusinessException(500, "导游余额更新失败"); } } public BigDecimal getAvailableTeamAmount(Long teamId) { if (teamId == null) return BigDecimal.ZERO.setScale(2); GuideTeam team = guideTeamMapper.selectById(teamId); return money(team == null ? null : team.getBalance()); } public boolean debitTeam(Long teamId, BigDecimal amount) { BigDecimal value = money(amount); return teamId != null && value.signum() > 0 && guideTeamMapper.decreaseBalance(teamId, value) == 1; } public boolean debitTeamForRefund(Long teamId, BigDecimal amount) { BigDecimal value = money(amount); return teamId != null && value.signum() > 0 && guideTeamMapper.decreaseBalanceForRefund(teamId, value) == 1; } public void creditTeam(Long teamId, BigDecimal amount) { BigDecimal value = money(amount); if (value.signum() == 0) return; if (teamId == null || value.signum() < 0 || guideTeamMapper.increaseBalance(teamId, value) != 1) { throw new BusinessException(500, "讲解队余额更新失败"); } } private BigDecimal money(BigDecimal value) { return (value == null ? BigDecimal.ZERO : value).setScale(2, RoundingMode.HALF_UP); } }