mifosx-61: provide ability to close loans as reschedule or obligations met if loan is within defined tolerance.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
alter table m_loan_transaction drop column interest_waived_derived;
|
||||
@@ -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<LoanTransactionNewData> 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<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "type", "date", "currency", "amount"));
|
||||
|
||||
Set<String> 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<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "type", "date", "currency", "amount"));
|
||||
|
||||
final Set<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
+32
-48
@@ -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;
|
||||
}
|
||||
}
|
||||
-1
@@ -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;
|
||||
|
||||
+1
-2
@@ -88,7 +88,6 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
||||
final MonetaryCurrency currency,
|
||||
final List<LoanRepaymentScheduleInstallment> 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
|
||||
|
||||
+6
-8
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -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 {
|
||||
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+9
-10
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -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(
|
||||
|
||||
@@ -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<AppUser, Long> {
|
||||
|
||||
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<AppUser, Long> {
|
||||
}
|
||||
|
||||
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<AppUser, Long> {
|
||||
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<AppUser, Long> {
|
||||
|
||||
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<AppUser, Long> {
|
||||
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<AppUser, Long> {
|
||||
return regenerationRequired;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public LoanPayoffSummary getPayoffSummaryOn(
|
||||
final LocalDate projectedPayoffDate) {
|
||||
|
||||
@@ -1246,6 +1310,10 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
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<AppUser, Long> {
|
||||
return cumulativePaid;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Money calculateRebateWhenPaidInFullOn(final LocalDate paidInFullDate) {
|
||||
|
||||
Money loanPrincipal = this.loanRepaymentScheduleDetail.getPrincipal();
|
||||
@@ -1290,8 +1359,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
Money cumulativeInterest = Money.zero(loanCurrency());
|
||||
|
||||
for (LoanRepaymentScheduleInstallment scheduledRepayment : this.repaymentScheduleInstallments) {
|
||||
cumulativeInterest = cumulativeInterest.plus(scheduledRepayment
|
||||
.getInterest(loanCurrency()));
|
||||
cumulativeInterest = cumulativeInterest.plus(scheduledRepayment.getInterest(loanCurrency()));
|
||||
}
|
||||
|
||||
return cumulativeInterest;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+3
-15
@@ -43,9 +43,6 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@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<AppUser, Long> {
|
||||
*
|
||||
* 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<AppUser, Long> {
|
||||
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<AppUser, Long> {
|
||||
public void resetDerivedComponents() {
|
||||
this.principalPortion = null;
|
||||
this.interestPortion = null;
|
||||
this.interestWaivedPortion = null;
|
||||
this.chargesPortion = null;
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -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) {
|
||||
|
||||
|
||||
+19
-13
@@ -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
|
||||
|
||||
+3
@@ -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);
|
||||
|
||||
+31
-4
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-7
@@ -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(
|
||||
|
||||
+2
-6
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user