package ltd.lulz.service import io.github.oshai.kotlinlogging.KotlinLogging import java.math.BigDecimal import java.math.BigDecimal.ZERO import java.util.UUID import ltd.lulz.exception.InsufficientFundsException import ltd.lulz.model.AccountEntity import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional private val log = KotlinLogging.logger {} @Service class TransactionService( private val accountService: AccountService, ) { @Transactional suspend fun deposit( id: UUID, amount: BigDecimal, ): AccountEntity = accountService.getForUpdateById(id) .let { log.trace { "Deposited $amount to account ${it.id}" } accountService.save(it.copy(amount = it.amount + amount)) } @Transactional suspend fun withdrawal( account: UUID, amount: BigDecimal, ): AccountEntity = accountService.getForUpdateById(account) .let { val entity = it.copy(amount = it.amount - amount) if (entity.amount < ZERO) { throw InsufficientFundsException() } log.trace { "withdrawal $amount from account ${it.id}" } accountService.save(entity) } @Transactional suspend fun transfer( account: UUID, receiver: UUID, amount: BigDecimal, ) { withdrawal(account, amount) deposit(receiver, amount) } }