Merge branch 'MIFOSX-1068' of git://github.com/Nayan/mifosx into Nayan-MIFOSX-1068

Conflicts:
	mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java
	mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java
	mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java
This commit is contained in:
Vishwas Babu A J
2014-11-13 21:35:54 +05:30
15 changed files with 552 additions and 164 deletions
+9
View File
@@ -8023,6 +8023,15 @@ Request Body:
<td>approvedOnDate</td> <td>approvedOnDate</td>
</tr> </tr>
</table> </table>
</br>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Optional Fields</div></td>
</tr>
<tr class=alt>
<td>approvedLoanAmount</td>
</tr>
</table>
</div> </div>
<div class="method-example"> <div class="method-example">
<code class="method-declaration"> <code class="method-declaration">
@@ -0,0 +1,107 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.integrationtests;
import java.util.HashMap;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.builder.ResponseSpecBuilder;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
import org.mifosplatform.integrationtests.common.ClientHelper;
import org.mifosplatform.integrationtests.common.CommonConstants;
import org.mifosplatform.integrationtests.common.Utils;
import org.mifosplatform.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.mifosplatform.integrationtests.common.loans.LoanProductTestBuilder;
import org.mifosplatform.integrationtests.common.loans.LoanStatusChecker;
import org.mifosplatform.integrationtests.common.loans.LoanTransactionHelper;
@SuppressWarnings("rawtypes")
public class LoanApplicationApprovalTest {
private ResponseSpecification responseSpec;
private ResponseSpecification responseSpecForStatusCode403;
private RequestSpecification requestSpec;
private LoanTransactionHelper loanTransactionHelper;
@Before
public void setup() {
Utils.initializeRESTAssured();
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.responseSpecForStatusCode403 = new ResponseSpecBuilder().expectStatusCode(403).build();
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
}
/*
* Positive test case: Approved amount non zero is less than proposed amount
*
*/
@Test
public void loanApplicationApprovedAmountLessThanProposedAmount() {
final String proposedAmount = "8000";
final String approvalAmount = "5000";
final String approveDate = "20 September 2012";
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder().build(null));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, proposedAmount);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, approvalAmount, loanID);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
}
/*
* Negative test case: Approved amount non zero is greater than proposed amount
*
*/
@Test
public void loanApplicationApprovedAmountGreaterThanProposedAmount() {
final String proposedAmount = "5000";
final String approvalAmount = "9000";
final String approveDate = "20 September 2011";
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder().build(null));
final Integer loanID = applyForLoanApplication(clientID, loanProductID, proposedAmount);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpecForStatusCode403);
@SuppressWarnings("unchecked")
List<HashMap> error = (List<HashMap>) this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, approvalAmount, loanID,
CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.loan.approval.amount.can't.be.greater.than.loan.amount.demanded", error
.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
}
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String proposedAmount) {
final String loanApplication = new LoanApplicationTestBuilder().withPrincipal(proposedAmount).withLoanTermFrequency("5")
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1")
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("04 April 2012")
.withSubmittedOnDate("02 April 2012").build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplication);
}
}
@@ -97,6 +97,19 @@ public class LoanTransactionHelper {
public HashMap approveLoan(final String approvalDate, final Integer loanID) { public HashMap approveLoan(final String approvalDate, final Integer loanID) {
return performLoanTransaction(createLoanOperationURL(APPROVE_LOAN_COMMAND, loanID), getApproveLoanAsJSON(approvalDate)); return performLoanTransaction(createLoanOperationURL(APPROVE_LOAN_COMMAND, loanID), getApproveLoanAsJSON(approvalDate));
} }
public HashMap approveLoanWithApproveAmount(final String approvalDate, final String approvalAmount, final Integer loanID) {
return performLoanTransaction(createLoanOperationURL(APPROVE_LOAN_COMMAND, loanID), getApproveLoanAsJSON(approvalDate, approvalAmount));
}
public Object approveLoanWithApproveAmount(final String approvalDate, final String approvalAmount, final Integer loanID,
final String responseAttribute) {
final String approvalURL = createLoanOperationURL(APPROVE_LOAN_COMMAND, loanID);
final String approvalJSONData = getApproveLoanAsJSON(approvalDate, approvalAmount);
return performLoanTransaction(approvalURL, approvalJSONData, responseAttribute);
}
public HashMap undoApproval(final Integer loanID) { public HashMap undoApproval(final Integer loanID) {
final String undoBodyJson = "{'note':'UNDO APPROVAL'}"; final String undoBodyJson = "{'note':'UNDO APPROVAL'}";
@@ -206,6 +219,16 @@ public class LoanTransactionHelper {
map.put("note", "Approval NOTE"); map.put("note", "Approval NOTE");
return new Gson().toJson(map); return new Gson().toJson(map);
} }
private String getApproveLoanAsJSON(final String approvalDate, final String approvalAmount) {
final HashMap<String, String> map = new HashMap<>();
map.put("locale", "en");
map.put("dateFormat", "dd MMMM yyyy");
map.put("approvedLoanAmount", approvalAmount);
map.put("approvedOnDate", approvalDate);
map.put("note", "Approval NOTE");
return new Gson().toJson(map);
}
private String getRepaymentBodyAsJSON(final String transactionDate, final Float transactionAmount) { private String getRepaymentBodyAsJSON(final String transactionDate, final Float transactionAmount) {
final HashMap<String, String> map = new HashMap<>(); final HashMap<String, String> map = new HashMap<>();
@@ -356,6 +379,11 @@ public class LoanTransactionHelper {
return (HashMap) response.get("status"); return (HashMap) response.get("status");
} }
private Object performLoanTransaction(final String postURLForLoanTransaction, final String jsonToBeSent, final String responseAttribute) {
return Utils.performServerPost(this.requestSpec, this.responseSpec, postURLForLoanTransaction, jsonToBeSent, responseAttribute);
}
public HashMap getPrepayAmount(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer loanID) { public HashMap getPrepayAmount(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer loanID) {
final String URL = "/mifosng-provider/api/v1/loans/" + loanID + "/transactions/template?command=prepayLoan&" + Utils.TENANT_IDENTIFIER; final String URL = "/mifosng-provider/api/v1/loans/" + loanID + "/transactions/template?command=prepayLoan&" + Utils.TENANT_IDENTIFIER;
final HashMap response = Utils.performServerGet(requestSpec, responseSpec, URL, ""); final HashMap response = Utils.performServerGet(requestSpec, responseSpec, URL, "");
@@ -8,30 +8,20 @@ package org.mifosplatform.portfolio.loanaccount.api;
public interface LoanApiConstants { public interface LoanApiConstants {
public static final String emiAmountParameterName = "fixedEmiAmount"; public static final String emiAmountParameterName = "fixedEmiAmount";
public static final String maxOutstandingBalanceParameterName = "maxOutstandingLoanBalance"; public static final String maxOutstandingBalanceParameterName = "maxOutstandingLoanBalance";
public static final String disbursementDataParameterName = "disbursementData"; public static final String disbursementDataParameterName = "disbursementData";
public static final String disbursementDateParameterName = "expectedDisbursementDate"; public static final String disbursementDateParameterName = "expectedDisbursementDate";
public static final String disbursementPrincipalParameterName = "principal"; public static final String disbursementPrincipalParameterName = "principal";
public static final String DISBURSEMENT_DATE_START_WITH_ERROR = "first.disbursement.date.must.start.with.expected.disbursement.date";
public static final String PRINCIPAL_AMOUNT_SHOULD_BE_SAME = "sum.of.multi.disburse.amounts.must.equal.with.total.principal";
public static final String DISBURSEMENT_DATE_UNIQUE_ERROR = "disbursement.date.must.be.unique.for.tranches";
public static final String disbursementIdParameterName = "id"; public static final String disbursementIdParameterName = "id";
public static final String principalDisbursedParameterName = "transactionAmount"; public static final String principalDisbursedParameterName = "transactionAmount";
public static final String ALREADY_DISBURSED = "can.not.change.disbursement.date"; public static final String approvedLoanAmountParameterName = "approvedLoanAmount";
public static final String approvedOnDateParameterName = "approvedOnDate";
public static final String LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_INTEREST_CALCULATION_TYPE= "loancharge.with.calculation.type.interest.not.allowed"; public static final String noteParameterName = "note";
public static final String localeParameterName = "locale";
public static final String LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_PRINCIPAL_CALCULATION_TYPE= "loancharge.with.calculation.type.principal.not.allowed"; public static final String dateFormatParameterName = "dateFormat";
public static final String rejectedOnDateParameterName = "rejectedOnDate";
public static final String withdrawnOnDateParameterName = "withdrawnOnDate";
// Interest recalculation related // Interest recalculation related
public static final String isInterestRecalculationEnabledParameterName = "isInterestRecalculationEnabled"; public static final String isInterestRecalculationEnabledParameterName = "isInterestRecalculationEnabled";
@@ -39,5 +29,13 @@ public interface LoanApiConstants {
public static final String daysInMonthTypeParameterName = "daysInMonthType"; public static final String daysInMonthTypeParameterName = "daysInMonthType";
public static final String interestRecalculationCompoundingMethodParameterName = "interestRecalculationCompoundingMethod"; public static final String interestRecalculationCompoundingMethodParameterName = "interestRecalculationCompoundingMethod";
public static final String rescheduleStrategyMethodParameterName = "rescheduleStrategyMethod"; public static final String rescheduleStrategyMethodParameterName = "rescheduleStrategyMethod";
// Error codes
public static final String LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_INTEREST_CALCULATION_TYPE= "loancharge.with.calculation.type.interest.not.allowed";
public static final String LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_PRINCIPAL_CALCULATION_TYPE= "loancharge.with.calculation.type.principal.not.allowed";
public static final String DISBURSEMENT_DATE_START_WITH_ERROR = "first.disbursement.date.must.start.with.expected.disbursement.date";
public static final String PRINCIPAL_AMOUNT_SHOULD_BE_SAME = "sum.of.multi.disburse.amounts.must.equal.with.total.principal";
public static final String DISBURSEMENT_DATE_UNIQUE_ERROR = "disbursement.date.must.be.unique.for.tranches";
public static final String ALREADY_DISBURSED = "can.not.change.disbursement.date";
} }
@@ -65,6 +65,7 @@ import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.mifosplatform.portfolio.group.service.SearchParameters; import org.mifosplatform.portfolio.group.service.SearchParameters;
import org.mifosplatform.portfolio.loanaccount.data.DisbursementData; import org.mifosplatform.portfolio.loanaccount.data.DisbursementData;
import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData; import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData;
import org.mifosplatform.portfolio.loanaccount.data.LoanApprovalData;
import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData;
import org.mifosplatform.portfolio.loanaccount.data.LoanTermVariationsData; import org.mifosplatform.portfolio.loanaccount.data.LoanTermVariationsData;
import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData; import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData;
@@ -110,11 +111,13 @@ public class LoansApiResource {
"expectedFirstRepaymentOnDate", "graceOnPrincipalPayment", "graceOnInterestPayment", "graceOnInterestCharged", "expectedFirstRepaymentOnDate", "graceOnPrincipalPayment", "graceOnInterestPayment", "graceOnInterestCharged",
"interestChargedFromDate", "timeline", "totalFeeChargesAtDisbursement", "summary", "repaymentSchedule", "transactions", "interestChargedFromDate", "timeline", "totalFeeChargesAtDisbursement", "summary", "repaymentSchedule", "transactions",
"charges", "collateral", "guarantors", "meeting", "productOptions", "amortizationTypeOptions", "interestTypeOptions", "charges", "collateral", "guarantors", "meeting", "productOptions", "amortizationTypeOptions", "interestTypeOptions",
"interestCalculationPeriodTypeOptions", "repaymentFrequencyTypeOptions", "repaymentFrequencyNthDayTypeOptions", "repaymentFrequencyDaysOfWeekTypeOptions", "termFrequencyTypeOptions", "interestCalculationPeriodTypeOptions", "repaymentFrequencyTypeOptions", "repaymentFrequencyNthDayTypeOptions",
"interestRateFrequencyTypeOptions", "fundOptions", "repaymentStrategyOptions", "chargeOptions", "loanOfficerOptions", "repaymentFrequencyDaysOfWeekTypeOptions", "termFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions",
"loanPurposeOptions", "loanCollateralOptions", "chargeTemplate", "calendarOptions", "syncDisbursementWithMeeting", "repaymentStrategyOptions", "chargeOptions", "loanOfficerOptions", "loanPurposeOptions", "loanCollateralOptions",
"loanCounter", "loanProductCounter", "notes", "accountLinkingOptions", "linkedAccount")); "chargeTemplate", "calendarOptions", "syncDisbursementWithMeeting", "loanCounter", "loanProductCounter", "notes",
"accountLinkingOptions", "linkedAccount"));
private final Set<String> LOAN_APPROVAL_DATA_PARAMETERS = new HashSet<>(Arrays.asList("approvalDate", "approvalAmount"));
private final String resourceNameForPermissions = "LOAN"; private final String resourceNameForPermissions = "LOAN";
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
@@ -130,6 +133,7 @@ public class LoansApiResource {
private final CodeValueReadPlatformService codeValueReadPlatformService; private final CodeValueReadPlatformService codeValueReadPlatformService;
private final GroupReadPlatformService groupReadPlatformService; private final GroupReadPlatformService groupReadPlatformService;
private final DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer; private final DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer;
private final DefaultToApiJsonSerializer<LoanApprovalData> loanApprovalDataToApiJsonSerializer;
private final DefaultToApiJsonSerializer<LoanScheduleData> loanScheduleToApiJsonSerializer; private final DefaultToApiJsonSerializer<LoanScheduleData> loanScheduleToApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper; private final ApiRequestParameterHelper apiRequestParameterHelper;
private final FromJsonHelper fromJsonHelper; private final FromJsonHelper fromJsonHelper;
@@ -150,6 +154,7 @@ public class LoansApiResource {
final GuarantorReadPlatformService guarantorReadPlatformService, final GuarantorReadPlatformService guarantorReadPlatformService,
final CodeValueReadPlatformService codeValueReadPlatformService, final GroupReadPlatformService groupReadPlatformService, final CodeValueReadPlatformService codeValueReadPlatformService, final GroupReadPlatformService groupReadPlatformService,
final DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer, final DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer,
final DefaultToApiJsonSerializer<LoanApprovalData> loanApprovalDataToApiJsonSerializer,
final DefaultToApiJsonSerializer<LoanScheduleData> loanScheduleToApiJsonSerializer, final DefaultToApiJsonSerializer<LoanScheduleData> loanScheduleToApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper, final FromJsonHelper fromJsonHelper, final ApiRequestParameterHelper apiRequestParameterHelper, final FromJsonHelper fromJsonHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
@@ -170,6 +175,7 @@ public class LoansApiResource {
this.codeValueReadPlatformService = codeValueReadPlatformService; this.codeValueReadPlatformService = codeValueReadPlatformService;
this.groupReadPlatformService = groupReadPlatformService; this.groupReadPlatformService = groupReadPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer; this.toApiJsonSerializer = toApiJsonSerializer;
this.loanApprovalDataToApiJsonSerializer = loanApprovalDataToApiJsonSerializer;
this.loanScheduleToApiJsonSerializer = loanScheduleToApiJsonSerializer; this.loanScheduleToApiJsonSerializer = loanScheduleToApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper; this.apiRequestParameterHelper = apiRequestParameterHelper;
this.fromJsonHelper = fromJsonHelper; this.fromJsonHelper = fromJsonHelper;
@@ -181,6 +187,36 @@ public class LoansApiResource {
this.loanScheduleHistoryReadPlatformService = loanScheduleHistoryReadPlatformService; this.loanScheduleHistoryReadPlatformService = loanScheduleHistoryReadPlatformService;
} }
/*
* This template API is used for loan approval, ideally this should be
* invoked on loan that are pending for approval. But system does not
* validate the status of the loan, it returns the template irrespective of
* loan status
*/
@GET
@Path("{loanId}/template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveApprovalTemplate(@PathParam("loanId") final Long loanId, @QueryParam("templateType") final String templateType,
@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
LoanApprovalData loanApprovalTemplate = null;
if (templateType == null) {
final String errorMsg = "Loan template type must be provided";
throw new LoanTemplateTypeRequiredException(errorMsg);
} else if (templateType.equals("approval")) {
loanApprovalTemplate = this.loanReadPlatformService.retrieveApprovalTemplate(loanId);
}
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.loanApprovalDataToApiJsonSerializer.serialize(settings, loanApprovalTemplate, this.LOAN_APPROVAL_DATA_PARAMETERS);
}
@GET @GET
@Path("template") @Path("template")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@@ -413,8 +449,6 @@ public class LoansApiResource {
Collection<LoanProductData> productOptions = null; Collection<LoanProductData> productOptions = null;
Collection<EnumOptionData> loanTermFrequencyTypeOptions = null; Collection<EnumOptionData> loanTermFrequencyTypeOptions = null;
Collection<EnumOptionData> repaymentFrequencyTypeOptions = null; Collection<EnumOptionData> repaymentFrequencyTypeOptions = null;
Collection<EnumOptionData> repaymentFrequencyNthDayTypeOptions = null;
Collection<EnumOptionData> repaymentFrequencyDaysOfWeekTypeOptions = null;
Collection<TransactionProcessingStrategyData> repaymentStrategyOptions = null; Collection<TransactionProcessingStrategyData> repaymentStrategyOptions = null;
Collection<EnumOptionData> interestRateFrequencyTypeOptions = null; Collection<EnumOptionData> interestRateFrequencyTypeOptions = null;
Collection<EnumOptionData> amortizationTypeOptions = null; Collection<EnumOptionData> amortizationTypeOptions = null;
@@ -434,8 +468,6 @@ public class LoansApiResource {
productOptions = this.loanProductReadPlatformService.retrieveAllLoanProductsForLookup(); productOptions = this.loanProductReadPlatformService.retrieveAllLoanProductsForLookup();
loanTermFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions(); loanTermFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions();
repaymentFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions(); repaymentFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions();
repaymentFrequencyNthDayTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyOptionsForNthDayOfMonth();
repaymentFrequencyDaysOfWeekTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyOptionsForDaysOfWeek();
interestRateFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveInterestRateFrequencyTypeOptions(); interestRateFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveInterestRateFrequencyTypeOptions();
amortizationTypeOptions = this.dropdownReadPlatformService.retrieveLoanAmortizationTypeOptions(); amortizationTypeOptions = this.dropdownReadPlatformService.retrieveLoanAmortizationTypeOptions();
@@ -75,6 +75,8 @@ public class LoanAccountData {
private final CurrencyData currency; private final CurrencyData currency;
private final BigDecimal principal; private final BigDecimal principal;
private final BigDecimal approvedPrincipal; private final BigDecimal approvedPrincipal;
private final BigDecimal proposedPrincipal;
private final Integer termFrequency; private final Integer termFrequency;
private final EnumOptionData termPeriodFrequencyType; private final EnumOptionData termPeriodFrequencyType;
private final Integer numberOfRepayments; private final Integer numberOfRepayments;
@@ -199,6 +201,7 @@ public class LoanAccountData {
final Long loanOfficerId = null; final Long loanOfficerId = null;
final String loanOfficerName = null; final String loanOfficerName = null;
final CurrencyData currencyData = null; final CurrencyData currencyData = null;
final BigDecimal proposedPrincipal = null;
final BigDecimal principal = null; final BigDecimal principal = null;
final BigDecimal totalOverpaid = null; final BigDecimal totalOverpaid = null;
final BigDecimal inArrearsTolerance = null; final BigDecimal inArrearsTolerance = null;
@@ -275,16 +278,16 @@ public class LoanAccountData {
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId, return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal, principal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, currencyData, proposedPrincipal, principal, principal, totalOverpaid, inArrearsTolerance, termFrequency,
numberOfRepayments, repaymentEvery, repaymentFrequencyType, repaymentFrequencyNthDayType, repaymentFrequencyDayOfWeekType, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, repaymentFrequencyNthDayType,
transactionProcessingStrategyId, transactionProcessingStrategyName, amortizationType, interestRatePerPeriod, repaymentFrequencyDayOfWeekType, transactionProcessingStrategyId, transactionProcessingStrategyName, amortizationType,
interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType,
graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, summary, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges,
productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, collateral, guarantors, calendarData, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions,
repaymentFrequencyDayOfWeekTypeOptions, transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, transactionProcessingStrategyOptions,
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount, syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance, emiAmountVariations, memberVariations, disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance, emiAmountVariations, memberVariations,
product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType, product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType,
@@ -314,6 +317,7 @@ public class LoanAccountData {
final Long loanOfficerId = null; final Long loanOfficerId = null;
final String loanOfficerName = null; final String loanOfficerName = null;
final CurrencyData currencyData = null; final CurrencyData currencyData = null;
final BigDecimal proposedPrincipal = null;
final BigDecimal principal = null; final BigDecimal principal = null;
final BigDecimal totalOverpaid = null; final BigDecimal totalOverpaid = null;
final BigDecimal inArrearsTolerance = null; final BigDecimal inArrearsTolerance = null;
@@ -391,16 +395,16 @@ public class LoanAccountData {
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId, return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal, principal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, currencyData, proposedPrincipal, principal, principal, totalOverpaid, inArrearsTolerance, termFrequency,
numberOfRepayments, repaymentEvery, repaymentFrequencyType, repaymentFrequencyNthDayType, repaymentFrequencyDayOfWeekType, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, repaymentFrequencyNthDayType,
transactionProcessingStrategyId, transactionProcessingStrategyName, amortizationType, interestRatePerPeriod, repaymentFrequencyDayOfWeekType, transactionProcessingStrategyId, transactionProcessingStrategyName, amortizationType,
interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType,
graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, summary, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges,
productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, collateral, guarantors, calendarData, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions,
repaymentFrequencyDayOfWeekTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, repaymentStrategyOptions,
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount, syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance, emiAmountVariations, memberVariations, disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance, emiAmountVariations, memberVariations,
product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType, product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType,
@@ -413,7 +417,7 @@ public class LoanAccountData {
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, clientAcc.clientId, clientAcc.clientName, return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, clientAcc.clientId, clientAcc.clientName,
clientAcc.clientOfficeId, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, clientAcc.clientOfficeId, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription,
acc.fundId, acc.fundName, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.fundId, acc.fundName, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency,
acc.principal, acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.proposedPrincipal, acc.principal, acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency,
acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType,
acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId, acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId,
acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType,
@@ -456,6 +460,7 @@ public class LoanAccountData {
final Long loanOfficerId = null; final Long loanOfficerId = null;
final String loanOfficerName = null; final String loanOfficerName = null;
final CurrencyData currencyData = null; final CurrencyData currencyData = null;
final BigDecimal proposedPrincipal = null;
final BigDecimal principal = null; final BigDecimal principal = null;
final BigDecimal totalOverpaid = null; final BigDecimal totalOverpaid = null;
final BigDecimal inArrearsTolerance = null; final BigDecimal inArrearsTolerance = null;
@@ -533,16 +538,16 @@ public class LoanAccountData {
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId, return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal, principal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, currencyData, proposedPrincipal, principal, principal, totalOverpaid, inArrearsTolerance, termFrequency,
numberOfRepayments, repaymentEvery, repaymentFrequencyType, repaymentFrequencyNthDayType, repaymentFrequencyDayOfWeekType, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, repaymentFrequencyNthDayType,
transactionProcessingStrategyId, transactionProcessingStrategyName, amortizationType, interestRatePerPeriod, repaymentFrequencyDayOfWeekType, transactionProcessingStrategyId, transactionProcessingStrategyName, amortizationType,
interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType,
graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, summary, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges,
productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, collateral, guarantors, calendarData, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions,
repaymentFrequencyDayOfWeekTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, repaymentStrategyOptions,
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount, syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingBalance, emiAmountVariations, memberVariations, product, disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingBalance, emiAmountVariations, memberVariations, product,
inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
@@ -553,16 +558,16 @@ public class LoanAccountData {
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
groupAcc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, groupAcc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName,
acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.proposedPrincipal,
acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.principal, acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency,
acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, acc.repaymentFrequencyNthDayType, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType,
acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId, acc.transactionProcessingStrategyName, acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId,
acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType,
acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate,
acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, groupAcc.timeline, acc.summary, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate,
acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors, groupAcc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges,
acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, acc.collateral, acc.guarantors, acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions,
acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions, acc.repaymentFrequencyTypeOptions, acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions,
acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions,
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions, acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
@@ -649,6 +654,8 @@ public class LoanAccountData {
final Collection<DisbursementData> disbursementData = null; final Collection<DisbursementData> disbursementData = null;
final Collection<LoanTermVariationsData> emiAmountVariations = null; final Collection<LoanTermVariationsData> emiAmountVariations = null;
BigDecimal principal = null; BigDecimal principal = null;
BigDecimal proposedPrincipal = null;
BigDecimal interestRatePerPeriod = null; BigDecimal interestRatePerPeriod = null;
Integer numberOfRepayments = null; Integer numberOfRepayments = null;
if (product.useBorrowerCycle() && loanCycleNumber > 0) { if (product.useBorrowerCycle() && loanCycleNumber > 0) {
@@ -659,6 +666,7 @@ public class LoanAccountData {
Collection<LoanProductBorrowerCycleVariationData> repaymentVariationsForBorrowerCycle = product Collection<LoanProductBorrowerCycleVariationData> repaymentVariationsForBorrowerCycle = product
.getNumberOfRepaymentVariationsForBorrowerCycle(); .getNumberOfRepaymentVariationsForBorrowerCycle();
principal = fetchLoanCycleDefaultValue(principalVariationsForBorrowerCycle, loanCycleNumber); principal = fetchLoanCycleDefaultValue(principalVariationsForBorrowerCycle, loanCycleNumber);
proposedPrincipal = principal;
interestRatePerPeriod = fetchLoanCycleDefaultValue(interestForVariationsForBorrowerCycle, loanCycleNumber); interestRatePerPeriod = fetchLoanCycleDefaultValue(interestForVariationsForBorrowerCycle, loanCycleNumber);
BigDecimal numberofRepaymentval = fetchLoanCycleDefaultValue(repaymentVariationsForBorrowerCycle, loanCycleNumber); BigDecimal numberofRepaymentval = fetchLoanCycleDefaultValue(repaymentVariationsForBorrowerCycle, loanCycleNumber);
if (numberofRepaymentval != null) { if (numberofRepaymentval != null) {
@@ -667,6 +675,7 @@ public class LoanAccountData {
} }
if (principal == null) { if (principal == null) {
principal = product.getPrincipal(); principal = product.getPrincipal();
proposedPrincipal = principal;
} }
if (interestRatePerPeriod == null) { if (interestRatePerPeriod == null) {
interestRatePerPeriod = product.getInterestRatePerPeriod(); interestRatePerPeriod = product.getInterestRatePerPeriod();
@@ -685,9 +694,9 @@ public class LoanAccountData {
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType,
product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(), loanPurposeId, product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(), loanPurposeId,
loanPurposeName, loanOfficerId, loanOfficerName, product.getCurrency(), principal, principal, totalOverpaid, loanPurposeName, loanOfficerId, loanOfficerName, product.getCurrency(), proposedPrincipal, principal, principal,
product.getInArrearsTolerance(), termFrequency, termPeriodFrequencyType, numberOfRepayments, product.getRepaymentEvery(), totalOverpaid, product.getInArrearsTolerance(), termFrequency, termPeriodFrequencyType, numberOfRepayments,
product.getRepaymentFrequencyType(), null, null, product.getTransactionProcessingStrategyId(), product.getRepaymentEvery(), product.getRepaymentFrequencyType(), null, null, product.getTransactionProcessingStrategyId(),
transactionProcessingStrategyName, product.getAmortizationType(), interestRatePerPeriod, transactionProcessingStrategyName, product.getAmortizationType(), interestRatePerPeriod,
product.getInterestRateFrequencyType(), product.getAnnualInterestRate(), product.getInterestType(), product.getInterestRateFrequencyType(), product.getAnnualInterestRate(), product.getInterestType(),
product.getInterestCalculationPeriodType(), expectedFirstRepaymentOnDate, product.getGraceOnPrincipalPayment(), product.getInterestCalculationPeriodType(), expectedFirstRepaymentOnDate, product.getGraceOnPrincipalPayment(),
@@ -739,9 +748,9 @@ public class LoanAccountData {
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
acc.group, acc.loanType, product.getId(), product.getName(), product.getDescription(), product.getFundId(), acc.group, acc.loanType, product.getId(), product.getName(), product.getDescription(), product.getFundId(),
product.getFundName(), acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, product.getFundName(), acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName,
product.getCurrency(), product.getPrincipal(), product.getPrincipal(), acc.totalOverpaid, product.getInArrearsTolerance(), product.getCurrency(), product.getPrincipal(), product.getPrincipal(), product.getPrincipal(), acc.totalOverpaid,
termFrequency, termPeriodFrequencyType, product.getNumberOfRepayments(), product.getRepaymentEvery(), product.getInArrearsTolerance(), termFrequency, termPeriodFrequencyType, product.getNumberOfRepayments(),
product.getRepaymentFrequencyType(), null, null, product.getTransactionProcessingStrategyId(), product.getRepaymentEvery(), product.getRepaymentFrequencyType(), null, null, product.getTransactionProcessingStrategyId(),
product.getTransactionProcessingStrategyName(), product.getAmortizationType(), product.getInterestRatePerPeriod(), product.getTransactionProcessingStrategyName(), product.getAmortizationType(), product.getInterestRatePerPeriod(),
product.getInterestRateFrequencyType(), product.getAnnualInterestRate(), product.getInterestType(), product.getInterestRateFrequencyType(), product.getAnnualInterestRate(), product.getInterestType(),
product.getInterestCalculationPeriodType(), acc.expectedFirstRepaymentOnDate, product.getGraceOnPrincipalPayment(), product.getInterestCalculationPeriodType(), acc.expectedFirstRepaymentOnDate, product.getGraceOnPrincipalPayment(),
@@ -766,10 +775,10 @@ public class LoanAccountData {
final String externalId, final Long clientId, final String clientName, final Long clientOfficeId, final GroupGeneralData group, final String externalId, final Long clientId, final String clientName, final Long clientOfficeId, final GroupGeneralData group,
final EnumOptionData loanType, final Long loanProductId, final String loanProductName, final String loanProductDescription, final EnumOptionData loanType, final Long loanProductId, final String loanProductName, final String loanProductDescription,
final Long fundId, final String fundName, final Long loanPurposeId, final String loanPurposeName, final Long loanOfficerId, final Long fundId, final String fundName, final Long loanPurposeId, final String loanPurposeName, final Long loanOfficerId,
final String loanOfficerName, final CurrencyData currencyData, final BigDecimal principal, final BigDecimal approvedPrincipal, final String loanOfficerName, final CurrencyData currencyData, final BigDecimal proposedPrincipal, final BigDecimal principal,
final BigDecimal totalOverpaid, final BigDecimal inArrearsTolerance, final Integer termFrequency, final BigDecimal approvedPrincipal, final BigDecimal totalOverpaid, final BigDecimal inArrearsTolerance,
final EnumOptionData termPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery, final Integer termFrequency, final EnumOptionData termPeriodFrequencyType, final Integer numberOfRepayments,
final EnumOptionData repaymentFrequencyType, EnumOptionData repaymentFrequencyNthDayType, final Integer repaymentEvery, final EnumOptionData repaymentFrequencyType, EnumOptionData repaymentFrequencyNthDayType,
EnumOptionData repaymentFrequencyDayOfWeekType, final Long transactionStrategyId, final String transactionStrategyName, EnumOptionData repaymentFrequencyDayOfWeekType, final Long transactionStrategyId, final String transactionStrategyName,
final EnumOptionData amortizationType, final BigDecimal interestRatePerPeriod, final EnumOptionData interestRateFrequencyType, final EnumOptionData amortizationType, final BigDecimal interestRatePerPeriod, final EnumOptionData interestRateFrequencyType,
final BigDecimal annualInterestRate, final EnumOptionData interestType, final EnumOptionData interestCalculationPeriodType, final BigDecimal annualInterestRate, final EnumOptionData interestType, final EnumOptionData interestCalculationPeriodType,
@@ -817,11 +826,11 @@ public class LoanAccountData {
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId, return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal, approvedPrincipal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, currencyData, proposedPrincipal, principal, approvedPrincipal, totalOverpaid, inArrearsTolerance, termFrequency,
numberOfRepayments, repaymentEvery, repaymentFrequencyType, repaymentFrequencyNthDayType, repaymentFrequencyDayOfWeekType, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, repaymentFrequencyNthDayType,
transactionStrategyId, transactionStrategyName, amortizationType, interestRatePerPeriod, interestRateFrequencyType, repaymentFrequencyDayOfWeekType, transactionStrategyId, transactionStrategyName, amortizationType, interestRatePerPeriod,
annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate,
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, loanSummary, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, loanSummary,
feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData,
productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions,
repaymentFrequencyDayOfWeekTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions,
@@ -856,18 +865,18 @@ public class LoanAccountData {
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName,
acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.proposedPrincipal,
acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.principal, acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency,
acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, acc.repaymentFrequencyNthDayType, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType,
acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId, acc.transactionProcessingStrategyName, acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId,
acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType,
acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate,
acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate,
acc.feeChargesAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral,
productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, guarantors, calendarData, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions,
repaymentFrequencyDayOfWeekTypeOptions, transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, transactionProcessingStrategyOptions,
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes, accountLinkingOptions, linkedAccount, acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance, emiAmountVariations, disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance, emiAmountVariations,
acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, overdueCharges, acc.isNPA, acc.daysInMonthType, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, overdueCharges, acc.isNPA, acc.daysInMonthType,
@@ -890,16 +899,16 @@ public class LoanAccountData {
public static LoanAccountData associateGroup(final LoanAccountData acc, final GroupGeneralData group) { public static LoanAccountData associateGroup(final LoanAccountData acc, final GroupGeneralData group) {
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName,
acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.proposedPrincipal,
acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.principal, acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency,
acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, acc.repaymentFrequencyNthDayType, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType,
acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId, acc.transactionProcessingStrategyName, acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId,
acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType,
acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate,
acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate,
acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges,
acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, acc.collateral, acc.guarantors, acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions,
acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions, acc.repaymentFrequencyTypeOptions, acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions,
acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions,
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions, acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
@@ -950,16 +959,16 @@ public class LoanAccountData {
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName,
acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.proposedPrincipal,
acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.principal, acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency,
acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, acc.repaymentFrequencyNthDayType, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType,
acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId, acc.transactionProcessingStrategyName, acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId,
acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType,
acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate,
acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate,
acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges,
acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, acc.collateral, acc.guarantors, acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions,
acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions, acc.repaymentFrequencyTypeOptions, acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions,
acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions,
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions, acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
@@ -976,16 +985,16 @@ public class LoanAccountData {
acc.interestRecalculationData, calendarData); acc.interestRecalculationData, calendarData);
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName,
acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.proposedPrincipal,
acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.principal, acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency,
acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, acc.repaymentFrequencyNthDayType, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType,
acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId, acc.transactionProcessingStrategyName, acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId,
acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType,
acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate,
acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate,
acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges,
acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, acc.collateral, acc.guarantors, acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions,
acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions, acc.repaymentFrequencyTypeOptions, acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions,
acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions,
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions, acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
@@ -1000,16 +1009,16 @@ public class LoanAccountData {
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName,
acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.proposedPrincipal,
acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.principal, acc.approvedPrincipal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency,
acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, acc.repaymentFrequencyNthDayType, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType,
acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId, acc.transactionProcessingStrategyName, acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId,
acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType,
acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate,
acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate,
acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges,
acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, acc.collateral, acc.guarantors, acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions,
acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions, acc.repaymentFrequencyTypeOptions, acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions,
acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions,
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions, acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
@@ -1040,12 +1049,13 @@ public class LoanAccountData {
final Long loanOfficerId, final Long loanOfficerId,
final String loanOfficerName, // final String loanOfficerName, //
final CurrencyData currency, final CurrencyData currency,
BigDecimal proposedPrincipal,
final BigDecimal principal, final BigDecimal principal,
final BigDecimal approvedPrincipal, final BigDecimal approvedPrincipal,
final BigDecimal totalOverpaid, final BigDecimal totalOverpaid, //
final BigDecimal inArrearsTolerance, // final BigDecimal inArrearsTolerance,
final Integer termFrequency, final Integer termFrequency, //
final EnumOptionData termPeriodFrequencyType, // final EnumOptionData termPeriodFrequencyType,
final Integer numberOfRepayments, final Integer numberOfRepayments,
final Integer repaymentEvery, final Integer repaymentEvery,
final EnumOptionData repaymentFrequencyType, // final EnumOptionData repaymentFrequencyType, //
@@ -1078,6 +1088,7 @@ public class LoanAccountData {
final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled, final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled,
final LoanInterestRecalculationData interestRecalculationData, final LoanScheduleData originalSchedule, final LoanInterestRecalculationData interestRecalculationData, final LoanScheduleData originalSchedule,
final Boolean createStandingInstructionAtDisbursement) { final Boolean createStandingInstructionAtDisbursement) {
this.id = id; this.id = id;
this.accountNo = accountNo; this.accountNo = accountNo;
this.status = status; this.status = status;
@@ -1097,6 +1108,7 @@ public class LoanAccountData {
this.loanOfficerId = loanOfficerId; this.loanOfficerId = loanOfficerId;
this.loanOfficerName = loanOfficerName; this.loanOfficerName = loanOfficerName;
this.currency = currency; this.currency = currency;
this.proposedPrincipal = proposedPrincipal;
this.principal = principal; this.principal = principal;
this.approvedPrincipal = approvedPrincipal; this.approvedPrincipal = approvedPrincipal;
this.totalOverpaid = totalOverpaid; this.totalOverpaid = totalOverpaid;
@@ -0,0 +1,33 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.data;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
/**
* Immutable data object representing a loan transaction.
*/
public class LoanApprovalData {
private final LocalDate approvalDate;
private final BigDecimal approvalAmount;
public LoanApprovalData(final BigDecimal approvalAmount, final LocalDate approvalDate) {
this.approvalDate = approvalDate;
this.approvalAmount = approvalAmount;
}
public LocalDate getApprovalDate() {
return this.approvalDate;
}
public BigDecimal getApprovalAmount() {
return this.approvalAmount;
}
}
@@ -306,6 +306,9 @@ public class Loan extends AbstractPersistable<Long> {
@Transient @Transient
private LoanSummaryWrapper loanSummaryWrapper; private LoanSummaryWrapper loanSummaryWrapper;
@Column(name = "principal_amount_proposed", scale = 6, precision = 19, nullable = false)
private BigDecimal proposedPrincipal;
@Column(name = "approved_principal", scale = 6, precision = 19, nullable = false) @Column(name = "approved_principal", scale = 6, precision = 19, nullable = false)
private BigDecimal approvedPrincipal; private BigDecimal approvedPrincipal;
@@ -436,6 +439,16 @@ public class Loan extends AbstractPersistable<Long> {
this.disbursementDetails = disbursementDetails; this.disbursementDetails = disbursementDetails;
this.approvedPrincipal = this.loanRepaymentScheduleDetail.getPrincipal().getAmount(); this.approvedPrincipal = this.loanRepaymentScheduleDetail.getPrincipal().getAmount();
this.createStandingInstructionAtDisbursement = createStandingInstructionAtDisbursement; this.createStandingInstructionAtDisbursement = createStandingInstructionAtDisbursement;
/*
* During loan origination stage and before loan is approved
* principal_amount, approved_principal and principal_amount_demanded
* will same amount and that amount is same as applicant loan demanded
* amount.
*/
this.proposedPrincipal = this.loanRepaymentScheduleDetail.getPrincipal().getAmount();
} }
private LoanSummary updateSummaryWithTotalFeeChargesDueAtDisbursement(final BigDecimal feeChargesDueAtDisbursement) { private LoanSummary updateSummaryWithTotalFeeChargesDueAtDisbursement(final BigDecimal feeChargesDueAtDisbursement) {
@@ -1359,6 +1372,11 @@ public class Loan extends AbstractPersistable<Long> {
this.approvedPrincipal = newValue; this.approvedPrincipal = newValue;
} }
if (command.isChangeInBigDecimalParameterNamed(principalParamName, this.proposedPrincipal)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(principalParamName);
this.proposedPrincipal = newValue;
}
if (loanProduct.isMultiDisburseLoan()) { if (loanProduct.isMultiDisburseLoan()) {
updateDisbursementDetails(command, actualChanges); updateDisbursementDetails(command, actualChanges);
if (command.isChangeInBigDecimalParameterNamed(LoanApiConstants.emiAmountParameterName, this.fixedEmiAmount)) { if (command.isChangeInBigDecimalParameterNamed(LoanApiConstants.emiAmountParameterName, this.fixedEmiAmount)) {
@@ -1839,9 +1857,25 @@ public class Loan extends AbstractPersistable<Long> {
final Map<String, Object> actualChanges = new LinkedHashMap<>(); final Map<String, Object> actualChanges = new LinkedHashMap<>();
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVED, LoanStatus.fromInt(this.loanStatus)); /*
if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) { * statusEnum is holding the possible new status derived from
this.loanStatus = statusEnum.getValue(); * loanLifecycleStateMachine.transition.
*/
final LoanStatus newStatusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVED, LoanStatus.fromInt(this.loanStatus));
/*
* FIXME: There is no need to check below condition, if
* loanLifecycleStateMachine.transition is doing it's responsibility
* properly. Better implementation approach is, if code passes invalid
* combination of states (fromState and toState), state machine should
* return invalidate state and below if condition should check for not
* equal to invalidateState, instead of check new value is same as
* present value.
*/
if (!newStatusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
this.loanStatus = newStatusEnum.getValue();
actualChanges.put("status", LoanEnumerations.status(this.loanStatus)); actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
// only do below if status has changed in the 'approval' case // only do below if status has changed in the 'approval' case
@@ -1852,6 +1886,35 @@ public class Loan extends AbstractPersistable<Long> {
approvedOnDateChange = command.stringValueOfParameterNamed("eventDate"); approvedOnDateChange = command.stringValueOfParameterNamed("eventDate");
} }
BigDecimal approvedLoanAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.approvedLoanAmountParameterName);
if (approvedLoanAmount != null) {
// Approved amount has to be less than or equal to principal
// amount demanded
if (approvedLoanAmount.compareTo(this.proposedPrincipal) < 1) {
this.approvedPrincipal = approvedLoanAmount;
/*
* All the calculations are done based on the principal
* amount, so it is necessary to set principal amount to
* approved amount
*/
this.loanRepaymentScheduleDetail.setPrincipal(approvedLoanAmount);
actualChanges.put(LoanApiConstants.approvedLoanAmountParameterName, approvedLoanAmount);
actualChanges.put(LoanApiConstants.disbursementPrincipalParameterName, approvedLoanAmount);
} else {
final String errorMessage = "Loan approved amount can't be greater than loan amount demanded.";
throw new InvalidLoanStateTransitionException("approval", "amount.can't.be.greater.than.loan.amount.demanded",
errorMessage, this.proposedPrincipal, approvedLoanAmount);
}
}
this.approvedOnDate = approvedOn.toDate(); this.approvedOnDate = approvedOn.toDate();
this.approvedBy = currentUser; this.approvedBy = currentUser;
actualChanges.put("locale", command.locale()); actualChanges.put("locale", command.locale());
@@ -1896,6 +1959,16 @@ public class Loan extends AbstractPersistable<Long> {
this.approvedOnDate = null; this.approvedOnDate = null;
this.approvedBy = null; this.approvedBy = null;
if (this.approvedPrincipal.compareTo(this.proposedPrincipal) != 0) {
this.approvedPrincipal = this.proposedPrincipal;
this.loanRepaymentScheduleDetail.setPrincipal(this.proposedPrincipal);
actualChanges.put(LoanApiConstants.approvedLoanAmountParameterName, this.proposedPrincipal);
actualChanges.put(LoanApiConstants.disbursementPrincipalParameterName, this.proposedPrincipal);
}
actualChanges.put("approvedOnDate", ""); actualChanges.put("approvedOnDate", "");
this.loanOfficerHistory.clear(); this.loanOfficerHistory.clear();
@@ -2176,7 +2249,7 @@ public class Loan extends AbstractPersistable<Long> {
* Ability to regenerate the repayment schedule based on the loans current * Ability to regenerate the repayment schedule based on the loans current
* details/state. * details/state.
*/ */
private void regenerateRepaymentSchedule(final ScheduleGeneratorDTO scheduleGeneratorDTO) { public void regenerateRepaymentSchedule(final ScheduleGeneratorDTO scheduleGeneratorDTO) {
final LoanScheduleModel loanSchedule = regenerateScheduleModel(scheduleGeneratorDTO); final LoanScheduleModel loanSchedule = regenerateScheduleModel(scheduleGeneratorDTO);
@@ -2342,7 +2415,7 @@ public class Loan extends AbstractPersistable<Long> {
final boolean isScheduleRegenerateRequired = isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate); final boolean isScheduleRegenerateRequired = isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate);
this.actualDisbursementDate = null; this.actualDisbursementDate = null;
this.disbursedBy = null; this.disbursedBy = null;
boolean isDisbueseAmtChanged = !this.approvedPrincipal.equals(this.loanRepaymentScheduleDetail.getPrincipal()); boolean isDisbursedAmountChanged = !this.approvedPrincipal.equals(this.loanRepaymentScheduleDetail.getPrincipal());
this.loanRepaymentScheduleDetail.setPrincipal(this.approvedPrincipal); this.loanRepaymentScheduleDetail.setPrincipal(this.approvedPrincipal);
if (this.loanProduct.isMultiDisburseLoan()) { if (this.loanProduct.isMultiDisburseLoan()) {
for (final LoanDisbursementDetails details : this.disbursementDetails) { for (final LoanDisbursementDetails details : this.disbursementDetails) {
@@ -2352,13 +2425,13 @@ public class Loan extends AbstractPersistable<Long> {
} }
boolean isEmiAmountChanged = this.loanTermVariations.size() > 0; boolean isEmiAmountChanged = this.loanTermVariations.size() > 0;
updateLoanToPreDisbursalState(); updateLoanToPreDisbursalState();
if (isScheduleRegenerateRequired || isDisbueseAmtChanged || isEmiAmountChanged if (isScheduleRegenerateRequired || isDisbursedAmountChanged || isEmiAmountChanged
|| this.repaymentScheduleDetail().isInterestRecalculationEnabled()) { || this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
// clear off actual disbusrement date so schedule regeneration // clear off actual disbusrement date so schedule regeneration
// uses expected date. // uses expected date.
regenerateRepaymentSchedule(scheduleGeneratorDTO); regenerateRepaymentSchedule(scheduleGeneratorDTO);
if (isDisbueseAmtChanged) { if (isDisbursedAmountChanged) {
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
} }
} }
@@ -3358,6 +3431,10 @@ public class Loan extends AbstractPersistable<Long> {
return expectedDisbursementDate; return expectedDisbursementDate;
} }
/*
* Reason for derving
*/
public BigDecimal getDisburseAmountForTemplate() { public BigDecimal getDisburseAmountForTemplate() {
BigDecimal principal = this.loanRepaymentScheduleDetail.getPrincipal().getAmount(); BigDecimal principal = this.loanRepaymentScheduleDetail.getPrincipal().getAmount();
Collection<LoanDisbursementDetails> details = fetchUndisbursedDetail(); Collection<LoanDisbursementDetails> details = fetchUndisbursedDetail();
@@ -3679,6 +3756,10 @@ public class Loan extends AbstractPersistable<Long> {
return this.collateral; return this.collateral;
} }
public BigDecimal getProposedPrincipal() {
return this.proposedPrincipal;
}
public Map<String, Object> deriveAccountingBridgeData(final CurrencyData currencyData, final List<Long> existingTransactionIds, public Map<String, Object> deriveAccountingBridgeData(final CurrencyData currencyData, final List<Long> existingTransactionIds,
final List<Long> existingReversedTransactionIds, boolean isAccountTransfer) { final List<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
@@ -10,6 +10,7 @@ import java.math.BigDecimal;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.portfolio.calendar.domain.CalendarInstance; import org.mifosplatform.portfolio.calendar.domain.CalendarInstance;
import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail; import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
public interface LoanAccountDomainService { public interface LoanAccountDomainService {
@@ -39,4 +40,16 @@ public interface LoanAccountDomainService {
* @param loan * @param loan
*/ */
void recalculateAccruals(Loan loan); void recalculateAccruals(Loan loan);
/**
* This method is used for building ScheduleGeneratorDTO from loan, usages
* are as, if have loan and some of the terms are modified which may impact
* the schedule, in that case need to recompute the schedule, so this method
* helps to build the ScheduleGeneratorDTO from modified loan.
*
* @param loan
*/
public ScheduleGeneratorDTO buildScheduleGeneratorDTO(final Loan loan);
} }
@@ -500,5 +500,26 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
this.accountTransferRepository.save(transferTransaction); this.accountTransferRepository.save(transferTransaction);
} }
} }
public ScheduleGeneratorDTO buildScheduleGeneratorDTO(final Loan loan) {
final MonetaryCurrency currency = loan.getCurrency();
ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
LocalDate calculatedRepaymentsStartingFromDate = loan.getExpectedFirstRepaymentOnDate();
final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan
.getExpectedDisbursedOnLocalDate().toDate(), HolidayStatusType.ACTIVE.getValue());
final WorkingDays workingDays = this.workingDaysRepository.findOne();
final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled();
final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled();
HolidayDetailDTO holidayDetailDTO = new HolidayDetailDTO(isHolidayEnabled, holidays, workingDays, allowTransactionsOnHoliday,
allowTransactionsOnNonWorkingDay);
ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency,
calculatedRepaymentsStartingFromDate, holidayDetailDTO);
return scheduleGeneratorDTO;
}
} }
@@ -6,6 +6,7 @@
package org.mifosplatform.portfolio.loanaccount.serialization; package org.mifosplatform.portfolio.loanaccount.serialization;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
@@ -20,6 +21,7 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -45,7 +47,9 @@ public final class LoanApplicationTransitionApiJsonValidator {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> disbursementParameters = new HashSet<>(Arrays.asList("approvedOnDate", "note", "locale", "dateFormat")); final Set<String> disbursementParameters = new HashSet<>(Arrays.asList(LoanApiConstants.approvedLoanAmountParameterName,
LoanApiConstants.approvedOnDateParameterName, LoanApiConstants.noteParameterName, LoanApiConstants.localeParameterName,
LoanApiConstants.dateFormatParameterName));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType(); final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters); this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
@@ -54,11 +58,18 @@ public final class LoanApplicationTransitionApiJsonValidator {
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication"); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication");
final JsonElement element = this.fromApiJsonHelper.parse(json); final JsonElement element = this.fromApiJsonHelper.parse(json);
final LocalDate approvedOnDate = this.fromApiJsonHelper.extractLocalDateNamed("approvedOnDate", element);
baseDataValidator.reset().parameter("approvedOnDate").value(approvedOnDate).notNull();
final String note = this.fromApiJsonHelper.extractStringNamed("note", element); final BigDecimal principal = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000); LoanApiConstants.approvedLoanAmountParameterName, element);
baseDataValidator.reset().parameter(LoanApiConstants.approvedLoanAmountParameterName).value(principal).ignoreIfNull()
.positiveAmount();
final LocalDate approvedOnDate = this.fromApiJsonHelper
.extractLocalDateNamed(LoanApiConstants.approvedOnDateParameterName, element);
baseDataValidator.reset().parameter(LoanApiConstants.approvedOnDateParameterName).value(approvedOnDate).notNull();
final String note = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.noteParameterName, element);
baseDataValidator.reset().parameter(LoanApiConstants.noteParameterName).value(note).notExceedingLengthOf(1000);
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
} }
@@ -67,7 +78,8 @@ public final class LoanApplicationTransitionApiJsonValidator {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> disbursementParameters = new HashSet<>(Arrays.asList("rejectedOnDate", "note", "locale", "dateFormat")); final Set<String> disbursementParameters = new HashSet<>(Arrays.asList(LoanApiConstants.rejectedOnDateParameterName,
LoanApiConstants.noteParameterName, LoanApiConstants.localeParameterName, LoanApiConstants.dateFormatParameterName));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType(); final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters); this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
@@ -76,11 +88,11 @@ public final class LoanApplicationTransitionApiJsonValidator {
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication"); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication");
final JsonElement element = this.fromApiJsonHelper.parse(json); final JsonElement element = this.fromApiJsonHelper.parse(json);
final LocalDate rejectedOnDate = this.fromApiJsonHelper.extractLocalDateNamed("rejectedOnDate", element); final LocalDate rejectedOnDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.rejectedOnDateParameterName, element);
baseDataValidator.reset().parameter("rejectedOnDate").value(rejectedOnDate).notNull(); baseDataValidator.reset().parameter(LoanApiConstants.rejectedOnDateParameterName).value(rejectedOnDate).notNull();
final String note = this.fromApiJsonHelper.extractStringNamed("note", element); final String note = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.noteParameterName, element);
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000); baseDataValidator.reset().parameter(LoanApiConstants.noteParameterName).value(note).notExceedingLengthOf(1000);
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
} }
@@ -89,7 +101,8 @@ public final class LoanApplicationTransitionApiJsonValidator {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> disbursementParameters = new HashSet<>(Arrays.asList("withdrawnOnDate", "note", "locale", "dateFormat")); final Set<String> disbursementParameters = new HashSet<>(Arrays.asList(LoanApiConstants.withdrawnOnDateParameterName,
LoanApiConstants.noteParameterName, LoanApiConstants.localeParameterName, LoanApiConstants.dateFormatParameterName));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType(); final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters); this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
@@ -98,11 +111,11 @@ public final class LoanApplicationTransitionApiJsonValidator {
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication"); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication");
final JsonElement element = this.fromApiJsonHelper.parse(json); final JsonElement element = this.fromApiJsonHelper.parse(json);
final LocalDate withdrawnOnDate = this.fromApiJsonHelper.extractLocalDateNamed("withdrawnOnDate", element); final LocalDate withdrawnOnDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.withdrawnOnDateParameterName, element);
baseDataValidator.reset().parameter("withdrawnOnDate").value(withdrawnOnDate).notNull(); baseDataValidator.reset().parameter(LoanApiConstants.withdrawnOnDateParameterName).value(withdrawnOnDate).notNull();
final String note = this.fromApiJsonHelper.extractStringNamed("note", element); final String note = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.noteParameterName, element);
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000); baseDataValidator.reset().parameter(LoanApiConstants.noteParameterName).value(note).notExceedingLengthOf(1000);
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
} }
@@ -49,9 +49,12 @@ import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.group.domain.Group; import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper; import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper;
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException; import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
import org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants;
import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData;
import org.mifosplatform.portfolio.loanaccount.data.ScheduleGeneratorDTO;
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
import org.mifosplatform.portfolio.loanaccount.domain.Loan; import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanAccountDomainService;
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge; import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
import org.mifosplatform.portfolio.loanaccount.domain.LoanLifecycleStateMachine; import org.mifosplatform.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
@@ -121,7 +124,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
private final AccountAssociationsRepository accountAssociationsRepository; private final AccountAssociationsRepository accountAssociationsRepository;
private final LoanReadPlatformService loanReadPlatformService; private final LoanReadPlatformService loanReadPlatformService;
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository; private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
private final LoanAccountDomainService loanAccountDomainService;
@Autowired @Autowired
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper, public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
final LoanApplicationTransitionApiJsonValidator loanApplicationTransitionApiJsonValidator, final LoanApplicationTransitionApiJsonValidator loanApplicationTransitionApiJsonValidator,
@@ -136,7 +140,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final CalendarRepository calendarRepository, final CalendarInstanceRepository calendarInstanceRepository, final CalendarRepository calendarRepository, final CalendarInstanceRepository calendarInstanceRepository,
final SavingsAccountAssembler savingsAccountAssembler, final AccountAssociationsRepository accountAssociationsRepository, final SavingsAccountAssembler savingsAccountAssembler, final AccountAssociationsRepository accountAssociationsRepository,
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository, final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
final LoanReadPlatformService loanReadPlatformService) { final LoanReadPlatformService loanReadPlatformService, final LoanAccountDomainService loanAccountDomainService) {
this.context = context; this.context = context;
this.fromJsonHelper = fromJsonHelper; this.fromJsonHelper = fromJsonHelper;
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator; this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
@@ -161,6 +165,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.accountAssociationsRepository = accountAssociationsRepository; this.accountAssociationsRepository = accountAssociationsRepository;
this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository; this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository;
this.loanReadPlatformService = loanReadPlatformService; this.loanReadPlatformService = loanReadPlatformService;
this.loanAccountDomainService = loanAccountDomainService;
} }
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
@@ -722,6 +728,14 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final Map<String, Object> changes = loan.loanApplicationApproval(currentUser, command, defaultLoanLifecycleStateMachine()); final Map<String, Object> changes = loan.loanApplicationApproval(currentUser, command, defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
// If loan approved amount less than loan demanded amount, then need
// to recompute the schedule
if (changes.containsKey(LoanApiConstants.approvedLoanAmountParameterName)) {
ScheduleGeneratorDTO scheduleGeneratorDTO = loanAccountDomainService.buildScheduleGeneratorDTO(loan);
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
}
this.loanRepository.save(loan); this.loanRepository.save(loan);
final String noteText = command.stringValueOfParameterNamed("note"); final String noteText = command.stringValueOfParameterNamed("note");
@@ -756,6 +770,16 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final Map<String, Object> changes = loan.undoApproval(defaultLoanLifecycleStateMachine()); final Map<String, Object> changes = loan.undoApproval(defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
// If loan approved amount is not same as loan amount demanded, then
// during undo, restore the demand amount to principal amount.
if (changes.containsKey(LoanApiConstants.approvedLoanAmountParameterName)
|| changes.containsKey(LoanApiConstants.disbursementPrincipalParameterName )) {
ScheduleGeneratorDTO scheduleGeneratorDTO = loanAccountDomainService.buildScheduleGeneratorDTO(loan);
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
}
this.loanRepository.save(loan); this.loanRepository.save(loan);
final String noteText = command.stringValueOfParameterNamed("note"); final String noteText = command.stringValueOfParameterNamed("note");
@@ -14,6 +14,7 @@ import org.mifosplatform.portfolio.calendar.data.CalendarData;
import org.mifosplatform.portfolio.group.service.SearchParameters; import org.mifosplatform.portfolio.group.service.SearchParameters;
import org.mifosplatform.portfolio.loanaccount.data.DisbursementData; import org.mifosplatform.portfolio.loanaccount.data.DisbursementData;
import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData; import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData;
import org.mifosplatform.portfolio.loanaccount.data.LoanApprovalData;
import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData; import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData;
import org.mifosplatform.portfolio.loanaccount.data.LoanTermVariationsData; import org.mifosplatform.portfolio.loanaccount.data.LoanTermVariationsData;
import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData; import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData;
@@ -44,6 +45,8 @@ public interface LoanReadPlatformService {
LoanTransactionData retrieveNewClosureDetails(); LoanTransactionData retrieveNewClosureDetails();
LoanTransactionData retrieveDisbursalTemplate(Long loanId, boolean paymentDetailsRequired); LoanTransactionData retrieveDisbursalTemplate(Long loanId, boolean paymentDetailsRequired);
LoanApprovalData retrieveApprovalTemplate(Long loanId);
LoanAccountData retrieveTemplateWithCompleteGroupAndProductDetails(Long groupId, Long productId); LoanAccountData retrieveTemplateWithCompleteGroupAndProductDetails(Long groupId, Long productId);
@@ -60,6 +60,7 @@ import org.mifosplatform.portfolio.group.service.SearchParameters;
import org.mifosplatform.portfolio.loanaccount.data.DisbursementData; import org.mifosplatform.portfolio.loanaccount.data.DisbursementData;
import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData; import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData;
import org.mifosplatform.portfolio.loanaccount.data.LoanApplicationTimelineData; import org.mifosplatform.portfolio.loanaccount.data.LoanApplicationTimelineData;
import org.mifosplatform.portfolio.loanaccount.data.LoanApprovalData;
import org.mifosplatform.portfolio.loanaccount.data.LoanInterestRecalculationData; import org.mifosplatform.portfolio.loanaccount.data.LoanInterestRecalculationData;
import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData; import org.mifosplatform.portfolio.loanaccount.data.LoanScheduleAccrualData;
import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData; import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData;
@@ -439,6 +440,16 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
} }
@Override
public LoanApprovalData retrieveApprovalTemplate(final Long loanId) {
final Loan loan = this.loanRepository.findOne(loanId);
if (loan == null) { throw new LoanNotFoundException(loanId); }
return new LoanApprovalData(loan.getProposedPrincipal(),DateUtils.getLocalDateOfTenant());
}
@Override @Override
public LoanTransactionData retrieveDisbursalTemplate(final Long loanId, boolean paymentDetailsRequired) { public LoanTransactionData retrieveDisbursalTemplate(final Long loanId, boolean paymentDetailsRequired) {
final Loan loan = this.loanRepository.findOne(loanId); final Loan loan = this.loanRepository.findOne(loanId);
@@ -498,7 +509,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
+ " l.expected_disbursedon_date as expectedDisbursementDate, l.disbursedon_date as actualDisbursementDate, dbu.username as disbursedByUsername, dbu.firstname as disbursedByFirstname, dbu.lastname as disbursedByLastname," + " l.expected_disbursedon_date as expectedDisbursementDate, l.disbursedon_date as actualDisbursementDate, dbu.username as disbursedByUsername, dbu.firstname as disbursedByFirstname, dbu.lastname as disbursedByLastname,"
+ " l.closedon_date as closedOnDate, cbu.username as closedByUsername, cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname, l.writtenoffon_date as writtenOffOnDate, " + " l.closedon_date as closedOnDate, cbu.username as closedByUsername, cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname, l.writtenoffon_date as writtenOffOnDate, "
+ " l.expected_firstrepaymenton_date as expectedFirstRepaymentOnDate, l.interest_calculated_from_date as interestChargedFromDate, l.expected_maturedon_date as expectedMaturityDate, " + " l.expected_firstrepaymenton_date as expectedFirstRepaymentOnDate, l.interest_calculated_from_date as interestChargedFromDate, l.expected_maturedon_date as expectedMaturityDate, "
+ " l.principal_amount as principal,l.approved_principal as approvedPrincipal, l.arrearstolerance_amount as inArrearsTolerance, l.number_of_repayments as numberOfRepayments, l.repay_every as repaymentEvery," + " l.principal_amount_proposed as proposedPrincipal, l.principal_amount as principal, l.approved_principal as approvedPrincipal, l.arrearstolerance_amount as inArrearsTolerance, l.number_of_repayments as numberOfRepayments, l.repay_every as repaymentEvery,"
+ " l.grace_on_principal_periods as graceOnPrincipalPayment, l.grace_on_interest_periods as graceOnInterestPayment, l.grace_interest_free_periods as graceOnInterestCharged,l.grace_on_arrears_ageing as graceOnArrearsAgeing," + " l.grace_on_principal_periods as graceOnPrincipalPayment, l.grace_on_interest_periods as graceOnInterestPayment, l.grace_interest_free_periods as graceOnInterestCharged,l.grace_on_arrears_ageing as graceOnArrearsAgeing,"
+ " l.nominal_interest_rate_per_period as interestRatePerPeriod, l.annual_nominal_interest_rate as annualInterestRate, " + " l.nominal_interest_rate_per_period as interestRatePerPeriod, l.annual_nominal_interest_rate as annualInterestRate, "
+ " l.repayment_period_frequency_enum as repaymentFrequencyType, l.repayment_frequency_nth_day_enum as repaymentFrequencyNthDayType, l.repayment_frequency_day_of_week_enum as repaymentFrequencyDayOfWeekType, l.interest_period_frequency_enum as interestRateFrequencyType, " + " l.repayment_period_frequency_enum as repaymentFrequencyType, l.repayment_frequency_nth_day_enum as repaymentFrequencyNthDayType, l.repayment_frequency_day_of_week_enum as repaymentFrequencyDayOfWeekType, l.interest_period_frequency_enum as interestRateFrequencyType, "
@@ -661,6 +672,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
final BigDecimal principal = rs.getBigDecimal("principal"); final BigDecimal principal = rs.getBigDecimal("principal");
final BigDecimal approvedPrincipal = rs.getBigDecimal("approvedPrincipal"); final BigDecimal approvedPrincipal = rs.getBigDecimal("approvedPrincipal");
final BigDecimal proposedPrincipal = rs.getBigDecimal("proposedPrincipal");
final BigDecimal totalOverpaid = rs.getBigDecimal("totalOverpaid"); final BigDecimal totalOverpaid = rs.getBigDecimal("totalOverpaid");
final BigDecimal inArrearsTolerance = rs.getBigDecimal("inArrearsTolerance"); final BigDecimal inArrearsTolerance = rs.getBigDecimal("inArrearsTolerance");
@@ -813,7 +825,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, groupData, return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, groupData,
loanType, loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanType, loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName,
loanOfficerId, loanOfficerName, currencyData, principal, approvedPrincipal, totalOverpaid, inArrearsTolerance, loanOfficerId, loanOfficerName, currencyData, proposedPrincipal, principal, approvedPrincipal, totalOverpaid, inArrearsTolerance,
termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType,
repaymentFrequencyNthDayType, repaymentFrequencyDayOfWeekType, transactionStrategyId, transactionStrategyName, repaymentFrequencyNthDayType, repaymentFrequencyDayOfWeekType, transactionStrategyId, transactionStrategyName,
amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType,
@@ -0,0 +1,2 @@
ALTER TABLE `m_loan` ADD COLUMN `principal_amount_proposed` DECIMAL(19,6) NOT NULL AFTER `currency_multiplesof`;
UPDATE m_loan SET principal_amount_proposed = approved_principal;