fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nazeer1100...@apache.org
Subject [1/2] incubator-fineract git commit: validating disbursement date against expected disbursement date
Date Tue, 02 Aug 2016 08:05:38 GMT
Repository: incubator-fineract
Updated Branches:
  refs/heads/develop 8dfcd1364 -> 56da30c3f


validating disbursement date against expected disbursement date


Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/68f013ab
Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/68f013ab
Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/68f013ab

Branch: refs/heads/develop
Commit: 68f013abc221686e74e933b7d9c5811843edaefe
Parents: 8dfcd13
Author: jinjurajan <jinju.rajan@confluxtechnologies.com>
Authored: Thu Jun 9 18:47:55 2016 +0530
Committer: Nazeer Hussain Shaik <nazeer.shaik@confluxtechnologies.com>
Committed: Tue Aug 2 11:53:22 2016 +0530

----------------------------------------------------------------------
 .../LoanDisbursalDateValidationTest.java        | 117 +++++++++++++++++++
 .../common/loans/LoanProductTestBuilder.java    |   9 ++
 .../common/loans/LoanTransactionHelper.java     |  10 ++
 .../exception/DateMismatchException.java        |  39 +++++++
 ...anWritePlatformServiceJpaRepositoryImpl.java |  29 ++++-
 .../loanproduct/data/LoanProductData.java       |  24 +++-
 .../loanproduct/domain/LoanProduct.java         |  29 ++++-
 .../serialization/LoanProductDataValidator.java |   2 +-
 .../LoanProductReadPlatformServiceImpl.java     |   6 +-
 ...with_disbursement_date_in_m_product_loan.sql |   1 +
 10 files changed, 253 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanDisbursalDateValidationTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanDisbursalDateValidationTest.java
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanDisbursalDateValidationTest.java
new file mode 100644
index 0000000..c7235da
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanDisbursalDateValidationTest.java
@@ -0,0 +1,117 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.CommonConstants;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+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;
+
+@SuppressWarnings("rawtypes")
+public class LoanDisbursalDateValidationTest {
+
+    private ResponseSpecification responseSpec;
+    private RequestSpecification requestSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+    private ResponseSpecification responseForbiddenError;
+
+    @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.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        this.responseForbiddenError = new ResponseSpecBuilder().expectStatusCode(403).build();
+    }
+
+    @Test
+    public void LoanApplicationValidateDisbursalDate() {
+
+        final String proposedAmount = "5000";
+        final String approveDate = "1 March 2014";
+        final String disbursalDate = "02 March 2014";
+
+        // CREATE CLIENT
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec,
"01 January 2014");
+        System.out.println("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------"
+                + clientID);
+
+        // CREATE LOAN  PRODUCT
+        final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder()
+                .withSyncExpectedWithDisbursementDate(true).build(null));
+        System.out.println("----------------------------------LOAN PRODUCT CREATED WITH ID-------------------------------------------"
+                + loanProductID);
+
+        // APPLY FOR LOAN 
+        final Integer loanID = applyForLoanApplication(clientID, loanProductID, proposedAmount);
+        System.out.println("-----------------------------------LOAN CREATED WITH LOANID-------------------------------------------------"
+                + loanID);
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec,
loanID);
+
+        // VALIDATE THE LOAN STATUS
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoan(approveDate, loanID);
+
+        // VALIDATE THE LOAN IS APPROVED
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        // DISBURSE A LOAN
+        @SuppressWarnings("unchecked")
+        List<HashMap> disbursalError = (List<HashMap>) this.loanTransactionHelper.disburseLoan(disbursalDate,
loanID, this.responseForbiddenError);
+        
+        Assert.assertEquals("error.msg.actual.disbursement.date.does.not.match.with.expected.disbursal.date",
+        	disbursalError.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("1 March 2014")
+                .withSubmittedOnDate("26 February 2014").
+                build(clientID.toString(), loanProductID.toString(), null);
+        return this.loanTransactionHelper.getLoanId(loanApplication);
+    }
+
+    
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
index 5f90468..45dae9f 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
@@ -124,6 +124,7 @@ public class LoanProductTestBuilder {
     private Integer recalculationRestFrequencyOnDayType = null;
     private Integer recalculationCompoundingFrequencyDayOfWeekType = null;
     private Integer recalculationRestFrequencyDayOfWeekType = null;
+    private boolean syncExpectedWithDisbursementDate = false;
 
     public String build(final String chargeId) {
         final HashMap<String, Object> map = new HashMap<>();
@@ -211,6 +212,8 @@ public class LoanProductTestBuilder {
             map.put("minimumGap", minimumGap) ;
             map.put("maximumGap", maximumGap) ;
         }
+        map.put("syncExpectedWithDisbursementDate", 
+        		this.syncExpectedWithDisbursementDate);
         return new Gson().toJson(map);
     }
 
@@ -498,4 +501,10 @@ public class LoanProductTestBuilder {
         this.maximumGap = maximumGap;
         return this ;
     }
+    
+    public LoanProductTestBuilder withSyncExpectedWithDisbursementDate(Boolean syncExpectedWithDisbursementDate)
{
+        this.syncExpectedWithDisbursementDate = 
+        		syncExpectedWithDisbursementDate ;
+        return this ;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index 4f2c8cb..65cf2b6 100755
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
+import org.apache.fineract.integrationtests.common.CommonConstants;
 import org.apache.fineract.integrationtests.common.Utils;
 import org.joda.time.LocalDate;
 
@@ -176,6 +177,10 @@ public class LoanTransactionHelper {
         return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID),
getDisburseLoanAsJSON(date, disburseAmt));
     }
 
+    public Object disburseLoan(final String date, final Integer loanID, ResponseSpecification
responseValidationError) {
+        return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID),
getDisburseLoanAsJSON(date, null),  responseValidationError);
+    }
+    
     public HashMap disburseLoanToSavings(final String date, final Integer loanID) {
         return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_TO_SAVINGS_COMMAND,
loanID), getDisburseLoanAsJSON(date, null));
     }
@@ -492,6 +497,11 @@ public class LoanTransactionHelper {
     private Object performLoanTransaction(final String postURLForLoanTransaction, final String
jsonToBeSent, final String responseAttribute) {
         return Utils.performServerPost(this.requestSpec, this.responseSpec, postURLForLoanTransaction,
jsonToBeSent, responseAttribute);
     }
+    
+    private Object performLoanTransaction(final String postURLForLoanTransaction, final String
jsonToBeSent, ResponseSpecification responseValidationError) {
+    	
+        return  Utils.performServerPost(this.requestSpec, responseValidationError, postURLForLoanTransaction,
jsonToBeSent, CommonConstants.RESPONSE_ERROR);    	       
+   }
 
     public Object adjustLoanTransaction(final Integer loanId, final Integer transactionId,
final String date,
             final String transactionAmount, final String responseAttribute) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/DateMismatchException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/DateMismatchException.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/DateMismatchException.java
new file mode 100644
index 0000000..b0e09c4
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/DateMismatchException.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.loanaccount.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
+import org.joda.time.LocalDate;
+
+/**
+ * {@link AbstractPlatformDomainRuleException} thrown when 
+ * actual disbursement date does not match with
+ * expected disbursement date
+ * 
+ */
+public class DateMismatchException extends AbstractPlatformDomainRuleException {
+
+    public DateMismatchException(final LocalDate actualDisbursementDate, 
+    		final LocalDate expectedDisbursedOnLocalDate) {
+        super("error.msg.actual.disbursement.date.does.not.match.with.expected.disbursal.date",
+                "Actual disbursement date  (" + actualDisbursementDate + ") "
+                		+ "should be equal to Expected disbursal date (" + expectedDisbursedOnLocalDate+
")", actualDisbursementDate,
+                		expectedDisbursedOnLocalDate, null);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index ad04d15..e3f6ccb 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -142,6 +142,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementC
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
+import org.apache.fineract.portfolio.loanaccount.exception.DateMismatchException;
 import org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException;
 import org.apache.fineract.portfolio.loanaccount.exception.InvalidPaidInAdvanceAmountException;
 import org.apache.fineract.portfolio.loanaccount.exception.LoanDisbursalException;
@@ -164,6 +165,7 @@ import org.apache.fineract.portfolio.loanaccount.serialization.LoanEventApiJsonV
 import org.apache.fineract.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer;
 import org.apache.fineract.portfolio.loanproduct.data.LoanOverdueDTO;
 import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
 import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
 import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException;
 import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
@@ -312,6 +314,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
         this.loanEventApiJsonValidator.validateDisbursement(command.json(), isAccountTransfer);
 
         final Loan loan = this.loanAssembler.assembleFrom(loanId);
+        
+        final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
+        
+        // validate ActualDisbursement Date Against Expected Disbursement Date
+        LoanProduct loanProduct = loan.loanProduct();
+        if(loanProduct.syncExpectedWithDisbursementDate()){
+        	syncExpectedDateWithActualDisbursementDate(loan, actualDisbursementDate);
+        }
         checkClientOrGroupActive(loan);
 
         final LocalDate nextPossibleRepaymentDate = loan.getNextPossibleRepaymentDateForRescheduling();
@@ -321,14 +331,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
         checkForProductMixRestrictions(loan);
         
         LocalDate recalculateFrom = null;
-        final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
         ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan,
recalculateFrom);
 
         // validate actual disbursement date against meeting date
         final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(),
                 CalendarEntityType.LOANS.getValue());
         if (loan.isSyncDisbursementWithMeeting()) {
-            
             this.loanEventApiJsonValidator.validateDisbursementDateWithMeetingDate(actualDisbursementDate,
calendarInstance, 
                     scheduleGeneratorDTO.isSkipRepaymentOnFirstDayofMonth(), scheduleGeneratorDTO.getNumberOfdays());
         }
@@ -346,6 +354,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
         final Boolean isPaymnetypeApplicableforDisbursementCharge = configurationDomainService
                 .isPaymnetypeApplicableforDisbursementCharge();
 
+        // Recalculate first repayment date based in actual disbursement date.
         updateLoanCounters(loan, actualDisbursementDate);
         Money amountBeforeAdjust = loan.getPrincpal();
         loan.validateAccountStatus(LoanEvent.LOAN_DISBURSED);
@@ -571,6 +580,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
             final SingleDisbursalCommand singleLoanDisbursalCommand = disbursalCommand[i];
 
             final Loan loan = this.loanAssembler.assembleFrom(singleLoanDisbursalCommand.getLoanId());
+            final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
+            
+            // validate ActualDisbursement Date Against Expected Disbursement Date
+            LoanProduct loanProduct = loan.loanProduct();
+            if(loanProduct.syncExpectedWithDisbursementDate()){
+            	syncExpectedDateWithActualDisbursementDate(loan, actualDisbursementDate);
+            }
             checkClientOrGroupActive(loan);
             this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_DISBURSAL,
                     constructEntityMap(BUSINESS_ENTITY.LOAN, loan));
@@ -586,7 +602,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
             // disbursement date and next available meeting dates
             // assuming repayment schedule won't regenerate because expected
             // disbursement and actual disbursement happens on same date
-            final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
             loan.validateAccountStatus(LoanEvent.LOAN_DISBURSED);
             updateLoanCounters(loan, actualDisbursementDate);
             boolean canDisburse = loan.canDisburse(actualDisbursementDate);
@@ -2949,4 +2964,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
         }
 
     }
+    
+    private void syncExpectedDateWithActualDisbursementDate(final Loan loan, LocalDate actualDisbursementDate){
+	   	if(!loan.getExpectedDisbursedOnLocalDate().equals(actualDisbursementDate)){
+	   		throw new DateMismatchException(actualDisbursementDate, 
+	   				loan.getExpectedDisbursedOnLocalDate());
+	   	}
+	   	
+	   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
index 2418945..68d1724 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
@@ -181,6 +181,7 @@ public class LoanProductData {
     private final LoanProductGuaranteeData productGuaranteeData;
     private final Boolean accountMovesOutOfNPAOnlyOnArrearsCompletion;
     private LoanProductConfigurableAttributes allowAttributeOverrides;
+    private final boolean syncExpectedWithDisbursementDate;
 
     /**
      * Used when returning lookup information about loan product for dropdowns.
@@ -255,6 +256,7 @@ public class LoanProductData {
         final boolean canDefineInstallmentAmount = false;
         final Integer installmentAmountInMultiplesOf = null;
         final LoanProductConfigurableAttributes loanProductConfigurableAttributes = null;
+        final boolean syncExpectedWithDisbursementDate = false;
 
         return new LoanProductData(id, name, shortName, description, currency, principal,
minPrincipal, maxPrincipal, tolerance,
                 numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery,
interestRatePerPeriod,
@@ -269,7 +271,8 @@ public class LoanProductData {
                 accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,
installmentAmountInMultiplesOf,
                 loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, floatingRateId,
floatingRateName,
                 interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
maxDifferentialLendingRate,
-                isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed,
minimumGap, maximumGap);
+                isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed,
minimumGap, maximumGap,
+                syncExpectedWithDisbursementDate);
 
     }
 
@@ -344,6 +347,7 @@ public class LoanProductData {
         final boolean canDefineInstallmentAmount = false;
         final Integer installmentAmountInMultiplesOf = null;
         final LoanProductConfigurableAttributes loanProductConfigurableAttributes = null;
+        final boolean syncExpectedWithDisbursementDate = false;
 
         return new LoanProductData(id, name, shortName, description, currency, principal,
minPrincipal, maxPrincipal, tolerance,
                 numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery,
interestRatePerPeriod,
@@ -358,7 +362,8 @@ public class LoanProductData {
                 accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,
installmentAmountInMultiplesOf,
                 loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, floatingRateId,
floatingRateName,
                 interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
maxDifferentialLendingRate,
-                isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed,
minimumGap, maximumGap);
+                isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed,
minimumGap, maximumGap,
+                syncExpectedWithDisbursementDate);
 
     }
 
@@ -440,6 +445,7 @@ public class LoanProductData {
         final boolean canDefineInstallmentAmount = false;
         final Integer installmentAmountInMultiplesOf = null;
         final LoanProductConfigurableAttributes loanProductConfigurableAttributes = null;
+        final boolean syncExpectedWithDisbursementDate = false;
 
         return new LoanProductData(id, name, shortName, description, currency, principal,
minPrincipal, maxPrincipal, tolerance,
                 numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery,
interestRatePerPeriod,
@@ -454,8 +460,10 @@ public class LoanProductData {
                 principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion,
canDefineInstallmentAmount,
                 installmentAmountInMultiplesOf, loanProductConfigurableAttributes, isLinkedToFloatingInterestRates,
floatingRateId,
                 floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
-                maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed,
minimumGap, maximumGap);
+                maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed,
minimumGap, maximumGap,
+                syncExpectedWithDisbursementDate);
 
+        
     }
 
     public static LoanProductData withAccountingDetails(final LoanProductData productData,
final Map<String, Object> accountingMappings,
@@ -493,7 +501,8 @@ public class LoanProductData {
             boolean isLinkedToFloatingInterestRates, Integer floatingRateId, String floatingRateName,
BigDecimal interestRateDifferential,
             BigDecimal minDifferentialLendingRate, BigDecimal defaultDifferentialLendingRate,
BigDecimal maxDifferentialLendingRate,
             boolean isFloatingInterestRateCalculationAllowed, final boolean isVariableInstallmentsAllowed,
-            final Integer minimumGapBetweenInstallments, final Integer maximumGapBetweenInstallments)
{
+            final Integer minimumGapBetweenInstallments, final Integer maximumGapBetweenInstallments,

+            final boolean syncExpectedWithDisbursementDate) {
         this.id = id;
         this.name = name;
         this.shortName = shortName;
@@ -595,6 +604,7 @@ public class LoanProductData {
         this.canDefineInstallmentAmount = canDefineInstallmentAmount;
         this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
         this.preClosureInterestCalculationStrategyOptions = null;
+        this.syncExpectedWithDisbursementDate = syncExpectedWithDisbursementDate;
 
     }
 
@@ -729,6 +739,7 @@ public class LoanProductData {
         this.canDefineInstallmentAmount = productData.canDefineInstallmentAmount;
         this.installmentAmountInMultiplesOf = productData.installmentAmountInMultiplesOf;
         this.preClosureInterestCalculationStrategyOptions = preCloseInterestCalculationStrategyOptions;
+        this.syncExpectedWithDisbursementDate = productData.syncExpectedWithDisbursementDate;
     }
 
     private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges)
{
@@ -1077,4 +1088,9 @@ public class LoanProductData {
     public Boolean getAllowPartialPeriodInterestCalcualtion() {
         return this.allowPartialPeriodInterestCalcualtion;
     }
+
+	public boolean syncExpectedWithDisbursementDate() {
+		return syncExpectedWithDisbursementDate;
+	}
+    
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
----------------------------------------------------------------------
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 c66e70b..2cdb0d1 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
@@ -175,6 +175,9 @@ public class LoanProduct extends AbstractPersistable<Long> {
 
     @OneToOne(cascade = CascadeType.ALL, mappedBy = "loanProduct", optional = true, orphanRemoval
= true, fetch=FetchType.EAGER)
     private LoanProductVariableInstallmentConfig variableInstallmentConfig;
+    
+    @Column(name = "sync_expected_with_disbursement_date")
+    private boolean syncExpectedWithDisbursementDate;
 
     public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy
loanTransactionProcessingStrategy,
             final List<Charge> productCharges, final JsonCommand command, final AprCalculator
aprCalculator, FloatingRate floatingRate) {
@@ -318,6 +321,8 @@ public class LoanProduct extends AbstractPersistable<Long> {
         final Integer installmentAmountInMultiplesOf = command
                 .integerValueOfParameterNamed(LoanProductConstants.installmentAmountInMultiplesOfParamName);
 
+        final boolean syncExpectedWithDisbursementDate = command.booleanPrimitiveValueOfParameterNamed("syncExpectedWithDisbursementDate");
+        
         return new LoanProduct(fund, loanTransactionProcessingStrategy, name, shortName,
description, currency, principal, minPrincipal,
                 maxPrincipal, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod,
interestFrequencyType,
                 annualInterestRate, interestMethod, interestCalculationPeriodMethod, allowPartialPeriodInterestCalcualtion,
repaymentEvery,
@@ -331,7 +336,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
                 installmentAmountInMultiplesOf, loanConfigurableAttributes, isLinkedToFloatingInterestRates,
floatingRate,
                 interestRateDifferential, minDifferentialLendingRate, maxDifferentialLendingRate,
defaultDifferentialLendingRate,
                 isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed,
minimumGapBetweenInstallments,
-                maximumGapBetweenInstallments);
+                maximumGapBetweenInstallments, syncExpectedWithDisbursementDate);
 
     }
 
@@ -562,7 +567,8 @@ public class LoanProduct extends AbstractPersistable<Long> {
             Boolean isLinkedToFloatingInterestRates, FloatingRate floatingRate, BigDecimal
interestRateDifferential,
             BigDecimal minDifferentialLendingRate, BigDecimal maxDifferentialLendingRate,
BigDecimal defaultDifferentialLendingRate,
             Boolean isFloatingInterestRateCalculationAllowed, final Boolean isVariableInstallmentsAllowed,
-            final Integer minimumGapBetweenInstallments, final Integer maximumGapBetweenInstallments)
{
+            final Integer minimumGapBetweenInstallments, final Integer maximumGapBetweenInstallments,
+            final boolean syncExpectedWithDisbursementDate) {
         this.fund = fund;
         this.transactionProcessingStrategy = transactionProcessingStrategy;
         this.name = name.trim();
@@ -636,6 +642,8 @@ public class LoanProduct extends AbstractPersistable<Long> {
         this.accountMovesOutOfNPAOnlyOnArrearsCompletion = accountMovesOutOfNPAOnlyOnArrearsCompletion;
         this.canDefineInstallmentAmount = canDefineEmiAmount;
         this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
+        this.syncExpectedWithDisbursementDate = 
+        		syncExpectedWithDisbursementDate;
     }
 
     public MonetaryCurrency getCurrency() {
@@ -858,6 +866,13 @@ public class LoanProduct extends AbstractPersistable<Long> {
             actualChanges.put("locale", localeAsInput);
             this.minimumDaysBetweenDisbursalAndFirstRepayment = newValue;
         }
+        
+        if(command.isChangeInBooleanParameterNamed("syncExpectedWithDisbursementDate"
+        		, this.syncExpectedWithDisbursementDate)){
+        	final boolean newValue = command.booleanPrimitiveValueOfParameterNamed("syncExpectedWithDisbursementDate");
+        	actualChanges.put("syncExpectedWithDisbursementDate", newValue);
+        	this.syncExpectedWithDisbursementDate = newValue;
+        }
 
         /**
          * Update interest recalculation settings
@@ -1154,8 +1169,16 @@ public class LoanProduct extends AbstractPersistable<Long> {
         }
         return borrowerCycleVariation;
     }
+    
+    public boolean syncExpectedWithDisbursementDate() {
+		return syncExpectedWithDisbursementDate;
+	}
+
+	public void setSyncExpectedWithDisbursementDate(boolean syncExpectedWithDisbursementDate)
{
+		this.syncExpectedWithDisbursementDate = syncExpectedWithDisbursementDate;
+	}
 
-    public Map<String, BigDecimal> fetchBorrowerCycleVariationsForCycleNumber(final
Integer cycleNumber) {
+	public Map<String, BigDecimal> fetchBorrowerCycleVariationsForCycleNumber(final Integer
cycleNumber) {
         Map<String, BigDecimal> borrowerCycleVariations = new HashMap<>();
         borrowerCycleVariations.put(LoanProductConstants.principal, this.loanProductRelatedDetail.getPrincipal().getAmount());
         borrowerCycleVariations.put(LoanProductConstants.interestRatePerPeriod,

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java
----------------------------------------------------------------------
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 d8cb55d..f9c673b 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
@@ -70,7 +70,7 @@ public final class LoanProductDataValidator {
             "transactionProcessingStrategyId", "graceOnPrincipalPayment", "recurringMoratoriumOnPrincipalPeriods",
"graceOnInterestPayment", "graceOnInterestCharged", "charges",
             "accountingRule", "includeInBorrowerCycle", "startDate", "closeDate", "externalId",
"isLinkedToFloatingInterestRates",
             "floatingRatesId", "interestRateDifferential", "minDifferentialLendingRate",
"defaultDifferentialLendingRate",
-            "maxDifferentialLendingRate", "isFloatingInterestRateCalculationAllowed","recurringMoratoriumOnPrincipalPeriods",
+            "maxDifferentialLendingRate", "isFloatingInterestRateCalculationAllowed", "syncExpectedWithDisbursementDate",
             LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),
             LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
             LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
index 31c7903..e3a511d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
@@ -206,6 +206,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
                     + "lpr.allow_compounding_on_eod as allowCompoundingOnEod, "
                     + "lp.hold_guarantee_funds as holdGuaranteeFunds, "
                     + "lp.principal_threshold_for_last_installment as principalThresholdForLastInstallment,
"
+                    + "lp.sync_expected_with_disbursement_date as syncExpectedWithDisbursementDate,
"
                     + "lpg.id as lpgId, lpg.mandatory_guarantee as mandatoryGuarantee, "
                     + "lpg.minimum_guarantee_from_own_funds as minimumGuaranteeFromOwnFunds,
lpg.minimum_guarantee_from_guarantor_funds as minimumGuaranteeFromGuarantor, "
                     + "lp.account_moves_out_of_npa_only_on_arrears_completion as accountMovesOutOfNPAOnlyOnArrearsCompletion,
"
@@ -441,7 +442,8 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
 
             final BigDecimal principalThresholdForLastInstallment = rs.getBigDecimal("principalThresholdForLastInstallment");
             final boolean accountMovesOutOfNPAOnlyOnArrearsCompletion = rs.getBoolean("accountMovesOutOfNPAOnlyOnArrearsCompletion");
-
+            final boolean syncExpectedWithDisbursementDate = rs.getBoolean("syncExpectedWithDisbursementDate");
+            
             return new LoanProductData(id, name, shortName, description, currency, principal,
minPrincipal, maxPrincipal, tolerance,
                     numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery,
interestRatePerPeriod,
                     minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate,
repaymentFrequencyType,
@@ -457,7 +459,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
                     installmentAmountInMultiplesOf, allowAttributeOverrides, isLinkedToFloatingInterestRates,
floatingRateId,
                     floatingRateName, interestRateDifferential, minDifferentialLendingRate,
defaultDifferentialLendingRate,
                     maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed,
isVariableIntallmentsAllowed, minimumGap,
-                    maximumGap);
+                    maximumGap, syncExpectedWithDisbursementDate);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/68f013ab/fineract-provider/src/main/resources/sql/migrations/core_db/V310__add_sync_expected_with_disbursement_date_in_m_product_loan.sql
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V310__add_sync_expected_with_disbursement_date_in_m_product_loan.sql
b/fineract-provider/src/main/resources/sql/migrations/core_db/V310__add_sync_expected_with_disbursement_date_in_m_product_loan.sql
new file mode 100644
index 0000000..980d6d3
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V310__add_sync_expected_with_disbursement_date_in_m_product_loan.sql
@@ -0,0 +1 @@
+ALTER TABLE `m_product_loan`ADD COLUMN `sync_expected_with_disbursement_date` TINYINT NULL
 DEFAULT '0'  AFTER `instalment_amount_in_multiples_of`;
\ No newline at end of file



Mime
View raw message