handle loan creation with no charges after refactoring.

This commit is contained in:
Keith Woodlock
2012-12-20 12:36:46 +00:00
parent 94459fe2a5
commit 3224836989
2 changed files with 160 additions and 166 deletions
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@@ -165,7 +166,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
@LazyCollection(LazyCollectionOption.FALSE) @LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true) @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true)
private Set<LoanCharge> charges; private Set<LoanCharge> charges = new HashSet<LoanCharge>();
@LazyCollection(LazyCollectionOption.FALSE) @LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true) @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true)
@@ -276,7 +277,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
Money chargesDue = Money.of(getCurrency(), BigDecimal.ZERO); Money chargesDue = Money.of(getCurrency(), BigDecimal.ZERO);
for (LoanCharge charge : this.charges) { for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
if (charge.isDueAtDisbursement()) { if (charge.isDueAtDisbursement()) {
chargesDue = chargesDue.plus(charge.amount()); chargesDue = chargesDue.plus(charge.amount());
} }
@@ -319,7 +320,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate()); validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
loanCharge.update(this); loanCharge.update(this);
this.charges.add(loanCharge); getNullPointerSafeLoanCharges().add(loanCharge);
updateTotalChargesDueAtDisbursement(); updateTotalChargesDueAtDisbursement();
@@ -334,11 +335,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
// transaction. // transaction.
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
getCurrency(), this.repaymentScheduleInstallments, this.charges); getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} else { } else {
// just reprocess the loan schedule only for now. // just reprocess the loan schedule only for now.
LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, this.charges); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} }
} }
@@ -378,7 +379,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
// if you want ability to remove loan charges that are waived. // if you want ability to remove loan charges that are waived.
validateLoanChargeIsNotWaived(loanCharge); validateLoanChargeIsNotWaived(loanCharge);
boolean removed = this.charges.remove(loanCharge); boolean removed = getNullPointerSafeLoanCharges().remove(loanCharge);
if (removed) { if (removed) {
updateTotalChargesDueAtDisbursement(); updateTotalChargesDueAtDisbursement();
} }
@@ -390,7 +391,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) { if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
getCurrency(), this.repaymentScheduleInstallments, this.charges); getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} }
} }
@@ -427,7 +428,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
validateLoanIsNotClosed(loanCharge); validateLoanIsNotClosed(loanCharge);
if (this.charges.contains(loanCharge)) { if (getNullPointerSafeLoanCharges().contains(loanCharge)) {
final Map<String, Object> loanChargeChanges = loanCharge.update(command, getPrincpal().getAmount()); final Map<String, Object> loanChargeChanges = loanCharge.update(command, getPrincpal().getAmount());
actualChanges.putAll(loanChargeChanges); actualChanges.putAll(loanChargeChanges);
updateTotalChargesDueAtDisbursement(); updateTotalChargesDueAtDisbursement();
@@ -438,11 +439,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
if (!loanCharge.isDueAtDisbursement()) { if (!loanCharge.isDueAtDisbursement()) {
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
getCurrency(), this.repaymentScheduleInstallments, this.charges); getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} else { } else {
// reprocess loan schedule based on charge been waived. // reprocess loan schedule based on charge been waived.
LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, this.charges); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} }
return actualChanges; return actualChanges;
@@ -480,11 +481,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) { if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
getCurrency(), this.repaymentScheduleInstallments, this.charges); getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} else { } else {
// reprocess loan schedule based on charge been waived. // reprocess loan schedule based on charge been waived.
LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, this.charges); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} }
doPostLoanTransactionChecks(waiveLoanChargeTransaction.getTransactionDate(), loanLifecycleStateMachine); doPostLoanTransactionChecks(waiveLoanChargeTransaction.getTransactionDate(), loanLifecycleStateMachine);
@@ -521,8 +522,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
} }
public void updateLoanCharges(final Set<LoanCharge> loanCharges) { public void updateLoanCharges(final Set<LoanCharge> loanCharges) {
this.charges.clear(); getNullPointerSafeLoanCharges().clear();
this.charges.addAll(associateChargesWithThisLoan(loanCharges)); getNullPointerSafeLoanCharges().addAll(associateChargesWithThisLoan(loanCharges));
this.totalChargesDueAtDisbursement = deriveSumTotalOfChargesDueAtDisbursement(); this.totalChargesDueAtDisbursement = deriveSumTotalOfChargesDueAtDisbursement();
} }
@@ -548,7 +549,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor
.determineProcessor(this.transactionProcessingStrategy); .determineProcessor(this.transactionProcessingStrategy);
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), repaymentsOrWaivers, getCurrency(), loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), repaymentsOrWaivers, getCurrency(),
this.repaymentScheduleInstallments, this.charges); this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} }
public void updateLoanScheduleDependentDerivedFields() { public void updateLoanScheduleDependentDerivedFields() {
@@ -677,14 +678,22 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
Arrays.sort(newLoanChargeData); Arrays.sort(newLoanChargeData);
return !Arrays.equals(existingLoanChargeData, newLoanChargeData); return !Arrays.equals(existingLoanChargeData, newLoanChargeData);
} }
private Set<LoanCharge> getNullPointerSafeLoanCharges() {
Set<LoanCharge> loanCharges = this.charges;
if (this.charges == null) {
loanCharges = new HashSet<LoanCharge>();
}
return loanCharges;
}
private LoanChargeCommand[] getLoanCharges() { private LoanChargeCommand[] getLoanCharges() {
LoanChargeCommand[] existingLoanCharges = null; LoanChargeCommand[] existingLoanCharges = null;
if (this.charges != null && !this.charges.isEmpty()) { if (!getNullPointerSafeLoanCharges().isEmpty()) {
List<LoanChargeCommand> loanChargesList = new ArrayList<LoanChargeCommand>(); List<LoanChargeCommand> loanChargesList = new ArrayList<LoanChargeCommand>();
for (LoanCharge loanCharge : this.charges) { for (LoanCharge loanCharge : getNullPointerSafeLoanCharges()) {
loanChargesList.add(loanCharge.toCommand()); loanChargesList.add(loanCharge.toCommand());
} }
@@ -748,10 +757,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
} }
// charges are optional // charges are optional
if (this.charges != null) { for (LoanCharge loanCharge : getNullPointerSafeLoanCharges()) {
for (LoanCharge loanCharge : this.charges) { validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
}
} }
this.externalId = externalId; this.externalId = externalId;
@@ -974,7 +981,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
final LoanSchedule loanSchedule = new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, interestRatePerPeriod, final LoanSchedule loanSchedule = new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, interestRatePerPeriod,
interestRatePeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, interestRatePeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod,
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod, loanTermFrequency, repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod, loanTermFrequency,
loanTermPeriodFrequencyType, this.charges, this.getDisbursementDate(), this.getExpectedFirstRepaymentOnDate(), loanTermPeriodFrequencyType, getNullPointerSafeLoanCharges(), this.getDisbursementDate(), this.getExpectedFirstRepaymentOnDate(),
this.getInterestChargedFromDate(), inArrearsTolerance); this.getInterestChargedFromDate(), inArrearsTolerance);
final LoanScheduleData generatedData = loanSchedule.generate(); final LoanScheduleData generatedData = loanSchedule.generate();
@@ -982,7 +989,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
updateLoanSchedule(generatedData); updateLoanSchedule(generatedData);
} }
private void handleDisbursementTransaction(LocalDate disbursedOn) { private void handleDisbursementTransaction(final LocalDate disbursedOn) {
// track disbursement transaction // track disbursement transaction
final LoanTransaction loanTransaction = LoanTransaction.disbursement(this.loanRepaymentScheduleDetail.getPrincipal(), disbursedOn); final LoanTransaction loanTransaction = LoanTransaction.disbursement(this.loanRepaymentScheduleDetail.getPrincipal(), disbursedOn);
loanTransaction.updateLoan(this); loanTransaction.updateLoan(this);
@@ -998,7 +1005,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
chargesPayment.updateLoan(this); chargesPayment.updateLoan(this);
this.loanTransactions.add(chargesPayment); this.loanTransactions.add(chargesPayment);
for (LoanCharge charge : this.charges) { for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
if (charge.isDueAtDisbursement()) { if (charge.isDueAtDisbursement()) {
charge.markAsFullyPaid(); charge.markAsFullyPaid();
} }
@@ -1051,7 +1058,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
this.loanTransactions.clear(); this.loanTransactions.clear();
this.disbursedOnDate = null; this.disbursedOnDate = null;
for (LoanCharge charge : this.charges) { for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
charge.resetToOriginal(loanCurrency()); charge.resetToOriginal(loanCurrency());
} }
@@ -1060,7 +1067,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
} }
LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, this.charges); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} }
public LoanTransaction waiveInterest(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine) { public LoanTransaction waiveInterest(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine) {
@@ -1136,11 +1143,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
.determineProcessor(this.transactionProcessingStrategy); .determineProcessor(this.transactionProcessingStrategy);
if (isTransactionChronologicallyLatest && adjustedTransaction == null) { if (isTransactionChronologicallyLatest && adjustedTransaction == null) {
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments, loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments,
this.charges); getNullPointerSafeLoanCharges());
} else { } else {
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
getCurrency(), this.repaymentScheduleInstallments, this.charges); getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
} }
doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine); doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
@@ -8,151 +8,138 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money; import org.mifosplatform.organisation.monetary.domain.Money;
/** /**
* A wrapper around loan schedule related data exposing needed behaviour by loan. * A wrapper around loan schedule related data exposing needed behaviour by
* loan.
* *
* This wrapper should be side-effect free. It should not attempt to change state of loan parts passed through to it. * This wrapper should be side-effect free. It should not attempt to change
* state of loan parts passed through to it.
*/ */
public class LoanScheduleWrapper { public class LoanScheduleWrapper {
public Money calculateTotalOutstanding( public Money calculateTotalOutstanding(final MonetaryCurrency currency, final List<LoanRepaymentScheduleInstallment> installments) {
final MonetaryCurrency currency,
final List<LoanRepaymentScheduleInstallment> installments) {
Money cumulativeValue = Money.zero(currency); Money cumulativeValue = Money.zero(currency);
for (LoanRepaymentScheduleInstallment scheduledRepayment : installments) { for (LoanRepaymentScheduleInstallment scheduledRepayment : installments) {
cumulativeValue = cumulativeValue.plus(scheduledRepayment.getTotalOutstanding(currency)); cumulativeValue = cumulativeValue.plus(scheduledRepayment.getTotalOutstanding(currency));
} }
return cumulativeValue; return cumulativeValue;
} }
/** /**
* FIXME - this is not a side effect free approach so move this into a specific wrapper than makes this obvious from the read-only wrapper. * FIXME - this is not a side effect free approach so move this into a
*/ * specific wrapper than makes this obvious from the read-only wrapper.
public void reprocess( */
final MonetaryCurrency currency, public void reprocess(final MonetaryCurrency currency, final LocalDate disbursementDate,
final LocalDate disbursementDate, final List<LoanRepaymentScheduleInstallment> repaymentPeriods, final Set<LoanCharge> loanCharges) {
final List<LoanRepaymentScheduleInstallment> repaymentPeriods,
final Set<LoanCharge> loanCharges) {
LocalDate startDate = disbursementDate;
for (LoanRepaymentScheduleInstallment period : repaymentPeriods) {
final Money feeChargesDueForRepaymentPeriod = cumulativeFeeChargesDueWithin(startDate, period.getDueDate(), loanCharges, currency);
final Money feeChargesWaivedForRepaymentPeriod = cumulativeFeeChargesWaivedWithin(startDate, period.getDueDate(), loanCharges, currency);
final Money feeChargesWrittenOffForRepaymentPeriod = cumulativeFeeChargesWrittenOffWithin(startDate, period.getDueDate(), loanCharges, currency);
final Money penaltyChargesDueForRepaymentPeriod = cumulativePenaltyChargesDueWithin(startDate, period.getDueDate(), loanCharges, currency);
final Money penaltyChargesWaivedForRepaymentPeriod = cumulativePenaltyChargesWaivedWithin(startDate, period.getDueDate(), loanCharges, currency);
final Money penaltyChargesWrittenOffForRepaymentPeriod = cumulativePenaltyChargesWrittenOffWithin(startDate, period.getDueDate(), loanCharges, currency);
period.updateChargePortion(feeChargesDueForRepaymentPeriod, feeChargesWaivedForRepaymentPeriod, feeChargesWrittenOffForRepaymentPeriod,
penaltyChargesDueForRepaymentPeriod, penaltyChargesWaivedForRepaymentPeriod, penaltyChargesWrittenOffForRepaymentPeriod);
startDate = period.getDueDate(); LocalDate startDate = disbursementDate;
} for (LoanRepaymentScheduleInstallment period : repaymentPeriods) {
}
final Money feeChargesDueForRepaymentPeriod = cumulativeFeeChargesDueWithin(startDate, period.getDueDate(), loanCharges,
private Money cumulativeFeeChargesDueWithin( currency);
final LocalDate periodStart, final Money feeChargesWaivedForRepaymentPeriod = cumulativeFeeChargesWaivedWithin(startDate, period.getDueDate(), loanCharges,
final LocalDate periodEnd, currency);
final Set<LoanCharge> loanCharges, final Money feeChargesWrittenOffForRepaymentPeriod = cumulativeFeeChargesWrittenOffWithin(startDate, period.getDueDate(),
final MonetaryCurrency monetaryCurrency) { loanCharges, currency);
Money cumulative = Money.zero(monetaryCurrency); final Money penaltyChargesDueForRepaymentPeriod = cumulativePenaltyChargesDueWithin(startDate, period.getDueDate(),
loanCharges, currency);
for (LoanCharge loanCharge : loanCharges) { final Money penaltyChargesWaivedForRepaymentPeriod = cumulativePenaltyChargesWaivedWithin(startDate, period.getDueDate(),
if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isFeeCharge()) { loanCharges, currency);
cumulative = cumulative.plus(loanCharge.amount()); final Money penaltyChargesWrittenOffForRepaymentPeriod = cumulativePenaltyChargesWrittenOffWithin(startDate,
} period.getDueDate(), loanCharges, currency);
}
period.updateChargePortion(feeChargesDueForRepaymentPeriod, feeChargesWaivedForRepaymentPeriod,
return cumulative; feeChargesWrittenOffForRepaymentPeriod, penaltyChargesDueForRepaymentPeriod, penaltyChargesWaivedForRepaymentPeriod,
} penaltyChargesWrittenOffForRepaymentPeriod);
private Money cumulativeFeeChargesWaivedWithin( startDate = period.getDueDate();
final LocalDate periodStart, }
final LocalDate periodEnd, }
final Set<LoanCharge> loanCharges,
final MonetaryCurrency currency) { private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd, final Set<LoanCharge> loanCharges,
final MonetaryCurrency monetaryCurrency) {
Money cumulative = Money.zero(currency);
Money cumulative = Money.zero(monetaryCurrency);
for (LoanCharge loanCharge : loanCharges) {
if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isFeeCharge()) { for (LoanCharge loanCharge : loanCharges) {
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency)); if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isFeeCharge()) {
} cumulative = cumulative.plus(loanCharge.amount());
} }
}
return cumulative;
} return cumulative;
}
private Money cumulativeFeeChargesWrittenOffWithin(
final LocalDate periodStart, private Money cumulativeFeeChargesWaivedWithin(final LocalDate periodStart, final LocalDate periodEnd,
final LocalDate periodEnd, final Set<LoanCharge> loanCharges, final MonetaryCurrency currency) {
final Set<LoanCharge> loanCharges,
final MonetaryCurrency currency) { Money cumulative = Money.zero(currency);
Money cumulative = Money.zero(currency); for (LoanCharge loanCharge : loanCharges) {
if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isFeeCharge()) {
for (LoanCharge loanCharge : loanCharges) { cumulative = cumulative.plus(loanCharge.getAmountWaived(currency));
if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isFeeCharge()) { }
cumulative = cumulative.plus(loanCharge.getAmountWrittenOff(currency)); }
}
} return cumulative;
}
return cumulative;
} private Money cumulativeFeeChargesWrittenOffWithin(final LocalDate periodStart, final LocalDate periodEnd,
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency) {
private Money cumulativePenaltyChargesDueWithin(
final LocalDate periodStart, Money cumulative = Money.zero(currency);
final LocalDate periodEnd,
final Set<LoanCharge> loanCharges, for (LoanCharge loanCharge : loanCharges) {
final MonetaryCurrency currency) { if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isFeeCharge()) {
cumulative = cumulative.plus(loanCharge.getAmountWrittenOff(currency));
Money cumulative = Money.zero(currency); }
}
for (LoanCharge loanCharge : loanCharges) {
if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isPenaltyCharge()) { return cumulative;
cumulative = cumulative.plus(loanCharge.amount()); }
}
} private Money cumulativePenaltyChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd,
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency) {
return cumulative;
} Money cumulative = Money.zero(currency);
private Money cumulativePenaltyChargesWaivedWithin( for (LoanCharge loanCharge : loanCharges) {
final LocalDate periodStart, if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isPenaltyCharge()) {
final LocalDate periodEnd, cumulative = cumulative.plus(loanCharge.amount());
final Set<LoanCharge> loanCharges, }
final MonetaryCurrency currency) { }
Money cumulative = Money.zero(currency); return cumulative;
}
for (LoanCharge loanCharge : loanCharges) {
if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isPenaltyCharge()) { private Money cumulativePenaltyChargesWaivedWithin(final LocalDate periodStart, final LocalDate periodEnd,
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency)); final Set<LoanCharge> loanCharges, final MonetaryCurrency currency) {
}
} Money cumulative = Money.zero(currency);
return cumulative; for (LoanCharge loanCharge : loanCharges) {
} if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isPenaltyCharge()) {
cumulative = cumulative.plus(loanCharge.getAmountWaived(currency));
private Money cumulativePenaltyChargesWrittenOffWithin( }
final LocalDate periodStart, }
final LocalDate periodEnd,
final Set<LoanCharge> loanCharges, return cumulative;
final MonetaryCurrency currency) { }
Money cumulative = Money.zero(currency); private Money cumulativePenaltyChargesWrittenOffWithin(final LocalDate periodStart, final LocalDate periodEnd,
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency) {
for (LoanCharge loanCharge : loanCharges) {
if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isPenaltyCharge()) { Money cumulative = Money.zero(currency);
cumulative = cumulative.plus(loanCharge.getAmountWrittenOff(currency));
} for (LoanCharge loanCharge : loanCharges) {
} if (loanCharge.isDueForCollectionBetween(periodStart, periodEnd) && loanCharge.isPenaltyCharge()) {
cumulative = cumulative.plus(loanCharge.getAmountWrittenOff(currency));
return cumulative; }
} }
return cumulative;
}
} }