From c4578672fabd06dc8f9c2c100bfa2a5ad43361ed Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Wed, 10 Oct 2012 15:02:41 +0100 Subject: [PATCH] mifosx-61: provide ability to close loans as reschedule or obligations met if loan is within defined tolerance. --- ...erest-waived-field-on-loan-transaction.sql | 1 + .../platform/api/LoansApiResource.java | 25 ++++- .../platform/api/data/LoanPermissionData.java | 80 ++++++-------- .../ApiDataConversionService.java | 1 - ...RepaymentScheduleTransactionProcessor.java | 3 +- ...RepaymentScheduleTransactionProcessor.java | 14 +-- ...RepaymentScheduleTransactionProcessor.java | 7 +- ...liningBalanceInterestRebateCalculator.java | 1 + ...quivalentFlatInterestRebateCalculator.java | 2 +- .../DefaultLoanLifecycleStateMachine.java | 2 +- ...RepaymentScheduleTransactionProcessor.java | 19 ++-- .../loan/domain/InterestRebateCalculator.java | 1 + .../mifosng/platform/loan/domain/Loan.java | 104 +++++++++++++++--- .../loan/domain/LoanPayoffSummary.java | 1 + .../platform/loan/domain/LoanTransaction.java | 18 +-- ...RepaymentScheduleTransactionProcessor.java | 7 +- .../CalculationPlatformServiceImpl.java | 4 + .../service/LoanReadPlatformServiceImpl.java | 32 +++--- .../service/LoanWritePlatformService.java | 3 + ...WritePlatformServiceJpaRepositoryImpl.java | 35 +++++- ...ymentScheduleTransactionProcessorTest.java | 10 +- ...ymentScheduleTransactionProcessorTest.java | 8 +- 22 files changed, 231 insertions(+), 147 deletions(-) create mode 100644 mifosng-db/patches/patch-0006-drop-interest-waived-field-on-loan-transaction.sql diff --git a/mifosng-db/patches/patch-0006-drop-interest-waived-field-on-loan-transaction.sql b/mifosng-db/patches/patch-0006-drop-interest-waived-field-on-loan-transaction.sql new file mode 100644 index 000000000..72bd4ee68 --- /dev/null +++ b/mifosng-db/patches/patch-0006-drop-interest-waived-field-on-loan-transaction.sql @@ -0,0 +1 @@ +alter table m_loan_transaction drop column interest_waived_derived; \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java index 25ceeae22..b3ef75d95 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java @@ -187,7 +187,7 @@ public class LoansApiResource { } boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); - LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService.retrieveLoanAccountDetails(loanId); + final LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService.retrieveLoanAccountDetails(loanId); int loanRepaymentsCount = 0; Collection loanRepayments = null; @@ -223,7 +223,9 @@ public class LoansApiResource { MoneyData totalOutstandingMoney = MoneyData.of(loanBasicDetails.getCurrency(), repaymentSchedule.totalOutstanding()); boolean isWaiveAllowed = totalOutstandingMoney.isGreaterThanZero() && (tolerance.isGreaterThan(totalOutstandingMoney) || tolerance.isEqualTo(totalOutstandingMoney)); - permissions = this.loanReadPlatformService.retrieveLoanPermissions(loanBasicDetails, isWaiveAllowed, loanRepaymentsCount); + if (responseParameters.contains("permissions")) { + permissions = this.loanReadPlatformService.retrieveLoanPermissions(loanBasicDetails, isWaiveAllowed, loanRepaymentsCount); + } convenienceDataRequired = true; } @@ -418,8 +420,10 @@ public class LoansApiResource { identifier = this.loanWritePlatformService.waiveInterestOnLoan(command); } else if (is(commandParam, "writeoff")) { identifier = this.loanWritePlatformService.writeOff(command); - } else if (is(commandParam, "closeasrescheduled")) { + } else if (is(commandParam, "close-rescheduled")) { identifier = this.loanWritePlatformService.closeAsRescheduled(command); + } else if (is(commandParam, "close")) { + identifier = this.loanWritePlatformService.closeLoan(command); } if (identifier == null) { @@ -474,7 +478,7 @@ public class LoansApiResource { final LoanTransactionNewData newTransactionData = this.loanReadPlatformService.retrieveNewClosureDetails(); return this.apiJsonSerializerService.serializeLoanTransactionDataToJson(prettyPrint, responseParameters, newTransactionData); - } else if (is(commandParam, "closeasrescheduled")) { + } else if (is(commandParam, "close-rescheduled")) { final Set typicalResponseParameters = new HashSet(Arrays.asList("id", "type", "date", "currency", "amount")); Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); @@ -485,7 +489,18 @@ public class LoansApiResource { final LoanTransactionNewData newTransactionData = this.loanReadPlatformService.retrieveNewClosureDetails(); return this.apiJsonSerializerService.serializeLoanTransactionDataToJson(prettyPrint, responseParameters, newTransactionData); - } else { + } else if (is(commandParam, "close")) { + final Set typicalResponseParameters = new HashSet(Arrays.asList("id", "type", "date", "currency", "amount")); + + final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + if (responseParameters.isEmpty()) { + responseParameters.addAll(typicalResponseParameters); + } + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + + final LoanTransactionNewData newTransactionData = this.loanReadPlatformService.retrieveNewClosureDetails(); + return this.apiJsonSerializerService.serializeLoanTransactionDataToJson(prettyPrint, responseParameters, newTransactionData); + } else { throw new UnrecognizedQueryParamException("command", commandParam); } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanPermissionData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanPermissionData.java index b3347d2ab..bdc342b80 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanPermissionData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanPermissionData.java @@ -1,7 +1,15 @@ package org.mifosng.platform.api.data; +/** + * Immutable data object containing information on permissions allowed on a given loan. + */ +@SuppressWarnings("unused") public class LoanPermissionData { + // permission for actions on loan + private final boolean closeLoanAllowed; + private final boolean closeLoanAsRescheduledAllowed; + private final boolean addLoanChargeAllowed; private final boolean waiveAllowed; private final boolean makeRepaymentAllowed; private final boolean rejectAllowed; @@ -9,15 +17,30 @@ public class LoanPermissionData { private final boolean undoApprovalAllowed; private final boolean disbursalAllowed; private final boolean undoDisbursalAllowed; - - private final boolean pendingApproval; - private final boolean waitingForDisbursal; private final boolean anyActionOnLoanAllowed; - public LoanPermissionData(final boolean waiveAllowed, - final boolean makeRepaymentAllowed, final boolean rejectAllowed, - final boolean withdrawnByApplicantAllowed, final boolean undoApprovalAllowed, - final boolean undoDisbursalAllowed, final boolean disbursalAllowed, final boolean pendingApproval, final boolean waitingForDisbursal) { + // status of loan + private final boolean pendingApproval; + private final boolean waitingForDisbursal; + private final boolean closedObligationsMet; + + public LoanPermissionData( + final boolean closeLoanAllowed, + final boolean closeLoanAsRescheduledAllowed, + final boolean addLoanChargeAllowed, + final boolean waiveAllowed, + final boolean makeRepaymentAllowed, + final boolean rejectAllowed, + final boolean withdrawnByApplicantAllowed, + final boolean undoApprovalAllowed, + final boolean undoDisbursalAllowed, + final boolean disbursalAllowed, + final boolean pendingApproval, + final boolean waitingForDisbursal, + final boolean closedObligationsMet) { + this.closeLoanAllowed = closeLoanAllowed; + this.closeLoanAsRescheduledAllowed = closeLoanAsRescheduledAllowed; + this.addLoanChargeAllowed = addLoanChargeAllowed; this.waiveAllowed = waiveAllowed; this.makeRepaymentAllowed = makeRepaymentAllowed; this.rejectAllowed = rejectAllowed; @@ -27,46 +50,7 @@ public class LoanPermissionData { this.disbursalAllowed = disbursalAllowed; this.pendingApproval = pendingApproval; this.waitingForDisbursal = waitingForDisbursal; - this.anyActionOnLoanAllowed = isRejectAllowed() || isWithdrawnByApplicantAllowed() || isPendingApproval() || isUndoDisbursalAllowed() || isMakeRepaymentAllowed(); - } - - public boolean isWaiveAllowed() { - return waiveAllowed; - } - - public boolean isMakeRepaymentAllowed() { - return makeRepaymentAllowed; - } - - public boolean isRejectAllowed() { - return rejectAllowed; - } - - public boolean isWithdrawnByApplicantAllowed() { - return withdrawnByApplicantAllowed; - } - - public boolean isUndoApprovalAllowed() { - return undoApprovalAllowed; - } - - public boolean isDisbursalAllowed() { - return disbursalAllowed; - } - - public boolean isUndoDisbursalAllowed() { - return undoDisbursalAllowed; - } - - public boolean isPendingApproval() { - return pendingApproval; - } - - public boolean isWaitingForDisbursal() { - return waitingForDisbursal; - } - - public boolean isAnyActionOnLoanAllowed() { - return anyActionOnLoanAllowed; + this.closedObligationsMet = closedObligationsMet; + this.anyActionOnLoanAllowed = closeLoanAllowed || closeLoanAsRescheduledAllowed || rejectAllowed || withdrawnByApplicantAllowed || pendingApproval || undoDisbursalAllowed || makeRepaymentAllowed; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java index bacaa8995..d29e696d1 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java @@ -11,7 +11,6 @@ import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand; import org.mifosng.platform.api.commands.DepositProductCommand; import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand; import org.mifosng.platform.api.commands.DepositStateTransitionCommand; -import org.mifosng.platform.api.commands.DocumentCommand; import org.mifosng.platform.api.commands.FundCommand; import org.mifosng.platform.api.commands.GroupCommand; import org.mifosng.platform.api.commands.LoanApplicationCommand; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/AbstractLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/AbstractLoanRepaymentScheduleTransactionProcessor.java index 3cc07e0a8..c3a0d5e6a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/AbstractLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/AbstractLoanRepaymentScheduleTransactionProcessor.java @@ -88,7 +88,6 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen final MonetaryCurrency currency, final List installments) { - final Money interestWaivedPortion = Money.zero(currency); Money principalPortion = Money.zero(currency); Money interestPortion = Money.zero(currency); Money chargesPortion = Money.zero(currency); @@ -102,7 +101,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen } } - loanTransaction.updateComponentsAndTotal(principalPortion, interestPortion, interestWaivedPortion, chargesPortion); + loanTransaction.updateComponentsAndTotal(principalPortion, interestPortion, chargesPortion); } // abstract interface diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/AdhikarLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/AdhikarLoanRepaymentScheduleTransactionProcessor.java index 7575b0f61..17355d748 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/AdhikarLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/AdhikarLoanRepaymentScheduleTransactionProcessor.java @@ -73,8 +73,7 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessor extends AbstractLo transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion); final Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); - final Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, chargesPortion); + loanTransaction.updateComponents(principalPortion, interestWaivedPortion, chargesPortion); } else { LoanRepaymentScheduleInstallment currentInstallmentBasedOnTransactionDate = nearestInstallment(loanTransaction.getTransactionDate(), installments); @@ -88,7 +87,7 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessor extends AbstractLo transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); Money principalPortion = Money.zero(currency); - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, Money.zero(transactionAmountRemaining.getCurrency())); + loanTransaction.updateComponents(principalPortion, interestPortion, Money.zero(transactionAmountRemaining.getCurrency())); } } @@ -99,7 +98,7 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessor extends AbstractLo transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); Money interestPortion = Money.zero(currency); - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, Money.zero(transactionAmountRemaining.getCurrency())); + loanTransaction.updateComponents(principalPortion, interestPortion, Money.zero(transactionAmountRemaining.getCurrency())); } } } @@ -130,14 +129,13 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessor extends AbstractLo final Money transactionAmountUnprocessed) { Money transactionAmountRemaining = transactionAmountUnprocessed; - Money interestWaivedPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); if (loanTransaction.isInterestWaiver()) { - interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion); + interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); } else { interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); @@ -147,7 +145,7 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessor extends AbstractLo transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); } - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, chargesPortion); + loanTransaction.updateComponents(principalPortion, interestPortion, chargesPortion); return transactionAmountRemaining; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/CreocoreLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/CreocoreLoanRepaymentScheduleTransactionProcessor.java index bbaee3124..65eacc7ac 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/CreocoreLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/CreocoreLoanRepaymentScheduleTransactionProcessor.java @@ -79,14 +79,13 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends final Money transactionAmountUnprocessed) { Money transactionAmountRemaining = transactionAmountUnprocessed; - Money interestWaivedPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); if (loanTransaction.isInterestWaiver()) { - interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion); + interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); } else { interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); @@ -96,7 +95,7 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); } - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, chargesPortion); + loanTransaction.updateComponents(principalPortion, interestPortion, chargesPortion); return transactionAmountRemaining; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DailyEquivalentDecliningBalanceInterestRebateCalculator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DailyEquivalentDecliningBalanceInterestRebateCalculator.java index 7c4a30d00..1e5bd6e5c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DailyEquivalentDecliningBalanceInterestRebateCalculator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DailyEquivalentDecliningBalanceInterestRebateCalculator.java @@ -11,6 +11,7 @@ import org.mifosng.platform.currency.domain.Money; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Deprecated public class DailyEquivalentDecliningBalanceInterestRebateCalculator implements InterestRebateCalculator { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DailyEquivalentFlatInterestRebateCalculator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DailyEquivalentFlatInterestRebateCalculator.java index 8a1b03a3f..afefbc778 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DailyEquivalentFlatInterestRebateCalculator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DailyEquivalentFlatInterestRebateCalculator.java @@ -9,8 +9,8 @@ import org.joda.time.LocalDate; import org.mifosng.platform.currency.domain.MonetaryCurrency; import org.mifosng.platform.currency.domain.Money; -// FIXME - KW - this might be deprecated now @SuppressWarnings("unused") +@Deprecated public class DailyEquivalentFlatInterestRebateCalculator implements InterestRebateCalculator { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DefaultLoanLifecycleStateMachine.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DefaultLoanLifecycleStateMachine.java index a2ab6a9c9..bb3535e5c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DefaultLoanLifecycleStateMachine.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DefaultLoanLifecycleStateMachine.java @@ -60,7 +60,7 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi } break; case REPAID_IN_FULL: - if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE)) { + if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE, LoanStatus.OVERPAID)) { newState = stateOf(LoanStatus.CLOSED_OBLIGATIONS_MET, allowedLoanStatuses); } break; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java index dc9d945d1..3e061b8f9 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java @@ -68,23 +68,23 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst final MonetaryCurrency currency = paymentInAdvance.getCurrency(); Money transactionAmountRemaining = paymentInAdvance; - Money interestWaivedPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); if (loanTransaction.isInterestWaiver()) { - interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion); + interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); } else { if (currentInstallment.isPrincipalNotCompleted(currency)) { principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); if (currentInstallment.isPrincipalCompleted(currency)) { - interestWaivedPortion = currentInstallment.waiveInterestComponent(currentInstallment.getInterest(currency)); + // FIXME - KW - if auto waiving interest need to create another transaction to handle this. + currentInstallment.waiveInterestComponent(currentInstallment.getInterest(currency)); } - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, chargesPortion); + loanTransaction.updateComponents(principalPortion, interestPortion, chargesPortion); transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); } @@ -96,7 +96,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); } - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, chargesPortion); + loanTransaction.updateComponents(principalPortion, interestPortion, chargesPortion); return transactionAmountRemaining; } @@ -111,14 +111,13 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst Money transactionAmountRemaining = transactionAmountUnprocessed; - Money interestWaivedPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); if (loanTransaction.isInterestWaiver()) { - interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion); + interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); } else { interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); @@ -128,7 +127,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); } - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, chargesPortion); + loanTransaction.updateComponents(principalPortion, interestPortion, chargesPortion); return transactionAmountRemaining; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/InterestRebateCalculator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/InterestRebateCalculator.java index 38bda1c3a..de521dac0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/InterestRebateCalculator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/InterestRebateCalculator.java @@ -6,6 +6,7 @@ import java.util.List; import org.joda.time.LocalDate; import org.mifosng.platform.currency.domain.Money; +@Deprecated public interface InterestRebateCalculator { Money calculate( diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java index 3497a9d5d..4b73e178f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java @@ -25,7 +25,6 @@ import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyCollectionOption; -import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.mifosng.platform.api.LoanScheduleData; import org.mifosng.platform.api.commands.LoanApplicationCommand; @@ -533,7 +532,7 @@ public class Loan extends AbstractAuditableCustom { LoanTransaction chargesPayment = LoanTransaction.repaymentAtDisbursement(getTotalChargesDueAtDisbursement(), disbursedOn); Money zero = Money.zero(getCurrency()); - chargesPayment.updateComponents(zero, zero, zero, getTotalChargesDueAtDisbursement()); + chargesPayment.updateComponents(zero, zero, getTotalChargesDueAtDisbursement()); chargesPayment.updateLoan(this); this.loanTransactions.add(chargesPayment); @@ -871,10 +870,14 @@ public class Loan extends AbstractAuditableCustom { } private boolean isOverPaid() { + return getTotalOverpayment().isGreaterThanZero(); + } + + private Money getTotalOverpayment() { - Money totalPaidInRepayments = getTotalPaidInRepayments(); + final Money totalPaidInRepayments = getTotalPaidInRepayments(); - MonetaryCurrency currency = loanCurrency(); + final MonetaryCurrency currency = loanCurrency(); Money cumulativeOriginalExpectedTotal = Money.zero(currency); Money cumulativeTotalPaidOnInstallments = Money.zero(currency); @@ -886,7 +889,7 @@ public class Loan extends AbstractAuditableCustom { cumulativeTotalWaivedOnInstallments = cumulativeTotalWaivedOnInstallments.plus(scheduledRepayment.getInterestWaived(currency)); } - return totalPaidInRepayments.isGreaterThan(cumulativeTotalPaidOnInstallments); + return totalPaidInRepayments.minus(cumulativeTotalPaidOnInstallments); } private MonetaryCurrency loanCurrency() { @@ -932,13 +935,76 @@ public class Loan extends AbstractAuditableCustom { return loanTransaction; } - - // FIXME - KW - finish off reschedule/restructure capability for loans. - public void reschedule( - final DateTime rescheduledOn, + + public LoanTransaction close( + final LocalDate closureDate, final LoanLifecycleStateMachine loanLifecycleStateMachine) { - LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, LoanStatus.fromInt(this.loanStatus)); + if (closureDate.isBefore(this.getDisbursementDate())) { + final String errorMessage = "The date on which a loan is closed cannot be before the loan disbursement date: " + getDisbursementDate().toString(); + throw new InvalidLoanStateTransitionException("close","cannot.be.before.submittal.date", errorMessage, closureDate, getDisbursementDate()); + } + + if (closureDate.isAfter(new LocalDate())) { + final String errorMessage = "The date on which a loan is closed cannot be in the future."; + throw new InvalidLoanStateTransitionException("close", "cannot.be.a.future.date", errorMessage, closureDate); + } + + LoanTransaction loanTransaction = null; + if (isOpen()) { + // 1. check total outstanding + final Money outstanding = getTotalOutstanding(); + if (outstanding.isGreaterThanZero() && getInArrearsTolerance().isGreaterThanOrEqualTo(outstanding)) { + + updateLoanForClosure(closureDate, loanLifecycleStateMachine); + + loanTransaction = LoanTransaction.writeoff(this, closureDate); + boolean isLastTransaction = isChronologicallyLatestTransaction(loanTransaction, loanTransactions); + if (!isLastTransaction) { + final String errorMessage = "The closing date of the loan must be on or after latest transaction date."; + throw new InvalidLoanStateTransitionException("close.loan","must.occur.on.or.after.latest.transaction.date", errorMessage, closureDate); + } + + this.loanTransactions.add(loanTransaction); + + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor(this.transactionProcessingStrategy); + loanRepaymentScheduleTransactionProcessor.handleWriteOff(loanTransaction, loanCurrency(), this.repaymentScheduleInstallments); + + } else if (outstanding.isGreaterThanZero()) { + final String errorMessage = "A loan with money outstanding cannot be closed"; + throw new InvalidLoanStateTransitionException("close", "loan.has.money.outstanding", errorMessage, outstanding.toString()); + } + } + + if (isOverPaid()) { + final Money totalLoanOverpayment = getTotalOverpayment(); + // FIXME - kw - use overpaymentTolerance setting when in place on loan product settings. + if (totalLoanOverpayment.isGreaterThanZero() && getInArrearsTolerance().isGreaterThanOrEqualTo(totalLoanOverpayment)) { + // TODO - technically should set somewhere that this loan has 'overpaid' amount + updateLoanForClosure(closureDate, loanLifecycleStateMachine); + } else if (totalLoanOverpayment.isGreaterThanZero()) { + final String errorMessage = "The loan is marked as 'Overpaid' and cannot be moved to 'Closed (obligations met)."; + throw new InvalidLoanStateTransitionException("close", "loan.is.overpaid", errorMessage, totalLoanOverpayment.toString()); + } + } + + return loanTransaction; + } + + private void updateLoanForClosure(final LocalDate closureDate, final LoanLifecycleStateMachine loanLifecycleStateMachine) { + final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, LoanStatus.fromInt(this.loanStatus)); + this.loanStatus = statusEnum.getValue(); + this.closedOnDate = closureDate.toDate(); + } + + /** + * Behaviour added to comply with capability of previous mifos product to support easier transition to mifosx platform. + */ + public void closeAsMarkedForReschedule( + final LocalDate rescheduledOn, + final LoanLifecycleStateMachine loanLifecycleStateMachine) { + + final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, LoanStatus.fromInt(this.loanStatus)); this.loanStatus = statusEnum.getValue(); this.closedOnDate = rescheduledOn.toDate(); @@ -948,15 +1014,12 @@ public class Loan extends AbstractAuditableCustom { if (rescheduledOnLocalDate.isBefore(this.getDisbursementDate())) { final String errorMessage = "The date on which a loan is rescheduled cannot be before the loan disbursement date: " + getDisbursementDate().toString(); - throw new InvalidLoanStateTransitionException("writeoff", - "cannot.be.before.submittal.date", errorMessage, - rescheduledOnLocalDate, getDisbursementDate()); + throw new InvalidLoanStateTransitionException("close.reschedule","cannot.be.before.submittal.date", errorMessage, rescheduledOnLocalDate, getDisbursementDate()); } + if (rescheduledOnLocalDate.isAfter(new LocalDate())) { final String errorMessage = "The date on which a loan is rescheduled cannot be in the future."; - throw new InvalidLoanStateTransitionException("writeoff", - "cannot.be.a.future.date", errorMessage, - rescheduledOnLocalDate); + throw new InvalidLoanStateTransitionException("close.reschedule", "cannot.be.a.future.date", errorMessage, rescheduledOnLocalDate); } } @@ -1219,6 +1282,7 @@ public class Loan extends AbstractAuditableCustom { return regenerationRequired; } + @Deprecated public LoanPayoffSummary getPayoffSummaryOn( final LocalDate projectedPayoffDate) { @@ -1246,6 +1310,10 @@ public class Loan extends AbstractAuditableCustom { rebateGivenOnProjectedPayoffDate); } + /* + * FIXME - KW - change what outstanding balance on loan can be accessed. This total outstanding method is wrong and + */ + @Deprecated public Money getTotalOutstanding() { return getTotalPrincipalOnLoan().plus(getTotalInterestOnLoan()).minus(getTotalPaidInRepayments()); } @@ -1262,6 +1330,7 @@ public class Loan extends AbstractAuditableCustom { return cumulativePaid; } + @Deprecated public Money calculateRebateWhenPaidInFullOn(final LocalDate paidInFullDate) { Money loanPrincipal = this.loanRepaymentScheduleDetail.getPrincipal(); @@ -1290,8 +1359,7 @@ public class Loan extends AbstractAuditableCustom { Money cumulativeInterest = Money.zero(loanCurrency()); for (LoanRepaymentScheduleInstallment scheduledRepayment : this.repaymentScheduleInstallments) { - cumulativeInterest = cumulativeInterest.plus(scheduledRepayment - .getInterest(loanCurrency())); + cumulativeInterest = cumulativeInterest.plus(scheduledRepayment.getInterest(loanCurrency())); } return cumulativeInterest; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanPayoffSummary.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanPayoffSummary.java index d63876cc8..054d7d2fc 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanPayoffSummary.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanPayoffSummary.java @@ -4,6 +4,7 @@ import org.joda.time.Days; import org.joda.time.LocalDate; import org.mifosng.platform.currency.domain.Money; +@Deprecated public class LoanPayoffSummary { private final Long reference; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransaction.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransaction.java index a5548c35d..8d0d7c17f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransaction.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransaction.java @@ -43,9 +43,6 @@ public class LoanTransaction extends AbstractAuditableCustom { @Column(name = "interest_portion_derived", scale = 6, precision = 19, nullable = false) private BigDecimal interestPortion = BigDecimal.ZERO; - @Column(name = "interest_waived_derived", scale = 6, precision = 19) - private BigDecimal interestWaivedPortion = BigDecimal.ZERO; - @Column(name = "charges_portion_derived", scale = 6, precision = 19, nullable = false) private BigDecimal chargesPortion = BigDecimal.ZERO; @@ -187,16 +184,15 @@ public class LoanTransaction extends AbstractAuditableCustom { * * This accumulates the values passed to the already existent values for each of the portions. */ - public void updateComponents(final Money principal, final Money interest, final Money interestWaivedPortion, final Money charges) { + public void updateComponents(final Money principal, final Money interest, final Money charges) { MonetaryCurrency currency = principal.getCurrency(); this.principalPortion = getPrincipalPortion(currency).plus(principal).getAmount(); this.interestPortion = getInterestPortion(currency).plus(interest).getAmount(); - this.interestWaivedPortion = getInterestWaivedPortion(currency).plus(interestWaivedPortion).getAmount(); this.chargesPortion = getChargesPortion(currency).plus(charges).getAmount(); } - public void updateComponentsAndTotal(final Money principal, final Money interest, final Money interestWaivedPortion, final Money charges) { - updateComponents(principal, interest, interestWaivedPortion, charges); + public void updateComponentsAndTotal(final Money principal, final Money interest, final Money charges) { + updateComponents(principal, interest, charges); final MonetaryCurrency currency = principal.getCurrency(); this.amount = getPrincipalPortion(currency).plus(getInterestPortion(currency)).plus(this.chargesPortion).getAmount(); @@ -210,13 +206,6 @@ public class LoanTransaction extends AbstractAuditableCustom { return Money.of(currency, interestPortion); } - public Money getInterestWaivedPortion(final MonetaryCurrency currency) { - if (this.interestWaivedPortion == null) { - this.interestWaivedPortion = BigDecimal.ZERO; - } - return Money.of(currency, interestWaivedPortion); - } - public Money getChargesPortion(final MonetaryCurrency currency) { if (this.chargesPortion == null) { this.chargesPortion = BigDecimal.ZERO; @@ -227,7 +216,6 @@ public class LoanTransaction extends AbstractAuditableCustom { public void resetDerivedComponents() { this.principalPortion = null; this.interestPortion = null; - this.interestWaivedPortion = null; this.chargesPortion = null; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/MifosStyleLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/MifosStyleLoanRepaymentScheduleTransactionProcessor.java index c9105c07d..8f1562e24 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/MifosStyleLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/MifosStyleLoanRepaymentScheduleTransactionProcessor.java @@ -70,14 +70,13 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends final Money transactionAmountUnprocessed) { Money transactionAmountRemaining = transactionAmountUnprocessed; - Money interestWaivedPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); if (loanTransaction.isInterestWaiver()) { - interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion); + interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); } else { interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); @@ -87,7 +86,7 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); } - loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion, chargesPortion); + loanTransaction.updateComponents(principalPortion, interestPortion, chargesPortion); return transactionAmountRemaining; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/CalculationPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/CalculationPlatformServiceImpl.java index d1cc16cde..d09100efa 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/CalculationPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/CalculationPlatformServiceImpl.java @@ -77,6 +77,10 @@ public class CalculationPlatformServiceImpl implements CalculationPlatformServic command.getInterestChargedFromDate(), loanCharges); } + /** + * @deprecated functionality from early prototype work with creocore + */ + @Deprecated @Override public LoanPayoffReadModel calculatePayoffOn(final Long loanId, final LocalDate payoffDate) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java index f7f23b256..735c473f1 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java @@ -185,28 +185,34 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final boolean isWaiverAllowed, final int repaymentAndWaiveCount) { - boolean pendingApproval = (loanBasicDetails.getStatus().getId().equals(100L)); - boolean waitingForDisbursal = (loanBasicDetails.getStatus().getId().equals(200L)); - boolean isActive = (loanBasicDetails.getStatus().getId().equals(300L)); + final boolean pendingApproval = (loanBasicDetails.getStatus().getId().equals(100L)); + final boolean waitingForDisbursal = (loanBasicDetails.getStatus().getId().equals(200L)); + final boolean isActive = (loanBasicDetails.getStatus().getId().equals(300L)); + final boolean closedObligationsMet = (loanBasicDetails.getStatus().getId().equals(600L)); + final boolean isOverpaid = (loanBasicDetails.getStatus().getId().equals(700L)); + final boolean addLoanChargeAllowed = !closedObligationsMet || !isOverpaid; - boolean waiveAllowed = isWaiverAllowed && isActive; - boolean makeRepaymentAllowed = isActive; - - boolean rejectAllowed = pendingApproval; - boolean withdrawnByApplicantAllowed = waitingForDisbursal + final boolean waiveAllowed = isWaiverAllowed && isActive; + final boolean makeRepaymentAllowed = isActive; + final boolean closeLoanAllowed = !closedObligationsMet; + final boolean closeLoanAsRescheduledAllowed = !closedObligationsMet && !isOverpaid; + + final boolean rejectAllowed = pendingApproval; + final boolean withdrawnByApplicantAllowed = waitingForDisbursal || pendingApproval; - boolean undoApprovalAllowed = waitingForDisbursal; + final boolean undoApprovalAllowed = waitingForDisbursal; - boolean undoDisbursalAllowed = isActive + final boolean undoDisbursalAllowed = isActive && (repaymentAndWaiveCount == 0); - boolean disbursalAllowed = waitingForDisbursal; + final boolean disbursalAllowed = waitingForDisbursal; - return new LoanPermissionData(waiveAllowed, makeRepaymentAllowed, + return new LoanPermissionData(closeLoanAllowed, closeLoanAsRescheduledAllowed, + addLoanChargeAllowed, waiveAllowed, makeRepaymentAllowed, rejectAllowed, withdrawnByApplicantAllowed, undoApprovalAllowed, undoDisbursalAllowed, disbursalAllowed, - pendingApproval, waitingForDisbursal); + pendingApproval, waitingForDisbursal, closedObligationsMet); } @Override diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformService.java index 5e861f10f..dda9288e0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformService.java @@ -49,6 +49,9 @@ public interface LoanWritePlatformService { @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')") EntityIdentifier writeOff(LoanTransactionCommand command); + + @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')") + EntityIdentifier closeLoan(LoanTransactionCommand command); @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')") EntityIdentifier closeAsRescheduled(LoanTransactionCommand command); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 0eea6663d..8fdb3699e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -568,6 +568,35 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf return new EntityIdentifier(loan.getId()); } + @Transactional + @Override + public EntityIdentifier closeLoan(final LoanTransactionCommand command) { + + context.authenticatedUser(); + + final LoanTransactionCommandValidator validator = new LoanTransactionCommandValidator(command); + validator.validateNonMonetaryTransaction(); + + final Loan loan = this.loanRepository.findOne(command.getLoanId()); + if (loan == null) { + throw new LoanNotFoundException(command.getLoanId()); + } + + final LoanTransaction possibleClosingTransaction = loan.close(command.getTransactionDate(), defaultLoanLifecycleStateMachine()); + if (possibleClosingTransaction != null) { + this.loanTransactionRepository.save(possibleClosingTransaction); + } + this.loanRepository.save(loan); + + final String noteText = command.getNote(); + if (StringUtils.isNotBlank(noteText)) { + final Note note = Note.loanNote(loan, noteText); + this.noteRepository.save(note); + } + + return new EntityIdentifier(loan.getId()); + } + @Transactional @Override public EntityIdentifier closeAsRescheduled(final LoanTransactionCommand command) { @@ -581,15 +610,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf throw new LoanNotFoundException(command.getLoanId()); } - // FIXME - kw - HANDLE closed and rescheduled case. - final LoanTransaction writeoff = loan.closeAsWrittenOff(command.getTransactionDate(), defaultLoanLifecycleStateMachine()); + loan.closeAsMarkedForReschedule(command.getTransactionDate(), defaultLoanLifecycleStateMachine()); - this.loanTransactionRepository.save(writeoff); this.loanRepository.save(loan); final String noteText = command.getNote(); if (StringUtils.isNotBlank(noteText)) { - final Note note = Note.loanTransactionNote(loan, writeoff, noteText); + final Note note = Note.loanNote(loan, noteText); this.noteRepository.save(note); } diff --git a/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/AdhikarLoanRepaymentScheduleTransactionProcessorTest.java b/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/AdhikarLoanRepaymentScheduleTransactionProcessorTest.java index f1254711c..4c038a1f9 100644 --- a/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/AdhikarLoanRepaymentScheduleTransactionProcessorTest.java +++ b/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/AdhikarLoanRepaymentScheduleTransactionProcessorTest.java @@ -49,7 +49,7 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessorTest { LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("100.00"), interestWaivedOf("0.00"), firstInstallment, usDollars); - assertThatLoanTransactionHasDerivedFieldsOf(principalOf("0.00"), interestOf("100.00"), interestWaivedOf("0.00"), onTimePartialRepayment, usDollars); + assertThatLoanTransactionHasDerivedFieldsOf(principalOf("0.00"), interestOf("100.00"), onTimePartialRepayment, usDollars); } /** @@ -77,7 +77,7 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessorTest { LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2); assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars); - assertThatLoanTransactionHasDerivedFieldsOf(principalOf("0.00"), interestOf("300.00"), interestWaivedOf("0.00"), lateRepayment, usDollars); + assertThatLoanTransactionHasDerivedFieldsOf(principalOf("0.00"), interestOf("300.00"), lateRepayment, usDollars); } /** @@ -105,13 +105,12 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessorTest { LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2); assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars); - assertThatLoanTransactionHasDerivedFieldsOf(principalOf("500.00"), interestOf("400.00"), interestWaivedOf("0.00"), lateRepayment, usDollars); + assertThatLoanTransactionHasDerivedFieldsOf(principalOf("500.00"), interestOf("400.00"), lateRepayment, usDollars); } private void assertThatLoanTransactionHasDerivedFieldsOf( final String principal, final String interest, - final String interestWaived, final LoanTransaction transaction, final MonetaryCurrency currency) { Money expectedPrincipalPortion = new MoneyBuilder().with(currency).with(principal).build(); @@ -119,9 +118,6 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessorTest { Money expectedInterestPortion = new MoneyBuilder().with(currency).with(interest).build(); assertThat("Interest portion of transaction not as expected: ", transaction.getInterestPortion(currency).toString(), is(expectedInterestPortion.toString())); - - Money expectedInterestWaivedPortion = new MoneyBuilder().with(currency).with(interestWaived).build(); - assertThat("Interest waived portion of transaction not as expected: ",transaction.getInterestWaivedPortion(currency).toString(), is(expectedInterestWaivedPortion.toString())); } private void assertThatLoanInstallmentHasDerivedFieldsOf( diff --git a/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest.java b/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest.java index cbffa258e..0fd1cd229 100644 --- a/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest.java +++ b/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest.java @@ -278,7 +278,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest { LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2); assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("800.00"), interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars); - assertThatLoanTransactionHasDerivedFieldsOf(principalOf("2800.00"), interestOf("200.00"), interestWaivedOf("200.00"), onTimePartialPayment, usDollars); + assertThatLoanTransactionHasDerivedFieldsOf(principalOf("2800.00"), interestOf("200.00"), onTimePartialPayment, usDollars); } /** @@ -353,7 +353,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest { LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2); assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars); - assertThatLoanTransactionHasDerivedFieldsOf(principalOf("3000.00"), interestOf("600.00"), interestWaivedOf("0.00"), lateRepaymentTransaction, usDollars); + assertThatLoanTransactionHasDerivedFieldsOf(principalOf("3000.00"), interestOf("600.00"), lateRepaymentTransaction, usDollars); } @@ -379,7 +379,6 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest { private void assertThatLoanTransactionHasDerivedFieldsOf( final String principal, final String interest, - final String interestWaived, final LoanTransaction transaction, final MonetaryCurrency currency) { Money expectedPrincipalPortion = new MoneyBuilder().with(currency).with(principal).build(); @@ -387,9 +386,6 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest { Money expectedInterestPortion = new MoneyBuilder().with(currency).with(interest).build(); assertThat("Interest portion of transaction not as expected: ", transaction.getInterestPortion(currency).toString(), is(expectedInterestPortion.toString())); - - Money expectedInterestWaivedPortion = new MoneyBuilder().with(currency).with(interestWaived).build(); - assertThat("Interest waived portion of transaction not as expected: ",transaction.getInterestWaivedPortion(currency).toString(), is(expectedInterestWaivedPortion.toString())); } private void assertThatLoanInstallmentHasDerivedFieldsOf(