From 63615022df42b766c0be0bbe600fb21db25daf5f Mon Sep 17 00:00:00 2001 From: Pramod Nuthakki Date: Wed, 19 Feb 2014 00:03:35 +0530 Subject: [PATCH] MIFOSX-847 - added variations in loan data for clients --- .../group/data/GroupGeneralData.java | 5 + .../loanaccount/api/LoansApiResource.java | 13 +++ .../loanaccount/data/LoanAccountData.java | 106 ++++++++++++++++-- .../data/LoanBorrowerCycleData.java | 21 ++++ 4 files changed, 134 insertions(+), 11 deletions(-) create mode 100755 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanBorrowerCycleData.java diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupGeneralData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupGeneralData.java index d0ef63e60..f7c77b018 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupGeneralData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/data/GroupGeneralData.java @@ -223,4 +223,9 @@ public class GroupGeneralData { staffName, hierarchy, clientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles, role, calendarsData, collectionMeetingCalendar, closureReasons,null); } + + + public Collection clientMembers() { + return this.clientMembers; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java index ae1634a28..d4e2fe990 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java @@ -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 memberLoanCycle = new HashMap(); + Collection 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); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java index 0802052fb..3f98d6167 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java @@ -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 emiAmountVariations; + private final LoanProductData product; + + private final Map 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 emiAmountVariations = null; + final Map 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 emiAmountVariations = null; + final Map 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 emiAmountVariations = null; + final Map 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 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= null; final Collection emiAmountVariations= null; + final Map 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 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 memberLoanCycle) { + + final Map memberVariations = new HashMap(); + for(Map.Entry 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 principalVariationsForBorrowerCycle = acc.product + .getPrincipalVariationsForBorrowerCycle(); + Collection interestForVariationsForBorrowerCycle = acc.product + .getInterestRateVariationsForBorrowerCycle(); + Collection 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 notes, final Collection accountLinkingOptions, final PortfolioAccountData linkedAccount,final Collection disbursementDetails,final Boolean multiDisburseLoan, BigDecimal fixedEmiAmount, - final BigDecimal maxOutstandingLoanBalance,final Collection emiAmountVariations) { + final BigDecimal maxOutstandingLoanBalance,final Collection emiAmountVariations, + final Map 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; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanBorrowerCycleData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanBorrowerCycleData.java new file mode 100755 index 000000000..5d5db5fcb --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanBorrowerCycleData.java @@ -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; + } +}