|
| 1 | +package io.reflectoring.buckpal.account.application.service; |
| 2 | + |
| 3 | +import io.reflectoring.buckpal.account.application.port.in.SendMoneyCommand; |
| 4 | +import io.reflectoring.buckpal.account.application.port.in.SendMoneyUseCase; |
| 5 | +import io.reflectoring.buckpal.account.application.port.out.AccountLock; |
| 6 | +import io.reflectoring.buckpal.account.application.port.out.LoadAccountPort; |
| 7 | +import io.reflectoring.buckpal.account.application.port.out.UpdateAccountStatePort; |
| 8 | +import io.reflectoring.buckpal.common.UseCase; |
| 9 | +import io.reflectoring.buckpal.account.domain.Account; |
| 10 | +import io.reflectoring.buckpal.account.domain.Account.AccountId; |
| 11 | +import lombok.RequiredArgsConstructor; |
| 12 | + |
| 13 | +import javax.transaction.Transactional; |
| 14 | +import java.time.LocalDateTime; |
| 15 | + |
| 16 | +@RequiredArgsConstructor |
| 17 | +@UseCase |
| 18 | +@Transactional |
| 19 | +public class SendMoneyService implements SendMoneyUseCase { |
| 20 | + |
| 21 | + private final LoadAccountPort loadAccountPort; |
| 22 | + private final AccountLock accountLock; |
| 23 | + private final UpdateAccountStatePort updateAccountStatePort; |
| 24 | + private final MoneyTransferProperties moneyTransferProperties; |
| 25 | + |
| 26 | + @Override |
| 27 | + public boolean sendMoney(SendMoneyCommand command) { |
| 28 | + |
| 29 | + checkThreshold(command); |
| 30 | + |
| 31 | + LocalDateTime baselineDate = LocalDateTime.now().minusDays(10); |
| 32 | + |
| 33 | + Account sourceAccount = loadAccountPort.loadAccount( |
| 34 | + command.getSourceAccountId(), |
| 35 | + baselineDate); |
| 36 | + |
| 37 | + Account targetAccount = loadAccountPort.loadAccount( |
| 38 | + command.getTargetAccountId(), |
| 39 | + baselineDate); |
| 40 | + |
| 41 | + AccountId sourceAccountId = sourceAccount.getId() |
| 42 | + .orElseThrow(() -> new IllegalStateException("expected source account ID not to be empty")); |
| 43 | + AccountId targetAccountId = targetAccount.getId() |
| 44 | + .orElseThrow(() -> new IllegalStateException("expected target account ID not to be empty")); |
| 45 | + |
| 46 | + accountLock.lockAccount(sourceAccountId); |
| 47 | + if (!sourceAccount.withdraw(command.getMoney(), targetAccountId)) { |
| 48 | + accountLock.releaseAccount(sourceAccountId); |
| 49 | + return false; |
| 50 | + } |
| 51 | + |
| 52 | + accountLock.lockAccount(targetAccountId); |
| 53 | + if (!targetAccount.deposit(command.getMoney(), sourceAccountId)) { |
| 54 | + accountLock.releaseAccount(sourceAccountId); |
| 55 | + accountLock.releaseAccount(targetAccountId); |
| 56 | + return false; |
| 57 | + } |
| 58 | + |
| 59 | + updateAccountStatePort.updateActivities(sourceAccount); |
| 60 | + updateAccountStatePort.updateActivities(targetAccount); |
| 61 | + |
| 62 | + accountLock.releaseAccount(sourceAccountId); |
| 63 | + accountLock.releaseAccount(targetAccountId); |
| 64 | + return true; |
| 65 | + } |
| 66 | + |
| 67 | + private void checkThreshold(SendMoneyCommand command) { |
| 68 | + if(command.getMoney().isGreaterThan(moneyTransferProperties.getMaximumTransferThreshold())){ |
| 69 | + throw new ThresholdExceededException(moneyTransferProperties.getMaximumTransferThreshold(), command.getMoney()); |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | +} |
| 74 | + |
| 75 | + |
| 76 | + |
| 77 | + |
0 commit comments