Repository: incubator-fineract
Updated Branches:
  refs/heads/develop b3c4f75f1 -> 580840c35


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/580840c3/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
index 4c1451c..88e4be9 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -39,6 +39,8 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.lang.StringUtils;
+import 
org.apache.fineract.accounting.journalentry.exception.JournalEntryInvalidException;
+import 
org.apache.fineract.accounting.journalentry.exception.JournalEntryInvalidException.GL_JOURNAL_ENTRY_INVALID_REASON;
 import 
org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
 import 
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
@@ -95,11 +97,14 @@ import 
org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrap
 import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
 import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
 import 
org.apache.fineract.portfolio.savings.domain.SavingsAccountTransactionRepository;
+import 
org.apache.fineract.portfolio.savings.exception.PostInterestAsOnDateException;
+import 
org.apache.fineract.portfolio.savings.exception.PostInterestClosingDateException;
 import 
org.apache.fineract.portfolio.savings.exception.SavingsAccountClosingNotAllowedException;
 import 
org.apache.fineract.portfolio.savings.exception.SavingsAccountTransactionNotFoundException;
 import 
org.apache.fineract.portfolio.savings.exception.SavingsOfficerAssignmentException;
 import 
org.apache.fineract.portfolio.savings.exception.SavingsOfficerUnassignmentException;
 import 
org.apache.fineract.portfolio.savings.exception.TransactionUpdateNotAllowedException;
+import 
org.apache.fineract.portfolio.savings.exception.PostInterestAsOnDateException.PostInterestAsOnException_TYPE;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper;
 import org.joda.time.LocalDate;
@@ -255,7 +260,6 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
 
         final SavingsAccount account = 
this.savingAccountAssembler.assembleFrom(savingsId);
         checkClientOrGroupActive(account);
-
         final Locale locale = command.extractLocale();
         final DateTimeFormatter fmt = 
DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
 
@@ -268,7 +272,6 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         boolean isRegularTransaction = true;
         final SavingsAccountTransaction deposit = 
this.savingsAccountDomainService.handleDeposit(account, fmt, transactionDate,
                 transactionAmount, paymentDetail, isAccountTransfer, 
isRegularTransaction);
-
         return new CommandProcessingResultBuilder() //
                 .withEntityId(deposit.getId()) //
                 .withOfficeId(account.officeId()) //
@@ -277,6 +280,7 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
                 .withSavingsId(savingsId) //
                 .with(changes) //
                 .build();
+       
     }
 
     private Long saveTransactionToGenerateTransactionId(final 
SavingsAccountTransaction transaction) {
@@ -300,8 +304,7 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         final PaymentDetail paymentDetail = 
this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, 
changes);
 
         final SavingsAccount account = 
this.savingAccountAssembler.assembleFrom(savingsId);
-        checkClientOrGroupActive(account);
-
+        checkClientOrGroupActive(account);        
         final boolean isAccountTransfer = false;
         final boolean isRegularTransaction = true;
         final boolean isApplyWithdrawFee = true;
@@ -359,7 +362,7 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         final MathContext mc = new MathContext(15, 
MoneyHelper.getRoundingMode());
         boolean isInterestTransfer = false;
         account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth);
+                financialYearBeginningMonth,false);
 
         this.savingAccountRepositoryWrapper.save(account);
 
@@ -371,13 +374,32 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
                 .withSavingsId(savingsId) //
                 .build();
     }
-
     @Override
-    public CommandProcessingResult postInterest(final Long savingsId) {
-
+    public CommandProcessingResult postInterest(final JsonCommand command) {
+        
+      Long savingsId=command.getSavingsId();
+      final boolean postInterestAs 
=command.booleanPrimitiveValueOfParameterNamed("isPostInterestAsOn");
+      final LocalDate transactionDate = 
command.localDateValueOfParameterNamed("transactionDate");
         final SavingsAccount account = 
this.savingAccountAssembler.assembleFrom(savingsId);
         checkClientOrGroupActive(account);
-        postInterest(account);
+        if (postInterestAs == true) {
+            
+            if (transactionDate == null) {
+
+            throw new 
PostInterestAsOnDateException(PostInterestAsOnException_TYPE.VALID_DATE); }
+            if 
(transactionDate.isBefore(account.accountSubmittedOrActivationDate())) { throw 
new PostInterestAsOnDateException(
+                    PostInterestAsOnException_TYPE.ACTIVATION_DATE); }
+            List<SavingsAccountTransaction> savingTransactions = 
account.getTransactions();
+            for (SavingsAccountTransaction savingTransaction : 
savingTransactions) {
+                if 
(transactionDate.toDate().before(savingTransaction.getDateOf())) { throw new 
PostInterestAsOnDateException(
+                        PostInterestAsOnException_TYPE.LAST_TRANSACTION_DATE); 
}
+            }
+
+            LocalDate today = DateUtils.getLocalDateOfTenant();
+            if (transactionDate.isAfter(today)) { throw new 
PostInterestAsOnDateException(PostInterestAsOnException_TYPE.FUTURE_DATE); }
+
+        }
+        postInterest(account,postInterestAs,transactionDate);
         return new CommandProcessingResultBuilder() //
                 .withEntityId(savingsId) //
                 .withOfficeId(account.officeId()) //
@@ -389,7 +411,7 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
 
     @Transactional
     @Override
-    public void postInterest(final SavingsAccount account) {
+    public void postInterest(final SavingsAccount account,final boolean 
postInterestAs,final LocalDate transactionDate) {
 
         final boolean isSavingsInterestPostingAtCurrentPeriodEnd = 
this.configurationDomainService
                 .isSavingsInterestPostingAtCurrentPeriodEnd();
@@ -403,14 +425,18 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
             final LocalDate today = DateUtils.getLocalDateOfTenant();
             final MathContext mc = new MathContext(10, 
MoneyHelper.getRoundingMode());
             boolean isInterestTransfer = false;
-            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
-
+            if(postInterestAs==false){
+            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth,postInterestAs);
+            }
+            else{
+            account.postInterest(mc, transactionDate, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth,postInterestAs);   
+            }
             // for generating transaction id's
             List<SavingsAccountTransaction> transactions = 
account.getTransactions();
             for (SavingsAccountTransaction accountTransaction : transactions) {
                 if (accountTransaction.getId() == null) {
                     
this.savingsAccountTransactionRepository.save(accountTransaction);
-                }
+                    }
             }
 
             this.savingAccountRepositoryWrapper.saveAndFlush(account);
@@ -418,7 +444,7 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
             postJournalEntries(account, existingTransactionIds, 
existingReversedTransactionIds);
         }
     }
-
+    
     @Override
     public CommandProcessingResult undoTransaction(final Long savingsId, final 
Long transactionId,
             final boolean allowAccountTransferModification) {
@@ -466,10 +492,10 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         checkClientOrGroupActive(account);
         if (savingsAccountTransaction.isPostInterestCalculationRequired()
                 && 
account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate()))
 {
-            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
+            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,false);
         } else {
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth);
+                    financialYearBeginningMonth,false);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) == 1) {
@@ -555,10 +581,10 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
 
         if (account.isBeforeLastPostingPeriod(transactionDate)
                 || 
account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate()))
 {
-            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
+            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,false);
         } else {
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth);
+                    financialYearBeginningMonth,false);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) == 1) {
@@ -604,9 +630,10 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
     @Override
     public CommandProcessingResult close(final Long savingsId, final 
JsonCommand command) {
         final AppUser user = this.context.authenticatedUser();
-
+        
         this.savingsAccountTransactionDataValidator.validateClosing(command);
         final SavingsAccount account = 
this.savingAccountAssembler.assembleFrom(savingsId);
+        
         final boolean isLinkedWithAnyActiveLoan = 
this.accountAssociationsReadPlatformService.isLinkedWithAnyActiveAccount(savingsId);
 
         if (isLinkedWithAnyActiveLoan) {
@@ -614,18 +641,36 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
                     + " is not allowed, since it is linked with one of the 
active accounts";
             throw new SavingsAccountClosingNotAllowedException("linked", 
defaultUserMessage, savingsId);
         }
+        
+       
 
         final boolean isWithdrawBalance = 
command.booleanPrimitiveValueOfParameterNamed(withdrawBalanceParamName);
 
         final Locale locale = command.extractLocale();
         final DateTimeFormatter fmt = 
DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
         final LocalDate closedDate = 
command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName);
-
+        final boolean isPostInterest = 
command.booleanPrimitiveValueOfParameterNamed(SavingsApiConstants.postInterestValidationOnClosure);
+       // postInterest(account,closedDate,flag);
+        if (isPostInterest) {
+            boolean postInterestOnClosingDate = false;
+            List<SavingsAccountTransaction> savingTransactions = 
account.getTransactions();
+            for (SavingsAccountTransaction savingTransaction : 
savingTransactions) {
+                if (closedDate.toDate().equals(savingTransaction.getDateOf())) 
if (savingTransaction.getTypeOf() == 
SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()) {
+                    postInterestOnClosingDate = true;
+                }
+            }
+            if (postInterestOnClosingDate == false) { throw new 
PostInterestClosingDateException(); }
+        }
+            
         final Map<String, Object> changes = new LinkedHashMap<>();
 
         if (isWithdrawBalance && 
account.getSummary().getAccountBalance(account.getCurrency()).isGreaterThanZero())
 {
 
+            
+            
+            
             final BigDecimal transactionAmount = 
account.getSummary().getAccountBalance();
+            
             final PaymentDetail paymentDetail = 
this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, 
changes);
 
             final boolean isAccountTransfer = false;
@@ -685,8 +730,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         
savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue());
         final MathContext mc = MathContext.DECIMAL64;
         boolean isInterestTransfer = false;
+        boolean postInterestAsOn = false;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth);
+                financialYearBeginningMonth, postInterestAsOn);
 
         this.savingsAccountTransactionRepository.save(newTransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -715,8 +761,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue());
         final MathContext mc = MathContext.DECIMAL64;
         boolean isInterestTransfer = false;
+        boolean postInterestAsOn =false;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth);
+                financialYearBeginningMonth, postInterestAsOn);
 
         
this.savingsAccountTransactionRepository.save(withdrawtransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -756,8 +803,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         }
         boolean isInterestTransfer = false;
         final MathContext mc = MathContext.DECIMAL64;
+        boolean postInterestAsOn = false;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth);
+                financialYearBeginningMonth, postInterestAsOn);
 
         
this.savingsAccountTransactionRepository.save(acceptTransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -906,14 +954,16 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
 
         account.waiveCharge(savingsAccountChargeId, user);
         boolean isInterestTransfer = false;
+        boolean postInterestAsOn = false;
         final MathContext mc = MathContext.DECIMAL64;
         if 
(account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate())) {
             final LocalDate today = DateUtils.getLocalDateOfTenant();
-            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
+            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
+                    postInterestAsOn);
         } else {
             final LocalDate today = DateUtils.getLocalDateOfTenant();
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth);
+                    financialYearBeginningMonth, postInterestAsOn);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) == 1) {
@@ -1038,14 +1088,16 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         updateExistingTransactionsDetails(account, existingTransactionIds, 
existingReversedTransactionIds);
         account.payCharge(savingsAccountCharge, amountPaid, transactionDate, 
formatter, user);
         boolean isInterestTransfer = false;
+        boolean postInterestAsOn = false;
         final MathContext mc = MathContext.DECIMAL64;
         if (account.isBeforeLastPostingPeriod(transactionDate)) {
             final LocalDate today = DateUtils.getLocalDateOfTenant();
-            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
+            account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
+                    postInterestAsOn);
         } else {
             final LocalDate today = DateUtils.getLocalDateOfTenant();
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth);
+                    financialYearBeginningMonth, postInterestAsOn);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) == 1) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/580840c3/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
index 7563f85..e3f2f0c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
@@ -60,7 +60,9 @@ public class SavingsSchedularServiceImpl implements 
SavingsSchedularService {
         for (final SavingsAccount savingsAccount : savingsAccounts) {
             try {
                 
this.savingAccountAssembler.assignSavingAccountHelpers(savingsAccount);
-                
this.savingsAccountWritePlatformService.postInterest(savingsAccount);
+                boolean postInterestAsOn = false;
+                LocalDate transactionDate = null;
+                
this.savingsAccountWritePlatformService.postInterest(savingsAccount, 
postInterestAsOn, transactionDate);
             } catch (Exception e) {
                 Throwable realCause = e;
                 if (e.getCause() != null) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/580840c3/fineract-provider/src/main/resources/sql/migrations/core_db/V321__boolean_field_As_Interest_PostedOn.sql
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/resources/sql/migrations/core_db/V321__boolean_field_As_Interest_PostedOn.sql
 
b/fineract-provider/src/main/resources/sql/migrations/core_db/V321__boolean_field_As_Interest_PostedOn.sql
new file mode 100644
index 0000000..19ba1da
--- /dev/null
+++ 
b/fineract-provider/src/main/resources/sql/migrations/core_db/V321__boolean_field_As_Interest_PostedOn.sql
@@ -0,0 +1,21 @@
+--
+-- 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.
+--
+
+ALTER TABLE m_savings_account_transaction
+ADD is_manual boolean default 0
\ No newline at end of file

Reply via email to