This is an automated email from the ASF dual-hosted git repository.

avikg pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new bd99138  FINERACT-893-fixed-deposit-rollover
     new 50d5d08  Merge pull request #769 from fynmanoj/findevfdrollover
bd99138 is described below

commit bd99138aadbb184f0ec563c8111cc79f132ee98d
Author: Manoj <ma...@fynarfin.io>
AuthorDate: Sat May 23 22:52:39 2020 +0530

    FINERACT-893-fixed-deposit-rollover
---
 .../integrationtests/FixedDepositTest.java         | 180 +++++++++++++++++++++
 .../fixeddeposit/FixedDepositAccountHelper.java    |   7 +
 .../infrastructure/core/api/JsonCommand.java       |  23 +++
 .../AccountAssociationsReadPlatformService.java    |   2 +
 ...AccountAssociationsReadPlatformServiceImpl.java |   5 +
 .../savings/DepositAccountOnClosureType.java       |  19 ++-
 .../portfolio/savings/DepositsApiConstants.java    |   5 +-
 .../api/FixedDepositAccountsApiResource.java       |   7 +-
 .../savings/data/DepositAccountDataValidator.java  |  29 ++++
 .../savings/data/FixedDepositAccountData.java      | 101 +++++++-----
 .../savings/domain/DepositAccountAssembler.java    |  12 +-
 .../domain/DepositAccountDomainService.java        |   9 +-
 .../domain/DepositAccountDomainServiceJpa.java     |  88 +++++++++-
 .../domain/DepositAccountTermAndPreClosure.java    |  37 ++++-
 .../savings/domain/FixedDepositAccount.java        |  30 ++++
 .../savings/domain/RecurringDepositAccount.java    |   4 +
 .../portfolio/savings/domain/SavingsAccount.java   |   1 -
 .../DepositAccountReadPlatformServiceImpl.java     |  19 ++-
 ...countWritePlatformServiceJpaRepositoryImpl.java |  39 ++++-
 .../DepositsDropdownReadPlatformService.java       |   2 +
 .../DepositsDropdownReadPlatformServiceImpl.java   |  12 ++
 .../savings/service/SavingsEnumerations.java       |  11 +-
 .../V358__fixed_deposit_rollover_transfer.sql      |  21 +++
 23 files changed, 597 insertions(+), 66 deletions(-)

diff --git 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java
 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java
index 815c485..dc06538 100644
--- 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java
+++ 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java
@@ -2400,6 +2400,175 @@ public class FixedDepositTest {
         Assert.assertEquals("Verifying Pre-Closure maturity amount", 
expectedPrematureAmount, maturityAmount);
     }
 
+    /***
+     * Test case for Fixed Deposit Account rollover with maturity
+     * instruction as re invest maturity amount(principal+interest)
+     */
+    @Test
+    public void testFixedDepositAccountWithRolloverMaturityAmount() {
+        this.fixedDepositProductHelper = new 
FixedDepositProductHelper(this.requestSpec, this.responseSpec);
+        this.accountHelper = new AccountHelper(this.requestSpec, 
this.responseSpec);
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
+        this.fixedDepositAccountHelper = new 
FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
+
+        /***
+         * Create GL Accounts for product account mapping
+         */
+        final Account assetAccount = this.accountHelper.createAssetAccount();
+        final Account incomeAccount = this.accountHelper.createIncomeAccount();
+        final Account expenseAccount = 
this.accountHelper.createExpenseAccount();
+        final Account liabilityAccount = 
this.accountHelper.createLiabilityAccount();
+
+        DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", 
Locale.US);
+        DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US);
+        DateFormat currentDateFormat = new SimpleDateFormat("dd");
+
+        Calendar todaysDate = Calendar.getInstance();
+        todaysDate.add(Calendar.MONTH, -3);
+        final String VALID_FROM = dateFormat.format(todaysDate.getTime());
+        todaysDate.add(Calendar.YEAR, 10);
+        final String VALID_TO = dateFormat.format(todaysDate.getTime());
+
+        todaysDate = Calendar.getInstance();
+        todaysDate.add(Calendar.MONTH, -1);
+        final String SUBMITTED_ON_DATE = 
dateFormat.format(todaysDate.getTime());
+        final String APPROVED_ON_DATE = 
dateFormat.format(todaysDate.getTime());
+        final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime());
+        final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime());
+
+        Integer currentDate = 
Integer.valueOf(currentDateFormat.format(todaysDate.getTime()));
+        Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE);
+        Integer numberOfDaysLeft = (daysInMonth - currentDate) + 1;
+        todaysDate.add(Calendar.DATE, numberOfDaysLeft);
+        final String INTEREST_POSTED_DATE = 
dateFormat.format(todaysDate.getTime());
+        final String CLOSED_ON_DATE = 
dateFormat.format(Calendar.getInstance().getTime());
+
+        Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec);
+        Assert.assertNotNull(clientId);
+
+        /***
+         * Create FD product with CashBased accounting enabled
+         */
+        final String accountingRule = CASH_BASED;
+        Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, 
VALID_TO, accountingRule, assetAccount, liabilityAccount,
+                incomeAccount, expenseAccount);
+        Assert.assertNotNull(fixedDepositProductId);
+
+        /***
+         * Set  maturityInstructionId as  re-invest principal+interest
+         * */
+        final Integer maturityInstructionId = 300;
+
+        /***
+         * Apply for FD account with created product and verify status
+         */
+        Integer fixedDepositAccountId = 
applyForFixedDepositApplication(clientId.toString(), 
fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM, maturityInstructionId);
+
+        Assert.assertNotNull(fixedDepositAccountId);
+
+        HashMap fixedDepositAccountStatusHashMap = 
FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
+                this.responseSpec, fixedDepositAccountId.toString());
+        
FixedDepositAccountStatusChecker.verifyFixedDepositIsPending(fixedDepositAccountStatusHashMap);
+
+        /***
+         * Approve the FD account and verify whether account is approved
+         */
+        fixedDepositAccountStatusHashMap = 
this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, 
APPROVED_ON_DATE);
+        
FixedDepositAccountStatusChecker.verifyFixedDepositIsApproved(fixedDepositAccountStatusHashMap);
+
+        /***
+         * Activate the FD Account and verify whether account is activated
+         */
+        fixedDepositAccountStatusHashMap = 
this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, 
ACTIVATION_DATE);
+        
FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap);
+    }
+
+
+    /***
+     * Test case for Fixed Deposit Account rollover with maturity
+     * instruction as re invest principal only
+     */
+    @Test
+    public void testFixedDepositAccountWithRolloverPrincipal() {
+        this.fixedDepositProductHelper = new 
FixedDepositProductHelper(this.requestSpec, this.responseSpec);
+        this.accountHelper = new AccountHelper(this.requestSpec, 
this.responseSpec);
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
+        this.fixedDepositAccountHelper = new 
FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
+
+        /***
+         * Create GL Accounts for product account mapping
+         */
+        final Account assetAccount = this.accountHelper.createAssetAccount();
+        final Account incomeAccount = this.accountHelper.createIncomeAccount();
+        final Account expenseAccount = 
this.accountHelper.createExpenseAccount();
+        final Account liabilityAccount = 
this.accountHelper.createLiabilityAccount();
+
+        DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", 
Locale.US);
+        DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US);
+        DateFormat currentDateFormat = new SimpleDateFormat("dd");
+
+        Calendar todaysDate = Calendar.getInstance();
+        todaysDate.add(Calendar.MONTH, -3);
+        final String VALID_FROM = dateFormat.format(todaysDate.getTime());
+        todaysDate.add(Calendar.YEAR, 10);
+        final String VALID_TO = dateFormat.format(todaysDate.getTime());
+
+        todaysDate = Calendar.getInstance();
+        todaysDate.add(Calendar.MONTH, -1);
+        final String SUBMITTED_ON_DATE = 
dateFormat.format(todaysDate.getTime());
+        final String APPROVED_ON_DATE = 
dateFormat.format(todaysDate.getTime());
+        final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime());
+        final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime());
+
+        Integer currentDate = 
Integer.valueOf(currentDateFormat.format(todaysDate.getTime()));
+        Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE);
+        Integer numberOfDaysLeft = (daysInMonth - currentDate) + 1;
+        todaysDate.add(Calendar.DATE, numberOfDaysLeft);
+        final String INTEREST_POSTED_DATE = 
dateFormat.format(todaysDate.getTime());
+        final String CLOSED_ON_DATE = 
dateFormat.format(Calendar.getInstance().getTime());
+
+        Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec);
+        Assert.assertNotNull(clientId);
+
+        /***
+         * Create FD product with CashBased accounting enabled
+         */
+        final String accountingRule = CASH_BASED;
+        Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, 
VALID_TO, accountingRule, assetAccount, liabilityAccount,
+                incomeAccount, expenseAccount);
+        Assert.assertNotNull(fixedDepositProductId);
+
+        /***
+         * Set  maturityInstructionId as  re-invest principal
+         * */
+        final Integer maturityInstructionId = 400;
+
+        /***
+         * Apply for FD account with created product and verify status
+         */
+        Integer fixedDepositAccountId = 
applyForFixedDepositApplication(clientId.toString(), 
fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM, maturityInstructionId);
+
+        Assert.assertNotNull(fixedDepositAccountId);
+
+        HashMap fixedDepositAccountStatusHashMap = 
FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
+                this.responseSpec, fixedDepositAccountId.toString());
+        
FixedDepositAccountStatusChecker.verifyFixedDepositIsPending(fixedDepositAccountStatusHashMap);
+
+        /***
+         * Approve the FD account and verify whether account is approved
+         */
+        fixedDepositAccountStatusHashMap = 
this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, 
APPROVED_ON_DATE);
+        
FixedDepositAccountStatusChecker.verifyFixedDepositIsApproved(fixedDepositAccountStatusHashMap);
+
+        /***
+         * Activate the FD Account and verify whether account is activated
+         */
+        fixedDepositAccountStatusHashMap = 
this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, 
ACTIVATION_DATE);
+        
FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap);
+    }
+
     private Integer createFixedDepositProduct(final String validFrom, final 
String validTo, final String accountingRule,
             Account... accounts) {
         LOG.info("------------------------------CREATING NEW FIXED DEPOSIT 
PRODUCT ---------------------------------------");
@@ -2471,6 +2640,17 @@ public class FixedDepositTest {
     }
 
     private Integer applyForFixedDepositApplication(final String clientID, 
final String productID, final String submittedOnDate,
+                                                    final String 
penalInterestType, final Integer maturityInstructionId) {
+        LOG.info("--------------------------------APPLYING FOR FIXED DEPOSIT 
ACCOUNT --------------------------------");
+        final String fixedDepositApplicationJSON = new 
FixedDepositAccountHelper(this.requestSpec, this.responseSpec) //
+                .withSubmittedOnDate(submittedOnDate)
+                .withMaturityInstructionId(maturityInstructionId)
+                .build(clientID, productID, penalInterestType);
+        return this.fixedDepositAccountHelper
+                .applyFixedDepositApplication(fixedDepositApplicationJSON, 
this.requestSpec, this.responseSpec);
+    }
+
+    private Integer applyForFixedDepositApplication(final String clientID, 
final String productID, final String submittedOnDate,
             final String penalInterestType, final String depositAmount, final 
String depositPeriod) {
         LOG.info("--------------------------------APPLYING FOR FIXED DEPOSIT 
ACCOUNT --------------------------------");
         final String fixedDepositApplicationJSON = new 
FixedDepositAccountHelper(this.requestSpec, this.responseSpec)
diff --git 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountHelper.java
 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountHelper.java
index ded5afb..fa4c50b 100644
--- 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountHelper.java
+++ 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountHelper.java
@@ -96,6 +96,7 @@ public class FixedDepositAccountHelper {
     private String submittedOnDate = "";
     private String savingsId = null;
     private boolean transferInterest = false;
+    private Integer maturityInstructionId;
 
     public String build(final String clientId, final String productId, final 
String penalInterestType) {
         final HashMap<String, Object> map = new HashMap<>();
@@ -127,6 +128,7 @@ public class FixedDepositAccountHelper {
         map.put("submittedOnDate", this.submittedOnDate);
         map.put("linkAccountId", savingsId);
         map.put("transferInterestToSavings", transferInterest);
+        map.put("maturityInstructionId", maturityInstructionId);
 
         String fixedDepositAccountJson = new Gson().toJson(map);
         LOG.info("{}", fixedDepositAccountJson);
@@ -489,4 +491,9 @@ public class FixedDepositAccountHelper {
         }
         return this.newDepositAmount;
     }
+
+    public FixedDepositAccountHelper withMaturityInstructionId(Integer 
maturityInstructionId){
+        this.maturityInstructionId = maturityInstructionId;
+        return this;
+    }
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
index 7ca8d3a..5008fde 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
@@ -131,6 +131,10 @@ public final class JsonCommand {
         return new JsonCommand(resourceId, parsedCommand);
     }
 
+    public static JsonCommand fromJsonElement(final Long resourceId, final 
JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper) {
+        return new JsonCommand(resourceId, parsedCommand, fromApiJsonHelper);
+    }
+
     public JsonCommand(final Long resourceId, final JsonElement parsedCommand) 
{
         this.parsedCommand = parsedCommand;
         this.resourceId = resourceId;
@@ -150,6 +154,25 @@ public final class JsonCommand {
         this.organisationCreditBureauId=null;
     }
 
+    public JsonCommand(final Long resourceId, final JsonElement parsedCommand, 
final FromJsonHelper fromApiJsonHelper) {
+        this.parsedCommand = parsedCommand;
+        this.resourceId = resourceId;
+        this.commandId = null;
+        this.jsonCommand = null;
+        this.fromApiJsonHelper = fromApiJsonHelper;
+        this.entityName = null;
+        this.subresourceId = null;
+        this.groupId = null;
+        this.clientId = null;
+        this.loanId = null;
+        this.savingsId = null;
+        this.transactionId = null;
+        this.url = null;
+        this.productId = null;
+        this.creditBureauId=null;
+        this.organisationCreditBureauId=null;
+    }
+
     public Long getOrganisationCreditBureauId() {
         return this.organisationCreditBureauId;
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformService.java
index aad6f34..2ae6eda 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformService.java
@@ -31,4 +31,6 @@ public interface AccountAssociationsReadPlatformService {
     public PortfolioAccountData retriveSavingsLinkedAssociation(final Long 
savingsId);
 
     public Collection<AccountAssociationsData> retriveLoanAssociations(Long 
loanId, Integer associationType);
+
+    PortfolioAccountData retriveSavingsAccount(Long savingsId);
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImpl.java
index 8c0bfa4..9f6a9bb 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImpl.java
@@ -191,4 +191,9 @@ public class AccountAssociationsReadPlatformServiceImpl 
implements AccountAssoci
         }
 
     }
+    @Override
+    public PortfolioAccountData retriveSavingsAccount(final Long savingsId){
+        String accountNo = jdbcTemplate.queryForObject("select account_no from 
m_savings_account where id = ?", String.class, savingsId);
+        return PortfolioAccountData.lookup(savingsId, accountNo);
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositAccountOnClosureType.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositAccountOnClosureType.java
index 29ccd73..fc7a2dc 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositAccountOnClosureType.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositAccountOnClosureType.java
@@ -32,7 +32,8 @@ public enum DepositAccountOnClosureType {
     INVALID(0, "depositAccountClosureType.invalid"), //
     WITHDRAW_DEPOSIT(100, "depositAccountClosureType.withdrawDeposit"), //
     TRANSFER_TO_SAVINGS(200, "depositAccountClosureType.transferToSavings"), //
-    REINVEST(300, "depositAccountClosureType.reinvest"); //
+    REINVEST_PRINCIPAL_AND_INTEREST(300, 
"depositAccountClosureType.reinvestPrincipalAndInterest"),
+    REINVEST_PRINCIPAL_ONLY(400, 
"depositAccountClosureType.reinvestPrincipalOnly"); //
 
     private final Integer value;
     private final String code;
@@ -63,7 +64,10 @@ public enum DepositAccountOnClosureType {
                 accountOnClosureType = 
DepositAccountOnClosureType.TRANSFER_TO_SAVINGS;
             break;
             case 300:
-                accountOnClosureType = DepositAccountOnClosureType.REINVEST;
+                accountOnClosureType = 
DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST;
+            break;
+            case 400:
+                accountOnClosureType = 
DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY;
             break;
         }
         return accountOnClosureType;
@@ -78,7 +82,16 @@ public enum DepositAccountOnClosureType {
     }
 
     public boolean isReinvest() {
-        return 
this.value.equals(DepositAccountOnClosureType.REINVEST.getValue());
+        return 
this.value.equals(DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST.getValue())
 ||
+                       
this.value.equals(DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY.getValue());
+    }
+
+    public boolean isReinvestPrincipal() {
+        return 
this.value.equals(DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY.getValue());
+    }
+
+    public boolean isReinvestPrincipalAndInterest() {
+        return 
this.value.equals(DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST.getValue());
     }
 
     public boolean isInvalid() {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
index b667fcc..44266f1 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/DepositsApiConstants.java
@@ -190,6 +190,8 @@ public class DepositsApiConstants {
     public static final String transferDescriptionParamName = 
"transferDescription";
     public static final String toSavingsAccountIdParamName = 
"toSavingsAccountId";
     public static final String savingsAccounts = "savingsAccounts";
+    public static final String maturityInstructionIdParamName = 
"maturityInstructionId";
+    public static final String transferToSavingsIdParamName = 
"transferToSavingsId";
 
     public static final String preMatureCloseOnDateParamName = 
"preMatureCloseOnDate";
 
@@ -298,7 +300,8 @@ public class DepositsApiConstants {
                     interestCalculationTypeParamName, 
interestCalculationDaysInYearTypeParamName,
                     lockinPeriodFrequencyParamName, 
lockinPeriodFrequencyTypeParamName, chargesParamName,
                     chartsParamName, depositAmountParamName, 
depositPeriodParamName, depositPeriodFrequencyIdParamName,
-                    savingsAccounts, expectedFirstDepositOnDateParamName, 
SavingsApiConstants.withHoldTaxParamName));
+                    savingsAccounts, expectedFirstDepositOnDateParamName, 
SavingsApiConstants.withHoldTaxParamName,
+                    maturityInstructionIdParamName, 
transferToSavingsIdParamName));
 
     public static final Set<String> 
FIXED_DEPOSIT_ACCOUNT_REQUEST_DATA_PARAMETERS = 
fixedDepositAccountRequestData();
     public static final Set<String> 
FIXED_DEPOSIT_ACCOUNT_RESPONSE_DATA_PARAMETERS = 
fixedDepositAccountResponseData();
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/FixedDepositAccountsApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/FixedDepositAccountsApiResource.java
index c8ffc35..fa67b79 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/FixedDepositAccountsApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/FixedDepositAccountsApiResource.java
@@ -239,6 +239,7 @@ public class FixedDepositAccountsApiResource {
         Collection<SavingsAccountTransactionData> transactions = null;
         Collection<SavingsAccountChargeData> charges = null;
         PortfolioAccountData linkedAccount = null;
+        PortfolioAccountData transferToSavingsAccount = null;
 
         final Set<String> associationParameters = 
ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
         if (!associationParameters.isEmpty()) {
@@ -272,6 +273,10 @@ public class FixedDepositAccountsApiResource {
             }
         }
 
+        if(savingsAccount.getTransferToSavingsId() !=null){
+            transferToSavingsAccount = 
this.accountAssociationsReadPlatformService.retriveSavingsAccount(savingsAccount.getTransferToSavingsId());
+        }
+
         FixedDepositAccountData templateData = null;
         final ApiRequestJsonSerializationSettings settings = 
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
 
@@ -281,7 +286,7 @@ public class FixedDepositAccountsApiResource {
                     staffInSelectedOfficeOnly);
         }
 
-        return FixedDepositAccountData.associationsAndTemplate(savingsAccount, 
templateData, transactions, charges, linkedAccount);
+        return FixedDepositAccountData.associationsAndTemplate(savingsAccount, 
templateData, transactions, charges, linkedAccount, transferToSavingsAccount);
     }
 
     @PUT
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountDataValidator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountDataValidator.java
index b95c6c7..cc0a1bf 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountDataValidator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountDataValidator.java
@@ -29,6 +29,7 @@ import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.isCalen
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.isMandatoryDepositParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.linkedAccountParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.mandatoryRecommendedDepositAmountParamName;
+import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.maturityInstructionIdParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.maxDepositTermParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.maxDepositTermTypeIdParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.minDepositTermParamName;
@@ -39,6 +40,7 @@ import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.preClos
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.recurringFrequencyParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.recurringFrequencyTypeParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.transferInterestToSavingsParamName;
+import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.transferToSavingsIdParamName;
 import static 
org.apache.fineract.portfolio.savings.SavingsApiConstants.accountNoParamName;
 import static 
org.apache.fineract.portfolio.savings.SavingsApiConstants.amountParamName;
 import static 
org.apache.fineract.portfolio.savings.SavingsApiConstants.chargeIdParamName;
@@ -77,6 +79,7 @@ import 
org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
 import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
 import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.portfolio.savings.DepositAccountOnClosureType;
 import org.apache.fineract.portfolio.savings.DepositAccountType;
 import org.apache.fineract.portfolio.savings.DepositsApiConstants;
 import org.apache.fineract.portfolio.savings.PreClosurePenalInterestOnType;
@@ -308,6 +311,19 @@ public class DepositAccountDataValidator {
         } else {
             
baseDataValidator.reset().parameter(linkedAccountParamName).value(linkAccountId).ignoreIfNull().longGreaterThanZero();
         }
+
+        if 
(this.fromApiJsonHelper.parameterExists(maturityInstructionIdParamName, 
element)) {
+            final Integer depositRolloverId = 
this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
+                    maturityInstructionIdParamName, element);
+            
baseDataValidator.reset().parameter(maturityInstructionIdParamName).value(depositRolloverId).notNull()
+                    
.isOneOfTheseValues(DepositAccountOnClosureType.integerValues());
+
+            
if(depositRolloverId.equals(DepositAccountOnClosureType.TRANSFER_TO_SAVINGS.getValue())){
+                final Long transferToSavingsId = 
this.fromApiJsonHelper.extractLongNamed(
+                        transferToSavingsIdParamName, element);
+                
baseDataValidator.reset().parameter(transferToSavingsIdParamName).value(transferToSavingsId).notNull().longGreaterThanZero();
+            }
+        }
     }
 
     private void validateDepositDetailsForUpdate(final JsonElement element, 
final DataValidatorBuilder baseDataValidator) {
@@ -439,6 +455,19 @@ public class DepositAccountDataValidator {
             }
         }
 
+        if 
(this.fromApiJsonHelper.parameterExists(maturityInstructionIdParamName, 
element)) {
+            final Integer depositRolloverId = 
this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
+                    maturityInstructionIdParamName, element);
+            
baseDataValidator.reset().parameter(maturityInstructionIdParamName).value(depositRolloverId).notNull()
+                    
.isOneOfTheseValues(DepositAccountOnClosureType.integerValues());
+
+            
if(depositRolloverId.equals(DepositAccountOnClosureType.TRANSFER_TO_SAVINGS.getValue())){
+                final Long transferToSavingsId = 
this.fromApiJsonHelper.extractLongNamed(
+                        transferToSavingsIdParamName, element);
+                
baseDataValidator.reset().parameter(transferToSavingsIdParamName).value(transferToSavingsId).notNull().longGreaterThanZero();
+            }
+        }
+
     }
 
     private void validatePreClosureDetailForSubmit(final JsonElement element, 
final DataValidatorBuilder baseDataValidator) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/FixedDepositAccountData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/FixedDepositAccountData.java
index eb7a74d..63fccc1 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/FixedDepositAccountData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/FixedDepositAccountData.java
@@ -53,12 +53,14 @@ public class FixedDepositAccountData extends 
DepositAccountData {
     private Integer depositPeriod;
     private EnumOptionData depositPeriodFrequency;
     private BigDecimal activationCharge;
+    private Long transferToSavingsId;
 
     // used for account close
     private EnumOptionData onAccountClosure;
 
     private final PortfolioAccountData linkedAccount;
     private final Boolean transferInterestToSavings;
+    private final PortfolioAccountData transferToSavingsAccount;
 
     private Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions;
     private Collection<EnumOptionData> periodFrequencyTypeOptions;
@@ -67,6 +69,7 @@ public class FixedDepositAccountData extends 
DepositAccountData {
     // for account close
     private Collection<EnumOptionData> onAccountClosureOptions;
     private Collection<PaymentTypeData> paymentTypeOptions;
+    private final Collection<EnumOptionData> maturityInstructionOptions;
 
     //import fields
     private transient Integer rowIndex;
@@ -114,6 +117,7 @@ public class FixedDepositAccountData extends 
DepositAccountData {
         this.activationCharge = null;
         this.onAccountClosure = null;
         this.linkedAccount = null;
+        this.transferToSavingsAccount = null;
         this.transferInterestToSavings = null;
         this.preClosurePenalInterestOnTypeOptions = null;
         this.periodFrequencyTypeOptions = null;
@@ -125,6 +129,7 @@ public class FixedDepositAccountData extends 
DepositAccountData {
         this.locale= locale;
         this.submittedOnDate = submittedOnDate;
         this.depositPeriodFrequencyId = depositPeriodFrequencyId;
+        this.maturityInstructionOptions = null;
     }
 
     public Integer getRowIndex() {
@@ -136,11 +141,14 @@ public class FixedDepositAccountData extends 
DepositAccountData {
             final Integer maxDepositTerm, final EnumOptionData 
minDepositTermType, final EnumOptionData maxDepositTermType,
             final Integer inMultiplesOfDepositTerm, final EnumOptionData 
inMultiplesOfDepositTermType, final BigDecimal depositAmount,
             final BigDecimal maturityAmount, final LocalDate maturityDate, 
final Integer depositPeriod,
-            final EnumOptionData depositPeriodFrequency, final EnumOptionData 
onAccountClosure, final Boolean transferInterestToSavings) {
+            final EnumOptionData depositPeriodFrequency, final EnumOptionData 
onAccountClosure, final Boolean transferInterestToSavings,
+            final Long transferToSavingsId) {
 
         final PortfolioAccountData linkedAccount = null;
+        final PortfolioAccountData transferToSavingsAccount = null;
         final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions 
= null;
         final Collection<EnumOptionData> periodFrequencyTypeOptions = null;
+        final Collection<EnumOptionData> maturityInstructionOptions = null;
 
         final EnumOptionData depositType = 
SavingsEnumerations.depositType(DepositAccountType.FIXED_DEPOSIT.getValue());
         final Collection<EnumOptionData> onAccountClosureOptions = null;
@@ -166,7 +174,7 @@ public class FixedDepositAccountData extends 
DepositAccountData {
                 maxDepositTermType, inMultiplesOfDepositTerm, 
inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate,
                 depositPeriod, depositPeriodFrequency, 
periodFrequencyTypeOptions, depositType, onAccountClosure, 
onAccountClosureOptions,
                 paymentTypeOptions, savingsAccountDatas, linkedAccount, 
transferInterestToSavings, depositAccountData.withHoldTax,
-                depositAccountData.taxGroup);
+                depositAccountData.taxGroup, maturityInstructionOptions, 
transferToSavingsId, transferToSavingsAccount);
     }
 
     public static FixedDepositAccountData withInterestChart(final 
FixedDepositAccountData account,
@@ -187,12 +195,13 @@ public class FixedDepositAccountData extends 
DepositAccountData {
                 account.inMultiplesOfDepositTermType, account.depositAmount, 
account.maturityAmount, account.maturityDate,
                 account.depositPeriod, account.depositPeriodFrequency, 
account.periodFrequencyTypeOptions, account.depositType,
                 account.onAccountClosure, account.onAccountClosureOptions, 
account.paymentTypeOptions, account.savingsAccounts,
-                account.linkedAccount, account.transferInterestToSavings, 
account.withHoldTax, account.taxGroup);
+                account.linkedAccount, account.transferInterestToSavings, 
account.withHoldTax, account.taxGroup, account.maturityInstructionOptions,
+                account.transferToSavingsId, account.transferToSavingsAccount);
     }
 
     public static FixedDepositAccountData associationsAndTemplate(final 
FixedDepositAccountData account, FixedDepositAccountData template,
             final Collection<SavingsAccountTransactionData> transactions, 
final Collection<SavingsAccountChargeData> charges,
-            final PortfolioAccountData linkedAccount) {
+            final PortfolioAccountData linkedAccount, PortfolioAccountData 
transferToSavingsAccount ) {
 
         if (template == null) {
             template = account;
@@ -214,7 +223,8 @@ public class FixedDepositAccountData extends 
DepositAccountData {
                 account.inMultiplesOfDepositTermType, account.depositAmount, 
account.maturityAmount, account.maturityDate,
                 account.depositPeriod, account.depositPeriodFrequency, 
template.periodFrequencyTypeOptions, account.depositType,
                 account.onAccountClosure, account.onAccountClosureOptions, 
account.paymentTypeOptions, template.savingsAccounts,
-                linkedAccount, account.transferInterestToSavings, 
account.withHoldTax, account.taxGroup);
+                linkedAccount, account.transferInterestToSavings, 
account.withHoldTax, account.taxGroup, account.maturityInstructionOptions,
+                account.transferToSavingsId, transferToSavingsAccount);
     }
 
     public static FixedDepositAccountData withTemplateOptions(final 
FixedDepositAccountData account,
@@ -226,7 +236,8 @@ public class FixedDepositAccountData extends 
DepositAccountData {
             final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, 
final Collection<EnumOptionData> withdrawalFeeTypeOptions,
             final Collection<SavingsAccountTransactionData> transactions, 
final Collection<SavingsAccountChargeData> charges,
             final Collection<ChargeData> chargeOptions, final 
Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions,
-            final Collection<EnumOptionData> periodFrequencyTypeOptions, final 
Collection<SavingsAccountData> savingsAccounts) {
+            final Collection<EnumOptionData> periodFrequencyTypeOptions, final 
Collection<SavingsAccountData> savingsAccounts,
+            final Collection<EnumOptionData> maturityInstructionOptions) {
 
         return new FixedDepositAccountData(account.id, account.accountNo, 
account.externalId, account.groupId, account.groupName,
                 account.clientId, account.clientName, 
account.depositProductId, account.depositProductName, account.fieldOfficerId,
@@ -243,7 +254,8 @@ public class FixedDepositAccountData extends 
DepositAccountData {
                 account.inMultiplesOfDepositTermType, account.depositAmount, 
account.maturityAmount, account.maturityDate,
                 account.depositPeriod, account.depositPeriodFrequency, 
periodFrequencyTypeOptions, account.depositType,
                 account.onAccountClosure, account.onAccountClosureOptions, 
account.paymentTypeOptions, savingsAccounts,
-                account.linkedAccount, account.transferInterestToSavings, 
account.withHoldTax, account.taxGroup);
+                account.linkedAccount, account.transferInterestToSavings, 
account.withHoldTax, account.taxGroup, maturityInstructionOptions,
+                account.transferToSavingsId, account.transferToSavingsAccount);
     }
 
     public static FixedDepositAccountData withClientTemplate(final Long 
clientId, final String clientName, final Long groupId,
@@ -304,6 +316,7 @@ public class FixedDepositAccountData extends 
DepositAccountData {
         final EnumOptionData depositPeriodFrequency = null;
         final EnumOptionData onAccountClosure = null;
         final PortfolioAccountData linkedAccount = null;
+        final PortfolioAccountData transferToSavingsAccount = null;
         final Boolean transferInterestToSavings = null;
         final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions 
= null;
         final Collection<EnumOptionData> periodFrequencyTypeOptions = null;
@@ -312,6 +325,8 @@ public class FixedDepositAccountData extends 
DepositAccountData {
         final Collection<EnumOptionData> onAccountClosureOptions = null;
         final Collection<PaymentTypeData> paymentTypeOptions = null;
         final Collection<SavingsAccountData> savingsAccountDatas = null;
+        final Collection<EnumOptionData> maturityInstructionOptions = null;
+        final Long transferToSavingsId = null;
 
         return new FixedDepositAccountData(id, accountNo, externalId, groupId, 
groupName, clientId, clientName, productId, productName,
                 fieldOfficerId, fieldOfficerName, status, timeline, currency, 
nominalAnnualInterestRate, interestPeriodType,
@@ -324,7 +339,7 @@ public class FixedDepositAccountData extends 
DepositAccountData {
                 maxDepositTerm, minDepositTermType, maxDepositTermType, 
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType,
                 depositAmount, maturityAmount, maturityDate, depositPeriod, 
depositPeriodFrequency, periodFrequencyTypeOptions,
                 depositType, onAccountClosure, onAccountClosureOptions, 
paymentTypeOptions, savingsAccountDatas, linkedAccount,
-                transferInterestToSavings, withHoldTax, taxGroup);
+                transferInterestToSavings, withHoldTax, taxGroup, 
maturityInstructionOptions, transferToSavingsId, transferToSavingsAccount);
     }
 
     public static FixedDepositAccountData preClosureDetails(final Long 
accountId, BigDecimal maturityAmount,
@@ -393,6 +408,9 @@ public class FixedDepositAccountData extends 
DepositAccountData {
         final PortfolioAccountData linkedAccount = null;
         final boolean withHoldTax = false;
         final TaxGroupData taxGroup = null;
+        final Collection<EnumOptionData> maturityInstructionOptions = null;
+        final Long transferToSavingsId = null;
+        final PortfolioAccountData transferToSavingsAccount = null;
 
         return new FixedDepositAccountData(accountId, accountNo, externalId, 
groupId, groupName, clientId, clientName, productId,
                 productName, fieldOfficerId, fieldOfficerName, status, 
timeline, currency, nominalAnnualInterestRate, interestPeriodType,
@@ -405,7 +423,7 @@ public class FixedDepositAccountData extends 
DepositAccountData {
                 maxDepositTerm, minDepositTermType, maxDepositTermType, 
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType,
                 depositAmount, maturityAmount, maturityDate, depositPeriod, 
depositPeriodFrequency, periodFrequencyTypeOptions,
                 depositType, onAccountClosure, onAccountClosureOptions, 
paymentTypeOptions, savingsAccountDatas, linkedAccount,
-                transferInterestToSavings, withHoldTax, taxGroup);
+                transferInterestToSavings, withHoldTax, taxGroup, 
maturityInstructionOptions, transferToSavingsId, transferToSavingsAccount);
     }
 
     public static FixedDepositAccountData withClosureTemplateDetails(final 
FixedDepositAccountData account,
@@ -428,38 +446,40 @@ public class FixedDepositAccountData extends 
DepositAccountData {
                 account.inMultiplesOfDepositTermType, account.depositAmount, 
account.maturityAmount, account.maturityDate,
                 account.depositPeriod, account.depositPeriodFrequency, 
account.periodFrequencyTypeOptions, account.depositType,
                 account.onAccountClosure, onAccountClosureOptions, 
paymentTypeOptions, savingsAccountDatas, account.linkedAccount,
-                account.transferInterestToSavings, account.withHoldTax, 
account.taxGroup);
+                account.transferInterestToSavings, account.withHoldTax, 
account.taxGroup, account.maturityInstructionOptions,
+                account.transferToSavingsId, account.transferToSavingsAccount);
 
     }
 
     private FixedDepositAccountData(final Long id, final String accountNo, 
final String externalId, final Long groupId,
-            final String groupName, final Long clientId, final String 
clientName, final Long productId, final String productName,
-            final Long fieldofficerId, final String fieldofficerName, final 
SavingsAccountStatusEnumData status,
-            final SavingsAccountApplicationTimelineData timeline, final 
CurrencyData currency, final BigDecimal nominalAnnualInterestRate,
-            final EnumOptionData interestPeriodType, final EnumOptionData 
interestPostingPeriodType,
-            final EnumOptionData interestCalculationType, final EnumOptionData 
interestCalculationDaysInYearType,
-            final BigDecimal minRequiredOpeningBalance, final Integer 
lockinPeriodFrequency,
-            final EnumOptionData lockinPeriodFrequencyType, final boolean 
withdrawalFeeForTransfers,
-            final BigDecimal minBalanceForInterestCalculation, final 
SavingsAccountSummaryData summary,
-            final Collection<SavingsAccountTransactionData> transactions, 
final Collection<DepositProductData> productOptions,
-            final Collection<StaffData> fieldOfficerOptions, final 
Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
-            final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
-            final Collection<EnumOptionData> interestCalculationTypeOptions,
-            final Collection<EnumOptionData> 
interestCalculationDaysInYearTypeOptions,
-            final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, 
final Collection<EnumOptionData> withdrawalFeeTypeOptions,
-            final Collection<SavingsAccountChargeData> charges, final 
Collection<ChargeData> chargeOptions,
-            final DepositAccountInterestRateChartData accountChart, final 
DepositAccountInterestRateChartData chartTemplate,
-            final boolean preClosurePenalApplicable, final BigDecimal 
preClosurePenalInterest,
-            final EnumOptionData preClosurePenalInterestOnType, final 
Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions,
-            final Integer minDepositTerm, final Integer maxDepositTerm, final 
EnumOptionData minDepositTermType,
-            final EnumOptionData maxDepositTermType, final Integer 
inMultiplesOfDepositTerm,
-            final EnumOptionData inMultiplesOfDepositTermType, final 
BigDecimal depositAmount, final BigDecimal maturityAmount,
-            final LocalDate maturityDate, final Integer depositPeriod, final 
EnumOptionData depositPeriodFrequency,
-            final Collection<EnumOptionData> periodFrequencyTypeOptions, final 
EnumOptionData depositType,
-            final EnumOptionData onAccountClosure, final 
Collection<EnumOptionData> onAccountClosureOptions,
-            final Collection<PaymentTypeData> paymentTypeOptions, final 
Collection<SavingsAccountData> savingsAccountDatas,
-            final PortfolioAccountData linkedAccount, final Boolean 
transferInterestToSavings, final boolean withHoldTax,
-            final TaxGroupData taxGroup) {
+                                    final String groupName, final Long 
clientId, final String clientName, final Long productId, final String 
productName,
+                                    final Long fieldofficerId, final String 
fieldofficerName, final SavingsAccountStatusEnumData status,
+                                    final 
SavingsAccountApplicationTimelineData timeline, final CurrencyData currency, 
final BigDecimal nominalAnnualInterestRate,
+                                    final EnumOptionData interestPeriodType, 
final EnumOptionData interestPostingPeriodType,
+                                    final EnumOptionData 
interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
+                                    final BigDecimal 
minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
+                                    final EnumOptionData 
lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
+                                    final BigDecimal 
minBalanceForInterestCalculation, final SavingsAccountSummaryData summary,
+                                    final 
Collection<SavingsAccountTransactionData> transactions, final 
Collection<DepositProductData> productOptions,
+                                    final Collection<StaffData> 
fieldOfficerOptions, final Collection<EnumOptionData> 
interestCompoundingPeriodTypeOptions,
+                                    final Collection<EnumOptionData> 
interestPostingPeriodTypeOptions,
+                                    final Collection<EnumOptionData> 
interestCalculationTypeOptions,
+                                    final Collection<EnumOptionData> 
interestCalculationDaysInYearTypeOptions,
+                                    final Collection<EnumOptionData> 
lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> 
withdrawalFeeTypeOptions,
+                                    final Collection<SavingsAccountChargeData> 
charges, final Collection<ChargeData> chargeOptions,
+                                    final DepositAccountInterestRateChartData 
accountChart, final DepositAccountInterestRateChartData chartTemplate,
+                                    final boolean preClosurePenalApplicable, 
final BigDecimal preClosurePenalInterest,
+                                    final EnumOptionData 
preClosurePenalInterestOnType, final Collection<EnumOptionData> 
preClosurePenalInterestOnTypeOptions,
+                                    final Integer minDepositTerm, final 
Integer maxDepositTerm, final EnumOptionData minDepositTermType,
+                                    final EnumOptionData maxDepositTermType, 
final Integer inMultiplesOfDepositTerm,
+                                    final EnumOptionData 
inMultiplesOfDepositTermType, final BigDecimal depositAmount, final BigDecimal 
maturityAmount,
+                                    final LocalDate maturityDate, final 
Integer depositPeriod, final EnumOptionData depositPeriodFrequency,
+                                    final Collection<EnumOptionData> 
periodFrequencyTypeOptions, final EnumOptionData depositType,
+                                    final EnumOptionData onAccountClosure, 
final Collection<EnumOptionData> onAccountClosureOptions,
+                                    final Collection<PaymentTypeData> 
paymentTypeOptions, final Collection<SavingsAccountData> savingsAccountDatas,
+                                    final PortfolioAccountData linkedAccount, 
final Boolean transferInterestToSavings, final boolean withHoldTax,
+                                    final TaxGroupData taxGroup, final 
Collection<EnumOptionData> maturityInstructionOptions, final Long 
transferToSavingsId,
+                                    final PortfolioAccountData 
transferToSavingsAccount) {
 
         super(id, accountNo, externalId, groupId, groupName, clientId, 
clientName, productId, productName, fieldofficerId,
                 fieldofficerName, status, timeline, currency, 
nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType,
@@ -485,6 +505,7 @@ public class FixedDepositAccountData extends 
DepositAccountData {
         this.depositPeriodFrequency = depositPeriodFrequency;
         this.onAccountClosure = onAccountClosure;
         this.linkedAccount = linkedAccount;
+        this.transferToSavingsAccount = transferToSavingsAccount;
         this.transferInterestToSavings = transferInterestToSavings;
 
         // template
@@ -495,6 +516,8 @@ public class FixedDepositAccountData extends 
DepositAccountData {
         this.onAccountClosureOptions = onAccountClosureOptions;
         this.paymentTypeOptions = paymentTypeOptions;
         this.savingsAccounts = savingsAccountDatas;
+        this.maturityInstructionOptions = maturityInstructionOptions;
+        this.transferToSavingsId = transferToSavingsId;
     }
 
     @Override
@@ -521,4 +544,8 @@ public class FixedDepositAccountData extends 
DepositAccountData {
     public void setActivationCharge(BigDecimal activationCharge) {
         this.activationCharge = activationCharge;
     }
+
+    public Long getTransferToSavingsId() {
+        return transferToSavingsId;
+    }
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountAssembler.java
index 6591ec3..283bfd5 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountAssembler.java
@@ -32,7 +32,9 @@ import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.expecte
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.isCalendarInheritedParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.isMandatoryDepositParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.mandatoryRecommendedDepositAmountParamName;
+import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.maturityInstructionIdParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.transferInterestToSavingsParamName;
+import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.transferToSavingsIdParamName;
 import static 
org.apache.fineract.portfolio.savings.SavingsApiConstants.accountNoParamName;
 import static 
org.apache.fineract.portfolio.savings.SavingsApiConstants.clientIdParamName;
 import static 
org.apache.fineract.portfolio.savings.SavingsApiConstants.externalIdParamName;
@@ -298,6 +300,10 @@ public class DepositAccountAssembler {
                 throw new 
UnsupportedParameterException(Arrays.asList(withHoldTaxParamName));
             }
         }
+        Integer depositRolloverId =  null;
+        if(command.parameterExists(maturityInstructionIdParamName)){
+            depositRolloverId = 
command.integerValueOfParameterNamed(maturityInstructionIdParamName);
+        }
 
         SavingsAccount account = null;
         if (depositAccountType.isFixedDeposit()) {
@@ -375,10 +381,12 @@ public class DepositAccountAssembler {
         final BigDecimal maturityAmount = null;// calculated and updated in
                                                // account
         final LocalDate maturityDate = null;// calculated and updated in 
account
-        final DepositAccountOnClosureType accountOnClosureType = null;
+        final Integer accountOnClosureTypeId = 
command.integerValueOfParameterNamed(maturityInstructionIdParamName);
+        final DepositAccountOnClosureType accountOnClosureType = 
accountOnClosureTypeId != null ? 
DepositAccountOnClosureType.fromInt(accountOnClosureTypeId) :null;
+        final Long transferToSavingsId  = 
command.longValueOfParameterNamed(transferToSavingsIdParamName);
         return 
DepositAccountTermAndPreClosure.createNew(updatedProductPreClosure, 
updatedProductTerm, account, depositAmount,
                 maturityAmount, maturityDate, depositPeriod, 
depositPeriodFrequency, expectedFirstDepositOnDate, accountOnClosureType,
-                trasferInterest);
+                trasferInterest, transferToSavingsId);
     }
 
     public DepositAccountRecurringDetail assembleAccountRecurringDetail(final 
JsonCommand command,
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainService.java
index 08f602e..40d4a5f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainService.java
@@ -25,6 +25,7 @@ import 
org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.joda.time.LocalDate;
 import org.joda.time.format.DateTimeFormatter;
+import org.springframework.transaction.annotation.Transactional;
 
 public interface DepositAccountDomainService {
 
@@ -43,8 +44,14 @@ public interface DepositAccountDomainService {
     Long handleFDAccountClosure(FixedDepositAccount account, PaymentDetail 
paymentDetail, AppUser user, JsonCommand command,
             LocalDate tenantsTodayDate, Map<String, Object> changes);
 
+    @Transactional
+    Long handleFDAccountMaturityClosure(FixedDepositAccount account, 
PaymentDetail paymentDetail, AppUser user,
+                                        LocalDate tenantsTodayDate, 
DateTimeFormatter fmt,
+                                        LocalDate closedDate, Integer 
onAccountClosureId,
+                                        Long toSavingsId, String 
transferDescription, Map<String, Object> changes);
+
     Long handleRDAccountClosure(RecurringDepositAccount account, PaymentDetail 
paymentDetail, AppUser user, JsonCommand command,
-            LocalDate tenantsTodayDate, Map<String, Object> changes);
+                                LocalDate tenantsTodayDate, Map<String, 
Object> changes);
 
     Long handleFDAccountPreMatureClosure(FixedDepositAccount account, 
PaymentDetail paymentDetail, AppUser user, JsonCommand command,
             LocalDate tenantsTodayDate, Map<String, Object> changes);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java
index e8b5d7f..c9a5f97 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java
@@ -189,7 +189,7 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
     @Transactional
     @Override
     public Long handleFDAccountClosure(final FixedDepositAccount account, 
final PaymentDetail paymentDetail, final AppUser user,
-            final JsonCommand command, final LocalDate tenantsTodayDate, final 
Map<String, Object> changes) {
+                                       final JsonCommand command, final 
LocalDate tenantsTodayDate, final Map<String, Object> changes) {
 
         final boolean isSavingsInterestPostingAtCurrentPeriodEnd = 
this.configurationDomainService
                 .isSavingsInterestPostingAtCurrentPeriodEnd();
@@ -263,6 +263,85 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
 
     @Transactional
     @Override
+    public Long handleFDAccountMaturityClosure(final FixedDepositAccount 
account, final PaymentDetail paymentDetail, final AppUser user,
+                                               final LocalDate 
tenantsTodayDate, final DateTimeFormatter fmt,
+                                               final LocalDate closedDate, 
final Integer onAccountClosureId,
+                                               final Long toSavingsId, final 
String transferDescription,
+                                               Map<String, Object> changes) {
+
+        final boolean isSavingsInterestPostingAtCurrentPeriodEnd = 
this.configurationDomainService
+                .isSavingsInterestPostingAtCurrentPeriodEnd();
+        final Integer financialYearBeginningMonth = 
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
+
+        boolean isRegularTransaction = false;
+        boolean isAccountTransfer = false;
+        final boolean isPreMatureClosure = false;
+        final Set<Long> existingTransactionIds = new HashSet<>();
+        final Set<Long> existingReversedTransactionIds = new HashSet<>();
+        /***
+         * Update account transactionIds for post journal entries.
+         */
+        updateExistingTransactionsDetails(account, existingTransactionIds, 
existingReversedTransactionIds);
+
+        final MathContext mc = MathContext.DECIMAL64;
+        Long savingsTransactionId = null;
+        
account.postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth);
+        final DepositAccountOnClosureType onClosureType = 
DepositAccountOnClosureType.fromInt(onAccountClosureId);
+        if (onClosureType.isReinvest()) {
+            BigDecimal reInvestAmount;
+            if(onClosureType.isReinvestPrincipal())
+                reInvestAmount = account.getDepositAmount();
+            else
+                reInvestAmount = account.getAccountBalance();
+            FixedDepositAccount reinvestedDeposit = 
account.reInvest(reInvestAmount);
+            
this.depositAccountAssembler.assignSavingAccountHelpers(reinvestedDeposit);
+            
reinvestedDeposit.updateMaturityDateAndAmountBeforeAccountActivation(mc, 
isPreMatureClosure,
+                    isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth);
+
+            this.savingsAccountRepository.save(reinvestedDeposit);
+            autoGenerateAccountNumber(reinvestedDeposit);
+            final SavingsAccountTransaction withdrawal = 
this.handleWithdrawal(account, fmt, closedDate, reInvestAmount,
+                    paymentDetail, false, isRegularTransaction);
+            savingsTransactionId = withdrawal.getId();
+
+            if (onClosureType.isReinvestPrincipalAndInterest()) {
+                account.updateClosedStatus();
+                account.updateOnAccountClosureStatus(onClosureType);
+            }
+            changes.put("reinvestedDepositId", reinvestedDeposit.getId());
+            
reinvestedDeposit.approveAndActivateApplication(closedDate.toDate(), user);
+            this.savingsAccountRepository.save(reinvestedDeposit);
+
+        } else if (onClosureType.isTransferToSavings()) {
+            final SavingsAccount toSavingsAccount = 
this.depositAccountAssembler.assembleFrom(toSavingsId,
+                    DepositAccountType.SAVINGS_DEPOSIT);
+            final boolean isExceptionForBalanceCheck = false;
+            final AccountTransferDTO accountTransferDTO = new 
AccountTransferDTO(closedDate, account.getAccountBalance(),
+                    PortfolioAccountType.SAVINGS, 
PortfolioAccountType.SAVINGS, null, null, transferDescription, null, fmt, null, 
null,
+                    null, null, null, 
AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, 
toSavingsAccount, account,
+                    isAccountTransfer, isExceptionForBalanceCheck);
+            
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
+            updateAlreadyPostedTransactions(existingTransactionIds, account);
+            account.updateClosedStatus();
+            account.updateOnAccountClosureStatus(onClosureType);
+        } else {
+            final SavingsAccountTransaction withdrawal = 
this.handleWithdrawal(account, fmt, closedDate, account.getAccountBalance(),
+                    paymentDetail, false, isRegularTransaction);
+            savingsTransactionId = withdrawal.getId();
+        }
+
+        //if(!processMaturityInstructionOnly)
+          //  account.close(user, command, tenantsTodayDate, changes);
+
+        this.savingsAccountRepository.save(account);
+
+        postJournalEntries(account, existingTransactionIds, 
existingReversedTransactionIds, isAccountTransfer);
+
+        return savingsTransactionId;
+    }
+
+    @Transactional
+    @Override
     public Long handleRDAccountClosure(final RecurringDepositAccount account, 
final PaymentDetail paymentDetail, final AppUser user,
             final JsonCommand command, final LocalDate tenantsTodayDate, final 
Map<String, Object> changes) {
 
@@ -290,7 +369,12 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
         final Integer onAccountClosureId = 
command.integerValueOfParameterNamed(onAccountClosureIdParamName);
         final DepositAccountOnClosureType onClosureType = 
DepositAccountOnClosureType.fromInt(onAccountClosureId);
         if (onClosureType.isReinvest()) {
-            RecurringDepositAccount reinvestedDeposit = 
account.reInvest(transactionAmount);
+            BigDecimal reInvestAmount;
+            if(onClosureType.isReinvestPrincipal())
+                reInvestAmount = account.getDepositAmount();
+            else
+                reInvestAmount = account.getAccountBalance();
+            RecurringDepositAccount reinvestedDeposit = 
account.reInvest(reInvestAmount);
             
depositAccountAssembler.assignSavingAccountHelpers(reinvestedDeposit);
             this.savingsAccountRepository.save(reinvestedDeposit);
             final CalendarInstance calendarInstance = 
getCalendarInstance(account, reinvestedDeposit);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountTermAndPreClosure.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountTermAndPreClosure.java
index 3b833a5..f13a1b4 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountTermAndPreClosure.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountTermAndPreClosure.java
@@ -24,7 +24,9 @@ import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.deposit
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.depositPeriodParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.expectedFirstDepositOnDateParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.localeParamName;
+import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.maturityInstructionIdParamName;
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.transferInterestToSavingsParamName;
+import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.transferToSavingsIdParamName;
 
 import java.math.BigDecimal;
 import java.util.Date;
@@ -90,6 +92,9 @@ public class DepositAccountTermAndPreClosure extends 
AbstractPersistableCustom {
     @Column(name = "transfer_interest_to_linked_account", nullable = false)
     private boolean transferInterestToLinkedAccount;
 
+    @Column(name = "transfer_to_savings_account_id")
+    private Long transferToSavingsAccountId;
+
     protected DepositAccountTermAndPreClosure() {
         super();
     }
@@ -97,16 +102,16 @@ public class DepositAccountTermAndPreClosure extends 
AbstractPersistableCustom {
     public static DepositAccountTermAndPreClosure 
createNew(DepositPreClosureDetail preClosureDetail, DepositTermDetail 
depositTermDetail,
             SavingsAccount account, BigDecimal depositAmount, BigDecimal 
maturityAmount, final LocalDate maturityDate,
             Integer depositPeriod, final SavingsPeriodFrequencyType 
depositPeriodFrequency, final LocalDate expectedFirstDepositOnDate,
-            final DepositAccountOnClosureType accountOnClosureType, Boolean 
trasferInterest) {
+            final DepositAccountOnClosureType accountOnClosureType, Boolean 
trasferInterest, Long transferToSavingsId) {
 
         return new DepositAccountTermAndPreClosure(preClosureDetail, 
depositTermDetail, account, depositAmount, maturityAmount,
-                maturityDate, depositPeriod, depositPeriodFrequency, 
expectedFirstDepositOnDate, accountOnClosureType, trasferInterest);
+                maturityDate, depositPeriod, depositPeriodFrequency, 
expectedFirstDepositOnDate, accountOnClosureType, trasferInterest, 
transferToSavingsId);
     }
 
     private DepositAccountTermAndPreClosure(DepositPreClosureDetail 
preClosureDetail, DepositTermDetail depositTermDetail,
             SavingsAccount account, BigDecimal depositAmount, BigDecimal 
maturityAmount, final LocalDate maturityDate,
             Integer depositPeriod, final SavingsPeriodFrequencyType 
depositPeriodFrequency, final LocalDate expectedFirstDepositOnDate,
-            final DepositAccountOnClosureType accountOnClosureType, Boolean 
transferInterest) {
+            final DepositAccountOnClosureType accountOnClosureType, Boolean 
transferInterest, Long transferToSavingsId) {
         this.depositAmount = depositAmount;
         this.maturityAmount = maturityAmount;
         this.maturityDate = (maturityDate == null) ? null : 
maturityDate.toDate();
@@ -118,6 +123,7 @@ public class DepositAccountTermAndPreClosure extends 
AbstractPersistableCustom {
         this.expectedFirstDepositOnDate = expectedFirstDepositOnDate == null ? 
null : expectedFirstDepositOnDate.toDate();
         this.onAccountClosureType = (accountOnClosureType == null) ? null : 
accountOnClosureType.getValue();
         this.transferInterestToLinkedAccount = transferInterest;
+        this.transferToSavingsAccountId = transferToSavingsId;
     }
 
     public Map<String, Object> update(final JsonCommand command, final 
DataValidatorBuilder baseDataValidator) {
@@ -158,6 +164,20 @@ public class DepositAccountTermAndPreClosure extends 
AbstractPersistableCustom {
             this.transferInterestToLinkedAccount = newValue;
         }
 
+        if 
(command.isChangeInIntegerParameterNamed(maturityInstructionIdParamName, 
this.onAccountClosureType) || command.integerValueOfParameterNamed(
+                maturityInstructionIdParamName) == null) {
+            final Integer newValue = 
command.integerValueOfParameterNamed(maturityInstructionIdParamName);
+            actualChanges.put(maturityInstructionIdParamName, newValue);
+            this.onAccountClosureType = newValue != null ? 
DepositAccountOnClosureType.fromInt(newValue).getValue() : null;
+        }
+
+        if (command.isChangeInLongParameterNamed(transferToSavingsIdParamName, 
this.transferToSavingsAccountId) || command.integerValueOfParameterNamed(
+                transferToSavingsIdParamName) == null) {
+            final Long newValue = 
command.longValueOfParameterNamed(transferToSavingsIdParamName);
+            actualChanges.put(transferToSavingsIdParamName, newValue);
+            this.transferToSavingsAccountId = newValue ;
+        }
+
         if (this.preClosureDetail != null) {
             actualChanges.putAll(this.preClosureDetail.update(command, 
baseDataValidator));
         }
@@ -291,9 +311,10 @@ public class DepositAccountTermAndPreClosure extends 
AbstractPersistableCustom {
         final Boolean transferInterestToLinkedAccount = false;
 
         final DepositAccountOnClosureType accountOnClosureType = null;
+        final Long transferToSavingsId = null;
         return DepositAccountTermAndPreClosure.createNew(preClosureDetail, 
depositTermDetail, account, actualDepositAmount, maturityAmount,
                 maturityDate, depositPeriod, depositPeriodFrequency, 
expectedFirstDepositOnDate, accountOnClosureType,
-                transferInterestToLinkedAccount);
+                transferInterestToLinkedAccount, transferToSavingsId);
     }
 
     public void updateExpectedFirstDepositDate(final LocalDate 
expectedFirstDepositOnDate) {
@@ -311,4 +332,12 @@ public class DepositAccountTermAndPreClosure extends 
AbstractPersistableCustom {
         }
         return isAfterExpectedFirstDepositDate;
     }
+
+    public Integer getOnAccountClosureType() {
+        return onAccountClosureType;
+    }
+
+    public Long getTransferToSavingsAccountId() {
+        return transferToSavingsAccountId;
+    }
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java
index 2c909ef..d5e23b9 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java
@@ -259,6 +259,8 @@ public class FixedDepositAccount extends SavingsAccount {
         }
     }
 
+
+
     public LocalDate calculateMaturityDate() {
 
         final LocalDate startDate = accountSubmittedOrActivationDate();
@@ -489,6 +491,14 @@ public class FixedDepositAccount extends SavingsAccount {
         // this.savingsAccountTransactionSummaryWrapper, this.transactions);
     }
 
+    public void updateClosedStatus(){
+        this.status = SavingsAccountStatusType.CLOSED.getValue();
+    }
+
+    public void updateOnAccountClosureStatus(DepositAccountOnClosureType 
onClosureType){
+        
this.accountTermAndPreClosure.updateOnAccountClosureStatus(onClosureType);
+    }
+
     public void postMaturityInterest(final boolean 
isSavingsInterestPostingAtCurrentPeriodEnd, final Integer 
financialYearBeginningMonth) {
         final LocalDate interestPostingUpToDate = maturityDate();
         final MathContext mc = MathContext.DECIMAL64;
@@ -756,6 +766,14 @@ public class FixedDepositAccount extends SavingsAccount {
         return this.accountTermAndPreClosure.isTransferToSavingsOnClosure();
     }
 
+    public Integer getOnAccountClosureId(){
+        return this.accountTermAndPreClosure.getOnAccountClosureType();
+    }
+
+    public Long getTransferToSavingsAccountId() {
+        return this.accountTermAndPreClosure.getTransferToSavingsAccountId();
+    }
+
     public FixedDepositAccount reInvest(BigDecimal depositAmount) {
 
         final DepositAccountTermAndPreClosure newAccountTermAndPreClosure = 
this.accountTermAndPreClosure.copy(depositAmount);
@@ -830,4 +848,16 @@ public class FixedDepositAccount extends SavingsAccount {
         super.loadLazyCollections();
         this.chart.getId() ;
     }
+
+    public BigDecimal getDepositAmount() {
+        return this.accountTermAndPreClosure.depositAmount();
+    }
+    @Override
+    public BigDecimal getAccountBalance() {
+        return this.summary.getAccountBalance(this.currency).getAmount();
+    }
+    public boolean isMatured(){
+        return SavingsAccountStatusType.MATURED.getValue().equals(this.status);
+    }
+
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
index 79d592d..670d53c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
@@ -1232,4 +1232,8 @@ public class RecurringDepositAccount extends 
SavingsAccount {
         super.loadLazyCollections();
         this.chart.getId() ;
     }
+
+    public BigDecimal getDepositAmount() {
+        return this.accountTermAndPreClosure.depositAmount();
+    }
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
index c52e676..a1499c1 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
@@ -1433,7 +1433,6 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
                 
baseDataValidator.reset().parameter(withHoldTaxParamName).failWithCode("not.supported.for.this.account");
             }
         }
-
         validateLockinDetails(baseDataValidator);
         esnureOverdraftLimitsSetForOverdraftAccounts();
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java
index 1a70557..55b43fc 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java
@@ -378,6 +378,8 @@ public class DepositAccountReadPlatformServiceImpl 
implements DepositAccountRead
             final boolean feeChargesOnly = false;
             final Collection<ChargeData> chargeOptions = 
this.chargeReadPlatformService.retrieveSavingsProductApplicableCharges(feeChargesOnly);
 
+            final Collection<EnumOptionData> maturityInstructionOptions = 
this.depositsDropdownReadPlatformService.maturityInstructionOptions();
+
             Collection<StaffData> fieldOfficerOptions = null;
 
             if (officeId != null) {
@@ -405,7 +407,7 @@ public class DepositAccountReadPlatformServiceImpl 
implements DepositAccountRead
             }
 
             // retrieve chart Slabs
-            final InterestRateChartData productChartData = 
this.productChartReadPlatformService.retrieveActiveChartWithTemplate(productId);
+                final InterestRateChartData productChartData = 
this.productChartReadPlatformService.retrieveActiveChartWithTemplate(productId);
             final DepositAccountInterestRateChartData accountChart = 
DepositAccountInterestRateChartData.from(productChartData);
 
             if (depositAccountType.isFixedDeposit()) {
@@ -414,7 +416,7 @@ public class DepositAccountReadPlatformServiceImpl 
implements DepositAccountRead
                         fieldOfficerOptions, 
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
                         interestCalculationTypeOptions, 
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
                         withdrawalFeeTypeOptions, transactions, charges, 
chargeOptions, preClosurePenalInterestOnTypeOptions,
-                        periodFrequencyTypeOptions, savingsAccountDatas);
+                        periodFrequencyTypeOptions, savingsAccountDatas, 
maturityInstructionOptions);
 
                 template = 
FixedDepositAccountData.withInterestChart((FixedDepositAccountData) template, 
accountChart);
             } else if (depositAccountType.isRecurringDeposit()) {
@@ -450,6 +452,7 @@ public class DepositAccountReadPlatformServiceImpl 
implements DepositAccountRead
 
             final Collection<SavingsAccountTransactionData> transactions = 
null;
             final Collection<SavingsAccountChargeData> charges = null;
+                final Collection<EnumOptionData> maturityInstructionOptions = 
null;
 
             final boolean feeChargesOnly = true;
             final Collection<ChargeData> chargeOptions = 
this.chargeReadPlatformService.retrieveSavingsProductApplicableCharges(feeChargesOnly);
@@ -462,7 +465,7 @@ public class DepositAccountReadPlatformServiceImpl 
implements DepositAccountRead
                         fieldOfficerOptions, 
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
                         interestCalculationTypeOptions, 
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
                         withdrawalFeeTypeOptions, transactions, charges, 
chargeOptions, preClosurePenalInterestOnTypeOptions,
-                        periodFrequencyTypeOptions, savingsAccountDatas);
+                        periodFrequencyTypeOptions, savingsAccountDatas, 
maturityInstructionOptions);
             } else if (depositAccountType.isRecurringDeposit()) {
 
                 template = 
RecurringDepositAccountData.withClientTemplate(clientId, clientName, groupId, 
groupName);
@@ -778,7 +781,8 @@ public class DepositAccountReadPlatformServiceImpl 
implements DepositAccountRead
             sqlBuilder.append("datp.deposit_period as depositPeriod, ");
             sqlBuilder.append("datp.deposit_period_frequency_enum as 
depositPeriodFrequencyTypeId, ");
             sqlBuilder.append("datp.on_account_closure_enum as 
onAccountClosureId, ");
-            sqlBuilder.append("datp.transfer_interest_to_linked_account as 
transferInterestToSavings ");
+            sqlBuilder.append("datp.transfer_interest_to_linked_account as 
transferInterestToSavings, ");
+            sqlBuilder.append("datp.transfer_to_savings_account_id as 
transferToSavingsId ");
 
             sqlBuilder.append(super.selectTablesSql());
 
@@ -826,10 +830,13 @@ public class DepositAccountReadPlatformServiceImpl 
implements DepositAccountRead
                     .depositAccountOnClosureType(onAccountClosureId);
             final Boolean transferInterestToSavings = 
rs.getBoolean("transferInterestToSavings");
 
+            final Long transferToSavingsId = JdbcSupport.getLong(rs, 
"transferToSavingsId");
+
+
             return FixedDepositAccountData.instance(depositAccountData, 
preClosurePenalApplicable, preClosurePenalInterest,
                     preClosurePenalInterestOnType, minDepositTerm, 
maxDepositTerm, minDepositTermType, maxDepositTermType,
                     inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, 
depositAmount, maturityAmount, maturityDate, depositPeriod,
-                    depositPeriodFrequencyType, onAccountClosureType, 
transferInterestToSavings);
+                    depositPeriodFrequencyType, onAccountClosureType, 
transferInterestToSavings, transferToSavingsId);
         }
     }
 
@@ -1266,7 +1273,7 @@ public class DepositAccountReadPlatformServiceImpl 
implements DepositAccountRead
             return FixedDepositAccountData.instance(depositAccountData, 
preClosurePenalApplicable, preClosurePenalInterest,
                     preClosurePenalInterestOnType, minDepositTerm, 
maxDepositTerm, minDepositTermType, maxDepositTermType,
                     inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, 
depositAmount, maturityAmount, maturityDate, depositPeriod,
-                    depositPeriodFrequencyType, onAccountClosureType, 
transferInterestToSavings);
+                    depositPeriodFrequencyType, onAccountClosureType, 
transferInterestToSavings, null);
         }
     }
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
index c1c5fc5..2e42c5c 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -28,6 +28,7 @@ import java.math.BigDecimal;
 import java.math.MathContext;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -44,6 +45,7 @@ import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuild
 import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
 import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
@@ -145,6 +147,7 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
     private final HolidayRepositoryWrapper holidayRepository;
     private final WorkingDaysRepositoryWrapper workingDaysRepository;
     private final DepositAccountOnHoldTransactionRepository 
depositAccountOnHoldTransactionRepository;
+    private final FromJsonHelper fromApiJsonHelper;
 
     @Autowired
     public DepositAccountWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context,
@@ -164,7 +167,8 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
             final AccountTransfersWritePlatformService 
accountTransfersWritePlatformService,
             final DepositAccountReadPlatformService 
depositAccountReadPlatformService,
             final CalendarInstanceRepository calendarInstanceRepository, final 
ConfigurationDomainService configurationDomainService,
-            final DepositAccountOnHoldTransactionRepository 
depositAccountOnHoldTransactionRepository) {
+            final DepositAccountOnHoldTransactionRepository 
depositAccountOnHoldTransactionRepository,
+            final FromJsonHelper fromApiJsonHelper) {
 
         this.context = context;
         this.savingAccountRepositoryWrapper = savingAccountRepositoryWrapper;
@@ -188,6 +192,7 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         this.calendarInstanceRepository = calendarInstanceRepository;
         this.configurationDomainService = configurationDomainService;
         this.depositAccountOnHoldTransactionRepository = 
depositAccountOnHoldTransactionRepository;
+        this.fromApiJsonHelper = fromApiJsonHelper;
     }
 
     @Transactional
@@ -798,14 +803,14 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         this.depositAccountTransactionDataValidator.validateClosing(command, 
DepositAccountType.FIXED_DEPOSIT, isPreMatureClose);
 
         final Map<String, Object> changes = new LinkedHashMap<>();
-        final PaymentDetail paymentDetail = 
this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, 
changes);
+        final PaymentDetail
+                paymentDetail = 
this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, 
changes);
 
         final FixedDepositAccount account = (FixedDepositAccount) 
this.depositAccountAssembler.assembleFrom(savingsId,
                 DepositAccountType.FIXED_DEPOSIT);
         checkClientOrGroupActive(account);
 
-        this.depositAccountDomainService.handleFDAccountClosure(account, 
paymentDetail, user, command, DateUtils.getLocalDateOfTenant(),
-                changes);
+        this.depositAccountDomainService.handleFDAccountClosure(account, 
paymentDetail, user, command, DateUtils.getLocalDateOfTenant(), changes);
 
         final String noteText = command.stringValueOfParameterNamed("note");
         if (StringUtils.isNotBlank(noteText)) {
@@ -1352,6 +1357,32 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
 
         if (depositAccountType.isFixedDeposit()) {
             ((FixedDepositAccount) 
account).updateMaturityStatus(isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth);
+            FixedDepositAccount fdAccount = ((FixedDepositAccount) account);
+            //handle maturity instructions
+
+            if(fdAccount.isMatured() && (fdAccount.isReinvestOnClosure() || 
fdAccount.isTransferToSavingsOnClosure())){
+                DateTimeFormatter fmt = 
DateTimeFormat.forPattern("yyyy-MM-dd");
+                Map<String, Object> changes = new HashMap<>();
+                AppUser user = context.authenticatedUser();
+                Long toSavingsId = fdAccount.getTransferToSavingsAccountId();
+                
this.depositAccountDomainService.handleFDAccountMaturityClosure(fdAccount, 
null, user,
+                        fdAccount.maturityDate(), fmt, 
fdAccount.maturityDate(),
+                        fdAccount.getOnAccountClosureId(), toSavingsId, "Apply 
maturity instructions", changes);
+
+                if(changes.get("reinvestedDepositId") != null) {
+                    Long reinvestedDepositId = (Long) 
changes.get("reinvestedDepositId");
+                    Money amountForDeposit = account.activateWithBalance();
+                    final FixedDepositAccount reinvestAccount = 
(FixedDepositAccount) 
this.depositAccountAssembler.assembleFrom(reinvestedDepositId,
+                            DepositAccountType.FIXED_DEPOSIT);
+                    Money activationChargeAmount = 
getActivationCharge(reinvestAccount);
+                    if(activationChargeAmount.isGreaterThanZero()){
+                        payActivationCharge(reinvestAccount, user);
+                        amountForDeposit  = 
amountForDeposit.plus(activationChargeAmount);
+                    }
+                    
this.depositAccountDomainService.handleFDDeposit(reinvestAccount, fmt, 
fdAccount.maturityDate(),
+                            amountForDeposit.getAmount(), null);
+                }
+            }
         } else if (depositAccountType.isRecurringDeposit()) {
             ((RecurringDepositAccount) 
account).updateMaturityStatus(isSavingsInterestPostingAtCurrentPeriodEnd,
                     financialYearBeginningMonth);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositsDropdownReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositsDropdownReadPlatformService.java
index d186a69..07c041f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositsDropdownReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositsDropdownReadPlatformService.java
@@ -27,6 +27,8 @@ public interface DepositsDropdownReadPlatformService {
 
     Collection<EnumOptionData> retrievePreClosurePenalInterestOnTypeOptions();
 
+    Collection<EnumOptionData> maturityInstructionOptions();
+
     /*
      * Collection<EnumOptionData> retrieveDepositTermTypeOptions();
      *
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositsDropdownReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositsDropdownReadPlatformServiceImpl.java
index 70ce68f..7c172e0 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositsDropdownReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositsDropdownReadPlatformServiceImpl.java
@@ -18,8 +18,10 @@
  */
 package org.apache.fineract.portfolio.savings.service;
 
+import java.util.Arrays;
 import java.util.Collection;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.portfolio.savings.DepositAccountOnClosureType;
 import org.apache.fineract.portfolio.savings.PreClosurePenalInterestOnType;
 import org.springframework.stereotype.Service;
 
@@ -48,4 +50,14 @@ public class DepositsDropdownReadPlatformServiceImpl 
implements DepositsDropdown
      * .recurringDepositFrequencyType(SavingsPeriodFrequencyType.values()); }
      */
 
+
+    @Override
+    public Collection<EnumOptionData> maturityInstructionOptions() {
+        return  Arrays.asList(
+            
SavingsEnumerations.depositAccountOnClosureType(DepositAccountOnClosureType.WITHDRAW_DEPOSIT),
+            
SavingsEnumerations.depositAccountOnClosureType(DepositAccountOnClosureType.TRANSFER_TO_SAVINGS),
+            
SavingsEnumerations.depositAccountOnClosureType(DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST),
+            
SavingsEnumerations.depositAccountOnClosureType(DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY));
+
+    }
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsEnumerations.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsEnumerations.java
index b552cbd..b0b2644 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsEnumerations.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsEnumerations.java
@@ -795,10 +795,14 @@ public class SavingsEnumerations {
                 optionData = new 
EnumOptionData(DepositAccountOnClosureType.TRANSFER_TO_SAVINGS.getValue().longValue(),
                         
DepositAccountOnClosureType.TRANSFER_TO_SAVINGS.getCode(), "Transfer to 
Savings");
             break;
-            case REINVEST:
-                optionData = new 
EnumOptionData(DepositAccountOnClosureType.REINVEST.getValue().longValue(),
-                        DepositAccountOnClosureType.REINVEST.getCode(), 
"Re-Invest");
+            case REINVEST_PRINCIPAL_AND_INTEREST:
+                optionData = new 
EnumOptionData(DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST.getValue().longValue(),
+                        
DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST.getCode(), 
"Re-Invest Maturity Amount");
             break;
+            case REINVEST_PRINCIPAL_ONLY:
+                optionData = new 
EnumOptionData(DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY.getValue().longValue(),
+                                                
DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY.getCode(), "Re-Invest 
Principal Only");
+                break;
         }
         return optionData;
     }
@@ -835,5 +839,4 @@ public class SavingsEnumerations {
         }
         return optionData;
     }
-
 }
\ No newline at end of file
diff --git 
a/fineract-provider/src/main/resources/sql/migrations/core_db/V358__fixed_deposit_rollover_transfer.sql
 
b/fineract-provider/src/main/resources/sql/migrations/core_db/V358__fixed_deposit_rollover_transfer.sql
new file mode 100644
index 0000000..6bb8300
--- /dev/null
+++ 
b/fineract-provider/src/main/resources/sql/migrations/core_db/V358__fixed_deposit_rollover_transfer.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_deposit_account_term_and_preclosure add column 
transfer_to_savings_account_id bigint(20) DEFAULT NULL,
+add  CONSTRAINT FOREIGN KEY (`transfer_to_savings_account_id`) REFERENCES 
`m_savings_account` (`id`);
\ No newline at end of file

Reply via email to