package ru.soune.nocopy.service.payout; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.soune.nocopy.entity.referral.Referral; import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.exception.InsufficientFundsException; import ru.soune.nocopy.repository.ReferralJpaRepository; import java.math.BigDecimal; @Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class BalanceService { private final ReferralJpaRepository referralJpaRepository; public boolean hasSufficientFunds(User user, BigDecimal amount) { Referral referral = referralJpaRepository.findByUserId(user.getId()); BigDecimal available = BigDecimal.valueOf(referral.getAvailableIncome()); return available.compareTo(amount) >= 0; } public BigDecimal getBalance(User user) { Referral referral = referralJpaRepository.findByUserId(user.getId()); return BigDecimal.valueOf(referral.getAvailableIncome()); } public BigDecimal getFrozenBalance(User user) { Referral referral = referralJpaRepository.findByUserId(user.getId()); return BigDecimal.valueOf(referral.getHoldBalance()); } @Transactional public void freezeAmount(User user, BigDecimal amount) { Referral referral = referralJpaRepository.findByUserId(user.getId()); BigDecimal available = BigDecimal.valueOf(referral.getAvailableIncome()); if (available.compareTo(amount) < 0) { throw new InsufficientFundsException( String.format("Not have amount. Amount have: %.2f", available) ); } BigDecimal newAvailable = available.subtract(amount); BigDecimal newHold = BigDecimal.valueOf(referral.getHoldBalance()).add(amount); referral.setAvailableIncome(newAvailable.intValue()); referral.setHoldBalance(newHold.intValue()); referralJpaRepository.save(referral); log.info("Amount freeze. Have: {}, Frozen: {}", newAvailable, newHold); } @Transactional public void unfreezeAmount(Long userId, BigDecimal amount) { log.info("Unfreeze {} for user {}", amount, userId); Referral referral = referralJpaRepository.findByUserId(userId); BigDecimal hold = BigDecimal.valueOf(referral.getHoldBalance()); if (hold.compareTo(amount) < 0) { throw new IllegalStateException( String.format("Not have freeze amount. Frozen: %.2f", hold) ); } BigDecimal newAvailable = BigDecimal.valueOf(referral.getAvailableIncome()).add(amount); BigDecimal newHold = hold.subtract(amount); referral.setAvailableIncome(newAvailable.intValue()); referral.setHoldBalance(newHold.intValue()); referralJpaRepository.save(referral); log.info("Amount frozen. Have: {}, Frozen: {}", newAvailable, newHold); } public void withdrawAmount(Long userId, BigDecimal amount) { Referral referral = referralJpaRepository.findByUserId(userId); if (referral.getHoldBalance() < amount.intValue()) { throw new IllegalStateException("Not have amount"); } referral.setHoldBalance(referral.getHoldBalance() - amount.intValue()); } }