Untitled

 avatar
unknown
plain_text
2 years ago
3.3 kB
2
Indexable
@RequiredArgsConstructor
final class CreateStatementService implements CreateStatementUseCase {

    private final Customers customers;
    private final Accounts accounts;
    private final TransactionHistory transactionHistory;
    private final AccountBalances accountBalances;

    @Override
    public Either<Failure, Statement> create(CreateStatement command) {
        Optional<Account> account = accounts.find(command.accountId());
        if (account.isEmpty()) {
            return Either.left(new NotFound("Account"));
        }

        Optional<Customer> customer = customers.find(command.customerId());
        if (customer.isEmpty()) {
            return Either.left(new NotFound("Customer"));
        }

        List<Transaction> sortedTransactionList = transactionHistory
                .findAll(account.get().getAccountNumber(), command.interval())
                .stream()
                .sorted(Comparator.comparing(Transaction::getOccurredAt))
                .collect(Collectors.toList());

        Either<Failure, Tuple2<MonetaryAmount, MonetaryAmount>> initialAndFinalBalance = getInitialAndFinalBalance(
                command.accountId(), command.interval(), sortedTransactionList
        );
        if (initialAndFinalBalance.isLeft()) {
            return Either.left(initialAndFinalBalance.getLeft());
        }

        return Either.right(new Statement(
                customer.get(),
                account.get(),
                command.interval(),
                sortedTransactionList,
                initialAndFinalBalance.get()._1(),
                initialAndFinalBalance.get()._2()
        ));
    }

    private Either<Failure, Tuple2<MonetaryAmount, MonetaryAmount>> getInitialAndFinalBalance(
            String accountId, Interval interval, List<Transaction> transactionList
    ) {
        if (!transactionList.isEmpty()) {
            return Either.right(getBalanceBasedOnTransactions(transactionList));
        }

        Optional<MonetaryAmount> initialBalance = accountBalances.find(accountId, interval.getStart());
        if (initialBalance.isEmpty()) {
            return Either.left(new NotFound("Initial Balance"));
        }

        Optional<MonetaryAmount> finalBalance;
        if (interval.getEnd() == null) {
            finalBalance = accountBalances.find(accountId);
        } else {
            finalBalance = accountBalances.find(accountId, interval.getEnd());
        }
        if (finalBalance.isEmpty()) {
            return Either.left(new NotFound("Final Balance"));
        }

        return Either.right(new Tuple2<>(initialBalance.get(), finalBalance.get()));
    }

    private Tuple2<MonetaryAmount, MonetaryAmount> getBalanceBasedOnTransactions(List<Transaction> transactionList) {
        Transaction first = transactionList.get(0);
        Transaction last = transactionList.get(transactionList.size() - 1);

        MonetaryAmount initialBalance = first
                .getBalanceAfterTransaction()
                .add(first.getTotalTransactionAmountInAccountCurrency());
        MonetaryAmount finalBalance = last.getBalanceAfterTransaction();

        return new Tuple2<>(initialBalance, finalBalance);
    }
}