[FINERACT-131] Topup Loan Feature

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

Branch: refs/heads/develop
Commit: 961aa3df868d41985b8b4e56495e012bef2d12e2
Parents: 11cd6ef
Author: satish-conflux <satish.saj...@confluxtechnologies.com>
Authored: Tue Aug 16 14:32:27 2016 +0530
Committer: Adi Narayana Raju <adi.r...@confluxtechnologies.com>
Committed: Tue Aug 16 14:32:27 2016 +0530

----------------------------------------------------------------------
 .../journalentry/data/LoanTransactionDTO.java   |   9 ++
 .../service/AccountingProcessorHelper.java      |   7 +-
 .../AccrualBasedAccountingProcessorForLoan.java |  12 +-
 .../CashBasedAccountingProcessorForLoan.java    |  11 +-
 .../account/data/AccountTransferDTO.java        |  44 ++++++
 .../domain/AccountTransferAssembler.java        |  15 +++
 .../domain/AccountTransferDetailAssembler.java  |  10 ++
 .../account/domain/AccountTransferDetails.java  |   5 +
 .../domain/AccountTransferTransaction.java      |   6 +
 .../AccountTransfersWritePlatformService.java   |   3 +
 ...ccountTransfersWritePlatformServiceImpl.java |  40 +++++-
 .../AccountDetailsReadPlatformService.java      |   2 +
 ...ilsReadPlatformServiceJpaRepositoryImpl.java |   5 +
 .../loanaccount/api/LoanApiConstants.java       |   6 +
 .../loanaccount/api/LoansApiResource.java       |  18 ++-
 .../loanaccount/data/LoanAccountData.java       | 135 ++++++++++++-------
 .../portfolio/loanaccount/domain/Loan.java      | 110 ++++++++-------
 .../domain/LoanAccountDomainService.java        |   8 ++
 .../domain/LoanAccountDomainServiceJpa.java     |  29 +++-
 .../loanaccount/domain/LoanRepository.java      |   5 +
 .../loanaccount/domain/LoanTopupDetails.java    |  68 ++++++++++
 ...ulateLoanScheduleQueryFromApiJsonHelper.java |   3 +-
 ...LoanApplicationCommandFromApiJsonHelper.java |  28 +++-
 ...onWritePlatformServiceJpaRepositoryImpl.java | 118 ++++++++++++++--
 .../service/LoanReadPlatformServiceImpl.java    |  39 ++++--
 ...anWritePlatformServiceJpaRepositoryImpl.java |  53 ++++++--
 .../loanproduct/LoanProductConstants.java       |   2 +
 .../api/LoanProductsApiResource.java            |   2 +-
 .../loanproduct/data/LoanProductData.java       |  27 ++--
 .../loanproduct/domain/LoanProduct.java         |  34 +++--
 .../serialization/LoanProductDataValidator.java |  15 ++-
 .../LoanProductReadPlatformServiceImpl.java     |   7 +-
 .../sql/migrations/core_db/V318__topuploan.sql  |  40 ++++++
 33 files changed, 741 insertions(+), 175 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
index 89306e5..3b77236 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
@@ -51,6 +51,8 @@ public class LoanTransactionDTO {
 
     private final boolean isAccountTransfer;
 
+    private boolean isLoanToLoanTransfer;
+
     public LoanTransactionDTO(final Long officeId, final Long paymentTypeId, 
final String transactionId, final Date transactionDate,
             final LoanTransactionEnumData transactionType, final BigDecimal 
amount, final BigDecimal principal, final BigDecimal interest,
             final BigDecimal fees, final BigDecimal penalties, final 
BigDecimal overPayment, final boolean reversed,
@@ -132,4 +134,11 @@ public class LoanTransactionDTO {
         return this.isAccountTransfer;
     }
 
+        public void setIsLoanToLoanTransfer(boolean isLoanToLoanTransfer) {
+                this.isLoanToLoanTransfer = isLoanToLoanTransfer;
+        }
+
+        public boolean isLoanToLoanTransfer(){
+            return this.isLoanToLoanTransfer;
+        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
index c7a0c23..fa3e763 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
@@ -170,7 +170,12 @@ public class AccountingProcessorHelper {
             final LoanTransactionDTO transaction = new 
LoanTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
                     transactionDate, transactionType, amount, principal, 
interest, fees, penalties, overPayments, reversed,
                     feePaymentDetails, penaltyPaymentDetails, 
isAccountTransfer);
-
+            Boolean isLoanToLoanTransfer = (Boolean) 
accountingBridgeData.get("isLoanToLoanTransfer");
+            if(isLoanToLoanTransfer != null && isLoanToLoanTransfer){
+                transaction.setIsLoanToLoanTransfer(true);
+            } else {
+                transaction.setIsLoanToLoanTransfer(false);
+            }
             newLoanTransactions.add(transaction);
 
         }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
index 7408ac9..8baa00a 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
@@ -124,7 +124,11 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
 
         // create journal entries for the disbursement (or disbursement
         // reversal)
-        if (loanTransactionDTO.isAccountTransfer()) {
+        if(loanTransactionDTO.isLoanToLoanTransfer()){
+            
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, 
currencyCode,
+                    ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), 
FINANCIAL_ACTIVITY.ASSET_TRANSFER.getValue(), loanProductId,
+                    paymentTypeId, loanId, transactionId, transactionDate, 
disbursalAmount, isReversed);
+        } else if (loanTransactionDTO.isAccountTransfer()) {
             
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, 
currencyCode,
                     ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), 
FINANCIAL_ACTIVITY.LIABILITY_TRANSFER.getValue(), loanProductId,
                     paymentTypeId, loanId, transactionId, transactionDate, 
disbursalAmount, isReversed);
@@ -296,7 +300,11 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
                         
ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue(), loanProductId, 
paymentTypeId, loanId, transactionId,
                         transactionDate, totalDebitAmount, isReversal);
             } else {
-                if (loanTransactionDTO.isAccountTransfer()) {
+                if(loanTransactionDTO.isLoanToLoanTransfer()){
+                    
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
+                            FINANCIAL_ACTIVITY.ASSET_TRANSFER.getValue(), 
loanProductId, paymentTypeId, loanId, transactionId,
+                            transactionDate, totalDebitAmount, isReversal);
+                } else if (loanTransactionDTO.isAccountTransfer()) {
                     
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
                             FINANCIAL_ACTIVITY.LIABILITY_TRANSFER.getValue(), 
loanProductId, paymentTypeId, loanId, transactionId,
                             transactionDate, totalDebitAmount, isReversal);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java
index a71016f..f288736 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java
@@ -132,7 +132,11 @@ public class CashBasedAccountingProcessorForLoan 
implements AccountingProcessorF
         final BigDecimal disbursalAmount = loanTransactionDTO.getAmount();
         final boolean isReversal = loanTransactionDTO.isReversed();
         final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
-        if (loanTransactionDTO.isAccountTransfer()) {
+        if(loanTransactionDTO.isLoanToLoanTransfer()){
+            
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, 
currencyCode,
+                    CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), 
FINANCIAL_ACTIVITY.ASSET_TRANSFER.getValue(), loanProductId,
+                    paymentTypeId, loanId, transactionId, transactionDate, 
disbursalAmount, isReversal);
+        } else if (loanTransactionDTO.isAccountTransfer()) {
             
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, 
currencyCode,
                     CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), 
FINANCIAL_ACTIVITY.LIABILITY_TRANSFER.getValue(), loanProductId,
                     paymentTypeId, loanId, transactionId, transactionDate, 
disbursalAmount, isReversal);
@@ -240,7 +244,10 @@ public class CashBasedAccountingProcessorForLoan 
implements AccountingProcessorF
         }
 
         /*** create a single debit entry (or reversal) for the entire amount 
**/
-        if (loanTransactionDTO.isAccountTransfer()) {
+        if(loanTransactionDTO.isLoanToLoanTransfer()){
+            this.helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, FINANCIAL_ACTIVITY.ASSET_TRANSFER.getValue(),
+                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, totalDebitAmount, isReversal);
+        } else if (loanTransactionDTO.isAccountTransfer()) {
             this.helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, FINANCIAL_ACTIVITY.LIABILITY_TRANSFER.getValue(),
                     loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, totalDebitAmount, isReversal);
         } else {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/AccountTransferDTO.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/AccountTransferDTO.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/AccountTransferDTO.java
index 9c62046..73fb9a8 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/AccountTransferDTO.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/AccountTransferDTO.java
@@ -50,6 +50,8 @@ public class AccountTransferDTO {
     private final String noteText;
     private final String txnExternalId;
     private final Loan loan;
+    private final Loan fromLoan;
+    private final Loan toLoan;
     private final SavingsAccount toSavingsAccount;
     private final SavingsAccount fromSavingsAccount;
     private final Boolean isRegularTransaction;
@@ -81,12 +83,46 @@ public class AccountTransferDTO {
         this.noteText = noteText;
         this.txnExternalId = txnExternalId;
         this.loan = loan;
+        this.fromLoan = null;
+        this.toLoan = null;
         this.toSavingsAccount = toSavingsAccount;
         this.fromSavingsAccount = fromSavingsAccount;
         this.isRegularTransaction = isRegularTransaction;
         this.isExceptionForBalanceCheck = isExceptionForBalanceCheck;
     }
 
+    public AccountTransferDTO(final LocalDate transactionDate, final 
BigDecimal transactionAmount,
+            final PortfolioAccountType fromAccountType, final 
PortfolioAccountType toAccountType, final Long fromAccountId,
+            final Long toAccountId, final String description, final Locale 
locale, final DateTimeFormatter fmt,
+            final Integer fromTransferType, final Integer toTransferType, 
final String txnExternalId,
+            final Loan fromLoan, final Loan toLoan) {
+        this.transactionDate = transactionDate;
+        this.transactionAmount = transactionAmount;
+        this.fromAccountType = fromAccountType;
+        this.toAccountType = toAccountType;
+        this.fromAccountId = fromAccountId;
+        this.toAccountId = toAccountId;
+        this.description = description;
+        this.locale = locale;
+        this.fmt = fmt;
+        this.paymentDetail = null;
+        this.fromTransferType = fromTransferType;
+        this.toTransferType = toTransferType;
+        this.chargeId = null;
+        this.loanInstallmentNumber = null;
+        this.transferType = null;
+        this.accountTransferDetails = null;
+        this.noteText = null;
+        this.txnExternalId = txnExternalId;
+        this.fromLoan = fromLoan;
+        this.toLoan = toLoan;
+        this.loan = null;
+        this.toSavingsAccount = null;
+        this.fromSavingsAccount = null;
+        this.isRegularTransaction = null;
+        this.isExceptionForBalanceCheck = null;
+    }
+
     public LocalDate getTransactionDate() {
         return this.transactionDate;
     }
@@ -163,6 +199,14 @@ public class AccountTransferDTO {
         return this.loan;
     }
 
+    public Loan getFromLoan() {
+        return this.fromLoan;
+    }
+
+    public Loan getToLoan() {
+        return this.toLoan;
+    }
+
     public SavingsAccount getToSavingsAccount() {
         return this.toSavingsAccount;
     }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferAssembler.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferAssembler.java
index e1550e3..96501eb 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferAssembler.java
@@ -145,4 +145,19 @@ public class AccountTransferAssembler {
         return accountTransferDetails;
     }
 
+    public AccountTransferDetails assembleLoanToLoanTransfer(final 
AccountTransferDTO accountTransferDTO, final Loan fromLoanAccount,
+            final Loan toLoanAccount, final LoanTransaction 
disburseTransaction, final LoanTransaction repaymentTransaction) {
+        final Money transactionMonetaryAmount = 
Money.of(fromLoanAccount.getCurrency(), 
accountTransferDTO.getTransactionAmount());
+        AccountTransferDetails accountTransferDetails = 
accountTransferDTO.getAccountTransferDetails();
+        if (accountTransferDetails == null) {
+            accountTransferDetails = 
this.accountTransferDetailAssembler.assembleLoanToLoanTransfer(fromLoanAccount, 
toLoanAccount,
+                    accountTransferDTO.getFromTransferType());
+        }
+        AccountTransferTransaction accountTransferTransaction = 
AccountTransferTransaction.LoanToLoanTransfer(accountTransferDetails,
+                disburseTransaction, repaymentTransaction, 
accountTransferDTO.getTransactionDate(), transactionMonetaryAmount,
+                accountTransferDTO.getDescription());
+        
accountTransferDetails.addAccountTransferTransaction(accountTransferTransaction);
+        return accountTransferDetails;
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetailAssembler.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetailAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetailAssembler.java
index 3ffa445..f9f4f20 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetailAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetailAssembler.java
@@ -201,4 +201,14 @@ public class AccountTransferDetailAssembler {
         return AccountTransferDetails.LoanTosavingsTransfer(fromOffice, 
fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount,
                 transferType);
     }
+
+    public AccountTransferDetails assembleLoanToLoanTransfer(Loan 
fromLoanAccount, Loan toLoanAccount, Integer transferType) {
+        final Office fromOffice = fromLoanAccount.getOffice();
+        final Client fromClient = fromLoanAccount.client();
+        final Office toOffice = toLoanAccount.getOffice();
+        final Client toClient = toLoanAccount.client();
+
+        return AccountTransferDetails.LoanToLoanTransfer(fromOffice, 
fromClient, fromLoanAccount, toOffice, toClient, toLoanAccount,
+                transferType);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetails.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetails.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetails.java
index d8cd057..3a19ce6 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetails.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferDetails.java
@@ -156,4 +156,9 @@ public class AccountTransferDetails extends 
AbstractPersistable<Long> {
         return AccountTransferType.fromInt(this.transferType);
     }
 
+    public static AccountTransferDetails LoanToLoanTransfer(Office fromOffice, 
Client fromClient, Loan fromLoanAccount, Office toOffice, Client toClient,
+            Loan toLoanAccount, Integer transferType) {
+        return new AccountTransferDetails(fromOffice, fromClient, null, 
fromLoanAccount, toOffice, toClient, null, toLoanAccount,
+                transferType, null);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferTransaction.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferTransaction.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferTransaction.java
index d47ea1e..bcec4f4 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferTransaction.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/domain/AccountTransferTransaction.java
@@ -145,4 +145,10 @@ public class AccountTransferTransaction extends 
AbstractPersistable<Long> {
     public AccountTransferDetails accountTransferDetails() {
         return this.accountTransferDetails;
     }
+
+        public static AccountTransferTransaction 
LoanToLoanTransfer(AccountTransferDetails accountTransferDetails, 
LoanTransaction disburseTransaction,
+                LoanTransaction repaymentTransaction, LocalDate 
transactionDate, Money transactionMonetaryAmount, String description) {
+            return new AccountTransferTransaction(accountTransferDetails, 
null, null, repaymentTransaction, disburseTransaction, transactionDate,
+                    transactionMonetaryAmount, description);
+        }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformService.java
index eeac44d..107fa69 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformService.java
@@ -24,6 +24,7 @@ import 
org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import org.apache.fineract.portfolio.account.PortfolioAccountType;
 import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
+import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 
 public interface AccountTransfersWritePlatformService {
@@ -41,4 +42,6 @@ public interface AccountTransfersWritePlatformService {
     CommandProcessingResult refundByTransfer(JsonCommand command);
 
     void reverseTransfersWithFromAccountTransactions(Collection<Long> 
fromTransactionIds, PortfolioAccountType accountTypeId);
+
+    AccountTransferDetails repayLoanWithTopup(AccountTransferDTO 
accountTransferDTO);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java
index fb0c7ea..fa5ee15 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java
@@ -33,6 +33,7 @@ import java.util.Locale;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
+import 
org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
 import org.apache.fineract.portfolio.account.PortfolioAccountType;
 import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
 import 
org.apache.fineract.portfolio.account.data.AccountTransfersDataValidator;
@@ -253,7 +254,8 @@ public class AccountTransfersWritePlatformServiceImpl 
implements AccountTransfer
         for (final AccountTransferTransaction accountTransfer : 
acccountTransfers) {
             if (accountTransfer.getFromLoanTransaction() != null) {
                 
this.loanAccountDomainService.reverseTransfer(accountTransfer.getFromLoanTransaction());
-            } else if (accountTransfer.getToLoanTransaction() != null) {
+            }
+            if (accountTransfer.getToLoanTransaction() != null) {
                 
this.loanAccountDomainService.reverseTransfer(accountTransfer.getToLoanTransaction());
             }
             if (accountTransfer.getFromTransaction() != null) {
@@ -409,12 +411,48 @@ public class AccountTransfersWritePlatformServiceImpl 
implements AccountTransfer
                     toSavingsAccount, deposit, loanTransaction);
             
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
             transferTransactionId = accountTransferDetails.getId();
+        } else {
+            throw new 
GeneralPlatformDomainRuleException("error.msg.accounttransfer.loan.to.loan.not.supported",
+                    "Account transfer from loan to another loan is not 
supported");
         }
 
         return transferTransactionId;
     }
 
     @Override
+    public AccountTransferDetails repayLoanWithTopup(AccountTransferDTO 
accountTransferDTO) {
+        final boolean isAccountTransfer = true;
+        Loan fromLoanAccount = null;
+        if (accountTransferDTO.getFromLoan() == null) {
+            fromLoanAccount = 
this.loanAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
+        } else {
+            fromLoanAccount = accountTransferDTO.getFromLoan();
+            this.loanAccountAssembler.setHelpers(fromLoanAccount);
+        }
+        Loan toLoanAccount = null;
+        if (accountTransferDTO.getToLoan() == null) {
+            toLoanAccount = 
this.loanAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
+        } else {
+            toLoanAccount = accountTransferDTO.getToLoan();
+            this.loanAccountAssembler.setHelpers(toLoanAccount);
+        }
+
+        LoanTransaction disburseTransaction = 
this.loanAccountDomainService.makeDisburseTransaction(accountTransferDTO.getFromAccountId(),
+                accountTransferDTO.getTransactionDate(), 
accountTransferDTO.getTransactionAmount(),
+                accountTransferDTO.getPaymentDetail(), 
accountTransferDTO.getNoteText(), accountTransferDTO.getTxnExternalId(), true);
+
+        LoanTransaction repayTransaction = 
this.loanAccountDomainService.makeRepayment(toLoanAccount, new 
CommandProcessingResultBuilder(),
+                accountTransferDTO.getTransactionDate(), 
accountTransferDTO.getTransactionAmount(),
+                accountTransferDTO.getPaymentDetail(), null, null, false, 
isAccountTransfer,null,false, true);
+
+        AccountTransferDetails accountTransferDetails = 
this.accountTransferAssembler.assembleLoanToLoanTransfer(accountTransferDTO, 
fromLoanAccount,
+                toLoanAccount, disburseTransaction, repayTransaction);
+        
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
+
+        return accountTransferDetails;
+    }
+
+    @Override
     @Transactional
     public void updateLoanTransaction(final Long loanTransactionId, final 
LoanTransaction newLoanTransaction) {
         final AccountTransferTransaction transferTransaction = 
this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java
index 58bb057..dc28a44 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java
@@ -32,4 +32,6 @@ public interface AccountDetailsReadPlatformService {
     public Collection<LoanAccountSummaryData> 
retrieveClientLoanAccountsByLoanOfficerId(final Long clientId, final Long 
loanOfficerId);
 
     public Collection<LoanAccountSummaryData> 
retrieveGroupLoanAccountsByLoanOfficerId(final Long groupId, final Long 
loanOfficerId);
+
+    public Collection<LoanAccountSummaryData> 
retrieveClientActiveLoanAccountSummary(final Long clientId);
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java
index a693bd9..bde382a 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java
@@ -111,6 +111,11 @@ public class 
AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
         return retrieveLoanAccountDetails(loanWhereClause, new Object[] { 
groupId, loanOfficerId });
     }
 
+    @Override public Collection<LoanAccountSummaryData> 
retrieveClientActiveLoanAccountSummary(final Long clientId) {
+        final String loanWhereClause = " where l.client_id = ? and 
l.loan_status_id = 300 ";
+        return retrieveLoanAccountDetails(loanWhereClause, new Object[] { 
clientId });
+    }
+
     private List<LoanAccountSummaryData> retrieveLoanAccountDetails(final 
String loanwhereClause, final Object[] inputs) {
         final LoanAccountSummaryDataMapper rm = new 
LoanAccountSummaryDataMapper();
         final String sql = "select " + rm.loanAccountSummarySchema() + 
loanwhereClause;

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
index ee38428..d312324 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java
@@ -117,4 +117,10 @@ public interface LoanApiConstants {
     public static final String transactionDateParamName = "transactionDate";
     public static final String noteParamName = "note";
 
+    public static final String canUseForTopup = "canUseForTopup";
+    public static final String clientActiveLoanOptions = 
"clientActiveLoanOptions";
+    public static final String isTopup = "isTopup";
+    public static final String loanIdToClose = "loanIdToClose";
+    public static final String topupAmount = "topupAmount";
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
index 5f3754c..cfdf399 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
@@ -66,6 +66,8 @@ import 
org.apache.fineract.portfolio.account.data.PortfolioAccountDTO;
 import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
 import 
org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService;
 import 
org.apache.fineract.portfolio.account.service.PortfolioAccountReadPlatformService;
+import 
org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData;
+import 
org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService;
 import org.apache.fineract.portfolio.calendar.data.CalendarData;
 import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
 import 
org.apache.fineract.portfolio.calendar.service.CalendarReadPlatformService;
@@ -136,7 +138,8 @@ public class LoansApiResource {
             "termFrequencyTypeOptions", "interestRateFrequencyTypeOptions", 
"fundOptions", "repaymentStrategyOptions", "chargeOptions",
             "loanOfficerOptions", "loanPurposeOptions", 
"loanCollateralOptions", "chargeTemplate", "calendarOptions",
             "syncDisbursementWithMeeting", "loanCounter", 
"loanProductCounter", "notes", "accountLinkingOptions", "linkedAccount",
-            "interestRateDifferential", "isFloatingInterestRate", 
"interestRatesPeriods"));
+            "interestRateDifferential", "isFloatingInterestRate", 
"interestRatesPeriods", LoanApiConstants.canUseForTopup,
+            LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose, 
LoanApiConstants.topupAmount, LoanApiConstants.clientActiveLoanOptions));
 
     private final Set<String> LOAN_APPROVAL_DATA_PARAMETERS = new 
HashSet<>(Arrays.asList("approvalDate", "approvalAmount"));
     private final String resourceNameForPermissions = "LOAN";
@@ -164,6 +167,7 @@ public class LoansApiResource {
     private final PortfolioAccountReadPlatformService 
portfolioAccountReadPlatformService;
     private final AccountAssociationsReadPlatformService 
accountAssociationsReadPlatformService;
     private final LoanScheduleHistoryReadPlatformService 
loanScheduleHistoryReadPlatformService;
+    private final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService;
 
     @Autowired
     public LoansApiResource(final PlatformSecurityContext context, final 
LoanReadPlatformService loanReadPlatformService,
@@ -182,7 +186,8 @@ public class LoansApiResource {
             final CalendarReadPlatformService calendarReadPlatformService, 
final NoteReadPlatformServiceImpl noteReadPlatformService,
             final PortfolioAccountReadPlatformService 
portfolioAccountReadPlatformServiceImpl,
             final AccountAssociationsReadPlatformService 
accountAssociationsReadPlatformService,
-            final LoanScheduleHistoryReadPlatformService 
loanScheduleHistoryReadPlatformService) {
+            final LoanScheduleHistoryReadPlatformService 
loanScheduleHistoryReadPlatformService,
+            final AccountDetailsReadPlatformService 
accountDetailsReadPlatformService) {
         this.context = context;
         this.loanReadPlatformService = loanReadPlatformService;
         this.loanProductReadPlatformService = loanProductReadPlatformService;
@@ -206,6 +211,7 @@ public class LoansApiResource {
         this.portfolioAccountReadPlatformService = 
portfolioAccountReadPlatformServiceImpl;
         this.accountAssociationsReadPlatformService = 
accountAssociationsReadPlatformService;
         this.loanScheduleHistoryReadPlatformService = 
loanScheduleHistoryReadPlatformService;
+        this.accountDetailsReadPlatformService = 
accountDetailsReadPlatformService;
     }
 
     /*
@@ -514,6 +520,7 @@ public class LoansApiResource {
         Collection<CalendarData> calendarOptions = null;
         Collection<PortfolioAccountData> accountLinkingOptions = null;
         PaidInAdvanceData paidInAdvanceTemplate = null;
+        Collection<LoanAccountSummaryData> clientActiveLoanOptions = null;
 
         final boolean template = 
ApiParameterHelper.template(uriInfo.getQueryParameters());
         if (template) {
@@ -568,6 +575,11 @@ public class LoansApiResource {
                 calendarOptions = 
this.loanReadPlatformService.retrieveCalendars(loanBasicDetails.groupId());
             }
 
+            if(loanBasicDetails.product().canUseForTopup() && 
loanBasicDetails.clientId() != null){
+                clientActiveLoanOptions = 
this.accountDetailsReadPlatformService.retrieveClientActiveLoanAccountSummary(loanBasicDetails.clientId());
+            }
+
+
         }
 
         Collection<ChargeData> overdueCharges = 
this.chargeReadPlatformService.retrieveLoanProductCharges(loanBasicDetails.loanProductId(),
@@ -581,7 +593,7 @@ public class LoansApiResource {
                 interestRateFrequencyTypeOptions, amortizationTypeOptions, 
interestTypeOptions, interestCalculationPeriodTypeOptions, 
                 fundOptions, chargeOptions, chargeTemplate, 
allowedLoanOfficers, loanPurposeOptions, loanCollateralOptions, 
                 calendarOptions, notes, accountLinkingOptions, linkedAccount, 
disbursementData, emiAmountVariations,
-                overdueCharges, paidInAdvanceTemplate, interestRatesPeriods);
+                overdueCharges, paidInAdvanceTemplate, interestRatesPeriods, 
clientActiveLoanOptions);
 
         final ApiRequestJsonSerializationSettings settings = 
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(),
                 mandatoryResponseParameters);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
index 0c158ca..7927b68 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
@@ -31,6 +31,7 @@ import 
org.apache.fineract.infrastructure.core.data.EnumOptionData;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.organisation.staff.data.StaffData;
 import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
+import 
org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData;
 import org.apache.fineract.portfolio.calendar.data.CalendarData;
 import org.apache.fineract.portfolio.charge.data.ChargeData;
 import org.apache.fineract.portfolio.collateral.data.CollateralData;
@@ -39,7 +40,6 @@ import 
org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData;
 import org.apache.fineract.portfolio.fund.data.FundData;
 import org.apache.fineract.portfolio.group.data.GroupGeneralData;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanSubStatus;
 import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorData;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
 import 
org.apache.fineract.portfolio.loanproduct.data.LoanProductBorrowerCycleVariationData;
@@ -180,6 +180,12 @@ public class LoanAccountData {
     private final Boolean canDisburse;
 
     private final Collection<LoanTermVariationsData> emiAmountVariations;
+    private final Collection<LoanAccountSummaryData> clientActiveLoanOptions;
+    private final Boolean canUseForTopup;
+    private final boolean isTopup;
+    private final Long closureLoanId;
+    private final String closureLoanAccountNo;
+    private final BigDecimal topupAmount;
 
     private LoanProductData product;
 
@@ -319,6 +325,12 @@ public class LoanAccountData {
         final Boolean isVariableInstallmentsAllowed = Boolean.FALSE;
         final Integer minimumGap = null;
         final Integer maximumGap = null;
+        final Boolean canUseForTopup = null;
+        final Collection<LoanAccountSummaryData> clientActiveLoanOptions = 
null;
+        final boolean isTopup = false;
+        final Long closureLoanId = null;
+        final String closureLoanAccountNo = null;
+        final BigDecimal topupAmount = null;
 
         return new LoanAccountData(id, accountNo, status, externalId, 
clientId, clientAccountNo, clientName, clientOfficeId, group,
                 loanType, loanProductId, loanProductName, 
loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName,
@@ -338,7 +350,7 @@ public class LoanAccountData {
                 maxOutstandingLoanBalance, emiAmountVariations, 
memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges,
                 isNPA, daysInMonthType, daysInYearType, 
isInterestRecalculationEnabled, interestRecalculationData, originalSchedule,
                 createStandingInstructionAtDisbursement, paidInAdvance, 
interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap,
-                maximumGap, subStatus);
+                maximumGap, subStatus, canUseForTopup, 
clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, 
topupAmount);
 
     }
 
@@ -453,6 +465,12 @@ public class LoanAccountData {
         final Boolean isVariableInstallmentsAllowed = Boolean.FALSE;
         final Integer minimumGap = null;
         final Integer maximumGap = null;
+        final Boolean canUseForTopup = null;
+        final Collection<LoanAccountSummaryData> clientActiveLoanOptions = 
null;
+        final boolean isTopup = false;
+        final Long closureLoanId = null;
+        final String closureLoanAccountNo = null;
+        final BigDecimal topupAmount = null;
 
         return new LoanAccountData(id, accountNo, status, externalId, 
clientId, clientAccountNo, clientName, clientOfficeId, group,
                 loanType, loanProductId, loanProductName, 
loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName,
@@ -472,7 +490,7 @@ public class LoanAccountData {
                 maxOutstandingLoanBalance, emiAmountVariations, 
memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges,
                 isNPA, daysInMonthType, daysInYearType, 
isInterestRecalculationEnabled, interestRecalculationData, originalSchedule,
                 createStandingInstructionAtDisbursement, paidInAdvance, 
interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap,
-                maximumGap, subStatus);
+                maximumGap, subStatus, canUseForTopup, 
clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, 
topupAmount);
 
     }
 
@@ -501,7 +519,8 @@ public class LoanAccountData {
                 acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, 
acc.daysInMonthType, acc.daysInYearType,
                 acc.isInterestRecalculationEnabled, 
acc.interestRecalculationData, acc.originalSchedule,
                 acc.createStandingInstructionAtDisbursement, 
acc.paidInAdvance, acc.interestRatesPeriods,
-                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus);
+                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus, acc.canUseForTopup,
+                acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, 
acc.closureLoanAccountNo, acc.topupAmount);
     }
 
     /**
@@ -617,6 +636,12 @@ public class LoanAccountData {
         final Boolean isVariableInstallmentsAllowed = Boolean.FALSE;
         final Integer minimumGap = null;
         final Integer maximumGap = null;
+        final Boolean canUseForTopup = null;
+        final Collection<LoanAccountSummaryData> clientActiveLoanOptions = 
null;
+        final boolean isTopup = false;
+        final Long closureLoanId = null;
+        final String closureLoanAccountNo = null;
+        final BigDecimal topupAmount = null;
 
         return new LoanAccountData(id, accountNo, status, externalId, 
clientId, clientAccountNo, clientName, clientOfficeId, group,
                 loanType, loanProductId, loanProductName, 
loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName,
@@ -636,7 +661,7 @@ public class LoanAccountData {
                 maxOutstandingBalance, emiAmountVariations, memberVariations, 
product, inArrears, graceOnArrearsAgeing, overdueCharges,
                 isNPA, daysInMonthType, daysInYearType, 
isInterestRecalculationEnabled, interestRecalculationData, originalSchedule,
                 createStandingInstructionAtDisbursement, paidInAdvance, 
interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap,
-                maximumGap, subStatus);
+                maximumGap, subStatus, canUseForTopup, 
clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, 
topupAmount);
 
     }
 
@@ -665,7 +690,8 @@ public class LoanAccountData {
                 acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, 
acc.daysInMonthType, acc.daysInYearType,
                 acc.isInterestRecalculationEnabled, 
acc.interestRecalculationData, acc.originalSchedule,
                 acc.createStandingInstructionAtDisbursement, 
acc.paidInAdvance, acc.interestRatesPeriods,
-                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus);
+                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus, acc.canUseForTopup,
+                acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, 
acc.closureLoanAccountNo, acc.topupAmount);
 
     }
 
@@ -678,7 +704,7 @@ public class LoanAccountData {
             final Collection<EnumOptionData> interestTypeOptions, final 
Collection<EnumOptionData> interestCalculationPeriodTypeOptions,
             final Collection<FundData> fundOptions, final 
Collection<ChargeData> chargeOptions,
             final Collection<CodeValueData> loanPurposeOptions, final 
Collection<CodeValueData> loanCollateralOptions,
-            final Integer loanCycleNumber) {
+            final Integer loanCycleNumber, final 
Collection<LoanAccountSummaryData> clientActiveLoanOptions) {
 
         final Long id = null;
         final String accountNo = null;
@@ -790,6 +816,11 @@ public class LoanAccountData {
         final Boolean isVariableInstallmentsAllowed = Boolean.FALSE;
         final Integer minimumGap = null;
         final Integer maximumGap = null;
+        final Boolean canUseForTopup = product.canUseForTopup();
+        final boolean isTopup = false;
+        final Long closureLoanId = null;
+        final String closureLoanAccountNo = null;
+        final BigDecimal topupAmount = null;
 
         return new LoanAccountData(id, accountNo, status, externalId, 
clientId, clientAccountNo, clientName, clientOfficeId, group,
                 loanType, product.getId(), product.getName(), 
product.getDescription(), product.isLinkedToFloatingInterestRates(),
@@ -814,7 +845,8 @@ public class LoanAccountData {
                 product.getDaysInYearType(), 
product.isInterestRecalculationEnabled(), 
product.toLoanInterestRecalculationData(),
                 originalSchedule, createStandingInstructionAtDisbursement, 
paidInAdvance, interestRatesPeriods,
                 product.isVariableInstallmentsAllowed(), 
product.getMinimumGapBetweenInstallments(),
-                product.getMaximumGapBetweenInstallments(), subStatus);
+                product.getMaximumGapBetweenInstallments(), subStatus, 
canUseForTopup, clientActiveLoanOptions, isTopup, closureLoanId,
+                closureLoanAccountNo, topupAmount);
     }
 
     public static LoanAccountData populateLoanProductDefaults(final 
LoanAccountData acc, final LoanProductData product) {
@@ -873,7 +905,8 @@ public class LoanAccountData {
                 product.getDaysInMonthType(), product.getDaysInYearType(), 
product.isInterestRecalculationEnabled(),
                 product.toLoanInterestRecalculationData(), 
acc.originalSchedule, acc.createStandingInstructionAtDisbursement,
                 paidInAdvance, acc.interestRatesPeriods, 
product.isVariableInstallmentsAllowed(),
-                product.getMinimumGapBetweenInstallments(), 
product.getMaximumGapBetweenInstallments(), acc.subStatus);
+                product.getMinimumGapBetweenInstallments(), 
product.getMaximumGapBetweenInstallments(), acc.subStatus, acc.canUseForTopup,
+                acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, 
acc.closureLoanAccountNo, acc.topupAmount);
 
     }
 
@@ -903,7 +936,9 @@ public class LoanAccountData {
             final Integer graceOnArrearsAgeing, final Boolean isNPA, final 
EnumOptionData daysInMonthType,
             final EnumOptionData daysInYearType, final boolean 
isInterestRecalculationEnabled,
             final LoanInterestRecalculationData interestRecalculationData, 
final Boolean createStandingInstructionAtDisbursement,
-            final Boolean isVariableInstallmentsAllowed, Integer minimumGap, 
Integer maximumGap, final EnumOptionData subStatus) {
+            final Boolean isVariableInstallmentsAllowed, Integer minimumGap, 
Integer maximumGap, final EnumOptionData subStatus,
+            final boolean canUseForTopup, final boolean isTopup, final Long 
closureLoanId, final String closureLoanAccountNo,
+            final BigDecimal topupAmount) {
 
         final LoanScheduleData repaymentSchedule = null;
         final Collection<LoanTransactionData> transactions = null;
@@ -939,6 +974,7 @@ public class LoanAccountData {
         final LoanScheduleData originalSchedule = null;
         final PaidInAdvanceData paidInAdvance = null;
         final Collection<InterestRatePeriodData> interestRatesPeriods = null;
+        final Collection<LoanAccountSummaryData> clientActiveLoanOptions = 
null;
 
         return new LoanAccountData(id, accountNo, status, externalId, 
clientId, clientAccountNo, clientName, clientOfficeId, group,
                 loanType, loanProductId, loanProductName, 
loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName,
@@ -958,7 +994,7 @@ public class LoanAccountData {
                 outstandingLoanBalance, emiAmountVariations, memberVariations, 
product, inArrears, graceOnArrearsAgeing, overdueCharges,
                 isNPA, daysInMonthType, daysInYearType, 
isInterestRecalculationEnabled, interestRecalculationData, originalSchedule,
                 createStandingInstructionAtDisbursement, paidInAdvance, 
interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap,
-                maximumGap, subStatus);
+                maximumGap, subStatus, canUseForTopup, 
clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, 
topupAmount);
     }
 
     /*
@@ -981,7 +1017,8 @@ public class LoanAccountData {
             final Collection<NoteData> notes, final 
Collection<PortfolioAccountData> accountLinkingOptions,
             final PortfolioAccountData linkedAccount, final 
Collection<DisbursementData> disbursementDetails,
             final Collection<LoanTermVariationsData> emiAmountVariations, 
final Collection<ChargeData> overdueCharges,
-            final PaidInAdvanceData paidInAdvance, 
Collection<InterestRatePeriodData> interestRatesPeriods) {
+            final PaidInAdvanceData paidInAdvance, 
Collection<InterestRatePeriodData> interestRatesPeriods,
+            final Collection<LoanAccountSummaryData> clientActiveLoanOptions) {
         LoanProductConfigurableAttributes loanProductConfigurableAttributes = 
null;
         if (acc.product != null) {
             loanProductConfigurableAttributes = 
acc.product.getloanProductConfigurableAttributes();
@@ -1009,7 +1046,8 @@ public class LoanAccountData {
                 acc.graceOnArrearsAgeing, overdueCharges, acc.isNPA, 
acc.daysInMonthType, acc.daysInYearType,
                 acc.isInterestRecalculationEnabled, 
acc.interestRecalculationData, acc.originalSchedule,
                 acc.createStandingInstructionAtDisbursement, paidInAdvance, 
interestRatesPeriods, acc.isVariableInstallmentsAllowed,
-                acc.minimumGap, acc.maximumGap, acc.subStatus);
+                acc.minimumGap, acc.maximumGap, acc.subStatus, 
acc.canUseForTopup, clientActiveLoanOptions, acc.isTopup,
+                acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount);
     }
 
     public static LoanAccountData associationsAndTemplate(final 
LoanAccountData acc, final Collection<LoanProductData> productOptions,
@@ -1022,7 +1060,7 @@ public class LoanAccountData {
                 acc.interestTypeOptions, 
acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, 
null,
                 allowedLoanOfficers, acc.loanPurposeOptions, 
acc.loanCollateralOptions, calendarOptions, acc.notes, accountLinkingOptions,
                 acc.linkedAccount, acc.disbursementDetails, 
acc.emiAmountVariations, acc.overdueCharges, acc.paidInAdvance,
-                acc.interestRatesPeriods);
+                acc.interestRatesPeriods, acc.clientActiveLoanOptions);
     }
 
     public static LoanAccountData associateGroup(final LoanAccountData acc, 
final GroupGeneralData group) {
@@ -1050,7 +1088,8 @@ public class LoanAccountData {
                 acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, 
acc.daysInMonthType, acc.daysInYearType,
                 acc.isInterestRecalculationEnabled, 
acc.interestRecalculationData, acc.originalSchedule,
                 acc.createStandingInstructionAtDisbursement, 
acc.paidInAdvance, acc.interestRatesPeriods,
-                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus);
+                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus, acc.canUseForTopup,
+                acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, 
acc.closureLoanAccountNo, acc.topupAmount);
     }
 
     public static LoanAccountData associateMemberVariations(final 
LoanAccountData acc, final Map<Long, Integer> memberLoanCycle) {
@@ -1114,7 +1153,8 @@ public class LoanAccountData {
                 acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, 
acc.daysInMonthType, acc.daysInYearType,
                 acc.isInterestRecalculationEnabled, 
acc.interestRecalculationData, acc.originalSchedule,
                 acc.createStandingInstructionAtDisbursement, 
acc.paidInAdvance, acc.interestRatesPeriods,
-                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus);
+                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus, acc.canUseForTopup,
+                acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, 
acc.closureLoanAccountNo, acc.topupAmount);
 
     }
 
@@ -1147,7 +1187,8 @@ public class LoanAccountData {
                 acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, 
acc.daysInMonthType, acc.daysInYearType,
                 acc.isInterestRecalculationEnabled, interestRecalculationData, 
acc.originalSchedule,
                 acc.createStandingInstructionAtDisbursement, 
acc.paidInAdvance, acc.interestRatesPeriods,
-                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus);
+                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus, acc.canUseForTopup,
+                acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, 
acc.closureLoanAccountNo, acc.topupAmount);
     }
 
     public static LoanAccountData withLoanCalendarData(final LoanAccountData 
acc, final CalendarData calendarData) {
@@ -1174,7 +1215,8 @@ public class LoanAccountData {
                 acc.emiAmountVariations, acc.memberVariations, acc.product, 
acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
                 acc.isNPA, acc.daysInMonthType, acc.daysInYearType, 
acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
                 acc.originalSchedule, 
acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, 
acc.interestRatesPeriods,
-                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus);
+                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus, acc.canUseForTopup,
+                acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, 
acc.closureLoanAccountNo, acc.topupAmount);
     }
 
     public static LoanAccountData withOriginalSchedule(final LoanAccountData 
acc, final LoanScheduleData originalSchedule) {
@@ -1202,40 +1244,24 @@ public class LoanAccountData {
                 acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, 
acc.daysInMonthType, acc.daysInYearType,
                 acc.isInterestRecalculationEnabled, 
acc.interestRecalculationData, originalSchedule,
                 acc.createStandingInstructionAtDisbursement, 
acc.paidInAdvance, acc.interestRatesPeriods,
-                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus);
+                acc.isVariableInstallmentsAllowed, acc.minimumGap, 
acc.maximumGap, acc.subStatus, acc.canUseForTopup,
+                acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, 
acc.closureLoanAccountNo, acc.topupAmount);
     }
 
-    private LoanAccountData(
-            final Long id, //
+    private LoanAccountData(final Long id, //
             final String accountNo, //
             final LoanStatusEnumData status, //
             final String externalId, //
-            final Long clientId,
-            final String clientAccountNo,
-            final String clientName,
-            final Long clientOfficeId, //
-            final GroupGeneralData group,
-            final EnumOptionData loanType,
-            final Long loanProductId,
-            final String loanProductName,
+            final Long clientId, final String clientAccountNo, final String 
clientName, final Long clientOfficeId, //
+            final GroupGeneralData group, final EnumOptionData loanType, final 
Long loanProductId, final String loanProductName,
             final String loanProductDescription, //
-            final boolean isLoanProductLinkedToFloatingRate,
-            final Long fundId,
-            final String fundName,
-            final Long loanPurposeId,
+            final boolean isLoanProductLinkedToFloatingRate, final Long 
fundId, final String fundName, final Long loanPurposeId,
             final String loanPurposeName, //
-            final Long loanOfficerId,
-            final String loanOfficerName, //
-            final CurrencyData currency,
-            BigDecimal proposedPrincipal,
-            final BigDecimal principal,
-            final BigDecimal approvedPrincipal,
+            final Long loanOfficerId, final String loanOfficerName, //
+            final CurrencyData currency, BigDecimal proposedPrincipal, final 
BigDecimal principal, final BigDecimal approvedPrincipal,
             final BigDecimal totalOverpaid, //
-            final BigDecimal inArrearsTolerance,
-            final Integer termFrequency, //
-            final EnumOptionData termPeriodFrequencyType,
-            final Integer numberOfRepayments,
-            final Integer repaymentEvery,
+            final BigDecimal inArrearsTolerance, final Integer termFrequency, 
//
+            final EnumOptionData termPeriodFrequencyType, final Integer 
numberOfRepayments, final Integer repaymentEvery,
             final EnumOptionData repaymentFrequencyType, //
             final EnumOptionData repaymentFrequencyNthDayType, final 
EnumOptionData repaymentFrequencyDayOfWeekType,
             final Long transactionProcessingStrategyId, final String 
transactionProcessingStrategyName,
@@ -1244,12 +1270,10 @@ public class LoanAccountData {
             final BigDecimal interestRateDifferential, final EnumOptionData 
interestCalculationPeriodType,
             final Boolean allowPartialPeriodInterestCalcualtion, final 
LocalDate expectedFirstRepaymentOnDate,
             final Integer graceOnPrincipalPayment, final Integer 
recurringMoratoriumOnPrincipalPeriods, final Integer graceOnInterestPayment, 
final Integer graceOnInterestCharged,
-            final LocalDate interestChargedFromDate, final 
LoanApplicationTimelineData timeline, final LoanSummaryData summary,
-            final BigDecimal feeChargesDueAtDisbursementCharged, final 
LoanScheduleData repaymentSchedule,
-            final Collection<LoanTransactionData> transactions, final 
Collection<LoanChargeData> charges,
-            final Collection<CollateralData> collateral, final 
Collection<GuarantorData> guarantors, final CalendarData meeting,
-            final Collection<LoanProductData> productOptions, final 
Collection<EnumOptionData> termFrequencyTypeOptions,
-            final Collection<EnumOptionData> repaymentFrequencyTypeOptions,
+            final LocalDate interestChargedFromDate, final 
LoanApplicationTimelineData timeline, final LoanSummaryData summary, final 
BigDecimal feeChargesDueAtDisbursementCharged,
+            final LoanScheduleData repaymentSchedule, final 
Collection<LoanTransactionData> transactions, final Collection<LoanChargeData> 
charges,
+            final Collection<CollateralData> collateral, final 
Collection<GuarantorData> guarantors, final CalendarData meeting, final 
Collection<LoanProductData> productOptions,
+            final Collection<EnumOptionData> termFrequencyTypeOptions, final 
Collection<EnumOptionData> repaymentFrequencyTypeOptions,
             final Collection<EnumOptionData> 
repaymentFrequencyNthDayTypeOptions,
             final Collection<EnumOptionData> 
repaymentFrequencyDaysOfWeekTypeOptions,
             final Collection<TransactionProcessingStrategyData> 
transactionProcessingStrategyOptions,
@@ -1269,7 +1293,9 @@ public class LoanAccountData {
             final LoanInterestRecalculationData interestRecalculationData, 
final LoanScheduleData originalSchedule,
             final Boolean createStandingInstructionAtDisbursement, final 
PaidInAdvanceData paidInAdvance,
             final Collection<InterestRatePeriodData> interestRatesPeriods, 
final Boolean isVariableInstallmentsAllowed,
-            final Integer minimumGap, final Integer maximumGap, final 
EnumOptionData subStatus) {
+            final Integer minimumGap, final Integer maximumGap, final 
EnumOptionData subStatus, final Boolean canUseForTopup,
+            final Collection<LoanAccountSummaryData> clientActiveLoanOptions, 
final boolean isTopup,
+            final Long closureLoanId, final String closureLoanAccountNo, final 
BigDecimal topupAmount) {
 
         this.id = id;
         this.accountNo = accountNo;
@@ -1445,6 +1471,13 @@ public class LoanAccountData {
         this.isVariableInstallmentsAllowed = isVariableInstallmentsAllowed;
         this.minimumGap = minimumGap;
         this.maximumGap = maximumGap;
+        this.canUseForTopup = canUseForTopup;
+        this.clientActiveLoanOptions = clientActiveLoanOptions;
+        this.isTopup = isTopup;
+        this.closureLoanId = closureLoanId;
+        this.closureLoanAccountNo = closureLoanAccountNo;
+        this.topupAmount = topupAmount;
+
     }
 
     public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData() {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index adb516e..0ab4b2d 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -21,37 +21,9 @@ package org.apache.fineract.portfolio.loanaccount.domain;
 import java.math.BigDecimal;
 import java.math.MathContext;
 import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Embedded;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
-import javax.persistence.OrderBy;
-import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-import javax.persistence.Transient;
-import javax.persistence.UniqueConstraint;
-import javax.persistence.Version;
+import java.util.*;
+
+import javax.persistence.*;
 
 import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
@@ -101,33 +73,10 @@ import 
org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
 import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
-import 
org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanTransactionTypeException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.InvalidRefundDateException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.LoanApplicationDateException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.LoanDisbursalException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.LoanForeclosureException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerAssignmentDateException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerUnassignmentDateException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException;
-import 
org.apache.fineract.portfolio.loanaccount.exception.UndoLastTrancheDisbursementException;
+import org.apache.fineract.portfolio.loanaccount.exception.*;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
-import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
-import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
-import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
-import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
-import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
-import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
-import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
-import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanRescheduleStrategyMethod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
-import 
org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
+import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.*;
+import org.apache.fineract.portfolio.loanproduct.domain.*;
 import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
 import org.apache.fineract.useradministration.domain.AppUser;
@@ -397,6 +346,14 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "loan_sub_status_id", nullable = true)
     private Integer loanSubStatus;
 
+    @Column(name = "is_topup", nullable = false)
+    private boolean isTopup = false;
+
+//    @OneToOne(cascade = CascadeType.ALL,  orphanRemoval = true, 
fetch=FetchType.EAGER)
+//    @JoinColumn(name = "loan_id", referencedColumnName= "id" , nullable = 
true)
+    @OneToOne(cascade = CascadeType.ALL, mappedBy = "loan", optional = true, 
orphanRemoval = true, fetch=FetchType.EAGER)
+    private LoanTopupDetails loanTopupDetails;
+
     public static Loan newIndividualLoanApplication(final String accountNo, 
final Client client, final Integer loanType,
             final LoanProduct loanProduct, final Fund fund, final Staff 
officer, final CodeValue loanPurpose,
             final LoanTransactionProcessingStrategy 
transactionProcessingStrategy,
@@ -2769,6 +2726,11 @@ public class Loan extends AbstractPersistable<Long> {
                 }
             }
 
+            if(this.isTopup){
+                this.loanTopupDetails.setAccountTransferDetails(null);
+                this.loanTopupDetails.setTopupAmount(null);
+            }
+
             actualChanges.put("actualDisbursementDate", "");
 
             updateLoanSummaryDerivedFields();
@@ -4765,6 +4727,12 @@ public class Loan extends AbstractPersistable<Long> {
                             defaultUserMessage);
                     dataValidationErrors.add(error);
                 }
+                if(isOpen() && this.isTopup()){
+                    final String defaultUserMessage = "Loan Undo disbursal is 
not allowed on Topup Loans";
+                    final ApiParameterError error = 
ApiParameterError.generalError("error.msg.loan.undo.disbursal.not.allowed.on.topup.loan",
+                            defaultUserMessage);
+                    dataValidationErrors.add(error);
+                }
             break;
             case LOAN_REPAYMENT_OR_WAIVER:
                 if (!isOpen()) {
@@ -6353,4 +6321,32 @@ public class Loan extends AbstractPersistable<Long> {
         return retData.size()>0?retData:null;
        }
 
+    public void setIsTopup(final boolean isTopup) {
+        this.isTopup = isTopup;
+    }
+
+    public boolean isTopup() {
+        return this.isTopup;
+    }
+
+    public BigDecimal getFirstDisbursalAmount() {
+        BigDecimal firstDisbursalAmount;
+
+        if(this.isMultiDisburmentLoan()){
+            List<DisbursementData> disbursementData = getDisbursmentData();
+            Collections.sort(disbursementData);
+            firstDisbursalAmount = 
disbursementData.get(disbursementData.size()-1).amount();
+        }else{
+            firstDisbursalAmount = 
this.getLoanRepaymentScheduleDetail().getPrincipal().getAmount();
+        }
+        return firstDisbursalAmount;
+    }
+
+    public void setTopupLoanDetails(LoanTopupDetails topupLoanDetails) {
+        this.loanTopupDetails = topupLoanDetails;
+    }
+
+    public LoanTopupDetails getTopupLoanDetails() {
+        return this.loanTopupDetails;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java
index 407a706..aed808a 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java
@@ -25,6 +25,7 @@ import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuild
 import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
 import org.joda.time.LocalDate;
+import org.springframework.transaction.annotation.Transactional;
 
 public interface LoanAccountDomainService {
 
@@ -35,6 +36,9 @@ public interface LoanAccountDomainService {
     LoanTransaction makeRefund(Long accountId, CommandProcessingResultBuilder 
builderResult, LocalDate transactionDate,
             BigDecimal transactionAmount, PaymentDetail paymentDetail, String 
noteText, String txnExternalId);
 
+    LoanTransaction makeDisburseTransaction(Long loanId, LocalDate 
transactionDate, BigDecimal transactionAmount,
+            PaymentDetail paymentDetail, String noteText, String 
txnExternalId, boolean isLoanToLoanTransfer);
+
     void reverseTransfer(LoanTransaction loanTransaction);
 
     LoanTransaction makeChargePayment(Loan loan, Long chargeId, LocalDate 
transactionDate, BigDecimal transactionAmount,
@@ -55,6 +59,10 @@ public interface LoanAccountDomainService {
      */
     void recalculateAccruals(Loan loan);
 
+    LoanTransaction makeRepayment(Loan loan, CommandProcessingResultBuilder 
builderResult, LocalDate transactionDate,
+            BigDecimal transactionAmount, PaymentDetail paymentDetail, String 
noteText, String txnExternalId, boolean isRecoveryRepayment,
+            boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto, 
Boolean isHolidayValidationDone, boolean isLoanToLoanTransfer);
+
     void saveLoanWithDataIntegrityViolationChecks(Loan loan);
 
     Map<String, Object> foreCloseLoan(final Loan loan, final LocalDate 
foreClourseDate, String noteText);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
index f7b1a6b..58dc662 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
@@ -139,6 +139,16 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
             final LocalDate transactionDate, final BigDecimal 
transactionAmount, final PaymentDetail paymentDetail, final String noteText,
             final String txnExternalId, final boolean isRecoveryRepayment, 
boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto,
             Boolean isHolidayValidationDone) {
+        return makeRepayment(loan, builderResult, transactionDate, 
transactionAmount, paymentDetail, noteText,
+                txnExternalId, isRecoveryRepayment, isAccountTransfer, 
holidayDetailDto, isHolidayValidationDone, false);
+    }
+
+    @Transactional
+    @Override
+    public LoanTransaction makeRepayment(final Loan loan, final 
CommandProcessingResultBuilder builderResult,
+            final LocalDate transactionDate, final BigDecimal 
transactionAmount, final PaymentDetail paymentDetail, final String noteText,
+            final String txnExternalId, final boolean isRecoveryRepayment, 
boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto,
+            Boolean isHolidayValidationDone, final boolean 
isLoanToLoanTransfer) {
         AppUser currentUser = getAppUserIfPresent();
         checkClientOrGroupActive(loan);
         
this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT,
@@ -208,13 +218,13 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
             this.noteRepository.save(note);
         }
 
-        postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds, isAccountTransfer);
+        postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds, isAccountTransfer, isLoanToLoanTransfer);
 
         recalculateAccruals(loan);
 
         
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT,
                 constructEntityMap(BUSINESS_ENTITY.LOAN_TRANSACTION, 
newRepaymentTransaction));
-        
+
         // disable all active standing orders linked to this loan if status 
changes to closed
         disableStandingInstructionsLinkedToClosedLoan(loan);
 
@@ -336,12 +346,18 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
 
     private void postJournalEntries(final Loan loanAccount, final List<Long> 
existingTransactionIds,
             final List<Long> existingReversedTransactionIds, boolean 
isAccountTransfer) {
+        
postJournalEntries(loanAccount,existingTransactionIds,existingReversedTransactionIds,isAccountTransfer,
 false);
+    }
+
+    private void postJournalEntries(final Loan loanAccount, final List<Long> 
existingTransactionIds,
+            final List<Long> existingReversedTransactionIds, boolean 
isAccountTransfer, boolean isLoanToLoanTransfer) {
 
         final MonetaryCurrency currency = loanAccount.getCurrency();
         final ApplicationCurrency applicationCurrency = 
this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
 
         final Map<String, Object> accountingBridgeData = 
loanAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
                 existingTransactionIds, existingReversedTransactionIds, 
isAccountTransfer);
+        accountingBridgeData.put("isLoanToLoanTransfer", isLoanToLoanTransfer);
         
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
     }
 
@@ -409,6 +425,13 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
     @Override
     public LoanTransaction makeDisburseTransaction(final Long loanId, final 
LocalDate transactionDate, final BigDecimal transactionAmount,
             final PaymentDetail paymentDetail, final String noteText, final 
String txnExternalId) {
+        return makeDisburseTransaction(loanId, transactionDate, 
transactionAmount, paymentDetail, noteText, txnExternalId, false);
+    }
+
+    @Transactional
+    @Override
+    public LoanTransaction makeDisburseTransaction(final Long loanId, final 
LocalDate transactionDate, final BigDecimal transactionAmount,
+            final PaymentDetail paymentDetail, final String noteText, final 
String txnExternalId, final boolean isLoanToLoanTransfer) {
         AppUser currentUser = getAppUserIfPresent();
         final Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
         checkClientOrGroupActive(loan);
@@ -428,7 +451,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
             this.noteRepository.save(note);
         }
 
-        postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds, isAccountTransfer);
+        postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds, isAccountTransfer, isLoanToLoanTransfer);
         return disbursementTransaction;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
index b306d70..9292ace 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
@@ -71,6 +71,8 @@ public interface LoanRepository extends JpaRepository<Loan, 
Long>, JpaSpecificat
 
     public static final String FIND_BY_ACCOUNT_NUMBER = "from Loan loan where 
loan.accountNumber = :accountNumber and loan.loanStatus in 
(100,200,300,303,304)";
 
+    public static final String FIND_NON_CLOSED_LOAN_THAT_BELONGS_TO_CLIENT = 
"from Loan loan where loan.id = :loanId and loan.loanStatus = 300 and 
loan.client.id = :clientId";
+
     @Query(FIND_GROUP_LOANS_DISBURSED_AFTER)
     List<Loan> getGroupLoansDisbursedAfter(@Param("disbursementDate") Date 
disbursementDate, @Param("groupId") Long groupId,
             @Param("loanType") Integer loanType);
@@ -149,4 +151,7 @@ public interface LoanRepository extends JpaRepository<Loan, 
Long>, JpaSpecificat
     
     @Query(FIND_BY_ACCOUNT_NUMBER)
     Loan findNonClosedLoanByAccountNumber(@Param("accountNumber") String 
accountNumber);
+
+    @Query(FIND_NON_CLOSED_LOAN_THAT_BELONGS_TO_CLIENT)
+    Loan findNonClosedLoanThatBelongsToClient(@Param("loanId") Long loanId, 
@Param("clientId") Long clientId);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTopupDetails.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTopupDetails.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTopupDetails.java
new file mode 100644
index 0000000..106654e
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTopupDetails.java
@@ -0,0 +1,68 @@
+/**
+ * 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.domain;
+
+import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
+import org.springframework.data.jpa.domain.AbstractPersistable;
+import org.springframework.stereotype.Component;
+
+import javax.persistence.*;
+import java.math.BigDecimal;
+
+@Entity
+@Table(name = "m_loan_topup")
+public class LoanTopupDetails  extends AbstractPersistable<Long> {
+
+        @OneToOne
+        @JoinColumn(name = "loan_id", nullable = false)
+        private Loan loan;
+
+        @Column(name = "closure_loan_id", nullable = false)
+        private Long closureLoanId;
+
+        @Column(name = "account_transfer_details_id", nullable = true)
+        private Long accountTransferDetailsId;
+
+        @Column(name = "topup_amount", nullable = true)
+        private BigDecimal topupAmount;
+
+        protected LoanTopupDetails(){};
+
+        public LoanTopupDetails(final Loan loan, final Long loanIdToClose) {
+                this.loan = loan;
+                this.closureLoanId = loanIdToClose;
+        }
+
+        public Long getLoanIdToClose(){
+                return this.closureLoanId;
+        }
+
+        public BigDecimal getTopupAmount() {
+                return this.topupAmount;
+        }
+
+        public void setTopupAmount(BigDecimal topupAmount) {
+                this.topupAmount = topupAmount;
+        }
+
+        public void setAccountTransferDetails(Long accountTransferDetailsId) {
+                this.accountTransferDetailsId = accountTransferDetailsId;
+        }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/961aa3df/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
index a03fe9b..0485af5 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
@@ -68,7 +68,8 @@ public final class 
CalculateLoanScheduleQueryFromApiJsonHelper {
             LoanApiConstants.emiAmountParameterName, 
LoanApiConstants.maxOutstandingBalanceParameterName,
             LoanProductConstants.graceOnArrearsAgeingParameterName, 
LoanApiConstants.createStandingInstructionAtDisbursementParameterName,
             LoanApiConstants.isFloatingInterestRateParameterName, 
LoanApiConstants.interestRateDifferentialParameterName,
-            LoanApiConstants.repaymentFrequencyNthDayTypeParameterName, 
LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName));
+            LoanApiConstants.repaymentFrequencyNthDayTypeParameterName, 
LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName,
+            LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose));
 
     private final FromJsonHelper fromApiJsonHelper;
 

Reply via email to