Merge pull request #770 from pramodn02/MIFOSX-847_1

MIFOSX-847 - added variations in loan data for clients
This commit is contained in:
Vishwas Babu A J
2014-02-18 19:55:24 -08:00
4 changed files with 134 additions and 11 deletions
@@ -223,4 +223,9 @@ public class GroupGeneralData {
staffName, hierarchy, clientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles,
role, calendarsData, collectionMeetingCalendar, closureReasons,null);
}
public Collection<ClientData> clientMembers() {
return this.clientMembers;
}
}
@@ -7,7 +7,9 @@ package org.mifosplatform.portfolio.loanaccount.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.Consumes;
@@ -51,6 +53,7 @@ import org.mifosplatform.portfolio.calendar.data.CalendarData;
import org.mifosplatform.portfolio.calendar.service.CalendarReadPlatformService;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.collateral.data.CollateralData;
import org.mifosplatform.portfolio.collateral.service.CollateralReadPlatformService;
import org.mifosplatform.portfolio.fund.data.FundData;
@@ -235,6 +238,16 @@ public class LoansApiResource {
calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
newLoanAccount = newLoanAccount == null ? loanAccountGroupData : LoanAccountData.populateGroupDefaults(newLoanAccount,
loanAccountGroupData);
if(productId != null){
Map<Long, Integer> memberLoanCycle = new HashMap<Long, Integer>();
Collection<ClientData> members = loanAccountGroupData.groupData().clientMembers();
for(ClientData clientData:members){
Integer loanCounter = this.loanReadPlatformService.retriveLoanCounter(clientData.id(), productId);
memberLoanCycle.put(clientData.id(), loanCounter);
}
newLoanAccount = LoanAccountData.associateMemberVariations(newLoanAccount, memberLoanCycle);
}
} else {
final String errorMsg = "Loan template type '" + templateType + "' is not supported";
throw new NotSupportedLoanTemplateTypeException(errorMsg, templateType);
@@ -13,6 +13,8 @@ package org.mifosplatform.portfolio.loanaccount.data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.Transient;
@@ -149,6 +151,9 @@ public class LoanAccountData {
private final Collection<LoanTermVariationsData> emiAmountVariations;
private final LoanProductData product;
private final Map<Long, LoanBorrowerCycleData> memberVariations;
/**
* Used to produce a {@link LoanAccountData} with only collateral options
* for now.
@@ -229,6 +234,8 @@ public class LoanAccountData {
final BigDecimal fixedEmiAmount = null;
final BigDecimal maxOutstandingLoanBalance = null;
final Collection<LoanTermVariationsData> emiAmountVariations = null;
final Map<Long, LoanBorrowerCycleData> memberVariations = null;
final LoanProductData product = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
currencyData, principal,principal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments,
@@ -241,7 +248,7 @@ public class LoanAccountData {
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions,
chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount, disbursementData,
multiDisburseLoan, fixedEmiAmount,maxOutstandingLoanBalance,emiAmountVariations);
multiDisburseLoan, fixedEmiAmount,maxOutstandingLoanBalance,emiAmountVariations,memberVariations, product);
}
/**
@@ -324,6 +331,8 @@ public class LoanAccountData {
final BigDecimal fixedEmiAmount = null;
final BigDecimal maxOutstandingLoanBalance = null;
final Collection<LoanTermVariationsData> emiAmountVariations = null;
final Map<Long, LoanBorrowerCycleData> memberVariations = null;
final LoanProductData product = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
@@ -337,7 +346,7 @@ public class LoanAccountData {
interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions,
loanPurposeOptions, loanCollateralOptions, calendarOptions, syncDisbursementWithMeeting, loancounter, loanProductCounter,
notes, accountLinkingOptions, linkedAccount, disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance,
emiAmountVariations);
emiAmountVariations,memberVariations, product);
}
public static LoanAccountData populateClientDefaults(final LoanAccountData acc, final LoanAccountData clientAcc) {
@@ -357,7 +366,7 @@ public class LoanAccountData {
acc.chargeOptions, null, acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount,acc.maxOutstandingLoanBalance,
acc.emiAmountVariations);
acc.emiAmountVariations,acc.memberVariations, acc.product);
}
/**
@@ -441,6 +450,8 @@ public class LoanAccountData {
final BigDecimal fixedEmiAmount = null;
final BigDecimal maxOutstandingBalance = null;
final Collection<LoanTermVariationsData> emiAmountVariations = null;
final Map<Long, LoanBorrowerCycleData> memberVariations = null;
final LoanProductData product = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
@@ -454,7 +465,7 @@ public class LoanAccountData {
interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions,
loanPurposeOptions, loanCollateralOptions, calendarOptions, syncDisbursementWithMeeting, loancounter, loanProductCounter,
notes, accountLinkingOptions, linkedAccount, disbursementData, multiDisburseLoan, fixedEmiAmount,maxOutstandingBalance,
emiAmountVariations);
emiAmountVariations,memberVariations, product);
}
public static LoanAccountData populateGroupDefaults(final LoanAccountData acc, final LoanAccountData groupAcc) {
@@ -474,7 +485,7 @@ public class LoanAccountData {
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount,acc.maxOutstandingLoanBalance,
acc.emiAmountVariations);
acc.emiAmountVariations,acc.memberVariations, acc.product);
}
public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product,
@@ -577,6 +588,7 @@ public class LoanAccountData {
final Integer termFrequency = numberOfRepayments * product.getRepaymentEvery();
final BigDecimal fixedEmi = null;
Map<Long, LoanBorrowerCycleData> memberVariations = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType,
product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(), loanPurposeId,
@@ -592,7 +604,7 @@ public class LoanAccountData {
interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions,
loanPurposeOptions, loanCollateralOptions, calendarOptions, syncDisbursementWithMeeting, loancounter, loanProductCounter,
notes, accountLinkingOptions, linkedAccount, disbursementData, product.getMultiDisburseLoan(), fixedEmi, product.getOutstandingLoanBalance(),
emiAmountVariations);
emiAmountVariations,memberVariations, product);
}
public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) {
@@ -643,7 +655,7 @@ public class LoanAccountData {
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes, acc.accountLinkingOptions,
acc.linkedAccount, acc.disbursementDetails, product.getMultiDisburseLoan(), acc.fixedEmiAmount,product.getOutstandingLoanBalance(),
acc.emiAmountVariations);
acc.emiAmountVariations,acc.memberVariations, product);
}
/*
@@ -693,6 +705,8 @@ public class LoanAccountData {
final PortfolioAccountData linkedAccount = null;
final Collection<DisbursementData> disbursementData= null;
final Collection<LoanTermVariationsData> emiAmountVariations= null;
final Map<Long, LoanBorrowerCycleData> memberVariations = null;
final LoanProductData product = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
@@ -705,7 +719,8 @@ public class LoanAccountData {
repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions,
loanCollateralOptions, calendarOptions, syncDisbursementWithMeeting, loancounter, loanProductCounter, notes,
accountLinkingOptions, linkedAccount, disbursementData, multiDisburseLoan, fixedEmiAmont, outstandingLoanBalance,emiAmountVariations);
accountLinkingOptions, linkedAccount, disbursementData, multiDisburseLoan, fixedEmiAmont, outstandingLoanBalance,emiAmountVariations,
memberVariations, product);
}
/*
@@ -739,7 +754,7 @@ public class LoanAccountData {
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes, accountLinkingOptions, linkedAccount, disbursementDetails,
acc.multiDisburseLoan, acc.fixedEmiAmount,acc.maxOutstandingLoanBalance,emiAmountVariations);
acc.multiDisburseLoan, acc.fixedEmiAmount,acc.maxOutstandingLoanBalance,emiAmountVariations,acc.memberVariations, acc.product);
}
public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final Collection<LoanProductData> productOptions,
@@ -769,7 +784,63 @@ public class LoanAccountData {
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount,acc.maxOutstandingLoanBalance,
acc.emiAmountVariations);
acc.emiAmountVariations,acc.memberVariations, acc.product);
}
public static LoanAccountData associateMemberVariations(final LoanAccountData acc,final Map<Long,Integer> memberLoanCycle) {
final Map<Long, LoanBorrowerCycleData> memberVariations = new HashMap<Long, LoanBorrowerCycleData>();
for(Map.Entry<Long, Integer> mapEntry : memberLoanCycle.entrySet()){
BigDecimal principal = null;
BigDecimal interestRatePerPeriod = null;
Integer numberOfRepayments = null;
Long clientId = mapEntry.getKey();
Integer loanCycleNumber = mapEntry.getValue();
if (acc.product.useBorrowerCycle() && loanCycleNumber != null && loanCycleNumber > 0) {
Collection<LoanProductBorrowerCycleVariationData> principalVariationsForBorrowerCycle = acc.product
.getPrincipalVariationsForBorrowerCycle();
Collection<LoanProductBorrowerCycleVariationData> interestForVariationsForBorrowerCycle = acc.product
.getInterestRateVariationsForBorrowerCycle();
Collection<LoanProductBorrowerCycleVariationData> repaymentVariationsForBorrowerCycle = acc.product
.getNumberOfRepaymentVariationsForBorrowerCycle();
principal = fetchLoanCycleDefaultValue(principalVariationsForBorrowerCycle, loanCycleNumber);
interestRatePerPeriod = fetchLoanCycleDefaultValue(interestForVariationsForBorrowerCycle, loanCycleNumber);
BigDecimal numberofRepaymentval = fetchLoanCycleDefaultValue(repaymentVariationsForBorrowerCycle, loanCycleNumber);
if (numberofRepaymentval != null) {
numberOfRepayments = numberofRepaymentval.intValue();
}
}
if (principal == null) {
principal = acc.product.getPrincipal();
}
if (interestRatePerPeriod == null) {
interestRatePerPeriod = acc.product.getInterestRatePerPeriod();
}
if (numberOfRepayments == null) {
numberOfRepayments = acc.product.getNumberOfRepayments();
}
final Integer termFrequency = numberOfRepayments * acc.product.getRepaymentEvery();
LoanBorrowerCycleData borrowerCycleData = new LoanBorrowerCycleData(principal, interestRatePerPeriod, numberOfRepayments,termFrequency);
memberVariations.put(clientId, borrowerCycleData);
}
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.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal,acc.approvedPrincipal,
acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments,
acc.repaymentEvery, acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.transactionProcessingStrategyName,
acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType,
acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment,
acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary,
acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors,
acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions,
acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions,
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount,acc.maxOutstandingLoanBalance,
acc.emiAmountVariations,memberVariations, acc.product);
}
private LoanAccountData(
@@ -820,7 +891,8 @@ public class LoanAccountData {
final Boolean syncDisbursementWithMeeting, final Integer loanCounter, final Integer loanProductCounter,
final Collection<NoteData> notes, final Collection<PortfolioAccountData> accountLinkingOptions,
final PortfolioAccountData linkedAccount,final Collection<DisbursementData> disbursementDetails,final Boolean multiDisburseLoan, BigDecimal fixedEmiAmount,
final BigDecimal maxOutstandingLoanBalance,final Collection<LoanTermVariationsData> emiAmountVariations) {
final BigDecimal maxOutstandingLoanBalance,final Collection<LoanTermVariationsData> emiAmountVariations,
final Map<Long, LoanBorrowerCycleData> memberVariations, final LoanProductData product) {
this.id = id;
this.accountNo = accountNo;
this.status = status;
@@ -953,6 +1025,8 @@ public class LoanAccountData {
this.canDisburse = canDisburse;
}
this.emiAmountVariations = emiAmountVariations;
this.memberVariations = memberVariations;
this.product = product;
}
public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData() {
@@ -1018,4 +1092,14 @@ public class LoanAccountData {
return data.getBorrowerCycleNumber() == loanCycleNumber && data.getValueConditionType().equals(LoanProductValueConditionType.EQUAL);
}
public LoanProductData product() {
return this.product;
}
public GroupGeneralData groupData() {
return this.group;
}
}
@@ -0,0 +1,21 @@
package org.mifosplatform.portfolio.loanaccount.data;
import java.math.BigDecimal;
public class LoanBorrowerCycleData {
private final BigDecimal principal ;
private final BigDecimal interestRatePerPeriod ;
private final Integer numberOfRepayments;
private final Integer termFrequency;
public LoanBorrowerCycleData(final BigDecimal principal, final BigDecimal interestRatePerPeriod,final Integer numberOfRepayments,final Integer termFrequency) {
this.principal = principal;
this.interestRatePerPeriod = interestRatePerPeriod;
this.numberOfRepayments = numberOfRepayments;
this.termFrequency = termFrequency;
}
}