You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@fineract.apache.org by "ASF GitHub Bot (JIRA)" <ji...@apache.org> on 2018/11/22 08:49:00 UTC

[jira] [Commented] (FINERACT-416) Interest to be calculated for the whole loan term given

    [ https://issues.apache.org/jira/browse/FINERACT-416?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16695670#comment-16695670 ] 

ASF GitHub Bot commented on FINERACT-416:
-----------------------------------------

MexinaD closed pull request #436: FINERACT-416 Interest of the whole term
URL: https://github.com/apache/fineract/pull/436
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/domain/PeriodFrequencyType.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/domain/PeriodFrequencyType.java
index fba620795..6a60233e5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/domain/PeriodFrequencyType.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/domain/PeriodFrequencyType.java
@@ -27,7 +27,8 @@
     WEEKS(1, "periodFrequencyType.weeks"), //
     MONTHS(2, "periodFrequencyType.months"), //
     YEARS(3, "periodFrequencyType.years"), //
-    INVALID(4, "periodFrequencyType.invalid");
+    WHOLE_TERM(4, "periodFrequencyType.whole_term"), //
+    INVALID(5, "periodFrequencyType.invalid");
 
     private final Integer value;
     private final String code;
@@ -61,6 +62,9 @@ public static PeriodFrequencyType fromInt(final Integer frequency) {
                 case 3:
                     repaymentFrequencyType = PeriodFrequencyType.YEARS;
                 break;
+                case 4:
+                   repaymentFrequencyType = PeriodFrequencyType.WHOLE_TERM;
+                break;
             }
         }
         return repaymentFrequencyType;
@@ -82,6 +86,9 @@ public boolean isDaily() {
         return this.value.equals(PeriodFrequencyType.DAYS.getValue());
     }
     
+    public boolean isWholeTerm() {
+         return this.value.equals(PeriodFrequencyType.WHOLE_TERM.getValue());
+    }
     public boolean isInvalid() {
         return this.value.equals(PeriodFrequencyType.INVALID.getValue());
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/service/DropdownReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/service/DropdownReadPlatformServiceImpl.java
index 948328d4c..40a664b69 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/service/DropdownReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/service/DropdownReadPlatformServiceImpl.java
@@ -40,7 +40,7 @@
     public List<EnumOptionData> retrievePeriodFrequencyTypeOptions() {
         final List<EnumOptionData> loanTermFrequencyOptions = Arrays.asList(termFrequencyType(PeriodFrequencyType.DAYS, "frequency"),
                 termFrequencyType(PeriodFrequencyType.WEEKS, "frequency"), termFrequencyType(PeriodFrequencyType.MONTHS, "frequency"),
-                termFrequencyType(PeriodFrequencyType.YEARS, "frequency"));
+                 termFrequencyType(PeriodFrequencyType.YEARS, "frequency"), termFrequencyType(PeriodFrequencyType.WHOLE_TERM, "frequency"));
         return loanTermFrequencyOptions;
     }
 
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AprCalculator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AprCalculator.java
index 730949b7e..d60eceb60 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AprCalculator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AprCalculator.java
@@ -19,14 +19,14 @@
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
 import java.math.BigDecimal;
-
+import java.math.RoundingMode;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 import org.springframework.stereotype.Component;
 
 @Component
 public class AprCalculator {
 
-    public BigDecimal calculateFrom(final PeriodFrequencyType interestPeriodFrequencyType, final BigDecimal interestRatePerPeriod) {
+    public BigDecimal calculateFrom(final PeriodFrequencyType interestPeriodFrequencyType, final BigDecimal interestRatePerPeriod,  final Integer numberOfRepayments, final Integer repaymentEvery, final PeriodFrequencyType repaymentPeriodFrequencyType) {
         BigDecimal defaultAnnualNominalInterestRate = BigDecimal.ZERO;
         switch (interestPeriodFrequencyType) {
             case DAYS:
@@ -41,10 +41,29 @@ public BigDecimal calculateFrom(final PeriodFrequencyType interestPeriodFrequenc
             case YEARS:
                 defaultAnnualNominalInterestRate = interestRatePerPeriod.multiply(BigDecimal.valueOf(1));
             break;
+            case WHOLE_TERM:
+                        final BigDecimal ratePerPeriod = interestRatePerPeriod.divide(BigDecimal.valueOf(numberOfRepayments*repaymentEvery), 8, RoundingMode.HALF_UP);
+                         
+                         switch (repaymentPeriodFrequencyType) {
+                             case DAYS:
+                                 defaultAnnualNominalInterestRate = ratePerPeriod.multiply(BigDecimal.valueOf(365));
+                             break;
+                             case WEEKS:
+                                 defaultAnnualNominalInterestRate = ratePerPeriod.multiply(BigDecimal.valueOf(52));
+                            break;
+                             case MONTHS:
+                                 defaultAnnualNominalInterestRate = ratePerPeriod.multiply(BigDecimal.valueOf(12));
+                             break;
+                             case YEARS:
+                                 defaultAnnualNominalInterestRate = ratePerPeriod.multiply(BigDecimal.valueOf(1));
+                             break;
+                         }                    
+             break;
             case INVALID:
             break;
         }
+    
+            return defaultAnnualNominalInterestRate;
+        }
 
-        return defaultAnnualNominalInterestRate;
-    }
-}
\ No newline at end of file
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
index c3f48a850..69c0310b0 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
@@ -227,7 +227,7 @@ private LoanApplicationTerms assembleLoanApplicationTermsFrom(final JsonElement
 
         BigDecimal annualNominalInterestRate = BigDecimal.ZERO;
         if (interestRatePerPeriod != null) {
-            annualNominalInterestRate = this.aprCalculator.calculateFrom(interestRatePeriodFrequencyType, interestRatePerPeriod);
+       annualNominalInterestRate = this.aprCalculator.calculateFrom(interestRatePeriodFrequencyType, interestRatePerPeriod, numberOfRepayments, repaymentEvery, repaymentPeriodFrequencyType);
         }
 
         // disbursement details
@@ -1106,4 +1106,4 @@ private void validateMinimumDaysBetweenDisbursalAndFirstRepayment(final LocalDat
         if (firstRepaymentDate.isBefore(minimumFirstRepaymentDate)) { throw new MinDaysBetweenDisbursalAndFirstRepaymentViolationException(
                 disbursalDate, firstRepaymentDate, minimumDaysBetweenDisbursalAndFirstRepayment); }
     }
-}
\ No newline at end of file
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
index 443dd4f28..723166c4f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
@@ -223,6 +223,9 @@ public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactio
         Integer minimumGapBetweenInstallments = null;
         Integer maximumGapBetweenInstallments = null;
 
+
+        final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery");
+        final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments");
         final Boolean isLinkedToFloatingInterestRates = command.booleanObjectValueOfParameterNamed("isLinkedToFloatingInterestRates");
         if (isLinkedToFloatingInterestRates != null && isLinkedToFloatingInterestRates) {
             interestRateDifferential = command.bigDecimalValueOfParameterNamed("interestRateDifferential");
@@ -236,7 +239,8 @@ public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactio
             interestRatePerPeriod = command.bigDecimalValueOfParameterNamed("interestRatePerPeriod");
             minInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("minInterestRatePerPeriod");
             maxInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("maxInterestRatePerPeriod");
-            annualInterestRate = aprCalculator.calculateFrom(interestFrequencyType, interestRatePerPeriod);
+            annualInterestRate = aprCalculator.calculateFrom(interestFrequencyType, interestRatePerPeriod, numberOfRepayments, repaymentEvery, repaymentFrequencyType);
+
         }
 
         final Boolean isVariableInstallmentsAllowed = command
@@ -246,8 +250,6 @@ public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactio
             maximumGapBetweenInstallments = command.integerValueOfParameterNamed(LoanProductConstants.maximumGapBetweenInstallments);
         }
 
-        final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery");
-        final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments");
         final Integer minNumberOfRepayments = command.integerValueOfParameterNamed("minNumberOfRepayments");
         final Integer maxNumberOfRepayments = command.integerValueOfParameterNamed("maxNumberOfRepayments");
         final BigDecimal inArrearsTolerance = command.bigDecimalValueOfParameterNamed("inArrearsTolerance");
@@ -1380,4 +1382,4 @@ public void setEqualAmortization(boolean isEqualAmortization) {
         this.isEqualAmortization = isEqualAmortization;
     }
 
-}
\ No newline at end of file
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
index 25ce67d52..76b57fb59 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
@@ -561,7 +561,8 @@ private Integer defaultToZeroIfNull(final Integer value) {
     }
 
     private void updateInterestRateDerivedFields(final AprCalculator aprCalculator) {
-        this.annualNominalInterestRate = aprCalculator.calculateFrom(this.interestPeriodFrequencyType, this.nominalInterestRatePerPeriod);
+       this.annualNominalInterestRate = aprCalculator.calculateFrom(this.interestPeriodFrequencyType, this.nominalInterestRatePerPeriod, this.numberOfRepayments, this.repayEvery, this.repaymentPeriodFrequencyType);
+
     }
 
     public boolean hasCurrencyCodeOf(final String currencyCode) {
@@ -667,4 +668,4 @@ public void setEqualAmortization(boolean isEqualAmortization) {
         this.isEqualAmortization = isEqualAmortization;
     }
 
-}
\ No newline at end of file
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java
index 04bfa7f06..56446d0a8 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java
@@ -513,7 +513,7 @@ public void validateForCreate(final String json) {
 
             final Integer interestRateFrequencyType = this.fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element,
                     Locale.getDefault());
-            baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3);
+            baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 4);
         }
 
         // Guarantee Funds
@@ -1368,7 +1368,7 @@ public void validateForUpdate(final String json, final LoanProduct loanProduct)
                 interestRateFrequencyType = this.fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element,
                         Locale.getDefault());
             }
-            baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3);
+            baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 4);
         }
 
         // Guarantee Funds
@@ -2101,4 +2101,4 @@ private void validatePartialPeriodSupport(final Integer interestCalculationPerio
 
         }
     }
-}
\ No newline at end of file
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java
index b82763ff1..aad2eb576 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java
@@ -132,7 +132,7 @@ public LoanDropdownReadPlatformServiceImpl(final LoanTransactionProcessingStrate
     public List<EnumOptionData> retrieveInterestRateFrequencyTypeOptions() {
         // support for monthly and annual percentage rate (MPR) and (APR)
         final List<EnumOptionData> interestRateFrequencyTypeOptions = Arrays.asList(interestRateFrequencyType(PeriodFrequencyType.MONTHS),
-                interestRateFrequencyType(PeriodFrequencyType.YEARS));
+                  interestRateFrequencyType(PeriodFrequencyType.YEARS), interestRateFrequencyType(PeriodFrequencyType.WHOLE_TERM));
         return interestRateFrequencyTypeOptions;
     }
 
@@ -220,4 +220,4 @@ public LoanDropdownReadPlatformServiceImpl(final LoanTransactionProcessingStrate
                 preCloseInterestCalculationStrategy(LoanPreClosureInterestCalculationStrategy.TILL_REST_FREQUENCY_DATE));
         return preCloseInterestCalculationStrategyOptions;
     }
-}
\ No newline at end of file
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java
index 18c905860..638e011bd 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java
@@ -239,6 +239,10 @@ public static EnumOptionData interestRateFrequencyType(final PeriodFrequencyType
                 optionData = new EnumOptionData(PeriodFrequencyType.YEARS.getValue().longValue(), codePrefix
                         + PeriodFrequencyType.YEARS.getCode(), "Per year");
             break;
+            case WHOLE_TERM:
+                 optionData = new EnumOptionData(PeriodFrequencyType.WHOLE_TERM.getValue().longValue(), codePrefix
+                         + PeriodFrequencyType.WHOLE_TERM.getCode(), "Whole term");
+            break;
             default:
                 optionData = new EnumOptionData(PeriodFrequencyType.INVALID.getValue().longValue(), PeriodFrequencyType.INVALID.getCode(),
                         "Invalid");
@@ -726,4 +730,4 @@ public static EnumOptionData preCloseInterestCalculationStrategy(final LoanPreCl
         return optionData;
     }
 
-}
\ No newline at end of file
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


> Interest to be calculated for the whole loan term given
> -------------------------------------------------------
>
>                 Key: FINERACT-416
>                 URL: https://issues.apache.org/jira/browse/FINERACT-416
>             Project: Apache Fineract
>          Issue Type: Improvement
>          Components: Loan
>            Reporter: Mexina Daniel
>            Assignee: Markus Geiss
>            Priority: Critical
>              Labels: gsoc, p1
>             Fix For: 1.3.0
>
>
> As for some of the MFI practise here in our country, they specify the interest for the whole loan term given, i.e their loan product have the interest for the whole loan term regardless of the frequency of repayment ()
> To accomplish this in mifos, a user has to do calculation of finding an interest of a month/year with respect of the loan term of that specific client. This is a very tiresome work as for a day a user can have apply many loans and the task of calculation make the work even harder.
> I was suggesting improvement in the loan product, to be able to allow the interest rate of the whole loan term.
> Example:
> Loan product -  Development Loan
> Amount -  Min: 100,000, Max:1,000,000
> Interest - 20%
> Loan term - From 3months to 6months
> -- This means the interest given is for any loan term the client will want to take the loan.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)