package jamel.basicModel.banks; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * Represents a loan account. */ class LoanAccount { /** * The associated deposit account. */ final private DepositAccount depositAccount; /** * The list of the loans. */ final private List<Loan> list = new LinkedList<>(); /** * The total amount of the loans (overdue excepted). */ final private Amount loans = new Amount(); /** * The total amount of the loans at the bank level. */ final private Amount outstandingLoans; /** * The amount of overdue debt. */ final private Amount overdueDebt = new Amount(); /** * Creates a new loan account. * * @param depositAccount * the associated deposit account. * @param outstandingLoans * the amount of loans at the bank level. */ LoanAccount(final DepositAccount depositAccount, final Amount outstandingLoans) { this.depositAccount = depositAccount; this.outstandingLoans = outstandingLoans; } /** * Records a new overdue debt. * * @param amount * the amount of the new overdue debt. */ private void newOverdueDebt(long amount) { if (amount <= 0) { throw new RuntimeException("Bad amount: " + amount); } this.overdueDebt.plus(amount); this.outstandingLoans.plus(amount); this.depositAccount.newDeposit(amount); } /** * Adds a new loan to this account. * * @param loan * the new loan to be added. */ void add(final Loan loan) { this.list.add(loan); this.loans.plus(loan.getPrincipal()); this.outstandingLoans.plus(loan.getPrincipal()); this.depositAccount.newDeposit(loan.getPrincipal()); } /** * Recovers due debts. * * @param penaltyRate * the penalty rate on overdue loans. */ void debtRecovery(final double penaltyRate) { // TODO Vérifier qu'il n'est appelé qu'une fois par période // Paiement des intérêts sur la dette "overdue". { final long interest = (long) (penaltyRate * this.overdueDebt.getAmount()); if (interest > this.depositAccount.getAmount()) { final long newLoan = interest - this.depositAccount.getAmount(); this.newOverdueDebt(newLoan); } this.depositAccount.newWithdrawal(interest); } // Remboursement de la dette "overdue". { final long installment = Math.min(this.overdueDebt.getAmount(), this.depositAccount.getAmount()); this.overdueDebt.minus(installment); this.outstandingLoans.minus(installment); this.depositAccount.newWithdrawal(installment); } // Puis on s'occupe des crédits ordinaires final Iterator<Loan> it = this.list.iterator(); while (it.hasNext()) { final Loan loan = it.next(); if (loan.getPrincipal() == 0) { throw new RuntimeException("This loan is empty."); } final long interest = loan.getInterest(); final long installment = loan.getInstallment(); if (interest + installment >= 0) { if (interest + installment > this.depositAccount.getAmount()) { this.newOverdueDebt(interest + installment - this.depositAccount.getAmount()); } loan.cancel(installment); this.loans.minus(installment); this.outstandingLoans.minus(installment); this.depositAccount.newWithdrawal(installment + interest); if (loan.getPrincipal() == 0) { it.remove(); } } } } /** * Returns the amount of debts. * * @return the amount of debts. */ long getAmount() { return this.loans.getAmount() + this.overdueDebt.getAmount(); } }