mifosx-61: support waive of interest along with loan write off capability. refactor loanRepayments as transactions on api.
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
alter table m_loan_repayment_schedule add column principal_writtenoff_derived decimal(19,6) DEFAULT NULL after principal_completed_derived;
|
||||||
|
alter table m_loan_repayment_schedule add column interest_writtenoff_derived decimal(19,6) DEFAULT NULL after interest_completed_derived;
|
||||||
|
|
||||||
+44
-6
@@ -14,42 +14,57 @@ import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
|||||||
* <li>repayment schedule - the principal due, outstanding balance and cost of loan items such as interest and charges</li>
|
* <li>repayment schedule - the principal due, outstanding balance and cost of loan items such as interest and charges</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
// TODO - KW - rename file
|
public class LoanScheduleData {
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class LoanScheduleNewData {
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final Integer loanTermInDays;
|
private final Integer loanTermInDays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currency associated with all monetary values in loan schedule.
|
* The currency associated with all monetary values in loan schedule.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final CurrencyData currency;
|
private final CurrencyData currency;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cumulative total of all money (principal) disbursed to the loan applicant.
|
* The cumulative total of all money (principal) disbursed to the loan applicant.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativePrincipalDisbursed;
|
private final BigDecimal cumulativePrincipalDisbursed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cumulative total of all <code>principalDue</code> for each period of loan schedule. (originalPrincipal)
|
* The cumulative total of all <code>principalDue</code> for each period of loan schedule. (originalPrincipal)
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativePrincipalDue;
|
private final BigDecimal cumulativePrincipalDue;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativePrincipalPaid;
|
private final BigDecimal cumulativePrincipalPaid;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final BigDecimal cumulativePrincipalWrittenOff;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativePrincipalOutstanding;
|
private final BigDecimal cumulativePrincipalOutstanding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cumulative total of interest expected on any principal disbursed. (originalInterest)
|
* The cumulative total of interest expected on any principal disbursed. (originalInterest)
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativeInterestExpected;
|
private final BigDecimal cumulativeInterestExpected;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativeInterestPaid;
|
private final BigDecimal cumulativeInterestPaid;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativeInterestWaived;
|
private final BigDecimal cumulativeInterestWaived;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final BigDecimal cumulativeInterestWrittenOff;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativeInterestOutstanding;
|
private final BigDecimal cumulativeInterestOutstanding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cumulative total of all charges applied on the loan to date.
|
* The cumulative total of all charges applied on the loan to date.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativeChargesToDate;
|
private final BigDecimal cumulativeChargesToDate;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativeChargesPaid;
|
private final BigDecimal cumulativeChargesPaid;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal cumulativeChargesOutstanding;
|
private final BigDecimal cumulativeChargesOutstanding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,23 +75,33 @@ public class LoanScheduleNewData {
|
|||||||
* <li>Charges (fees and penalties)</li>
|
* <li>Charges (fees and penalties)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalCostOfLoan;
|
private final BigDecimal totalCostOfLoan;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sum of <code>principalDisbursed</code> and <code>totalCostOfLoan</code>. (originalTotal)
|
* The sum of <code>principalDisbursed</code> and <code>totalCostOfLoan</code>. (originalTotal)
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalExpectedRepayment;
|
private final BigDecimal totalExpectedRepayment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cumulative sum of all repayments to date. (totalPaid)
|
* The cumulative sum of all repayments to date. (totalPaid)
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalPaidToDate;
|
private final BigDecimal totalPaidToDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cumulative sum of all waivers to date.
|
* The cumulative sum of all waivers to date.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalWaivedToDate;
|
private final BigDecimal totalWaivedToDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cumulative sum of all waivers to date.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final BigDecimal totalWrittenOffToDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cumulative sum of all principal, interest & charges outstanding.
|
* The cumulative sum of all principal, interest & charges outstanding.
|
||||||
*/
|
*/
|
||||||
@@ -87,6 +112,7 @@ public class LoanScheduleNewData {
|
|||||||
*
|
*
|
||||||
* Different to outstanding as arrears is based on whether a portion of the total outstanding is late and above any tolerance setting.
|
* Different to outstanding as arrears is based on whether a portion of the total outstanding is late and above any tolerance setting.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalInArrears;
|
private final BigDecimal totalInArrears;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,15 +122,17 @@ public class LoanScheduleNewData {
|
|||||||
*/
|
*/
|
||||||
private final Collection<LoanSchedulePeriodData> periods;
|
private final Collection<LoanSchedulePeriodData> periods;
|
||||||
|
|
||||||
public LoanScheduleNewData() {
|
public LoanScheduleData() {
|
||||||
this.cumulativePrincipalDisbursed = null;
|
this.cumulativePrincipalDisbursed = null;
|
||||||
this.cumulativePrincipalPaid = null;
|
this.cumulativePrincipalPaid = null;
|
||||||
|
this.cumulativePrincipalWrittenOff = null;
|
||||||
this.cumulativePrincipalDue = null;
|
this.cumulativePrincipalDue = null;
|
||||||
this.cumulativePrincipalOutstanding = null;
|
this.cumulativePrincipalOutstanding = null;
|
||||||
|
|
||||||
this.cumulativeInterestExpected = null;
|
this.cumulativeInterestExpected = null;
|
||||||
this.cumulativeInterestPaid = null;
|
this.cumulativeInterestPaid = null;
|
||||||
this.cumulativeInterestWaived = null;
|
this.cumulativeInterestWaived = null;
|
||||||
|
this.cumulativeInterestWrittenOff = null;
|
||||||
this.cumulativeInterestOutstanding = null;
|
this.cumulativeInterestOutstanding = null;
|
||||||
|
|
||||||
this.cumulativeChargesToDate = null;
|
this.cumulativeChargesToDate = null;
|
||||||
@@ -116,6 +144,7 @@ public class LoanScheduleNewData {
|
|||||||
this.totalExpectedRepayment = null;
|
this.totalExpectedRepayment = null;
|
||||||
this.totalPaidToDate = null;
|
this.totalPaidToDate = null;
|
||||||
this.totalWaivedToDate = null;
|
this.totalWaivedToDate = null;
|
||||||
|
this.totalWrittenOffToDate = null;
|
||||||
this.totalOutstanding = null;
|
this.totalOutstanding = null;
|
||||||
this.totalInArrears = null;
|
this.totalInArrears = null;
|
||||||
|
|
||||||
@@ -124,7 +153,7 @@ public class LoanScheduleNewData {
|
|||||||
this.loanTermInDays = null;
|
this.loanTermInDays = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanScheduleNewData(
|
public LoanScheduleData(
|
||||||
final CurrencyData currency,
|
final CurrencyData currency,
|
||||||
final Collection<LoanSchedulePeriodData> periods,
|
final Collection<LoanSchedulePeriodData> periods,
|
||||||
final Integer loanTermInDays,
|
final Integer loanTermInDays,
|
||||||
@@ -141,11 +170,13 @@ public class LoanScheduleNewData {
|
|||||||
this.cumulativePrincipalDisbursed = cumulativePrincipalDisbursed;
|
this.cumulativePrincipalDisbursed = cumulativePrincipalDisbursed;
|
||||||
this.cumulativePrincipalDue = cumulativePrincipalDue;
|
this.cumulativePrincipalDue = cumulativePrincipalDue;
|
||||||
this.cumulativePrincipalPaid = null;
|
this.cumulativePrincipalPaid = null;
|
||||||
|
this.cumulativePrincipalWrittenOff = null;
|
||||||
this.cumulativePrincipalOutstanding = cumulativePrincipalOutstanding;
|
this.cumulativePrincipalOutstanding = cumulativePrincipalOutstanding;
|
||||||
|
|
||||||
this.cumulativeInterestExpected = cumulativeInterestExpected;
|
this.cumulativeInterestExpected = cumulativeInterestExpected;
|
||||||
this.cumulativeInterestPaid = null;
|
this.cumulativeInterestPaid = null;
|
||||||
this.cumulativeInterestWaived = null;
|
this.cumulativeInterestWaived = null;
|
||||||
|
this.cumulativeInterestWrittenOff = null;
|
||||||
this.cumulativeInterestOutstanding = null;
|
this.cumulativeInterestOutstanding = null;
|
||||||
|
|
||||||
this.cumulativeChargesToDate = cumulativeChargesToDate;
|
this.cumulativeChargesToDate = cumulativeChargesToDate;
|
||||||
@@ -163,6 +194,7 @@ public class LoanScheduleNewData {
|
|||||||
this.totalExpectedRepayment = totalExpectedRepayment;
|
this.totalExpectedRepayment = totalExpectedRepayment;
|
||||||
this.totalPaidToDate = BigDecimal.ZERO;
|
this.totalPaidToDate = BigDecimal.ZERO;
|
||||||
this.totalWaivedToDate = BigDecimal.ZERO;
|
this.totalWaivedToDate = BigDecimal.ZERO;
|
||||||
|
this.totalWrittenOffToDate = BigDecimal.ZERO;
|
||||||
this.totalOutstanding = totalExpectedRepayment;
|
this.totalOutstanding = totalExpectedRepayment;
|
||||||
this.totalInArrears = BigDecimal.ZERO;
|
this.totalInArrears = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
@@ -170,15 +202,17 @@ public class LoanScheduleNewData {
|
|||||||
/*
|
/*
|
||||||
* Used when fully populating
|
* Used when fully populating
|
||||||
*/
|
*/
|
||||||
public LoanScheduleNewData(final CurrencyData currency, final Collection<LoanSchedulePeriodData> periods,
|
public LoanScheduleData(final CurrencyData currency, final Collection<LoanSchedulePeriodData> periods,
|
||||||
final Integer loanTermInDays,
|
final Integer loanTermInDays,
|
||||||
final BigDecimal cumulativePrincipalDisbursed,
|
final BigDecimal cumulativePrincipalDisbursed,
|
||||||
final BigDecimal cumulativePrincipalDue,
|
final BigDecimal cumulativePrincipalDue,
|
||||||
final BigDecimal cumulativePrincipalPaid,
|
final BigDecimal cumulativePrincipalPaid,
|
||||||
|
final BigDecimal cumulativePrincipalWrittenOff,
|
||||||
final BigDecimal cumulativePrincipalOutstanding,
|
final BigDecimal cumulativePrincipalOutstanding,
|
||||||
final BigDecimal cumulativeInterestExpected,
|
final BigDecimal cumulativeInterestExpected,
|
||||||
final BigDecimal cumulativeInterestPaid,
|
final BigDecimal cumulativeInterestPaid,
|
||||||
final BigDecimal cumulativeInterestWaived,
|
final BigDecimal cumulativeInterestWaived,
|
||||||
|
final BigDecimal cumulativeInterestWrittenOff,
|
||||||
final BigDecimal cumulativeInterestOutstanding,
|
final BigDecimal cumulativeInterestOutstanding,
|
||||||
final BigDecimal cumulativeChargesToDate,
|
final BigDecimal cumulativeChargesToDate,
|
||||||
final BigDecimal cumulativeChargesPaid,
|
final BigDecimal cumulativeChargesPaid,
|
||||||
@@ -187,6 +221,7 @@ public class LoanScheduleNewData {
|
|||||||
final BigDecimal totalExpectedRepayment,
|
final BigDecimal totalExpectedRepayment,
|
||||||
final BigDecimal totalPaidToDate,
|
final BigDecimal totalPaidToDate,
|
||||||
final BigDecimal totalWaivedToDate,
|
final BigDecimal totalWaivedToDate,
|
||||||
|
final BigDecimal totalWrittenOffToDate,
|
||||||
final BigDecimal totalOutstanding,
|
final BigDecimal totalOutstanding,
|
||||||
final BigDecimal totalInArrears) {
|
final BigDecimal totalInArrears) {
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
@@ -196,9 +231,11 @@ public class LoanScheduleNewData {
|
|||||||
this.cumulativePrincipalDisbursed = cumulativePrincipalDisbursed;
|
this.cumulativePrincipalDisbursed = cumulativePrincipalDisbursed;
|
||||||
this.cumulativePrincipalDue = cumulativePrincipalDue;
|
this.cumulativePrincipalDue = cumulativePrincipalDue;
|
||||||
this.cumulativePrincipalPaid = cumulativePrincipalPaid;
|
this.cumulativePrincipalPaid = cumulativePrincipalPaid;
|
||||||
|
this.cumulativePrincipalWrittenOff = cumulativePrincipalWrittenOff;
|
||||||
this.cumulativePrincipalOutstanding = cumulativePrincipalOutstanding;
|
this.cumulativePrincipalOutstanding = cumulativePrincipalOutstanding;
|
||||||
this.cumulativeInterestExpected = cumulativeInterestExpected;
|
this.cumulativeInterestExpected = cumulativeInterestExpected;
|
||||||
this.cumulativeInterestPaid = cumulativeInterestPaid;
|
this.cumulativeInterestPaid = cumulativeInterestPaid;
|
||||||
|
this.cumulativeInterestWrittenOff = cumulativeInterestWrittenOff;
|
||||||
this.cumulativeInterestWaived = cumulativeInterestWaived;
|
this.cumulativeInterestWaived = cumulativeInterestWaived;
|
||||||
this.cumulativeInterestOutstanding = cumulativeInterestOutstanding;
|
this.cumulativeInterestOutstanding = cumulativeInterestOutstanding;
|
||||||
this.cumulativeChargesToDate = cumulativeChargesToDate;
|
this.cumulativeChargesToDate = cumulativeChargesToDate;
|
||||||
@@ -208,6 +245,7 @@ public class LoanScheduleNewData {
|
|||||||
this.totalExpectedRepayment = totalExpectedRepayment;
|
this.totalExpectedRepayment = totalExpectedRepayment;
|
||||||
this.totalPaidToDate = totalPaidToDate;
|
this.totalPaidToDate = totalPaidToDate;
|
||||||
this.totalWaivedToDate = totalWaivedToDate;
|
this.totalWaivedToDate = totalWaivedToDate;
|
||||||
|
this.totalWrittenOffToDate = totalWrittenOffToDate;
|
||||||
this.totalOutstanding = totalOutstanding;
|
this.totalOutstanding = totalOutstanding;
|
||||||
this.totalInArrears = totalInArrears;
|
this.totalInArrears = totalInArrears;
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,6 @@ import org.mifosng.platform.api.data.LoanBasicDetailsData;
|
|||||||
import org.mifosng.platform.api.data.LoanChargeData;
|
import org.mifosng.platform.api.data.LoanChargeData;
|
||||||
import org.mifosng.platform.api.data.LoanPermissionData;
|
import org.mifosng.platform.api.data.LoanPermissionData;
|
||||||
import org.mifosng.platform.api.data.LoanProductLookup;
|
import org.mifosng.platform.api.data.LoanProductLookup;
|
||||||
import org.mifosng.platform.api.data.LoanRepaymentTransactionData;
|
|
||||||
import org.mifosng.platform.api.data.LoanTransactionData;
|
import org.mifosng.platform.api.data.LoanTransactionData;
|
||||||
import org.mifosng.platform.api.data.LoanTransactionNewData;
|
import org.mifosng.platform.api.data.LoanTransactionNewData;
|
||||||
import org.mifosng.platform.api.data.MoneyData;
|
import org.mifosng.platform.api.data.MoneyData;
|
||||||
@@ -191,8 +190,8 @@ public class LoansApiResource {
|
|||||||
LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService.retrieveLoanAccountDetails(loanId);
|
LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService.retrieveLoanAccountDetails(loanId);
|
||||||
|
|
||||||
int loanRepaymentsCount = 0;
|
int loanRepaymentsCount = 0;
|
||||||
Collection<LoanRepaymentTransactionData> loanRepayments = null;
|
Collection<LoanTransactionNewData> loanRepayments = null;
|
||||||
LoanScheduleNewData repaymentSchedule = null;
|
LoanScheduleData repaymentSchedule = null;
|
||||||
LoanPermissionData permissions = null;
|
LoanPermissionData permissions = null;
|
||||||
Collection<LoanChargeData> charges = null;
|
Collection<LoanChargeData> charges = null;
|
||||||
|
|
||||||
@@ -201,18 +200,21 @@ public class LoansApiResource {
|
|||||||
if (!associationParameters.isEmpty()) {
|
if (!associationParameters.isEmpty()) {
|
||||||
|
|
||||||
if (associationParameters.contains("all")) {
|
if (associationParameters.contains("all")) {
|
||||||
responseParameters.addAll(Arrays.asList("repaymentSchedule", "loanRepayments", "permissions", "convenienceData", "charges"));
|
responseParameters.addAll(Arrays.asList("repaymentSchedule", "transactions", "permissions", "convenienceData", "charges"));
|
||||||
} else {
|
} else {
|
||||||
responseParameters.addAll(associationParameters);
|
responseParameters.addAll(associationParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<LoanRepaymentTransactionData> currentLoanRepayments = this.loanReadPlatformService.retrieveLoanPayments(loanId);
|
if (responseParameters.contains("transactions")) {
|
||||||
if (!CollectionUtils.isEmpty(currentLoanRepayments)) {
|
Collection<LoanTransactionNewData> currentLoanRepayments = this.loanReadPlatformService.retrieveLoanTransactions(loanId);
|
||||||
loanRepayments = currentLoanRepayments;
|
if (!CollectionUtils.isEmpty(currentLoanRepayments)) {
|
||||||
loanRepaymentsCount = loanRepayments.size();
|
loanRepayments = currentLoanRepayments;
|
||||||
|
loanRepaymentsCount = loanRepayments.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseParameters.contains("repaymentSchedule")) {
|
if (responseParameters.contains("repaymentSchedule")) {
|
||||||
|
|
||||||
DisbursementData singleDisbursement = loanBasicDetails.toDisburementData();
|
DisbursementData singleDisbursement = loanBasicDetails.toDisburementData();
|
||||||
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, loanBasicDetails.getCurrency(),
|
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, loanBasicDetails.getCurrency(),
|
||||||
singleDisbursement, loanBasicDetails.getTotalDisbursementCharges(), loanBasicDetails.getInArrearsTolerance());
|
singleDisbursement, loanBasicDetails.getTotalDisbursementCharges(), loanBasicDetails.getInArrearsTolerance());
|
||||||
@@ -275,7 +277,8 @@ public class LoansApiResource {
|
|||||||
repaymentSchedule, loanRepayments, permissions, charges,
|
repaymentSchedule, loanRepayments, permissions, charges,
|
||||||
productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
|
productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
|
||||||
repaymentStrategyOptions, interestRateFrequencyTypeOptions,
|
repaymentStrategyOptions, interestRateFrequencyTypeOptions,
|
||||||
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers);
|
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
|
||||||
|
fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers);
|
||||||
|
|
||||||
return this.apiJsonSerializerService.serializeLoanAccountDataToJson(prettyPrint, responseParameters, loanAccount);
|
return this.apiJsonSerializerService.serializeLoanAccountDataToJson(prettyPrint, responseParameters, loanAccount);
|
||||||
}
|
}
|
||||||
@@ -302,7 +305,7 @@ public class LoansApiResource {
|
|||||||
|
|
||||||
private String calculateLoanSchedule(final UriInfo uriInfo, final CalculateLoanScheduleCommand command) {
|
private String calculateLoanSchedule(final UriInfo uriInfo, final CalculateLoanScheduleCommand command) {
|
||||||
|
|
||||||
final LoanScheduleNewData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(command);
|
final LoanScheduleData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(command);
|
||||||
|
|
||||||
final Set<String> typicalLoanScheduleResponseParameters = new HashSet<String>(
|
final Set<String> typicalLoanScheduleResponseParameters = new HashSet<String>(
|
||||||
Arrays.asList("periods", "cumulativePrincipalDisbursed"));
|
Arrays.asList("periods", "cumulativePrincipalDisbursed"));
|
||||||
@@ -406,26 +409,24 @@ public class LoansApiResource {
|
|||||||
@QueryParam("command") final String commandParam,
|
@QueryParam("command") final String commandParam,
|
||||||
final String jsonRequestBody) {
|
final String jsonRequestBody) {
|
||||||
|
|
||||||
final LoanTransactionCommand command = this.apiDataConversionService
|
final LoanTransactionCommand command = this.apiDataConversionService.convertJsonToLoanTransactionCommand(loanId, jsonRequestBody);
|
||||||
.convertJsonToLoanTransactionCommand(loanId, jsonRequestBody);
|
|
||||||
|
|
||||||
Response response = null;
|
|
||||||
|
|
||||||
|
EntityIdentifier identifier = null;
|
||||||
if (is(commandParam, "repayment")) {
|
if (is(commandParam, "repayment")) {
|
||||||
EntityIdentifier identifier = this.loanWritePlatformService
|
identifier = this.loanWritePlatformService.makeLoanRepayment(command);
|
||||||
.makeLoanRepayment(command);
|
|
||||||
response = Response.ok().entity(identifier).build();
|
|
||||||
} else if (is(commandParam, "waiveinterest")) {
|
} else if (is(commandParam, "waiveinterest")) {
|
||||||
EntityIdentifier identifier = this.loanWritePlatformService
|
identifier = this.loanWritePlatformService.waiveInterestOnLoan(command);
|
||||||
.waiveInterestOnLoan(command);
|
} else if (is(commandParam, "writeoff")) {
|
||||||
response = Response.ok().entity(identifier).build();
|
identifier = this.loanWritePlatformService.writeOff(command);
|
||||||
|
} else if (is(commandParam, "closeasrescheduled")) {
|
||||||
|
identifier = this.loanWritePlatformService.closeAsRescheduled(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response == null) {
|
if (identifier == null) {
|
||||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return Response.ok().entity(identifier).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@@ -440,8 +441,8 @@ public class LoansApiResource {
|
|||||||
LoanTransactionData transactionData = null;
|
LoanTransactionData transactionData = null;
|
||||||
if (is(commandParam, "repayment")) {
|
if (is(commandParam, "repayment")) {
|
||||||
Set<String> typicalResponseParameters = new HashSet<String>(
|
Set<String> typicalResponseParameters = new HashSet<String>(
|
||||||
Arrays.asList("id", "transactionType", "date", "principal", "interest", "total", "totalWaived", "overpaid")
|
Arrays.asList("id", "transactionType", "date", "principal",
|
||||||
);
|
"interest", "total", "totalWaived", "overpaid"));
|
||||||
|
|
||||||
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
|
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||||
if (responseParameters.isEmpty()) {
|
if (responseParameters.isEmpty()) {
|
||||||
@@ -460,7 +461,29 @@ public class LoansApiResource {
|
|||||||
}
|
}
|
||||||
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
||||||
|
|
||||||
LoanTransactionNewData newTransactionData = this.loanReadPlatformService.retrieveNewLoanWaiveInterestDetails(loanId);
|
final LoanTransactionNewData newTransactionData = this.loanReadPlatformService.retrieveNewLoanWaiveInterestDetails(loanId);
|
||||||
|
return this.apiJsonSerializerService.serializeLoanTransactionDataToJson(prettyPrint, responseParameters, newTransactionData);
|
||||||
|
} else if (is(commandParam, "writeoff")) {
|
||||||
|
final Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "type", "date", "currency", "amount"));
|
||||||
|
|
||||||
|
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 if (is(commandParam, "closeasrescheduled")) {
|
||||||
|
final Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "type", "date", "currency", "amount"));
|
||||||
|
|
||||||
|
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);
|
return this.apiJsonSerializerService.serializeLoanTransactionDataToJson(prettyPrint, responseParameters, newTransactionData);
|
||||||
} else {
|
} else {
|
||||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object representing loan account data.
|
* Immutable data object representing loan account data.
|
||||||
@@ -55,8 +55,8 @@ public class LoanAccountData {
|
|||||||
private final LocalDate lifeCycleStatusDate;
|
private final LocalDate lifeCycleStatusDate;
|
||||||
|
|
||||||
// associations
|
// associations
|
||||||
private final LoanScheduleNewData repaymentSchedule;
|
private final LoanScheduleData repaymentSchedule;
|
||||||
private final Collection<LoanRepaymentTransactionData> loanRepayments;
|
private final Collection<LoanTransactionNewData> transactions;
|
||||||
private final Collection<LoanChargeData> charges;
|
private final Collection<LoanChargeData> charges;
|
||||||
private final LoanPermissionData permissions;
|
private final LoanPermissionData permissions;
|
||||||
private final LoanConvenienceData convenienceData;
|
private final LoanConvenienceData convenienceData;
|
||||||
@@ -78,8 +78,8 @@ public class LoanAccountData {
|
|||||||
public LoanAccountData(
|
public LoanAccountData(
|
||||||
final LoanBasicDetailsData basicDetails,
|
final LoanBasicDetailsData basicDetails,
|
||||||
final boolean convenienceDataRequired,
|
final boolean convenienceDataRequired,
|
||||||
final LoanScheduleNewData repaymentSchedule,
|
final LoanScheduleData repaymentSchedule,
|
||||||
final Collection<LoanRepaymentTransactionData> loanRepayments,
|
final Collection<LoanTransactionNewData> transactions,
|
||||||
final LoanPermissionData permissions,
|
final LoanPermissionData permissions,
|
||||||
final Collection<LoanChargeData> charges,
|
final Collection<LoanChargeData> charges,
|
||||||
final Collection<LoanProductLookup> productOptions,
|
final Collection<LoanProductLookup> productOptions,
|
||||||
@@ -95,7 +95,7 @@ public class LoanAccountData {
|
|||||||
final ChargeData chargeTemplate,
|
final ChargeData chargeTemplate,
|
||||||
final Collection<StaffData> loanOfficerOptions) {
|
final Collection<StaffData> loanOfficerOptions) {
|
||||||
this.repaymentSchedule = repaymentSchedule;
|
this.repaymentSchedule = repaymentSchedule;
|
||||||
this.loanRepayments = loanRepayments;
|
this.transactions = transactions;
|
||||||
this.permissions = permissions;
|
this.permissions = permissions;
|
||||||
this.charges = charges;
|
this.charges = charges;
|
||||||
this.productOptions = productOptions;
|
this.productOptions = productOptions;
|
||||||
|
|||||||
-59
@@ -1,59 +0,0 @@
|
|||||||
package org.mifosng.platform.api.data;
|
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This data object replaces {@link LoanTransactionData}.
|
|
||||||
*/
|
|
||||||
public class LoanRepaymentTransactionData {
|
|
||||||
|
|
||||||
private Long id;
|
|
||||||
private EnumOptionData transactionType;
|
|
||||||
private LocalDate date;
|
|
||||||
private MoneyData total;
|
|
||||||
|
|
||||||
public LoanRepaymentTransactionData() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoanRepaymentTransactionData(Long id, EnumOptionData transactionType,
|
|
||||||
final LocalDate date, final MoneyData total) {
|
|
||||||
this.id = id;
|
|
||||||
this.transactionType = transactionType;
|
|
||||||
this.date = date;
|
|
||||||
this.total = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EnumOptionData getTransactionType() {
|
|
||||||
return transactionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTransactionType(EnumOptionData transactionType) {
|
|
||||||
this.transactionType = transactionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalDate getDate() {
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDate(LocalDate date) {
|
|
||||||
this.date = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MoneyData getTotal() {
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTotal(MoneyData total) {
|
|
||||||
this.total = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+41
-9
@@ -9,7 +9,6 @@ import org.joda.time.LocalDate;
|
|||||||
* Immutable data object that represents a period of a loan schedule.
|
* Immutable data object that represents a period of a loan schedule.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class LoanSchedulePeriodData {
|
public class LoanSchedulePeriodData {
|
||||||
|
|
||||||
private final Integer period;
|
private final Integer period;
|
||||||
@@ -17,26 +16,37 @@ public class LoanSchedulePeriodData {
|
|||||||
private final LocalDate dueDate;
|
private final LocalDate dueDate;
|
||||||
private final Integer daysInPeriod;
|
private final Integer daysInPeriod;
|
||||||
private final BigDecimal principalDisbursed;
|
private final BigDecimal principalDisbursed;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal principalOriginalDue;
|
private final BigDecimal principalOriginalDue;
|
||||||
private final BigDecimal principalDue;
|
private final BigDecimal principalDue;
|
||||||
private final BigDecimal principalPaid;
|
private final BigDecimal principalPaid;
|
||||||
|
private final BigDecimal principalWrittenOff;
|
||||||
private final BigDecimal principalOutstanding;
|
private final BigDecimal principalOutstanding;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal principalLoanBalanceOutstanding;
|
private final BigDecimal principalLoanBalanceOutstanding;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal interestOriginalDue;
|
private final BigDecimal interestOriginalDue;
|
||||||
private final BigDecimal interestDue;
|
private final BigDecimal interestDue;
|
||||||
private final BigDecimal interestPaid;
|
private final BigDecimal interestPaid;
|
||||||
private final BigDecimal interestWaived;
|
private final BigDecimal interestWaived;
|
||||||
|
private final BigDecimal interestWrittenOff;
|
||||||
private final BigDecimal interestOutstanding;
|
private final BigDecimal interestOutstanding;
|
||||||
|
|
||||||
private final BigDecimal chargesDue;
|
private final BigDecimal chargesDue;
|
||||||
private final BigDecimal chargesPaid;
|
private final BigDecimal chargesPaid;
|
||||||
private final BigDecimal chargesOutstanding;
|
private final BigDecimal chargesOutstanding;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalOriginalDueForPeriod;
|
private final BigDecimal totalOriginalDueForPeriod;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalDueForPeriod;
|
private final BigDecimal totalDueForPeriod;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalPaidForPeriod;
|
private final BigDecimal totalPaidForPeriod;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final BigDecimal totalWaivedForPeriod;
|
private final BigDecimal totalWaivedForPeriod;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final BigDecimal totalWrittenOffForPeriod;
|
||||||
private final BigDecimal totalOutstandingForPeriod;
|
private final BigDecimal totalOutstandingForPeriod;
|
||||||
private final BigDecimal totalOverdue;
|
private final BigDecimal totalOverdue;
|
||||||
|
|
||||||
@@ -54,32 +64,34 @@ public class LoanSchedulePeriodData {
|
|||||||
final LocalDate fromDate, final LocalDate dueDate, final BigDecimal principalDue,
|
final LocalDate fromDate, final LocalDate dueDate, final BigDecimal principalDue,
|
||||||
final BigDecimal principalOutstanding, final BigDecimal interestDueOnPrincipalOutstanding, final BigDecimal totalDueForPeriod) {
|
final BigDecimal principalOutstanding, final BigDecimal interestDueOnPrincipalOutstanding, final BigDecimal totalDueForPeriod) {
|
||||||
|
|
||||||
BigDecimal principalDisbursed = null;
|
|
||||||
return new LoanSchedulePeriodData(periodNumber, fromDate, dueDate, principalDue, principalOutstanding, interestDueOnPrincipalOutstanding, totalDueForPeriod);
|
return new LoanSchedulePeriodData(periodNumber, fromDate, dueDate, principalDue, principalOutstanding, interestDueOnPrincipalOutstanding, totalDueForPeriod);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoanSchedulePeriodData repaymentPeriodWithPayments(
|
public static LoanSchedulePeriodData repaymentPeriodWithPayments(
|
||||||
final Long loanId,
|
@SuppressWarnings("unused") final Long loanId,
|
||||||
final Integer periodNumber,
|
final Integer periodNumber,
|
||||||
final LocalDate fromDate,
|
final LocalDate fromDate,
|
||||||
final LocalDate dueDate,
|
final LocalDate dueDate,
|
||||||
final BigDecimal principalOriginalDue,
|
final BigDecimal principalOriginalDue,
|
||||||
final BigDecimal principalPaid,
|
final BigDecimal principalPaid,
|
||||||
|
final BigDecimal principalWrittenOff,
|
||||||
final BigDecimal principalOutstanding,
|
final BigDecimal principalOutstanding,
|
||||||
final BigDecimal outstandingPrincipalBalanceOfLoan,
|
final BigDecimal outstandingPrincipalBalanceOfLoan,
|
||||||
final BigDecimal interestDueOnPrincipalOutstanding,
|
final BigDecimal interestDueOnPrincipalOutstanding,
|
||||||
final BigDecimal interestPaid,
|
final BigDecimal interestPaid,
|
||||||
final BigDecimal interestWaived,
|
final BigDecimal interestWaived,
|
||||||
|
final BigDecimal interestWrittenOff,
|
||||||
final BigDecimal interestOutstanding,
|
final BigDecimal interestOutstanding,
|
||||||
final BigDecimal totalDueForPeriod,
|
final BigDecimal totalDueForPeriod,
|
||||||
final BigDecimal totalPaid,
|
final BigDecimal totalPaid,
|
||||||
final BigDecimal totalWaived,
|
final BigDecimal totalWaived,
|
||||||
|
final BigDecimal totalWrittenOff,
|
||||||
final BigDecimal totalOutstanding) {
|
final BigDecimal totalOutstanding) {
|
||||||
|
|
||||||
return new LoanSchedulePeriodData(periodNumber, fromDate, dueDate,
|
return new LoanSchedulePeriodData(periodNumber, fromDate, dueDate,
|
||||||
principalOriginalDue, principalPaid, principalOutstanding, outstandingPrincipalBalanceOfLoan,
|
principalOriginalDue, principalPaid, principalWrittenOff, principalOutstanding, outstandingPrincipalBalanceOfLoan,
|
||||||
interestDueOnPrincipalOutstanding, interestPaid, interestWaived, interestOutstanding,
|
interestDueOnPrincipalOutstanding, interestPaid, interestWaived, interestWrittenOff, interestOutstanding,
|
||||||
totalDueForPeriod, totalPaid, totalWaived, totalOutstanding);
|
totalDueForPeriod, totalPaid, totalWaived, totalWrittenOff, totalOutstanding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -96,7 +108,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.fromDate = fromDate;
|
this.fromDate = fromDate;
|
||||||
this.dueDate = dueDate;
|
this.dueDate = dueDate;
|
||||||
if (fromDate != null) {
|
if (fromDate != null) {
|
||||||
this.daysInPeriod = Days.daysBetween(fromDate, dueDate).getDays();
|
this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays();
|
||||||
} else {
|
} else {
|
||||||
this.daysInPeriod = null;
|
this.daysInPeriod = null;
|
||||||
}
|
}
|
||||||
@@ -104,6 +116,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.principalOriginalDue = null;
|
this.principalOriginalDue = null;
|
||||||
this.principalDue = null;
|
this.principalDue = null;
|
||||||
this.principalPaid = null;
|
this.principalPaid = null;
|
||||||
|
this.principalWrittenOff = null;
|
||||||
this.principalOutstanding = null;
|
this.principalOutstanding = null;
|
||||||
this.principalLoanBalanceOutstanding = principalDisbursed;
|
this.principalLoanBalanceOutstanding = principalDisbursed;
|
||||||
|
|
||||||
@@ -111,6 +124,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.interestDue = null;
|
this.interestDue = null;
|
||||||
this.interestPaid = null;
|
this.interestPaid = null;
|
||||||
this.interestWaived = null;
|
this.interestWaived = null;
|
||||||
|
this.interestWrittenOff = null;
|
||||||
this.interestOutstanding = null;
|
this.interestOutstanding = null;
|
||||||
|
|
||||||
this.chargesDue = chargesDueAtTimeOfDisbursement;
|
this.chargesDue = chargesDueAtTimeOfDisbursement;
|
||||||
@@ -126,6 +140,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.totalDueForPeriod = chargesDueAtTimeOfDisbursement;
|
this.totalDueForPeriod = chargesDueAtTimeOfDisbursement;
|
||||||
this.totalPaidForPeriod = this.chargesPaid;
|
this.totalPaidForPeriod = this.chargesPaid;
|
||||||
this.totalWaivedForPeriod = null;
|
this.totalWaivedForPeriod = null;
|
||||||
|
this.totalWrittenOffForPeriod = null;
|
||||||
this.totalOutstandingForPeriod = this.chargesOutstanding;
|
this.totalOutstandingForPeriod = this.chargesOutstanding;
|
||||||
if (dueDate.isBefore(new LocalDate())) {
|
if (dueDate.isBefore(new LocalDate())) {
|
||||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
this.totalOverdue = this.totalOutstandingForPeriod;
|
||||||
@@ -146,7 +161,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.fromDate = fromDate;
|
this.fromDate = fromDate;
|
||||||
this.dueDate = dueDate;
|
this.dueDate = dueDate;
|
||||||
if (fromDate != null) {
|
if (fromDate != null) {
|
||||||
this.daysInPeriod = Days.daysBetween(fromDate, dueDate).getDays();
|
this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays();
|
||||||
} else {
|
} else {
|
||||||
this.daysInPeriod = null;
|
this.daysInPeriod = null;
|
||||||
}
|
}
|
||||||
@@ -154,6 +169,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.principalOriginalDue = principalOriginalDue;
|
this.principalOriginalDue = principalOriginalDue;
|
||||||
this.principalDue = principalOriginalDue;
|
this.principalDue = principalOriginalDue;
|
||||||
this.principalPaid = null;
|
this.principalPaid = null;
|
||||||
|
this.principalWrittenOff = null;
|
||||||
this.principalOutstanding = principalOriginalDue;
|
this.principalOutstanding = principalOriginalDue;
|
||||||
this.principalLoanBalanceOutstanding = principalOutstanding;
|
this.principalLoanBalanceOutstanding = principalOutstanding;
|
||||||
|
|
||||||
@@ -161,6 +177,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.interestDue = interestDueOnPrincipalOutstanding;
|
this.interestDue = interestDueOnPrincipalOutstanding;
|
||||||
this.interestPaid = null;
|
this.interestPaid = null;
|
||||||
this.interestWaived = null;
|
this.interestWaived = null;
|
||||||
|
this.interestWrittenOff = null;
|
||||||
this.interestOutstanding = interestDueOnPrincipalOutstanding;
|
this.interestOutstanding = interestDueOnPrincipalOutstanding;
|
||||||
|
|
||||||
this.chargesDue = BigDecimal.ZERO;
|
this.chargesDue = BigDecimal.ZERO;
|
||||||
@@ -171,6 +188,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.totalDueForPeriod = totalDueForPeriod;
|
this.totalDueForPeriod = totalDueForPeriod;
|
||||||
this.totalPaidForPeriod = BigDecimal.ZERO;
|
this.totalPaidForPeriod = BigDecimal.ZERO;
|
||||||
this.totalWaivedForPeriod = null;
|
this.totalWaivedForPeriod = null;
|
||||||
|
this.totalWrittenOffForPeriod = null;
|
||||||
this.totalOutstandingForPeriod = totalDueForPeriod;
|
this.totalOutstandingForPeriod = totalDueForPeriod;
|
||||||
if (dueDate.isBefore(new LocalDate())) {
|
if (dueDate.isBefore(new LocalDate())) {
|
||||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
this.totalOverdue = this.totalOutstandingForPeriod;
|
||||||
@@ -188,21 +206,24 @@ public class LoanSchedulePeriodData {
|
|||||||
final LocalDate dueDate,
|
final LocalDate dueDate,
|
||||||
final BigDecimal principalOriginalDue,
|
final BigDecimal principalOriginalDue,
|
||||||
final BigDecimal principalPaid,
|
final BigDecimal principalPaid,
|
||||||
|
final BigDecimal principalWrittenOff,
|
||||||
final BigDecimal principalOutstanding,
|
final BigDecimal principalOutstanding,
|
||||||
final BigDecimal principalLoanBalanceOutstanding,
|
final BigDecimal principalLoanBalanceOutstanding,
|
||||||
final BigDecimal interestDueOnPrincipalOutstanding,
|
final BigDecimal interestDueOnPrincipalOutstanding,
|
||||||
final BigDecimal interestPaid,
|
final BigDecimal interestPaid,
|
||||||
final BigDecimal interestWaived,
|
final BigDecimal interestWaived,
|
||||||
|
final BigDecimal interestWrittenOff,
|
||||||
final BigDecimal interestOutstanding,
|
final BigDecimal interestOutstanding,
|
||||||
final BigDecimal totalDueForPeriod,
|
final BigDecimal totalDueForPeriod,
|
||||||
final BigDecimal totalPaid,
|
final BigDecimal totalPaid,
|
||||||
final BigDecimal totalWaived,
|
final BigDecimal totalWaived,
|
||||||
|
final BigDecimal totalWrittenOff,
|
||||||
final BigDecimal totalOutstanding) {
|
final BigDecimal totalOutstanding) {
|
||||||
this.period = periodNumber;
|
this.period = periodNumber;
|
||||||
this.fromDate = fromDate;
|
this.fromDate = fromDate;
|
||||||
this.dueDate = dueDate;
|
this.dueDate = dueDate;
|
||||||
if (fromDate != null) {
|
if (fromDate != null) {
|
||||||
this.daysInPeriod = Days.daysBetween(fromDate, dueDate).getDays();
|
this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays();
|
||||||
} else {
|
} else {
|
||||||
this.daysInPeriod = null;
|
this.daysInPeriod = null;
|
||||||
}
|
}
|
||||||
@@ -210,6 +231,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.principalOriginalDue = principalOriginalDue;
|
this.principalOriginalDue = principalOriginalDue;
|
||||||
this.principalDue = principalOriginalDue;
|
this.principalDue = principalOriginalDue;
|
||||||
this.principalPaid = principalPaid;
|
this.principalPaid = principalPaid;
|
||||||
|
this.principalWrittenOff = principalWrittenOff;
|
||||||
this.principalOutstanding = principalOutstanding;
|
this.principalOutstanding = principalOutstanding;
|
||||||
this.principalLoanBalanceOutstanding = principalLoanBalanceOutstanding;
|
this.principalLoanBalanceOutstanding = principalLoanBalanceOutstanding;
|
||||||
|
|
||||||
@@ -217,6 +239,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.interestDue = interestDueOnPrincipalOutstanding;
|
this.interestDue = interestDueOnPrincipalOutstanding;
|
||||||
this.interestPaid = interestPaid;
|
this.interestPaid = interestPaid;
|
||||||
this.interestWaived = interestWaived;
|
this.interestWaived = interestWaived;
|
||||||
|
this.interestWrittenOff = interestWrittenOff;
|
||||||
this.interestOutstanding = interestOutstanding;
|
this.interestOutstanding = interestOutstanding;
|
||||||
|
|
||||||
this.chargesDue = BigDecimal.ZERO;
|
this.chargesDue = BigDecimal.ZERO;
|
||||||
@@ -227,6 +250,7 @@ public class LoanSchedulePeriodData {
|
|||||||
this.totalDueForPeriod = totalDueForPeriod;
|
this.totalDueForPeriod = totalDueForPeriod;
|
||||||
this.totalPaidForPeriod = totalPaid;
|
this.totalPaidForPeriod = totalPaid;
|
||||||
this.totalWaivedForPeriod = totalWaived;
|
this.totalWaivedForPeriod = totalWaived;
|
||||||
|
this.totalWrittenOffForPeriod = totalWrittenOff;
|
||||||
this.totalOutstandingForPeriod = totalOutstanding;
|
this.totalOutstandingForPeriod = totalOutstanding;
|
||||||
|
|
||||||
if (dueDate.isBefore(new LocalDate())) {
|
if (dueDate.isBefore(new LocalDate())) {
|
||||||
@@ -276,6 +300,10 @@ public class LoanSchedulePeriodData {
|
|||||||
return defaultToZeroIfNull(this.principalPaid);
|
return defaultToZeroIfNull(this.principalPaid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal principalWrittenOff() {
|
||||||
|
return defaultToZeroIfNull(this.principalWrittenOff);
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal principalOutstanding() {
|
public BigDecimal principalOutstanding() {
|
||||||
return defaultToZeroIfNull(this.principalOutstanding);
|
return defaultToZeroIfNull(this.principalOutstanding);
|
||||||
}
|
}
|
||||||
@@ -292,6 +320,10 @@ public class LoanSchedulePeriodData {
|
|||||||
return defaultToZeroIfNull(this.interestWaived);
|
return defaultToZeroIfNull(this.interestWaived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal interestWrittenOff() {
|
||||||
|
return defaultToZeroIfNull(this.interestWrittenOff);
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal interestOutstanding() {
|
public BigDecimal interestOutstanding() {
|
||||||
return defaultToZeroIfNull(this.interestOutstanding);
|
return defaultToZeroIfNull(this.interestOutstanding);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -25,11 +25,13 @@ public class LoanTransactionNewData {
|
|||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
|
|
||||||
public LoanTransactionNewData(
|
public LoanTransactionNewData(
|
||||||
final EnumOptionData transactionsType,
|
final Long id,
|
||||||
|
final EnumOptionData transactionType,
|
||||||
final CurrencyData currency,
|
final CurrencyData currency,
|
||||||
final LocalDate date,
|
final LocalDate date,
|
||||||
final BigDecimal amount) {
|
final BigDecimal amount) {
|
||||||
this.type = transactionsType;
|
this.id = id;
|
||||||
|
this.type = transactionType;
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@ package org.mifosng.platform.api.infrastructure;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.data.AdditionalFieldsSetData;
|
import org.mifosng.platform.api.data.AdditionalFieldsSetData;
|
||||||
import org.mifosng.platform.api.data.AppUserData;
|
import org.mifosng.platform.api.data.AppUserData;
|
||||||
import org.mifosng.platform.api.data.AuthenticatedUserData;
|
import org.mifosng.platform.api.data.AuthenticatedUserData;
|
||||||
@@ -99,7 +99,7 @@ public interface ApiJsonSerializerService {
|
|||||||
|
|
||||||
String serializeNoteDataToJson(boolean prettyPrint, Set<String> responseParameters, NoteData note);
|
String serializeNoteDataToJson(boolean prettyPrint, Set<String> responseParameters, NoteData note);
|
||||||
|
|
||||||
String serializeLoanScheduleDataToJson(boolean prettyPrint, Set<String> responseParameters, LoanScheduleNewData loanSchedule);
|
String serializeLoanScheduleDataToJson(boolean prettyPrint, Set<String> responseParameters, LoanScheduleData loanSchedule);
|
||||||
|
|
||||||
String serializeLoanAccountDataToJson(boolean prettyPrint, Set<String> responseParameters, LoanAccountData loanAccount);
|
String serializeLoanAccountDataToJson(boolean prettyPrint, Set<String> responseParameters, LoanAccountData loanAccount);
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -5,7 +5,7 @@ import java.util.Collection;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.data.AdditionalFieldsSetData;
|
import org.mifosng.platform.api.data.AdditionalFieldsSetData;
|
||||||
import org.mifosng.platform.api.data.AppUserData;
|
import org.mifosng.platform.api.data.AppUserData;
|
||||||
import org.mifosng.platform.api.data.AuthenticatedUserData;
|
import org.mifosng.platform.api.data.AuthenticatedUserData;
|
||||||
@@ -172,7 +172,7 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ
|
|||||||
"closedOnDate", "expectedMaturityDate",
|
"closedOnDate", "expectedMaturityDate",
|
||||||
"status",
|
"status",
|
||||||
"lifeCycleStatusDate", "repaymentSchedule",
|
"lifeCycleStatusDate", "repaymentSchedule",
|
||||||
"loanRepayments", "permissions", "convenienceData", "charges",
|
"transactions", "permissions", "convenienceData", "charges",
|
||||||
"productOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
|
"productOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
|
||||||
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "repaymentStrategyOptions", "chargeOptions",
|
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "repaymentStrategyOptions", "chargeOptions",
|
||||||
"loanOfficerId", "loanOfficerName", "loanOfficerOptions", "chargeTemplate"));
|
"loanOfficerId", "loanOfficerName", "loanOfficerOptions", "chargeTemplate"));
|
||||||
@@ -535,7 +535,7 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String serializeLoanScheduleDataToJson(final boolean prettyPrint, final Set<String> responseParameters, final LoanScheduleNewData loanSchedule) {
|
public String serializeLoanScheduleDataToJson(final boolean prettyPrint, final Set<String> responseParameters, final LoanScheduleData loanSchedule) {
|
||||||
final Gson gsonDeserializer = helper
|
final Gson gsonDeserializer = helper
|
||||||
.createGsonBuilderWithParameterExclusionSerializationStrategy(LOAN_SCHEDULE_DATA_PARAMETERS, prettyPrint, responseParameters);
|
.createGsonBuilderWithParameterExclusionSerializationStrategy(LOAN_SCHEDULE_DATA_PARAMETERS, prettyPrint, responseParameters);
|
||||||
return helper.serializedJsonFrom(gsonDeserializer, loanSchedule);
|
return helper.serializedJsonFrom(gsonDeserializer, loanSchedule);
|
||||||
|
|||||||
+32
-4
@@ -23,7 +23,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void handleTransaction(
|
public void handleTransaction(
|
||||||
final List<LoanTransaction> repaymentsOrWaivers,
|
final List<LoanTransaction> transactionsPostDisbursement,
|
||||||
final MonetaryCurrency currency,
|
final MonetaryCurrency currency,
|
||||||
final List<LoanRepaymentScheduleInstallment> installments) {
|
final List<LoanRepaymentScheduleInstallment> installments) {
|
||||||
|
|
||||||
@@ -31,10 +31,15 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
currentInstallment.resetDerivedComponents();
|
currentInstallment.resetDerivedComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (LoanTransaction loanTransaction : repaymentsOrWaivers) {
|
for (LoanTransaction loanTransaction : transactionsPostDisbursement) {
|
||||||
|
|
||||||
loanTransaction.resetDerivedComponents();
|
if (loanTransaction.isRepayment() || loanTransaction.isInterestWaiver()) {
|
||||||
handleTransaction(loanTransaction, currency, installments);
|
loanTransaction.resetDerivedComponents();
|
||||||
|
handleTransaction(loanTransaction, currency, installments);
|
||||||
|
} else if (loanTransaction.isWriteOff()) {
|
||||||
|
loanTransaction.resetDerivedComponents();
|
||||||
|
handleWriteOff(loanTransaction, currency, installments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +82,29 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleWriteOff(
|
||||||
|
final LoanTransaction loanTransaction,
|
||||||
|
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);
|
||||||
|
|
||||||
|
// determine how much is written off in total and breakdown for principal, interest and charges
|
||||||
|
for (LoanRepaymentScheduleInstallment currentInstallment : installments) {
|
||||||
|
|
||||||
|
if (currentInstallment.isNotFullyCompleted()) {
|
||||||
|
principalPortion = principalPortion.plus(currentInstallment.writeOffOutstandingPrincipal(currency));
|
||||||
|
interestPortion = interestPortion.plus(currentInstallment.writeOffOutstandingInterest(currency));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loanTransaction.updateComponentsAndTotal(principalPortion, interestPortion, interestWaivedPortion, chargesPortion);
|
||||||
|
}
|
||||||
|
|
||||||
// abstract interface
|
// abstract interface
|
||||||
/**
|
/**
|
||||||
* This method is responsible for checking if the current transaction is 'an
|
* This method is responsible for checking if the current transaction is 'an
|
||||||
|
|||||||
+2
-2
@@ -68,7 +68,7 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessor extends AbstractLo
|
|||||||
Money interestWaivedPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money interestWaivedPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
|
|
||||||
if (loanTransaction.isWaiver()) {
|
if (loanTransaction.isInterestWaiver()) {
|
||||||
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ public class AdhikarLoanRepaymentScheduleTransactionProcessor extends AbstractLo
|
|||||||
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
|
|
||||||
if (loanTransaction.isWaiver()) {
|
if (loanTransaction.isInterestWaiver()) {
|
||||||
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -84,7 +84,7 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends
|
|||||||
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
|
|
||||||
if (loanTransaction.isWaiver()) {
|
if (loanTransaction.isInterestWaiver()) {
|
||||||
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+8
-8
@@ -53,7 +53,7 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LOAN_REPAYMENT_OR_WAIVER:
|
case LOAN_REPAYMENT_OR_WAIVER:
|
||||||
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE, LoanStatus.CLOSED, LoanStatus.OVERPAID)) {
|
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE, LoanStatus.CLOSED_OBLIGATIONS_MET, LoanStatus.OVERPAID)) {
|
||||||
newState = stateOf(LoanStatus.ACTIVE, allowedLoanStatuses);
|
newState = stateOf(LoanStatus.ACTIVE, allowedLoanStatuses);
|
||||||
} else {
|
} else {
|
||||||
newState = from;
|
newState = from;
|
||||||
@@ -61,26 +61,26 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi
|
|||||||
break;
|
break;
|
||||||
case REPAID_IN_FULL:
|
case REPAID_IN_FULL:
|
||||||
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE)) {
|
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE)) {
|
||||||
newState = stateOf(LoanStatus.CLOSED, allowedLoanStatuses);
|
newState = stateOf(LoanStatus.CLOSED_OBLIGATIONS_MET, allowedLoanStatuses);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LOAN_WRITE_OFF:
|
case WRITE_OFF_OUTSTANDING:
|
||||||
if (this.anyOfAllowedWhenComingFrom(from,LoanStatus.ACTIVE)) {
|
if (this.anyOfAllowedWhenComingFrom(from,LoanStatus.ACTIVE)) {
|
||||||
newState = stateOf(LoanStatus.CLOSED, allowedLoanStatuses);
|
newState = stateOf(LoanStatus.CLOSED_WRITTEN_OFF, allowedLoanStatuses);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LOAN_RESCHEDULE:
|
case LOAN_RESCHEDULE:
|
||||||
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE)) {
|
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE)) {
|
||||||
newState = stateOf(LoanStatus.CLOSED, allowedLoanStatuses);
|
newState = stateOf(LoanStatus.CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT, allowedLoanStatuses);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INTERST_REBATE_OWED:
|
case INTERST_REBATE_OWED:
|
||||||
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.CLOSED)) {
|
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.CLOSED_OBLIGATIONS_MET)) {
|
||||||
newState = stateOf(LoanStatus.CLOSED, allowedLoanStatuses);
|
newState = stateOf(LoanStatus.CLOSED_OBLIGATIONS_MET, allowedLoanStatuses);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LOAN_OVERPAYMENT:
|
case LOAN_OVERPAYMENT:
|
||||||
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.CLOSED, LoanStatus.ACTIVE)) {
|
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.CLOSED_OBLIGATIONS_MET, LoanStatus.ACTIVE)) {
|
||||||
newState = stateOf(LoanStatus.OVERPAID, allowedLoanStatuses);
|
newState = stateOf(LoanStatus.OVERPAID, allowedLoanStatuses);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+2
-2
@@ -73,7 +73,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
|
|||||||
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
|
|
||||||
if (loanTransaction.isWaiver()) {
|
if (loanTransaction.isInterestWaiver()) {
|
||||||
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
||||||
} else {
|
} else {
|
||||||
@@ -116,7 +116,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
|
|||||||
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
|
|
||||||
if (loanTransaction.isWaiver()) {
|
if (loanTransaction.isInterestWaiver()) {
|
||||||
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.hibernate.annotations.LazyCollection;
|
|||||||
import org.hibernate.annotations.LazyCollectionOption;
|
import org.hibernate.annotations.LazyCollectionOption;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.commands.LoanApplicationCommand;
|
import org.mifosng.platform.api.commands.LoanApplicationCommand;
|
||||||
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
||||||
import org.mifosng.platform.client.domain.Client;
|
import org.mifosng.platform.client.domain.Client;
|
||||||
@@ -282,7 +282,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void modifyLoanApplication(final LoanApplicationCommand command, final Client client, final LoanProduct loanProduct,
|
public void modifyLoanApplication(final LoanApplicationCommand command, final Client client, final LoanProduct loanProduct,
|
||||||
final Fund fund, final LoanTransactionProcessingStrategy strategy, final LoanScheduleNewData modifiedLoanSchedule, final Set<LoanCharge> charges,
|
final Fund fund, final LoanTransactionProcessingStrategy strategy, final LoanScheduleData modifiedLoanSchedule, final Set<LoanCharge> charges,
|
||||||
final Staff loanOfficer) {
|
final Staff loanOfficer) {
|
||||||
|
|
||||||
if (command.isClientChanged()) {
|
if (command.isClientChanged()) {
|
||||||
@@ -361,7 +361,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if the loan application/contract is modified when repayments are already against it - then need to re-process it
|
// if the loan application/contract is modified when repayments are already against it - then need to re-process it
|
||||||
final List<LoanTransaction> repaymentsOrWaivers = retreiveListOfRepaymentOrWaiverTransactionsPostDisbursement();
|
final List<LoanTransaction> repaymentsOrWaivers = retreiveListOfTransactionsPostDisbursement();
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor(this.transactionProcessingStrategy);
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor(this.transactionProcessingStrategy);
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(repaymentsOrWaivers, getCurrency(), this.repaymentScheduleInstallments);
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(repaymentsOrWaivers, getCurrency(), this.repaymentScheduleInstallments);
|
||||||
@@ -617,7 +617,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||||
final LoanTransaction adjustedTransaction) {
|
final LoanTransaction adjustedTransaction) {
|
||||||
|
|
||||||
LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, LoanStatus.fromInt(this.loanStatus));
|
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, LoanStatus.fromInt(this.loanStatus));
|
||||||
this.loanStatus = statusEnum.getValue();
|
this.loanStatus = statusEnum.getValue();
|
||||||
|
|
||||||
loanTransaction.updateLoan(this);
|
loanTransaction.updateLoan(this);
|
||||||
@@ -626,7 +626,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
this.loanTransactions.add(loanTransaction);
|
this.loanTransactions.add(loanTransaction);
|
||||||
|
|
||||||
if (loanTransaction.isNotRepayment() && loanTransaction.isNotWaiver()) {
|
if (loanTransaction.isNotRepayment() && loanTransaction.isNotInterestWaiver()) {
|
||||||
final String errorMessage = "A transaction of type repayment or waiver was expected but not received.";
|
final String errorMessage = "A transaction of type repayment or waiver was expected but not received.";
|
||||||
throw new InvalidLoanTransactionTypeException("transaction",
|
throw new InvalidLoanTransactionTypeException("transaction",
|
||||||
"is.not.a.repayment.or.waiver.transaction", errorMessage);
|
"is.not.a.repayment.or.waiver.transaction", errorMessage);
|
||||||
@@ -647,7 +647,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
"cannot.be.a.future.date", errorMessage, loanTransactionDate);
|
"cannot.be.a.future.date", errorMessage, loanTransactionDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loanTransaction.isWaiver()) {
|
if (loanTransaction.isInterestWaiver()) {
|
||||||
Money totalInterestOutstandingOnLoan = getTotalInterestOutstandingOnLoan();
|
Money totalInterestOutstandingOnLoan = getTotalInterestOutstandingOnLoan();
|
||||||
if (adjustedTransaction != null) {
|
if (adjustedTransaction != null) {
|
||||||
totalInterestOutstandingOnLoan = totalInterestOutstandingOnLoan.plus(adjustedTransaction.getAmount());
|
totalInterestOutstandingOnLoan = totalInterestOutstandingOnLoan.plus(adjustedTransaction.getAmount());
|
||||||
@@ -663,14 +663,14 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
if (isTransactionChronologicallyLatest && adjustedTransaction == null) {
|
if (isTransactionChronologicallyLatest && adjustedTransaction == null) {
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments);
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments);
|
||||||
} else {
|
} else {
|
||||||
final List<LoanTransaction> repaymentsOrWaivers = retreiveListOfRepaymentOrWaiverTransactionsPostDisbursement();
|
final List<LoanTransaction> repaymentsOrWaivers = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(repaymentsOrWaivers, getCurrency(), this.repaymentScheduleInstallments);
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(repaymentsOrWaivers, getCurrency(), this.repaymentScheduleInstallments);
|
||||||
}
|
}
|
||||||
|
|
||||||
doPostLoanTransactionChecks(loanTransaction, loanLifecycleStateMachine);
|
doPostLoanTransactionChecks(loanTransaction, loanLifecycleStateMachine);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<LoanTransaction> retreiveListOfRepaymentOrWaiverTransactionsPostDisbursement() {
|
private List<LoanTransaction> retreiveListOfTransactionsPostDisbursement() {
|
||||||
List<LoanTransaction> repaymentsOrWaivers = new ArrayList<LoanTransaction>();
|
List<LoanTransaction> repaymentsOrWaivers = new ArrayList<LoanTransaction>();
|
||||||
for (LoanTransaction transaction : this.loanTransactions) {
|
for (LoanTransaction transaction : this.loanTransactions) {
|
||||||
if (!transaction.isDisbursement() && transaction.isNotContra()) {
|
if (!transaction.isDisbursement() && transaction.isNotContra()) {
|
||||||
@@ -739,6 +739,26 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
return isChronologicallyLatestRepaymentOrWaiver;
|
return isChronologicallyLatestRepaymentOrWaiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isChronologicallyLatestTransaction(
|
||||||
|
final LoanTransaction loanTransaction,
|
||||||
|
final List<LoanTransaction> loanTransactions) {
|
||||||
|
|
||||||
|
boolean isChronologicallyLatestRepaymentOrWaiver = true;
|
||||||
|
|
||||||
|
LocalDate currentTransactionDate = loanTransaction.getTransactionDate();
|
||||||
|
for (LoanTransaction previousTransaction : loanTransactions) {
|
||||||
|
if (previousTransaction.isNotContra()) {
|
||||||
|
if (currentTransactionDate.isBefore(previousTransaction.getTransactionDate()) ||
|
||||||
|
currentTransactionDate.isEqual(previousTransaction.getTransactionDate())) {
|
||||||
|
isChronologicallyLatestRepaymentOrWaiver = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isChronologicallyLatestRepaymentOrWaiver;
|
||||||
|
}
|
||||||
|
|
||||||
public LocalDate possibleNextRepaymentDate() {
|
public LocalDate possibleNextRepaymentDate() {
|
||||||
LocalDate earliestUnpaidInstallmentDate = new LocalDate();
|
LocalDate earliestUnpaidInstallmentDate = new LocalDate();
|
||||||
for (LoanRepaymentScheduleInstallment installment : this.repaymentScheduleInstallments) {
|
for (LoanRepaymentScheduleInstallment installment : this.repaymentScheduleInstallments) {
|
||||||
@@ -770,7 +790,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
for (LoanRepaymentScheduleInstallment installment : this.repaymentScheduleInstallments) {
|
for (LoanRepaymentScheduleInstallment installment : this.repaymentScheduleInstallments) {
|
||||||
if (installment.isNotFullyCompleted()) {
|
if (installment.isNotFullyCompleted()) {
|
||||||
possibleNextRepaymentAmount = installment.getTotalDue(currency);
|
possibleNextRepaymentAmount = installment.getTotalOutstanding(currency);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -805,14 +825,20 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
final LoanTransaction newTransactionDetail,
|
final LoanTransaction newTransactionDetail,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||||
|
|
||||||
if (transactionForAdjustment.isNotRepayment() && transactionForAdjustment.isNotWaiver()) {
|
if (transactionForAdjustment.isNotRepayment() && transactionForAdjustment.isNotInterestWaiver()) {
|
||||||
final String errorMessage = "A transaction of type repayment or waiver was expected but not received.";
|
final String errorMessage = "Only transactions of type repayment or interest waiver can be adjusted.";
|
||||||
throw new InvalidLoanTransactionTypeException("transaction",
|
throw new InvalidLoanTransactionTypeException("transaction",
|
||||||
"is.not.a.repayment.or.waiver.transaction", errorMessage);
|
"adjustment.is.only.allowed.to.repayment.or.waiver.transaction", errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isClosed()) {
|
||||||
|
final String errorMessage = "Transactions of a closed loan cannot be adjusted.";
|
||||||
|
throw new InvalidLoanTransactionTypeException("transaction",
|
||||||
|
"adjustment.is.not.allowed.on.closed.loan", errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionForAdjustment.contra();
|
transactionForAdjustment.contra();
|
||||||
if (newTransactionDetail.isRepayment() || newTransactionDetail.isWaiver()) {
|
if (newTransactionDetail.isRepayment() || newTransactionDetail.isInterestWaiver()) {
|
||||||
handleRepaymentOrWaiverTransaction(newTransactionDetail, loanLifecycleStateMachine, transactionForAdjustment);
|
handleRepaymentOrWaiverTransaction(newTransactionDetail, loanLifecycleStateMachine, transactionForAdjustment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -867,32 +893,49 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
return this.loanRepaymentScheduleDetail.getCurrency();
|
return this.loanRepaymentScheduleDetail.getCurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeOff(final DateTime writtenOffOn,
|
public LoanTransaction closeAsWrittenOff(
|
||||||
|
final LocalDate writtenOffOnLocalDate,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||||
|
|
||||||
LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_WRITE_OFF, LoanStatus.fromInt(this.loanStatus));
|
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING, LoanStatus.fromInt(this.loanStatus));
|
||||||
this.loanStatus = statusEnum.getValue();
|
this.loanStatus = statusEnum.getValue();
|
||||||
|
|
||||||
this.closedOnDate = writtenOffOn.toDate();
|
this.closedOnDate = writtenOffOnLocalDate.toDate();
|
||||||
this.writtenOffOnDate = writtenOffOn.toDate();
|
this.writtenOffOnDate = writtenOffOnLocalDate.toDate();
|
||||||
|
|
||||||
LocalDate writtenOffOnLocalDate = new LocalDate(writtenOffOnDate);
|
|
||||||
if (writtenOffOnLocalDate.isBefore(this.getDisbursementDate())) {
|
if (writtenOffOnLocalDate.isBefore(this.getDisbursementDate())) {
|
||||||
final String errorMessage = "The date on which a loan is withdrawn cannot be before the loan disbursement date: "
|
final String errorMessage = "The date on which a loan is written off cannot be before the loan disbursement date: "
|
||||||
+ getDisbursementDate().toString();
|
+ getDisbursementDate().toString();
|
||||||
throw new InvalidLoanStateTransitionException("writeoff",
|
throw new InvalidLoanStateTransitionException("writeoff",
|
||||||
"cannot.be.before.submittal.date", errorMessage,
|
"cannot.be.before.submittal.date", errorMessage,
|
||||||
writtenOffOnLocalDate, getDisbursementDate());
|
writtenOffOnLocalDate, getDisbursementDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writtenOffOnLocalDate.isAfter(new LocalDate())) {
|
if (writtenOffOnLocalDate.isAfter(new LocalDate())) {
|
||||||
final String errorMessage = "The date on which a loan is written off cannot be in the future.";
|
final String errorMessage = "The date on which a loan is written off cannot be in the future.";
|
||||||
throw new InvalidLoanStateTransitionException("writeoff",
|
throw new InvalidLoanStateTransitionException("writeoff",
|
||||||
"cannot.be.a.future.date", errorMessage,
|
"cannot.be.a.future.date", errorMessage,
|
||||||
writtenOffOnLocalDate);
|
writtenOffOnLocalDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final LoanTransaction loanTransaction = LoanTransaction.writeoff(this, writtenOffOnLocalDate);
|
||||||
|
boolean isLastTransaction = isChronologicallyLatestTransaction(loanTransaction, loanTransactions);
|
||||||
|
if (!isLastTransaction) {
|
||||||
|
final String errorMessage = "The date of the writeoff transaction must occur on or before previous transactions.";
|
||||||
|
throw new InvalidLoanStateTransitionException("writeoff","must.occur.on.or.after.other.transaction.dates", errorMessage, writtenOffOnLocalDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loanTransactions.add(loanTransaction);
|
||||||
|
|
||||||
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor(this.transactionProcessingStrategy);
|
||||||
|
loanRepaymentScheduleTransactionProcessor.handleWriteOff(loanTransaction, loanCurrency(), this.repaymentScheduleInstallments);
|
||||||
|
|
||||||
|
return loanTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reschedule(final DateTime rescheduledOn,
|
// FIXME - KW - finish off reschedule/restructure capability for loans.
|
||||||
|
public void reschedule(
|
||||||
|
final DateTime rescheduledOn,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||||
|
|
||||||
LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, LoanStatus.fromInt(this.loanStatus));
|
LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, LoanStatus.fromInt(this.loanStatus));
|
||||||
|
|||||||
@@ -1,8 +1,21 @@
|
|||||||
package org.mifosng.platform.loan.domain;
|
package org.mifosng.platform.loan.domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
public enum LoanEvent {
|
public enum LoanEvent {
|
||||||
|
|
||||||
LOAN_CREATED, LOAN_REJECTED, LOAN_WITHDRAWN, LOAN_APPROVED, LOAN_APPROVAL_UNDO, LOAN_DISBURSED, LOAN_DISBURSAL_UNDO, LOAN_REPAYMENT_OR_WAIVER,
|
LOAN_CREATED, //
|
||||||
//
|
LOAN_REJECTED, //
|
||||||
REPAID_IN_FULL, LOAN_WRITE_OFF, LOAN_RESCHEDULE, INTERST_REBATE_OWED, LOAN_OVERPAYMENT;
|
LOAN_WITHDRAWN, //
|
||||||
|
LOAN_APPROVED, //
|
||||||
|
LOAN_APPROVAL_UNDO, //
|
||||||
|
LOAN_DISBURSED, //
|
||||||
|
LOAN_DISBURSAL_UNDO, //
|
||||||
|
LOAN_REPAYMENT_OR_WAIVER, //
|
||||||
|
REPAID_IN_FULL, //
|
||||||
|
WRITE_OFF_OUTSTANDING, //
|
||||||
|
LOAN_RESCHEDULE, //
|
||||||
|
INTERST_REBATE_OWED, //
|
||||||
|
LOAN_OVERPAYMENT;
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-18
@@ -19,7 +19,7 @@ import org.mifosng.platform.user.domain.AppUser;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_loan_repayment_schedule")
|
@Table(name = "m_loan_repayment_schedule")
|
||||||
public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<AppUser, Long> {
|
public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<AppUser, Long> {
|
||||||
|
|
||||||
@ManyToOne(optional = false)
|
@ManyToOne(optional = false)
|
||||||
@JoinColumn(name = "loan_id")
|
@JoinColumn(name = "loan_id")
|
||||||
@@ -37,12 +37,18 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
@Column(name = "principal_completed_derived", scale=6, precision=19)
|
@Column(name = "principal_completed_derived", scale=6, precision=19)
|
||||||
private BigDecimal principalCompleted = BigDecimal.ZERO;
|
private BigDecimal principalCompleted = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
@Column(name = "principal_writtenoff_derived", scale=6, precision=19)
|
||||||
|
private BigDecimal principalWrittenOff = BigDecimal.ZERO;
|
||||||
|
|
||||||
@Column(name = "interest_completed_derived", scale = 6, precision = 19)
|
@Column(name = "interest_completed_derived", scale = 6, precision = 19)
|
||||||
private BigDecimal interestCompleted = BigDecimal.ZERO;
|
private BigDecimal interestCompleted = BigDecimal.ZERO;
|
||||||
|
|
||||||
@Column(name = "interest_waived_derived", scale = 6, precision = 19)
|
@Column(name = "interest_waived_derived", scale = 6, precision = 19)
|
||||||
private BigDecimal interestWaived = BigDecimal.ZERO;
|
private BigDecimal interestWaived = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
@Column(name = "interest_writtenoff_derived", scale=6, precision=19)
|
||||||
|
private BigDecimal interestWrittenOff = BigDecimal.ZERO;
|
||||||
|
|
||||||
@Column(name="completed_derived")
|
@Column(name="completed_derived")
|
||||||
private boolean completed;
|
private boolean completed;
|
||||||
|
|
||||||
@@ -93,8 +99,13 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
return Money.of(currency, this.principalCompleted);
|
return Money.of(currency, this.principalCompleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Money getPrincipalWrittenOff(final MonetaryCurrency currency) {
|
||||||
|
return Money.of(currency, this.principalWrittenOff);
|
||||||
|
}
|
||||||
|
|
||||||
public Money getPrincipalOutstanding(final MonetaryCurrency currency) {
|
public Money getPrincipalOutstanding(final MonetaryCurrency currency) {
|
||||||
return getPrincipal(currency).minus(getPrincipalCompleted(currency));
|
final Money principalAccountedFor = getPrincipalCompleted(currency).plus(getPrincipalWrittenOff(currency));
|
||||||
|
return getPrincipal(currency).minus(principalAccountedFor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getInterest(final MonetaryCurrency currency) {
|
public Money getInterest(final MonetaryCurrency currency) {
|
||||||
@@ -109,15 +120,20 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
return Money.of(currency, this.interestWaived);
|
return Money.of(currency, this.interestWaived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Money getInterestWrittenOff(final MonetaryCurrency currency) {
|
||||||
|
return Money.of(currency, this.interestWrittenOff);
|
||||||
|
}
|
||||||
|
|
||||||
public Money getInterestOutstanding(final MonetaryCurrency currency) {
|
public Money getInterestOutstanding(final MonetaryCurrency currency) {
|
||||||
return getInterest(currency).minus(getInterestCompleted(currency).plus(getInterestWaived(currency)));
|
final Money interestAccountedFor = getInterestCompleted(currency).plus(getInterestWaived(currency)).plus(getInterestWrittenOff(currency));
|
||||||
|
return getInterest(currency).minus(interestAccountedFor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInterestDue(final MonetaryCurrency currency) {
|
public boolean isInterestDue(final MonetaryCurrency currency) {
|
||||||
return getInterest(currency).minus(getInterestCompleted(currency).plus(getInterestWaived(currency))).isGreaterThanZero();
|
return getInterestOutstanding(currency).isGreaterThanZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getTotal(final MonetaryCurrency currency) {
|
public Money getTotalPrincipalAndInterest(final MonetaryCurrency currency) {
|
||||||
return getPrincipal(currency).plus(getInterest(currency));
|
return getPrincipal(currency).plus(getInterest(currency));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,22 +158,15 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPrincipalCompleted(final MonetaryCurrency currency) {
|
public boolean isPrincipalCompleted(final MonetaryCurrency currency) {
|
||||||
return getPrincipal(currency).minus(getPrincipalCompleted(currency)).isZero();
|
return getPrincipalOutstanding(currency).isZero();
|
||||||
}
|
|
||||||
|
|
||||||
public Money getTotalDue(MonetaryCurrency currency) {
|
|
||||||
final Money totalPaidOrWaived = getInterestWaived(currency).plus(getTotalCompleted(currency));
|
|
||||||
return getTotal(currency).minus(totalPaidOrWaived);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Money getTotalCompleted(MonetaryCurrency currency) {
|
|
||||||
return getPrincipalCompleted(currency).plus(getInterestCompleted(currency));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetDerivedComponents() {
|
public void resetDerivedComponents() {
|
||||||
this.principalCompleted = BigDecimal.ZERO;
|
this.principalCompleted = BigDecimal.ZERO;
|
||||||
|
this.principalWrittenOff = BigDecimal.ZERO;
|
||||||
this.interestCompleted = BigDecimal.ZERO;
|
this.interestCompleted = BigDecimal.ZERO;
|
||||||
this.interestWaived = BigDecimal.ZERO;
|
this.interestWaived = BigDecimal.ZERO;
|
||||||
|
this.interestWrittenOff = BigDecimal.ZERO;
|
||||||
this.completed = false;
|
this.completed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +184,7 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
interestPortionOfTransaction = interestPortionOfTransaction.plus(transactionAmountRemaining);
|
interestPortionOfTransaction = interestPortionOfTransaction.plus(transactionAmountRemaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.completed = getTotalDue(currency).isZero();
|
this.completed = getTotalOutstanding(currency).isZero();
|
||||||
|
|
||||||
return interestPortionOfTransaction;
|
return interestPortionOfTransaction;
|
||||||
}
|
}
|
||||||
@@ -194,7 +203,7 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
principalPortionOfTransaction = principalPortionOfTransaction.plus(transactionAmountRemaining);
|
principalPortionOfTransaction = principalPortionOfTransaction.plus(transactionAmountRemaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.completed = getTotalDue(currency).isZero();
|
this.completed = getTotalOutstanding(currency).isZero();
|
||||||
|
|
||||||
return principalPortionOfTransaction;
|
return principalPortionOfTransaction;
|
||||||
}
|
}
|
||||||
@@ -212,11 +221,29 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
waivedInterestPortionOfTransaction = waivedInterestPortionOfTransaction.plus(transactionAmountRemaining);
|
waivedInterestPortionOfTransaction = waivedInterestPortionOfTransaction.plus(transactionAmountRemaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.completed = getTotalDue(currency).isZero();
|
this.completed = getTotalOutstanding(currency).isZero();
|
||||||
|
|
||||||
return waivedInterestPortionOfTransaction;
|
return waivedInterestPortionOfTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Money writeOffOutstandingPrincipal(final MonetaryCurrency currency) {
|
||||||
|
|
||||||
|
final Money principalDue = getPrincipalOutstanding(currency);
|
||||||
|
this.principalWrittenOff = principalDue.getAmount();
|
||||||
|
this.completed = getTotalOutstanding(currency).isZero();
|
||||||
|
|
||||||
|
return principalDue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Money writeOffOutstandingInterest(final MonetaryCurrency currency) {
|
||||||
|
|
||||||
|
final Money interestDue = getInterestOutstanding(currency);
|
||||||
|
this.interestWrittenOff = interestDue.getAmount();
|
||||||
|
this.completed = getTotalOutstanding(currency).isZero();
|
||||||
|
|
||||||
|
return interestDue;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isOverdueOn(final LocalDate transactionDate) {
|
public boolean isOverdueOn(final LocalDate transactionDate) {
|
||||||
return this.getDueDate().isBefore(transactionDate);
|
return this.getDueDate().isBefore(transactionDate);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -10,4 +10,8 @@ public interface LoanRepaymentScheduleTransactionProcessor {
|
|||||||
|
|
||||||
void handleTransaction(List<LoanTransaction> repaymentsOrWaivers, MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments);
|
void handleTransaction(List<LoanTransaction> repaymentsOrWaivers, MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments);
|
||||||
|
|
||||||
|
void handleWriteOff(LoanTransaction loanTransaction,
|
||||||
|
MonetaryCurrency loanCurrency,
|
||||||
|
List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,9 @@ public enum LoanStatus {
|
|||||||
ACTIVE(300, "loanStatusType.active"), //
|
ACTIVE(300, "loanStatusType.active"), //
|
||||||
WITHDRAWN_BY_CLIENT(400, "loanStatusType.withdrawn.by.client"), //
|
WITHDRAWN_BY_CLIENT(400, "loanStatusType.withdrawn.by.client"), //
|
||||||
REJECTED(500, "loanStatusType.rejected"), //
|
REJECTED(500, "loanStatusType.rejected"), //
|
||||||
CLOSED(600, "loanStatusType.closed"), //
|
CLOSED_OBLIGATIONS_MET(600, "loanStatusType.closed.obligations.met"), //
|
||||||
|
CLOSED_WRITTEN_OFF(601, "loanStatusType.closed.written.off"), //
|
||||||
|
CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT(602, "loanStatusType.closed.reschedule.outstanding.amount"), //
|
||||||
OVERPAID(700, "loanStatusType.overpaid");
|
OVERPAID(700, "loanStatusType.overpaid");
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
@@ -37,7 +39,13 @@ public enum LoanStatus {
|
|||||||
enumeration = LoanStatus.REJECTED;
|
enumeration = LoanStatus.REJECTED;
|
||||||
break;
|
break;
|
||||||
case 600:
|
case 600:
|
||||||
enumeration = LoanStatus.CLOSED;
|
enumeration = LoanStatus.CLOSED_OBLIGATIONS_MET;
|
||||||
|
break;
|
||||||
|
case 601:
|
||||||
|
enumeration = LoanStatus.CLOSED_WRITTEN_OFF;
|
||||||
|
break;
|
||||||
|
case 602:
|
||||||
|
enumeration = LoanStatus.CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT;
|
||||||
break;
|
break;
|
||||||
case 700:
|
case 700:
|
||||||
enumeration = LoanStatus.OVERPAID;
|
enumeration = LoanStatus.OVERPAID;
|
||||||
@@ -76,7 +84,19 @@ public enum LoanStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return this.value.equals(LoanStatus.CLOSED.getValue());
|
return isClosedObligationsMet() || isClosedWrittenOff() || isClosedWithOutsandingAmountMarkedForReschedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isClosedObligationsMet() {
|
||||||
|
return this.value.equals(LoanStatus.CLOSED_OBLIGATIONS_MET.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isClosedWrittenOff() {
|
||||||
|
return this.value.equals(LoanStatus.CLOSED_WRITTEN_OFF.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isClosedWithOutsandingAmountMarkedForReschedule() {
|
||||||
|
return this.value.equals(LoanStatus.CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWithdrawnByClient() {
|
public boolean isWithdrawnByClient() {
|
||||||
|
|||||||
+25
-11
@@ -35,7 +35,7 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
private Loan loan;
|
private Loan loan;
|
||||||
|
|
||||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||||
private final BigDecimal amount;
|
private BigDecimal amount;
|
||||||
|
|
||||||
@Column(name = "principal_portion_derived", scale = 6, precision = 19, nullable = false)
|
@Column(name = "principal_portion_derived", scale = 6, precision = 19, nullable = false)
|
||||||
private BigDecimal principalPortion = BigDecimal.ZERO;
|
private BigDecimal principalPortion = BigDecimal.ZERO;
|
||||||
@@ -63,7 +63,6 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
protected LoanTransaction() {
|
protected LoanTransaction() {
|
||||||
this.loan = null;
|
this.loan = null;
|
||||||
this.amount = null;
|
|
||||||
this.dateOf = null;
|
this.dateOf = null;
|
||||||
this.typeOf = null;
|
this.typeOf = null;
|
||||||
}
|
}
|
||||||
@@ -81,15 +80,19 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static LoanTransaction waiver(final Loan loan, final Money waived, final LocalDate waiveDate) {
|
public static LoanTransaction waiver(final Loan loan, final Money waived, final LocalDate waiveDate) {
|
||||||
return new LoanTransaction(loan, LoanTransactionType.WAIVED, waived.getAmount(), waiveDate);
|
return new LoanTransaction(loan, LoanTransactionType.WAIVE_INTEREST, waived.getAmount(), waiveDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LoanTransaction contra(final LoanTransaction originalTransaction) {
|
private static LoanTransaction contra(final LoanTransaction originalTransaction) {
|
||||||
LoanTransaction contra = new LoanTransaction(null, LoanTransactionType.REVERSAL, originalTransaction.getAmount().negate(), new LocalDate(originalTransaction.getDateOf()));
|
LoanTransaction contra = new LoanTransaction(null, LoanTransactionType.CONTRA, originalTransaction.getAmount().negate(), new LocalDate(originalTransaction.getDateOf()));
|
||||||
contra.updateContra(originalTransaction);
|
contra.updateContra(originalTransaction);
|
||||||
return contra;
|
return contra;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LoanTransaction writeoff(final Loan loan, final LocalDate writeOffDate) {
|
||||||
|
return new LoanTransaction(loan, LoanTransactionType.WRITEOFF, null, writeOffDate);
|
||||||
|
}
|
||||||
|
|
||||||
public void updateContra(final LoanTransaction transaction) {
|
public void updateContra(final LoanTransaction transaction) {
|
||||||
this.contra = transaction;
|
this.contra = transaction;
|
||||||
}
|
}
|
||||||
@@ -142,23 +145,27 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
return LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.equals(getTypeOf());
|
return LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.equals(getTypeOf());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWaiver() {
|
public boolean isInterestWaiver() {
|
||||||
return LoanTransactionType.WAIVED.equals(getTypeOf()) && isNotContra();
|
return LoanTransactionType.WAIVE_INTEREST.equals(getTypeOf()) && isNotContra();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNotWaiver() {
|
public boolean isNotInterestWaiver() {
|
||||||
return !isWaiver();
|
return !isInterestWaiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIdentifiedBy(Long identifier) {
|
public boolean isWriteOff() {
|
||||||
|
return getTypeOf().isWriteOff() && isNotContra();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIdentifiedBy(final Long identifier) {
|
||||||
return this.getId().equals(identifier);
|
return this.getId().equals(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBelongingToLoanOf(Loan check) {
|
public boolean isBelongingToLoanOf(final Loan check) {
|
||||||
return this.loan.getId().equals(check.getId());
|
return this.loan.getId().equals(check.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNotBelongingToLoanOf(Loan check) {
|
public boolean isNotBelongingToLoanOf(final Loan check) {
|
||||||
return !isBelongingToLoanOf(check);
|
return !isBelongingToLoanOf(check);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +195,13 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
this.chargesPortion = getChargesPortion(currency).plus(charges).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);
|
||||||
|
|
||||||
|
final MonetaryCurrency currency = principal.getCurrency();
|
||||||
|
this.amount = getPrincipalPortion(currency).plus(getInterestPortion(currency)).plus(this.chargesPortion).getAmount();
|
||||||
|
}
|
||||||
|
|
||||||
public Money getPrincipalPortion(final MonetaryCurrency currency) {
|
public Money getPrincipalPortion(final MonetaryCurrency currency) {
|
||||||
return Money.of(currency, principalPortion);
|
return Money.of(currency, principalPortion);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,9 +13,9 @@ public class LoanTransactionComparator implements Comparator<LoanTransaction> {
|
|||||||
final int comparsion = o1.getTransactionDate().compareTo(o2.getTransactionDate());
|
final int comparsion = o1.getTransactionDate().compareTo(o2.getTransactionDate());
|
||||||
if (comparsion == 0) {
|
if (comparsion == 0) {
|
||||||
// equal transaction dates
|
// equal transaction dates
|
||||||
if (o1.isWaiver() && o2.isNotWaiver()) {
|
if (o1.isInterestWaiver() && o2.isNotInterestWaiver()) {
|
||||||
compareResult = -1;
|
compareResult = -1;
|
||||||
} else if (o1.isNotWaiver() && o2.isWaiver()) {
|
} else if (o1.isNotInterestWaiver() && o2.isInterestWaiver()) {
|
||||||
compareResult = 1;
|
compareResult = 1;
|
||||||
} else {
|
} else {
|
||||||
compareResult = 0;
|
compareResult = 0;
|
||||||
|
|||||||
+21
-5
@@ -5,9 +5,15 @@ public enum LoanTransactionType {
|
|||||||
INVALID(0, "loanTransactionType.invalid"), //
|
INVALID(0, "loanTransactionType.invalid"), //
|
||||||
DISBURSEMENT(1, "loanTransactionType.disbursement"), //
|
DISBURSEMENT(1, "loanTransactionType.disbursement"), //
|
||||||
REPAYMENT(2, "loanTransactionType.repayment"), //
|
REPAYMENT(2, "loanTransactionType.repayment"), //
|
||||||
REVERSAL(3, "loanTransactionType.reversal"), //
|
CONTRA(3, "loanTransactionType.contra"), //
|
||||||
WAIVED(4, "loanTransactionType.waiver"), //
|
WAIVE_INTEREST(4, "loanTransactionType.waiver"), //
|
||||||
REPAYMENT_AT_DISBURSEMENT(5, "loanTransactionType.repaymentAtDisbursement");
|
REPAYMENT_AT_DISBURSEMENT(5, "loanTransactionType.repaymentAtDisbursement"), //
|
||||||
|
WRITEOFF(6, "loanTransactionType.writeOff"),
|
||||||
|
MARKED_FOR_RESCHEDULING(7, "loanTransactionType.marked.for.rescheduling"), //
|
||||||
|
/**
|
||||||
|
* This type of transactions is allowed on written-off loans where mfi still attempts to recover payments from applicant after writing-off.
|
||||||
|
*/
|
||||||
|
RECOVERY_REPAYMENT(8, "loanTransactionType.recoveryRepayment");
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
private final String code;
|
private final String code;
|
||||||
@@ -40,18 +46,28 @@ public enum LoanTransactionType {
|
|||||||
loanTransactionType = LoanTransactionType.REPAYMENT;
|
loanTransactionType = LoanTransactionType.REPAYMENT;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
loanTransactionType = LoanTransactionType.REVERSAL;
|
loanTransactionType = LoanTransactionType.CONTRA;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
loanTransactionType = LoanTransactionType.WAIVED;
|
loanTransactionType = LoanTransactionType.WAIVE_INTEREST;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
loanTransactionType = LoanTransactionType.REPAYMENT_AT_DISBURSEMENT;
|
loanTransactionType = LoanTransactionType.REPAYMENT_AT_DISBURSEMENT;
|
||||||
break;
|
break;
|
||||||
|
case 6:
|
||||||
|
loanTransactionType = LoanTransactionType.WRITEOFF;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
loanTransactionType = LoanTransactionType.MARKED_FOR_RESCHEDULING;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
loanTransactionType = LoanTransactionType.INVALID;
|
loanTransactionType = LoanTransactionType.INVALID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return loanTransactionType;
|
return loanTransactionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWriteOff() {
|
||||||
|
return this.value.equals(LoanTransactionType.WRITEOFF.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -75,7 +75,7 @@ public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends
|
|||||||
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
Money chargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
|
||||||
|
|
||||||
if (loanTransaction.isWaiver()) {
|
if (loanTransaction.isInterestWaiver()) {
|
||||||
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
interestWaivedPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
|
||||||
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
transactionAmountRemaining = transactionAmountRemaining.minus(interestWaivedPortion);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
package org.mifosng.platform.loan.service;
|
package org.mifosng.platform.loan.service;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
|
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
|
||||||
|
|
||||||
public interface CalculationPlatformService {
|
public interface CalculationPlatformService {
|
||||||
|
|
||||||
LoanScheduleNewData calculateLoanScheduleNew(CalculateLoanScheduleCommand command);
|
LoanScheduleData calculateLoanScheduleNew(CalculateLoanScheduleCommand command);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not used at present from application.
|
* Not used at present from application.
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@ package org.mifosng.platform.loan.service;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
|
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
|
||||||
import org.mifosng.platform.api.data.CurrencyData;
|
import org.mifosng.platform.api.data.CurrencyData;
|
||||||
import org.mifosng.platform.api.data.MoneyData;
|
import org.mifosng.platform.api.data.MoneyData;
|
||||||
@@ -51,7 +51,7 @@ public class CalculationPlatformServiceImpl implements CalculationPlatformServic
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanScheduleNewData calculateLoanScheduleNew(final CalculateLoanScheduleCommand command) {
|
public LoanScheduleData calculateLoanScheduleNew(final CalculateLoanScheduleCommand command) {
|
||||||
|
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.commands.LoanApplicationCommand;
|
import org.mifosng.platform.api.commands.LoanApplicationCommand;
|
||||||
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
||||||
import org.mifosng.platform.client.domain.Client;
|
import org.mifosng.platform.client.domain.Client;
|
||||||
@@ -122,7 +122,7 @@ public class LoanAssembler {
|
|||||||
|
|
||||||
loan.setExternalId(command.getExternalId());
|
loan.setExternalId(command.getExternalId());
|
||||||
|
|
||||||
final LoanScheduleNewData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(command.toCalculateLoanScheduleCommand());
|
final LoanScheduleData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(command.toCalculateLoanScheduleCommand());
|
||||||
|
|
||||||
for (LoanSchedulePeriodData scheduledLoanInstallment : loanSchedule.getPeriods()) {
|
for (LoanSchedulePeriodData scheduledLoanInstallment : loanSchedule.getPeriods()) {
|
||||||
if (scheduledLoanInstallment.isRepaymentPeriod()) {
|
if (scheduledLoanInstallment.isRepaymentPeriod()) {
|
||||||
|
|||||||
+5
-4
@@ -3,12 +3,11 @@ package org.mifosng.platform.loan.service;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.data.CurrencyData;
|
import org.mifosng.platform.api.data.CurrencyData;
|
||||||
import org.mifosng.platform.api.data.DisbursementData;
|
import org.mifosng.platform.api.data.DisbursementData;
|
||||||
import org.mifosng.platform.api.data.LoanBasicDetailsData;
|
import org.mifosng.platform.api.data.LoanBasicDetailsData;
|
||||||
import org.mifosng.platform.api.data.LoanPermissionData;
|
import org.mifosng.platform.api.data.LoanPermissionData;
|
||||||
import org.mifosng.platform.api.data.LoanRepaymentTransactionData;
|
|
||||||
import org.mifosng.platform.api.data.LoanTransactionData;
|
import org.mifosng.platform.api.data.LoanTransactionData;
|
||||||
import org.mifosng.platform.api.data.LoanTransactionNewData;
|
import org.mifosng.platform.api.data.LoanTransactionNewData;
|
||||||
|
|
||||||
@@ -16,9 +15,9 @@ public interface LoanReadPlatformService {
|
|||||||
|
|
||||||
LoanBasicDetailsData retrieveLoanAccountDetails(Long loanId);
|
LoanBasicDetailsData retrieveLoanAccountDetails(Long loanId);
|
||||||
|
|
||||||
LoanScheduleNewData retrieveRepaymentSchedule(Long loanId, CurrencyData currency, DisbursementData disbursement, BigDecimal totalChargesAtDisbursement, BigDecimal inArrearsTolerance);
|
LoanScheduleData retrieveRepaymentSchedule(Long loanId, CurrencyData currency, DisbursementData disbursement, BigDecimal totalChargesAtDisbursement, BigDecimal inArrearsTolerance);
|
||||||
|
|
||||||
Collection<LoanRepaymentTransactionData> retrieveLoanPayments(Long loanId);
|
Collection<LoanTransactionNewData> retrieveLoanTransactions(Long loanId);
|
||||||
|
|
||||||
LoanPermissionData retrieveLoanPermissions(
|
LoanPermissionData retrieveLoanPermissions(
|
||||||
LoanBasicDetailsData loanBasicDetails, boolean isWaiverAllowed,
|
LoanBasicDetailsData loanBasicDetails, boolean isWaiverAllowed,
|
||||||
@@ -33,4 +32,6 @@ public interface LoanReadPlatformService {
|
|||||||
LoanTransactionNewData retrieveNewLoanWaiveInterestDetails(Long loanId);
|
LoanTransactionNewData retrieveNewLoanWaiveInterestDetails(Long loanId);
|
||||||
|
|
||||||
LoanTransactionData retrieveLoanTransactionDetails(Long loanId, Long transactionId);
|
LoanTransactionData retrieveLoanTransactionDetails(Long loanId, Long transactionId);
|
||||||
|
|
||||||
|
LoanTransactionNewData retrieveNewClosureDetails();
|
||||||
}
|
}
|
||||||
+58
-39
@@ -7,7 +7,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.data.ClientData;
|
import org.mifosng.platform.api.data.ClientData;
|
||||||
import org.mifosng.platform.api.data.CurrencyData;
|
import org.mifosng.platform.api.data.CurrencyData;
|
||||||
import org.mifosng.platform.api.data.DisbursementData;
|
import org.mifosng.platform.api.data.DisbursementData;
|
||||||
@@ -17,7 +17,6 @@ import org.mifosng.platform.api.data.LoanBasicDetailsData;
|
|||||||
import org.mifosng.platform.api.data.LoanChargeData;
|
import org.mifosng.platform.api.data.LoanChargeData;
|
||||||
import org.mifosng.platform.api.data.LoanPermissionData;
|
import org.mifosng.platform.api.data.LoanPermissionData;
|
||||||
import org.mifosng.platform.api.data.LoanProductData;
|
import org.mifosng.platform.api.data.LoanProductData;
|
||||||
import org.mifosng.platform.api.data.LoanRepaymentTransactionData;
|
|
||||||
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
||||||
import org.mifosng.platform.api.data.LoanTransactionData;
|
import org.mifosng.platform.api.data.LoanTransactionData;
|
||||||
import org.mifosng.platform.api.data.LoanTransactionNewData;
|
import org.mifosng.platform.api.data.LoanTransactionNewData;
|
||||||
@@ -97,7 +96,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanScheduleNewData retrieveRepaymentSchedule(final Long loanId,
|
public LoanScheduleData retrieveRepaymentSchedule(final Long loanId,
|
||||||
final CurrencyData currency,
|
final CurrencyData currency,
|
||||||
final DisbursementData disbursement,
|
final DisbursementData disbursement,
|
||||||
final BigDecimal totalChargesAtDisbursement,
|
final BigDecimal totalChargesAtDisbursement,
|
||||||
@@ -123,10 +122,12 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
final BigDecimal cumulativePrincipalDisbursed = wrapper.deriveCumulativePrincipalDisbursed();
|
final BigDecimal cumulativePrincipalDisbursed = wrapper.deriveCumulativePrincipalDisbursed();
|
||||||
final BigDecimal cumulativePrincipalDue = wrapper.deriveCumulativePrincipalDue();
|
final BigDecimal cumulativePrincipalDue = wrapper.deriveCumulativePrincipalDue();
|
||||||
final BigDecimal cumulativePrincipalPaid = wrapper.deriveCumulativePrincipalPaid();
|
final BigDecimal cumulativePrincipalPaid = wrapper.deriveCumulativePrincipalPaid();
|
||||||
|
final BigDecimal cumulativePrincipalWrittenOff = wrapper.deriveCumulativePrincipalWrittenOff();
|
||||||
final BigDecimal cumulativePrincipalOutstanding = wrapper.deriveCumulativePrincipalOutstanding();
|
final BigDecimal cumulativePrincipalOutstanding = wrapper.deriveCumulativePrincipalOutstanding();
|
||||||
final BigDecimal cumulativeInterestExpected = wrapper.deriveCumulativeInterestExpected();
|
final BigDecimal cumulativeInterestExpected = wrapper.deriveCumulativeInterestExpected();
|
||||||
final BigDecimal cumulativeInterestPaid = wrapper.deriveCumulativeInterestPaid();
|
final BigDecimal cumulativeInterestPaid = wrapper.deriveCumulativeInterestPaid();
|
||||||
final BigDecimal cumulativeInterestWaived = wrapper.deriveCumulativeInterestWaived();
|
final BigDecimal cumulativeInterestWaived = wrapper.deriveCumulativeInterestWaived();
|
||||||
|
final BigDecimal cumulativeInterestWrittenOff = wrapper.deriveCumulativeInterestWrittenOff();
|
||||||
final BigDecimal cumulativeInterestOutstanding = wrapper.deriveCumulativeInterestOutstanding();
|
final BigDecimal cumulativeInterestOutstanding = wrapper.deriveCumulativeInterestOutstanding();
|
||||||
final BigDecimal cumulativeChargesToDate = wrapper.deriveCumulativeChargesToDate();
|
final BigDecimal cumulativeChargesToDate = wrapper.deriveCumulativeChargesToDate();
|
||||||
final BigDecimal cumulativeChargesPaid = wrapper.deriveCumulativeChargesPaid();
|
final BigDecimal cumulativeChargesPaid = wrapper.deriveCumulativeChargesPaid();
|
||||||
@@ -136,6 +137,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
final BigDecimal totalExpectedRepayment = cumulativePrincipalDisbursed.add(totalCostOfLoan);
|
final BigDecimal totalExpectedRepayment = cumulativePrincipalDisbursed.add(totalCostOfLoan);
|
||||||
final BigDecimal totalPaidToDate = cumulativePrincipalPaid.add(cumulativeInterestPaid).add(cumulativeChargesPaid);
|
final BigDecimal totalPaidToDate = cumulativePrincipalPaid.add(cumulativeInterestPaid).add(cumulativeChargesPaid);
|
||||||
final BigDecimal totalWaivedToDate = cumulativeInterestWaived;
|
final BigDecimal totalWaivedToDate = cumulativeInterestWaived;
|
||||||
|
final BigDecimal totalWrittenOffToDate = cumulativePrincipalWrittenOff.add(cumulativeInterestWrittenOff);
|
||||||
final BigDecimal totalOutstanding = cumulativePrincipalOutstanding.add(cumulativeInterestOutstanding).add(cumulativeChargesOutstanding);
|
final BigDecimal totalOutstanding = cumulativePrincipalOutstanding.add(cumulativeInterestOutstanding).add(cumulativeChargesOutstanding);
|
||||||
|
|
||||||
final BigDecimal totalOverdue = wrapper.deriveCumulativeTotalOverdue();
|
final BigDecimal totalOverdue = wrapper.deriveCumulativeTotalOverdue();
|
||||||
@@ -149,31 +151,29 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
totalInArrears = totalOverdueMoney.getAmount();
|
totalInArrears = totalOverdueMoney.getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LoanScheduleNewData(currency, periods, loanTermInDays,
|
return new LoanScheduleData(currency, periods, loanTermInDays,
|
||||||
cumulativePrincipalDisbursed, cumulativePrincipalDue, cumulativePrincipalPaid, cumulativePrincipalOutstanding,
|
cumulativePrincipalDisbursed, cumulativePrincipalDue, cumulativePrincipalPaid, cumulativePrincipalWrittenOff, cumulativePrincipalOutstanding,
|
||||||
cumulativeInterestExpected, cumulativeInterestPaid, cumulativeInterestWaived, cumulativeInterestOutstanding,
|
cumulativeInterestExpected, cumulativeInterestPaid, cumulativeInterestWaived, cumulativeInterestWrittenOff, cumulativeInterestOutstanding,
|
||||||
cumulativeChargesToDate, cumulativeChargesPaid, cumulativeChargesOutstanding,
|
cumulativeChargesToDate, cumulativeChargesPaid, cumulativeChargesOutstanding,
|
||||||
totalCostOfLoan, totalExpectedRepayment, totalPaidToDate, totalWaivedToDate, totalOutstanding, totalInArrears);
|
totalCostOfLoan, totalExpectedRepayment, totalPaidToDate, totalWaivedToDate, totalWrittenOffToDate, totalOutstanding, totalInArrears);
|
||||||
} catch (EmptyResultDataAccessException e) {
|
} catch (EmptyResultDataAccessException e) {
|
||||||
throw new LoanNotFoundException(loanId);
|
throw new LoanNotFoundException(loanId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<LoanRepaymentTransactionData> retrieveLoanPayments(Long loanId) {
|
public Collection<LoanTransactionNewData> retrieveLoanTransactions(final Long loanId) {
|
||||||
try {
|
try {
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
|
|
||||||
LoanPaymentsMapper rm = new LoanPaymentsMapper();
|
LoanTransactionsMapper rm = new LoanTransactionsMapper();
|
||||||
|
|
||||||
// retrieve all loan transactions that are not invalid (0) and not
|
// retrieve all loan transactions that are not invalid and have not been 'contra'ed by another transaction
|
||||||
// disbursements (1) and have not been 'contra'ed by another transaction
|
|
||||||
// repayments at time of disbursement (e.g. charges)
|
// repayments at time of disbursement (e.g. charges)
|
||||||
String sql = "select "
|
String sql = "select "
|
||||||
+ rm.LoanPaymentsSchema()
|
+ rm.LoanPaymentsSchema()
|
||||||
+ " where tr.loan_id = ? and tr.transaction_type_enum not in (0, 1, 5) and tr.contra_id is null order by tr.transaction_date ASC";
|
+ " where tr.loan_id = ? and tr.transaction_type_enum not in (0, 3) and tr.contra_id is null order by tr.transaction_date ASC";
|
||||||
return this.jdbcTemplate.query(sql, rm, new Object[] { loanId });
|
return this.jdbcTemplate.query(sql, rm, new Object[] { loanId });
|
||||||
|
|
||||||
} catch (EmptyResultDataAccessException e) {
|
} catch (EmptyResultDataAccessException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -181,8 +181,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanPermissionData retrieveLoanPermissions(
|
public LoanPermissionData retrieveLoanPermissions(
|
||||||
LoanBasicDetailsData loanBasicDetails, boolean isWaiverAllowed,
|
final LoanBasicDetailsData loanBasicDetails,
|
||||||
int repaymentAndWaiveCount) {
|
final boolean isWaiverAllowed,
|
||||||
|
final int repaymentAndWaiveCount) {
|
||||||
|
|
||||||
boolean pendingApproval = (loanBasicDetails.getStatus().getId().equals(100L));
|
boolean pendingApproval = (loanBasicDetails.getStatus().getId().equals(100L));
|
||||||
boolean waitingForDisbursal = (loanBasicDetails.getStatus().getId().equals(200L));
|
boolean waitingForDisbursal = (loanBasicDetails.getStatus().getId().equals(200L));
|
||||||
@@ -307,9 +308,19 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
|
|
||||||
LoanTransaction waiveOfInterest = loan.deriveDefaultInterestWaiverTransaction();
|
LoanTransaction waiveOfInterest = loan.deriveDefaultInterestWaiverTransaction();
|
||||||
|
|
||||||
EnumOptionData waiverEnum = LoanEnumerations.transactionType(LoanTransactionType.WAIVED);
|
EnumOptionData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WAIVE_INTEREST);
|
||||||
|
|
||||||
return new LoanTransactionNewData(waiverEnum, currencyData, waiveOfInterest.getTransactionDate(), waiveOfInterest.getAmount());
|
return new LoanTransactionNewData(null, transactionType, currencyData, waiveOfInterest.getTransactionDate(), waiveOfInterest.getAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoanTransactionNewData retrieveNewClosureDetails() {
|
||||||
|
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
EnumOptionData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WRITEOFF);
|
||||||
|
|
||||||
|
return new LoanTransactionNewData(null, transactionType, null, new LocalDate(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -512,8 +523,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
public String loanScheduleSchema() {
|
public String loanScheduleSchema() {
|
||||||
|
|
||||||
return " ls.loan_id as loanId, ls.installment as period, ls.duedate as dueDate, "
|
return " ls.loan_id as loanId, ls.installment as period, ls.duedate as dueDate, "
|
||||||
+ " ls.principal_amount as principalDue, ls.principal_completed_derived as principalPaid, "
|
+ " ls.principal_amount as principalDue, ls.principal_completed_derived as principalPaid, ls.principal_writtenoff_derived as principalWrittenOff, "
|
||||||
+ " ls.interest_amount as interestDue, ls.interest_completed_derived as interestPaid, ls.interest_waived_derived as interestWaived "
|
+ " ls.interest_amount as interestDue, ls.interest_completed_derived as interestPaid, ls.interest_waived_derived as interestWaived, ls.interest_writtenoff_derived as interestWrittenOff "
|
||||||
+ " from m_loan l "
|
+ " from m_loan l "
|
||||||
+ " join m_loan_repayment_schedule ls on ls.loan_id = l.id ";
|
+ " join m_loan_repayment_schedule ls on ls.loan_id = l.id ";
|
||||||
}
|
}
|
||||||
@@ -526,18 +537,32 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
final LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate");
|
final LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate");
|
||||||
final BigDecimal principalDue = rs.getBigDecimal("principalDue");
|
final BigDecimal principalDue = rs.getBigDecimal("principalDue");
|
||||||
final BigDecimal principalPaid = rs.getBigDecimal("principalPaid");
|
final BigDecimal principalPaid = rs.getBigDecimal("principalPaid");
|
||||||
final BigDecimal principalOutstanding = principalDue.subtract(principalPaid);
|
BigDecimal principalWrittenOff = rs.getBigDecimal("principalWrittenOff");
|
||||||
|
if (principalWrittenOff == null) {
|
||||||
|
principalWrittenOff = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO - KW - rather than calculate this here should we put calculation on derived column on table like other columns?
|
||||||
|
final BigDecimal principalOutstanding = principalDue.subtract(principalPaid).subtract(principalWrittenOff);
|
||||||
|
|
||||||
final BigDecimal interestDue = rs.getBigDecimal("interestDue");
|
final BigDecimal interestDue = rs.getBigDecimal("interestDue");
|
||||||
final BigDecimal interestPaid = rs.getBigDecimal("interestPaid");
|
final BigDecimal interestPaid = rs.getBigDecimal("interestPaid");
|
||||||
BigDecimal interestWaived = rs.getBigDecimal("interestWaived");
|
BigDecimal interestWaived = rs.getBigDecimal("interestWaived");
|
||||||
if (interestWaived == null) {
|
if (interestWaived == null) {
|
||||||
interestWaived = BigDecimal.ZERO;
|
interestWaived = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
final BigDecimal interestOutstanding = interestDue.subtract(interestPaid).subtract(interestWaived);
|
BigDecimal interestWrittenOff = rs.getBigDecimal("interestWrittenOff");
|
||||||
|
if (interestWrittenOff == null) {
|
||||||
|
interestWrittenOff = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO - KW - rather than calculate this here should we put calculation on derived column on table like other columns?
|
||||||
|
final BigDecimal interestOutstanding = interestDue.subtract(interestPaid).subtract(interestWaived).subtract(interestWrittenOff);
|
||||||
|
|
||||||
final BigDecimal totalDueForPeriod = principalDue.add(interestDue);
|
final BigDecimal totalDueForPeriod = principalDue.add(interestDue);
|
||||||
final BigDecimal totalPaidForPeriod = principalPaid.add(interestPaid);
|
final BigDecimal totalPaidForPeriod = principalPaid.add(interestPaid);
|
||||||
final BigDecimal totalWaivedForPeriod = interestWaived;
|
final BigDecimal totalWaivedForPeriod = interestWaived;
|
||||||
|
final BigDecimal totalWrittenOffForPeriod = principalWrittenOff.add(interestWrittenOff);
|
||||||
final BigDecimal totalOutstandingForPeriod = principalOutstanding.add(interestOutstanding);
|
final BigDecimal totalOutstandingForPeriod = principalOutstanding.add(interestOutstanding);
|
||||||
|
|
||||||
final LocalDate fromDate = this.lastDueDate;
|
final LocalDate fromDate = this.lastDueDate;
|
||||||
@@ -548,50 +573,44 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
|||||||
outstandingLoanBalance = outstandingLoanBalance.subtract(principalDue);
|
outstandingLoanBalance = outstandingLoanBalance.subtract(principalDue);
|
||||||
|
|
||||||
return LoanSchedulePeriodData.repaymentPeriodWithPayments(loanId, period, fromDate, dueDate,
|
return LoanSchedulePeriodData.repaymentPeriodWithPayments(loanId, period, fromDate, dueDate,
|
||||||
principalDue, principalPaid, principalOutstanding, outstandingPrincipleBalanceOfLoan, interestDue,
|
principalDue, principalPaid, principalWrittenOff, principalOutstanding, outstandingPrincipleBalanceOfLoan, interestDue,
|
||||||
interestPaid, interestWaived, interestOutstanding, totalDueForPeriod, totalPaidForPeriod, totalWaivedForPeriod,
|
interestPaid, interestWaived, interestWrittenOff, interestOutstanding, totalDueForPeriod, totalPaidForPeriod, totalWaivedForPeriod, totalWrittenOffForPeriod,
|
||||||
totalOutstandingForPeriod);
|
totalOutstandingForPeriod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class LoanPaymentsMapper implements
|
private static final class LoanTransactionsMapper implements RowMapper<LoanTransactionNewData> {
|
||||||
RowMapper<LoanRepaymentTransactionData> {
|
|
||||||
|
|
||||||
public String LoanPaymentsSchema() {
|
public String LoanPaymentsSchema() {
|
||||||
|
|
||||||
return " tr.id as id, tr.transaction_type_enum as transactionType, tr.transaction_date as `date`, tr.amount as total, "
|
return " tr.id as id, tr.transaction_type_enum as transactionType, tr.transaction_date as `date`, tr.amount as total, "
|
||||||
+ " l.currency_code as currencyCode, l.currency_digits as currencyDigits, rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode "
|
+ " l.currency_code as currencyCode, l.currency_digits as currencyDigits, rc.`name` as currencyName, "
|
||||||
|
+ " rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode "
|
||||||
+ " from m_loan l "
|
+ " from m_loan l "
|
||||||
+ " join m_loan_transaction tr on tr.loan_id = l.id"
|
+ " join m_loan_transaction tr on tr.loan_id = l.id"
|
||||||
+ " join m_currency rc on rc.`code` = l.currency_code ";
|
+ " join m_currency rc on rc.`code` = l.currency_code ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanRepaymentTransactionData mapRow(final ResultSet rs,
|
public LoanTransactionNewData mapRow(final ResultSet rs,
|
||||||
@SuppressWarnings("unused") final int rowNum) throws SQLException {
|
@SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||||
|
|
||||||
String currencyCode = rs.getString("currencyCode");
|
String currencyCode = rs.getString("currencyCode");
|
||||||
String currencyName = rs.getString("currencyName");
|
String currencyName = rs.getString("currencyName");
|
||||||
String currencyNameCode = rs.getString("currencyNameCode");
|
String currencyNameCode = rs.getString("currencyNameCode");
|
||||||
String currencyDisplaySymbol = rs
|
String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||||
.getString("currencyDisplaySymbol");
|
Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||||
Integer currencyDigits = JdbcSupport.getInteger(rs,
|
|
||||||
"currencyDigits");
|
|
||||||
CurrencyData currencyData = new CurrencyData(currencyCode,
|
CurrencyData currencyData = new CurrencyData(currencyCode,
|
||||||
currencyName, currencyDigits, currencyDisplaySymbol,
|
currencyName, currencyDigits, currencyDisplaySymbol,
|
||||||
currencyNameCode);
|
currencyNameCode);
|
||||||
|
|
||||||
Long id = rs.getLong("id");
|
Long id = rs.getLong("id");
|
||||||
int transactionTypeInt = JdbcSupport.getInteger(rs,
|
int transactionTypeInt = JdbcSupport.getInteger(rs, "transactionType");
|
||||||
"transactionType");
|
EnumOptionData transactionType = LoanEnumerations.transactionType(transactionTypeInt);
|
||||||
EnumOptionData transactionType = LoanEnumerations
|
|
||||||
.transactionType(transactionTypeInt);
|
|
||||||
LocalDate date = JdbcSupport.getLocalDate(rs, "date");
|
LocalDate date = JdbcSupport.getLocalDate(rs, "date");
|
||||||
BigDecimal totalBD = rs.getBigDecimal("total");
|
BigDecimal totalAmount = rs.getBigDecimal("total");
|
||||||
MoneyData total = MoneyData.of(currencyData, totalBD);
|
|
||||||
|
|
||||||
return new LoanRepaymentTransactionData(id, transactionType, date, total);
|
return new LoanTransactionNewData(id, transactionType, currencyData, date, totalAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+16
@@ -37,6 +37,14 @@ public class LoanSchedulePeriodDataWrapper {
|
|||||||
return cumulativeValue;
|
return cumulativeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal deriveCumulativePrincipalWrittenOff() {
|
||||||
|
BigDecimal cumulativeValue = BigDecimal.ZERO;
|
||||||
|
for (LoanSchedulePeriodData period : this.periods) {
|
||||||
|
cumulativeValue = cumulativeValue.add(period.principalWrittenOff());
|
||||||
|
}
|
||||||
|
return cumulativeValue;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal deriveCumulativePrincipalOutstanding() {
|
public BigDecimal deriveCumulativePrincipalOutstanding() {
|
||||||
BigDecimal cumulativeValue = BigDecimal.ZERO;
|
BigDecimal cumulativeValue = BigDecimal.ZERO;
|
||||||
for (LoanSchedulePeriodData period : this.periods) {
|
for (LoanSchedulePeriodData period : this.periods) {
|
||||||
@@ -69,6 +77,14 @@ public class LoanSchedulePeriodDataWrapper {
|
|||||||
return cumulativeValue;
|
return cumulativeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal deriveCumulativeInterestWrittenOff() {
|
||||||
|
BigDecimal cumulativeValue = BigDecimal.ZERO;
|
||||||
|
for (LoanSchedulePeriodData period : this.periods) {
|
||||||
|
cumulativeValue = cumulativeValue.add(period.interestWrittenOff());
|
||||||
|
}
|
||||||
|
return cumulativeValue;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal deriveCumulativeInterestOutstanding() {
|
public BigDecimal deriveCumulativeInterestOutstanding() {
|
||||||
BigDecimal cumulativeValue = BigDecimal.ZERO;
|
BigDecimal cumulativeValue = BigDecimal.ZERO;
|
||||||
for (LoanSchedulePeriodData period : this.periods) {
|
for (LoanSchedulePeriodData period : this.periods) {
|
||||||
|
|||||||
+15
-1
@@ -12,7 +12,7 @@ public class LoanTransactionCommandValidator {
|
|||||||
|
|
||||||
private final LoanTransactionCommand command;
|
private final LoanTransactionCommand command;
|
||||||
|
|
||||||
public LoanTransactionCommandValidator(LoanTransactionCommand command) {
|
public LoanTransactionCommandValidator(final LoanTransactionCommand command) {
|
||||||
this.command = command;
|
this.command = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,4 +31,18 @@ public class LoanTransactionCommandValidator {
|
|||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void validateNonMonetaryTransaction() {
|
||||||
|
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
|
||||||
|
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.transaction");
|
||||||
|
|
||||||
|
baseDataValidator.reset().parameter("loanId").value(command.getLoanId()).notNull().integerGreaterThanZero();
|
||||||
|
baseDataValidator.reset().parameter("transactionDate").value(command.getTransactionDate()).notNull();
|
||||||
|
baseDataValidator.reset().parameter("note").value(command.getNote()).notExceedingLengthOf(1000);
|
||||||
|
|
||||||
|
if (!dataValidationErrors.isEmpty()) {
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+6
@@ -47,6 +47,12 @@ public interface LoanWritePlatformService {
|
|||||||
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')")
|
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')")
|
||||||
EntityIdentifier waiveInterestOnLoan(LoanTransactionCommand command);
|
EntityIdentifier waiveInterestOnLoan(LoanTransactionCommand command);
|
||||||
|
|
||||||
|
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')")
|
||||||
|
EntityIdentifier writeOff(LoanTransactionCommand command);
|
||||||
|
|
||||||
|
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')")
|
||||||
|
EntityIdentifier closeAsRescheduled(LoanTransactionCommand command);
|
||||||
|
|
||||||
@PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')")
|
@PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')")
|
||||||
EntityIdentifier addLoanCharge(LoanChargeCommand command);
|
EntityIdentifier addLoanCharge(LoanChargeCommand command);
|
||||||
|
|
||||||
|
|||||||
+62
-4
@@ -8,7 +8,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand;
|
import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand;
|
||||||
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
|
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
|
||||||
import org.mifosng.platform.api.commands.LoanApplicationCommand;
|
import org.mifosng.platform.api.commands.LoanApplicationCommand;
|
||||||
@@ -161,7 +161,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final LoanTransactionProcessingStrategy strategy = this.loanAssembler.findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
|
final LoanTransactionProcessingStrategy strategy = this.loanAssembler.findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
|
||||||
final Set<LoanCharge> charges = this.loanChargeAssembler.assembleFrom(command.getCharges(), loanProduct.getCharges(), loan.getPrincpal().getAmount());
|
final Set<LoanCharge> charges = this.loanChargeAssembler.assembleFrom(command.getCharges(), loanProduct.getCharges(), loan.getPrincpal().getAmount());
|
||||||
|
|
||||||
final LoanScheduleNewData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(command.toCalculateLoanScheduleCommand());
|
final LoanScheduleData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(command.toCalculateLoanScheduleCommand());
|
||||||
loan.modifyLoanApplication(command, client, loanProduct, fund, strategy, loanSchedule, charges, loanOfficer);
|
loan.modifyLoanApplication(command, client, loanProduct, fund, strategy, loanSchedule, charges, loanOfficer);
|
||||||
|
|
||||||
this.loanRepository.save(loan);
|
this.loanRepository.save(loan);
|
||||||
@@ -373,7 +373,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loanTermFrequency, loanTermFrequencyType,
|
loanTermFrequency, loanTermFrequencyType,
|
||||||
actualDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate, loanChargeCommands);
|
actualDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate, loanChargeCommands);
|
||||||
|
|
||||||
LoanScheduleNewData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(calculateCommand);
|
LoanScheduleData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(calculateCommand);
|
||||||
|
|
||||||
List<LoanRepaymentScheduleInstallment> modifiedLoanRepaymentSchedule = new ArrayList<LoanRepaymentScheduleInstallment>();
|
List<LoanRepaymentScheduleInstallment> modifiedLoanRepaymentSchedule = new ArrayList<LoanRepaymentScheduleInstallment>();
|
||||||
|
|
||||||
@@ -494,7 +494,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
// adjustment is only supported for repayments and waivers at present
|
// adjustment is only supported for repayments and waivers at present
|
||||||
LocalDate transactionDate = command.getTransactionDate();
|
LocalDate transactionDate = command.getTransactionDate();
|
||||||
LoanTransaction newTransactionDetail = LoanTransaction.repayment(transactionAmount, transactionDate);
|
LoanTransaction newTransactionDetail = LoanTransaction.repayment(transactionAmount, transactionDate);
|
||||||
if (transactionToAdjust.isWaiver()) {
|
if (transactionToAdjust.isInterestWaiver()) {
|
||||||
newTransactionDetail = LoanTransaction.waiver(loan, transactionAmount, transactionDate);
|
newTransactionDetail = LoanTransaction.waiver(loan, transactionAmount, transactionDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,6 +541,62 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
return new EntityIdentifier(loan.getId());
|
return new EntityIdentifier(loan.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public EntityIdentifier writeOff(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 writeoff = loan.closeAsWrittenOff(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);
|
||||||
|
this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EntityIdentifier(loan.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public EntityIdentifier closeAsRescheduled(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());
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME - kw - HANDLE closed and rescheduled case.
|
||||||
|
final LoanTransaction writeoff = loan.closeAsWrittenOff(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);
|
||||||
|
this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EntityIdentifier(loan.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public EntityIdentifier addLoanCharge(LoanChargeCommand command) {
|
public EntityIdentifier addLoanCharge(LoanChargeCommand command) {
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
@@ -579,6 +635,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
return new EntityIdentifier(loanCharge.getId());
|
return new EntityIdentifier(loanCharge.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public EntityIdentifier updateLoanCharge(final LoanChargeCommand command) {
|
public EntityIdentifier updateLoanCharge(final LoanChargeCommand command) {
|
||||||
|
|
||||||
@@ -604,6 +661,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
throw new ChargeNotFoundException(command.getId());
|
throw new ChargeNotFoundException(command.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public EntityIdentifier deleteLoanCharge(Long loanId, Long loanChargeId) {
|
public EntityIdentifier deleteLoanCharge(Long loanId, Long loanChargeId) {
|
||||||
|
|
||||||
|
|||||||
+31
-12
@@ -173,20 +173,32 @@ public class LoanEnumerations {
|
|||||||
public static EnumOptionData transactionType(final LoanTransactionType type) {
|
public static EnumOptionData transactionType(final LoanTransactionType type) {
|
||||||
EnumOptionData optionData = null;
|
EnumOptionData optionData = null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case INVALID:
|
||||||
|
optionData = new EnumOptionData(LoanTransactionType.INVALID.getValue().longValue(), LoanTransactionType.INVALID.getCode(), "Invalid");
|
||||||
|
break;
|
||||||
case DISBURSEMENT:
|
case DISBURSEMENT:
|
||||||
optionData= new EnumOptionData(LoanTransactionType.DISBURSEMENT.getValue().longValue(), LoanTransactionType.DISBURSEMENT.getCode(), "Dibursement");
|
optionData= new EnumOptionData(LoanTransactionType.DISBURSEMENT.getValue().longValue(), LoanTransactionType.DISBURSEMENT.getCode(), "Dibursement");
|
||||||
break;
|
break;
|
||||||
case REPAYMENT:
|
case REPAYMENT:
|
||||||
optionData = new EnumOptionData(LoanTransactionType.REPAYMENT.getValue().longValue(), LoanTransactionType.REPAYMENT.getCode(), "Repayment");
|
optionData = new EnumOptionData(LoanTransactionType.REPAYMENT.getValue().longValue(), LoanTransactionType.REPAYMENT.getCode(), "Repayment");
|
||||||
break;
|
break;
|
||||||
case REVERSAL:
|
case REPAYMENT_AT_DISBURSEMENT:
|
||||||
optionData = new EnumOptionData(LoanTransactionType.REVERSAL.getValue().longValue(), LoanTransactionType.REVERSAL.getCode(), "Reversal");
|
optionData = new EnumOptionData(LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue().longValue(), LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getCode(), "Repayment (at time of disbursement)");
|
||||||
break;
|
break;
|
||||||
case WAIVED:
|
case CONTRA:
|
||||||
optionData = new EnumOptionData(LoanTransactionType.WAIVED.getValue().longValue(), LoanTransactionType.WAIVED.getCode(), "Waiver");
|
optionData = new EnumOptionData(LoanTransactionType.CONTRA.getValue().longValue(), LoanTransactionType.CONTRA.getCode(), "Reversal");
|
||||||
break;
|
break;
|
||||||
default:
|
case WAIVE_INTEREST:
|
||||||
optionData = new EnumOptionData(LoanTransactionType.INVALID.getValue().longValue(), LoanTransactionType.INVALID.getCode(), "Invalid");
|
optionData = new EnumOptionData(LoanTransactionType.WAIVE_INTEREST.getValue().longValue(), LoanTransactionType.WAIVE_INTEREST.getCode(), "Waive interest");
|
||||||
|
break;
|
||||||
|
case MARKED_FOR_RESCHEDULING:
|
||||||
|
optionData = new EnumOptionData(LoanTransactionType.MARKED_FOR_RESCHEDULING.getValue().longValue(), LoanTransactionType.MARKED_FOR_RESCHEDULING.getCode(), "Close (as rescheduled)");
|
||||||
|
break;
|
||||||
|
case WRITEOFF:
|
||||||
|
optionData = new EnumOptionData(LoanTransactionType.WRITEOFF.getValue().longValue(), LoanTransactionType.WRITEOFF.getCode(), "Close (as written-off)");
|
||||||
|
break;
|
||||||
|
case RECOVERY_REPAYMENT:
|
||||||
|
optionData = new EnumOptionData(LoanTransactionType.RECOVERY_REPAYMENT.getValue().longValue(), LoanTransactionType.RECOVERY_REPAYMENT.getCode(), "Repayment (after write-off)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return optionData;
|
return optionData;
|
||||||
@@ -197,8 +209,11 @@ public class LoanEnumerations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static EnumOptionData status(final LoanStatus status) {
|
public static EnumOptionData status(final LoanStatus status) {
|
||||||
EnumOptionData optionData = null;
|
EnumOptionData optionData = new EnumOptionData(LoanStatus.INVALID.getValue().longValue(), LoanStatus.INVALID.getCode(), "Invalid");
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
case INVALID:
|
||||||
|
optionData = new EnumOptionData(LoanStatus.INVALID.getValue().longValue(), LoanStatus.INVALID.getCode(), "Invalid");
|
||||||
|
break;
|
||||||
case SUBMITED_AND_PENDING_APPROVAL:
|
case SUBMITED_AND_PENDING_APPROVAL:
|
||||||
optionData = new EnumOptionData(LoanStatus.SUBMITED_AND_PENDING_APPROVAL.getValue().longValue(), LoanStatus.SUBMITED_AND_PENDING_APPROVAL.getCode(), "Submitted and pending approval");
|
optionData = new EnumOptionData(LoanStatus.SUBMITED_AND_PENDING_APPROVAL.getValue().longValue(), LoanStatus.SUBMITED_AND_PENDING_APPROVAL.getCode(), "Submitted and pending approval");
|
||||||
break;
|
break;
|
||||||
@@ -214,16 +229,20 @@ public class LoanEnumerations {
|
|||||||
case WITHDRAWN_BY_CLIENT:
|
case WITHDRAWN_BY_CLIENT:
|
||||||
optionData = new EnumOptionData(LoanStatus.WITHDRAWN_BY_CLIENT.getValue().longValue(), LoanStatus.WITHDRAWN_BY_CLIENT.getCode(), "Withdrawn by applicant");
|
optionData = new EnumOptionData(LoanStatus.WITHDRAWN_BY_CLIENT.getValue().longValue(), LoanStatus.WITHDRAWN_BY_CLIENT.getCode(), "Withdrawn by applicant");
|
||||||
break;
|
break;
|
||||||
case CLOSED:
|
case CLOSED_OBLIGATIONS_MET:
|
||||||
optionData = new EnumOptionData(LoanStatus.CLOSED.getValue().longValue(), LoanStatus.CLOSED.getCode(), "Closed");
|
optionData = new EnumOptionData(LoanStatus.CLOSED_OBLIGATIONS_MET.getValue().longValue(), LoanStatus.CLOSED_OBLIGATIONS_MET.getCode(), "Closed (obligations met)");
|
||||||
|
break;
|
||||||
|
case CLOSED_WRITTEN_OFF:
|
||||||
|
optionData = new EnumOptionData(LoanStatus.CLOSED_WRITTEN_OFF.getValue().longValue(), LoanStatus.CLOSED_WRITTEN_OFF.getCode(), "Closed (written off)");
|
||||||
|
break;
|
||||||
|
case CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT:
|
||||||
|
optionData = new EnumOptionData(LoanStatus.CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT.getValue().longValue(), LoanStatus.CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT.getCode(), "Closed (rescheduled)");
|
||||||
break;
|
break;
|
||||||
case OVERPAID:
|
case OVERPAID:
|
||||||
optionData = new EnumOptionData(LoanStatus.OVERPAID.getValue().longValue(), LoanStatus.OVERPAID.getCode(), "Overpaid");
|
optionData = new EnumOptionData(LoanStatus.OVERPAID.getValue().longValue(), LoanStatus.OVERPAID.getCode(), "Overpaid");
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
optionData = new EnumOptionData(LoanStatus.INVALID.getValue().longValue(), LoanStatus.INVALID.getCode(), "Invalid");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return optionData;
|
return optionData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -5,14 +5,14 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
||||||
import org.mifosng.platform.loan.domain.LoanCharge;
|
import org.mifosng.platform.loan.domain.LoanCharge;
|
||||||
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
|
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
|
||||||
|
|
||||||
public interface AmortizationLoanScheduleGenerator {
|
public interface AmortizationLoanScheduleGenerator {
|
||||||
|
|
||||||
LoanScheduleNewData generate(
|
LoanScheduleData generate(
|
||||||
ApplicationCurrency applicationCurrency,
|
ApplicationCurrency applicationCurrency,
|
||||||
LoanProductRelatedDetail loanScheduleInfo,
|
LoanProductRelatedDetail loanScheduleInfo,
|
||||||
LocalDate disbursementDate,
|
LocalDate disbursementDate,
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
||||||
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
||||||
import org.mifosng.platform.loan.domain.LoanCharge;
|
import org.mifosng.platform.loan.domain.LoanCharge;
|
||||||
@@ -36,7 +36,7 @@ public class DecliningBalanceMethodLoanScheduleGenerator implements LoanSchedule
|
|||||||
private final AmortizationLoanScheduleGeneratorFactory amortizationLoanScheduleGeneratorFactory = new AmortizationLoanScheduleGeneratorFactory();
|
private final AmortizationLoanScheduleGeneratorFactory amortizationLoanScheduleGeneratorFactory = new AmortizationLoanScheduleGeneratorFactory();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanScheduleNewData generate(
|
public LoanScheduleData generate(
|
||||||
final ApplicationCurrency applicationCurrency,
|
final ApplicationCurrency applicationCurrency,
|
||||||
final LoanProductRelatedDetail loanScheduleInfo,
|
final LoanProductRelatedDetail loanScheduleInfo,
|
||||||
final Integer loanTermFrequency,
|
final Integer loanTermFrequency,
|
||||||
|
|||||||
+3
-3
@@ -8,7 +8,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.joda.time.Days;
|
import org.joda.time.Days;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.data.CurrencyData;
|
import org.mifosng.platform.api.data.CurrencyData;
|
||||||
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
||||||
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
||||||
@@ -27,7 +27,7 @@ public class EqualInstallmentsAmortizationLoanScheduleGenerator implements Amort
|
|||||||
private final PmtCalculator pmtCalculator = new PmtCalculator();
|
private final PmtCalculator pmtCalculator = new PmtCalculator();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanScheduleNewData generate(
|
public LoanScheduleData generate(
|
||||||
final ApplicationCurrency currency,
|
final ApplicationCurrency currency,
|
||||||
final LoanProductRelatedDetail loanScheduleInfo,
|
final LoanProductRelatedDetail loanScheduleInfo,
|
||||||
final LocalDate disbursementDate,
|
final LocalDate disbursementDate,
|
||||||
@@ -150,7 +150,7 @@ public class EqualInstallmentsAmortizationLoanScheduleGenerator implements Amort
|
|||||||
currency.getDisplaySymbol(),
|
currency.getDisplaySymbol(),
|
||||||
currency.getNameCode());
|
currency.getNameCode());
|
||||||
|
|
||||||
return new LoanScheduleNewData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue,
|
return new LoanScheduleData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue,
|
||||||
cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment);
|
cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -8,7 +8,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.joda.time.Days;
|
import org.joda.time.Days;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.data.CurrencyData;
|
import org.mifosng.platform.api.data.CurrencyData;
|
||||||
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
||||||
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
||||||
@@ -23,7 +23,7 @@ public class EqualPrincipalAmortizationLoanScheduleGenerator implements Amortiza
|
|||||||
private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator = new DefaultPaymentPeriodsInOneYearCalculator();
|
private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator = new DefaultPaymentPeriodsInOneYearCalculator();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanScheduleNewData generate(
|
public LoanScheduleData generate(
|
||||||
final ApplicationCurrency currency,
|
final ApplicationCurrency currency,
|
||||||
final LoanProductRelatedDetail loanScheduleInfo,
|
final LoanProductRelatedDetail loanScheduleInfo,
|
||||||
final LocalDate disbursementDate,
|
final LocalDate disbursementDate,
|
||||||
@@ -131,7 +131,7 @@ public class EqualPrincipalAmortizationLoanScheduleGenerator implements Amortiza
|
|||||||
currency.getDisplaySymbol(),
|
currency.getDisplaySymbol(),
|
||||||
currency.getNameCode());
|
currency.getNameCode());
|
||||||
|
|
||||||
return new LoanScheduleNewData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue,
|
return new LoanScheduleData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue,
|
||||||
cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment);
|
cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -10,7 +10,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.joda.time.Days;
|
import org.joda.time.Days;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.api.data.CurrencyData;
|
import org.mifosng.platform.api.data.CurrencyData;
|
||||||
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
||||||
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
||||||
@@ -26,7 +26,7 @@ public class FlatMethodLoanScheduleGenerator implements LoanScheduleGenerator {
|
|||||||
private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator = new DefaultPaymentPeriodsInOneYearCalculator();
|
private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator = new DefaultPaymentPeriodsInOneYearCalculator();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanScheduleNewData generate(
|
public LoanScheduleData generate(
|
||||||
final ApplicationCurrency currency,
|
final ApplicationCurrency currency,
|
||||||
final LoanProductRelatedDetail loanScheduleInfo,
|
final LoanProductRelatedDetail loanScheduleInfo,
|
||||||
final Integer loanTermFrequency,
|
final Integer loanTermFrequency,
|
||||||
@@ -138,7 +138,7 @@ public class FlatMethodLoanScheduleGenerator implements LoanScheduleGenerator {
|
|||||||
currency.getDisplaySymbol(),
|
currency.getDisplaySymbol(),
|
||||||
currency.getNameCode());
|
currency.getNameCode());
|
||||||
|
|
||||||
return new LoanScheduleNewData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue,
|
return new LoanScheduleData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue,
|
||||||
cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment);
|
cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -3,7 +3,7 @@ package org.mifosng.platform.loanschedule.domain;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
import org.mifosng.platform.api.LoanScheduleData;
|
||||||
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
import org.mifosng.platform.currency.domain.ApplicationCurrency;
|
||||||
import org.mifosng.platform.loan.domain.LoanCharge;
|
import org.mifosng.platform.loan.domain.LoanCharge;
|
||||||
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
|
import org.mifosng.platform.loan.domain.LoanProductRelatedDetail;
|
||||||
@@ -11,7 +11,7 @@ import org.mifosng.platform.loan.domain.PeriodFrequencyType;
|
|||||||
|
|
||||||
public interface LoanScheduleGenerator {
|
public interface LoanScheduleGenerator {
|
||||||
|
|
||||||
LoanScheduleNewData generate(ApplicationCurrency applicationCurrency,
|
LoanScheduleData generate(ApplicationCurrency applicationCurrency,
|
||||||
LoanProductRelatedDetail loanScheduleInfo,
|
LoanProductRelatedDetail loanScheduleInfo,
|
||||||
Integer loanTermFrequency,
|
Integer loanTermFrequency,
|
||||||
PeriodFrequencyType loanTermFrequencyType,
|
PeriodFrequencyType loanTermFrequencyType,
|
||||||
|
|||||||
Reference in New Issue
Block a user