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

ptuomola 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 0b51ab2  FINERACT-1396: Bulk Import Feature
0b51ab2 is described below

commit 0b51ab2429c55c4037b16c8cc5c331c5e3c6c517
Author: xurror <[email protected]>
AuthorDate: Tue May 25 11:21:59 2021 +0100

    FINERACT-1396: Bulk Import Feature
---
 .../bulkimport/constants/ChargeConstants.java      |  34 +++++++
 .../bulkimport/constants/LoanConstants.java        |  11 ++-
 .../constants/TemplatePopulateImportConstants.java |   1 +
 .../importhandler/ImportHandlerUtils.java          |  44 +++++++++
 .../importhandler/loan/LoanImportHandler.java      |  75 +++++++++++----
 .../bulkimport/populator/ChargeSheetPopulator.java |  86 +++++++++++++++++
 .../populator/LoanProductSheetPopulator.java       |   7 +-
 .../populator/charge/ChargeWorkbookPopulator.java  |  74 ++++++++++++++
 .../populator/loan/LoanWorkbookPopulator.java      | 106 +++++++++++++++++----
 .../BulkImportWorkbookPopulatorServiceImpl.java    |  10 +-
 .../fineract/portfolio/charge/data/ChargeData.java |  12 +++
 .../portfolio/loanaccount/data/LoanChargeData.java |  35 +++++++
 .../importhandler/loan/LoanImportHandlerTest.java  |  14 +++
 13 files changed, 468 insertions(+), 41 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ChargeConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ChargeConstants.java
new file mode 100644
index 0000000..584bef0
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ChargeConstants.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.infrastructure.bulkimport.constants;
+
+public final class ChargeConstants {
+
+    private ChargeConstants() {
+
+    }
+
+    // Column indices
+    public static final int CHARGE_NAME_COL = 1;
+    public static final int CHARGE_AMOUNT_COL = 2;
+    public static final int CHARGE_CALCULATION_TYPE_COL = 3;
+    // public static final int CHARGE_DUE_DATE_COL = 4;
+    public static final int CHARGE_TIME_TYPE_COL = 4;
+
+}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java
index 474f5d1..7d9fa3c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java
@@ -60,10 +60,11 @@ public final class LoanConstants {
     public static final int LOAN_ID_COL = 33;// AH
     public static final int FAILURE_REPORT_COL = 34;// AI
     public static final int EXTERNAL_ID_COL = 35;// AJ
-    public static final int CHARGE_ID_1 = 36;// AK
+    public static final int CHARGE_NAME_1 = 36;// AK
     public static final int CHARGE_AMOUNT_1 = 37;// AL
+
     public static final int CHARGE_DUE_DATE_1 = 38;// AM
-    public static final int CHARGE_ID_2 = 39;// AN
+    public static final int CHARGE_NAME_2 = 39;// AO
     public static final int CHARGE_AMOUNT_2 = 40;// AO
     public static final int CHARGE_DUE_DATE_2 = 41;// AP
     public static final int GROUP_ID = 42;// AQ
@@ -71,8 +72,10 @@ public final class LoanConstants {
     public static final int LOOKUP_CLIENT_EXTERNAL_ID = 44;// AS
     public static final int LOOKUP_ACTIVATION_DATE_COL = 45;// AT
     public static final int LINK_ACCOUNT_ID = 46;// AU
-    public static final int LOAN_COLLATERAL_ID = 47;
-    public static final int LOAN_COLLATERAL_QUANTITY = 48;
+    public static final int LOAN_COLLATERAL_ID = 47;// AV
+    public static final int LOAN_COLLATERAL_QUANTITY = 48;// AW
+    public static final int CHARGE_AMOUNT_TYPE_1 = 49;// AX
+    public static final int CHARGE_AMOUNT_TYPE_2 = 50;// AY
 
     public static final String LOAN_TYPE_INDIVIDUAL = "Individual";
     public static final String LOAN_TYPE_GROUP = "Group";
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/TemplatePopulateImportConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/TemplatePopulateImportConstants.java
index c18abbb..a93f674 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/TemplatePopulateImportConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/TemplatePopulateImportConstants.java
@@ -35,6 +35,7 @@ public final class TemplatePopulateImportConstants {
     public static final String CENTER_SHEET_NAME = "Centers";
     public static final String STAFF_SHEET_NAME = "Staff";
     public static final String GROUP_SHEET_NAME = "Groups";
+    public static final String CHARGE_SHEET_NAME = "Charges";
     public static final String CHART_OF_ACCOUNTS_SHEET_NAME = 
"ChartOfAccounts";
     public static final String CLIENT_ENTITY_SHEET_NAME = "ClientEntity";
     public static final String CLIENT_PERSON_SHEET_NAME = "ClientPerson";
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java
index 4b7bc7a..af7c3a6 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java
@@ -24,6 +24,7 @@ import java.time.LocalDate;
 import java.util.List;
 import 
org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
 import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
 import 
org.apache.fineract.infrastructure.core.exception.AbstractPlatformException;
 import 
org.apache.fineract.infrastructure.core.exception.UnsupportedParameterException;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
@@ -304,6 +305,7 @@ public final class ImportHandlerUtils {
                             if 
(sheetName.equals(TemplatePopulateImportConstants.OFFICE_SHEET_NAME)
                                     || 
sheetName.equals(TemplatePopulateImportConstants.GL_ACCOUNTS_SHEET_NAME)
                                     || 
sheetName.equals(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME)
+                                    || 
sheetName.equals(TemplatePopulateImportConstants.CHARGE_SHEET_NAME)
                                     || 
sheetName.equals(TemplatePopulateImportConstants.SHARED_PRODUCTS_SHEET_NAME)
                                     || 
sheetName.equals(TemplatePopulateImportConstants.ROLES_SHEET_NAME)) {
                                 if (row.getCell(cell.getColumnIndex() - 
1).getCellType() == CellType.NUMERIC) {
@@ -342,6 +344,48 @@ public final class ImportHandlerUtils {
         return 0L;
     }
 
+    public static EnumOptionData getChargeTimeTypeEmun(Sheet sheet, String 
name) {
+        String sheetName = sheet.getSheetName();
+        String chargeTimeType = "";
+        EnumOptionData chargeTimeTypeEnum = null;
+        if 
(sheetName.equals(TemplatePopulateImportConstants.CHARGE_SHEET_NAME)) {
+            for (Row row : sheet) {
+                for (Cell cell : row) {
+                    if (name != null) {
+                        if (cell.getCellType() == CellType.STRING && 
cell.getRichStringCellValue().getString().trim().equals(name)) {
+                            chargeTimeType = row.getCell(cell.getColumnIndex() 
+ 3).getStringCellValue().toString();
+
+                        }
+                    }
+                }
+            }
+        }
+        if (!chargeTimeType.equals("")) {
+            String chargeTimeTypeId = "";
+            if (chargeTimeType.equalsIgnoreCase("Disbursement")) {
+                chargeTimeTypeId = "1";
+            }
+            chargeTimeTypeEnum = new EnumOptionData(null, null, 
chargeTimeTypeId);
+        }
+        return chargeTimeTypeEnum;
+    }
+
+    public static EnumOptionData getChargeAmountTypeEnum(final String 
chargeAmountType) {
+        EnumOptionData chargeAmountTypeEnum = null;
+        if (chargeAmountType != null) {
+            String chargeAmountTypeId = "";
+            if (chargeAmountType.equalsIgnoreCase("Flat")) {
+                chargeAmountTypeId = "1";
+            } else if (chargeAmountType.equalsIgnoreCase("% Amount")) {
+                chargeAmountTypeId = "2";
+            } else {
+                chargeAmountTypeId = chargeAmountType;
+            }
+            chargeAmountTypeEnum = new EnumOptionData(null, null, 
chargeAmountTypeId);
+        }
+        return chargeAmountTypeEnum;
+    }
+
     public static String getCodeByName(Sheet sheet, String name) {
         String sheetName = sheet.getSheetName();
         if 
(sheetName.equals(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME)) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
index 654fa17..8c92ade 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
@@ -45,6 +45,7 @@ import 
org.apache.fineract.portfolio.loanaccount.data.LoanApprovalData;
 import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
 import 
org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
 import 
org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.IndexedColors;
@@ -174,19 +175,21 @@ public class LoanImportHandler implements ImportHandler {
                 repaidEveryFrequencyId = "1";
             } else if (repaidEveryFrequency.equalsIgnoreCase("Months")) {
                 repaidEveryFrequencyId = "2";
+            } else if (repaidEveryFrequency.equalsIgnoreCase("Semi Month")) {
+                repaidEveryFrequencyId = "5";
             }
             repaidEveryFrequencyEnums = new EnumOptionData(null, null, 
repaidEveryFrequencyId);
         }
         Integer loanTerm = 
ImportHandlerUtils.readAsInt(LoanConstants.LOAN_TERM_COL, row);
-        String loanTermFrequency = 
ImportHandlerUtils.readAsString(LoanConstants.LOAN_TERM_FREQUENCY_COL, row);
+        String loanTermFrequencyType = 
ImportHandlerUtils.readAsString(LoanConstants.LOAN_TERM_FREQUENCY_COL, row);
         EnumOptionData loanTermFrequencyEnum = null;
-        if (loanTermFrequency != null) {
+        if (loanTermFrequencyType != null) {
             String loanTermFrequencyId = "";
-            if (loanTermFrequency.equalsIgnoreCase("Days")) {
+            if (loanTermFrequencyType.equalsIgnoreCase("Days")) {
                 loanTermFrequencyId = "0";
-            } else if (loanTermFrequency.equalsIgnoreCase("Weeks")) {
+            } else if (loanTermFrequencyType.equalsIgnoreCase("Weeks")) {
                 loanTermFrequencyId = "1";
-            } else if (loanTermFrequency.equalsIgnoreCase("Months")) {
+            } else if (loanTermFrequencyType.equalsIgnoreCase("Months")) {
                 loanTermFrequencyId = "2";
             }
             loanTermFrequencyEnum = new EnumOptionData(null, null, 
loanTermFrequencyId);
@@ -269,8 +272,19 @@ public class LoanImportHandler implements ImportHandler {
 
         List<LoanChargeData> charges = new ArrayList<>();
 
-        Long charge1 = 
ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_1, row);
-        Long charge2 = 
ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_2, row);
+        String chargeOneName = 
ImportHandlerUtils.readAsString(LoanConstants.CHARGE_NAME_1, row);
+        String chargeTwoName = 
ImportHandlerUtils.readAsString(LoanConstants.CHARGE_NAME_2, row);
+
+        Long chargeOneId = null;
+        if (chargeOneName != null) {
+            chargeOneId = 
ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CHARGE_SHEET_NAME),
+                    chargeOneName);
+        }
+        Long chargeTwoId = null;
+        if (chargeTwoName != null) {
+            chargeTwoId = 
ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CHARGE_SHEET_NAME),
+                    chargeTwoName);
+        }
 
         Long collateralId = 
ImportHandlerUtils.readAsLong(LoanConstants.LOAN_COLLATERAL_ID, row);
 
@@ -278,25 +292,47 @@ public class LoanImportHandler implements ImportHandler {
 
         String linkAccountId = 
ImportHandlerUtils.readAsString(LoanConstants.LINK_ACCOUNT_ID, row);
 
-        if (charge1 != null) {
+        if (chargeOneId != null) {
             if (ImportHandlerUtils.readAsDouble(LoanConstants.CHARGE_AMOUNT_1, 
row) != null) {
-                charges.add(new 
LoanChargeData(ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_1, row),
-                        
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_1, row),
-                        
BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanConstants.CHARGE_AMOUNT_1,
 row))));
+                EnumOptionData chargeOneTimeTypeEnum = ImportHandlerUtils
+                        
.getChargeTimeTypeEmun(workbook.getSheet(TemplatePopulateImportConstants.CHARGE_SHEET_NAME),
 chargeOneName);
+                EnumOptionData chargeOneAmountTypeEnum = ImportHandlerUtils
+                        
.getChargeAmountTypeEnum(ImportHandlerUtils.readAsString(LoanConstants.CHARGE_AMOUNT_TYPE_1,
 row));
+
+                BigDecimal chargeAmount;
+                BigDecimal amountOrPercentage = 
BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanConstants.CHARGE_AMOUNT_1,
 row));
+                if (chargeOneAmountTypeEnum.getValue().equalsIgnoreCase("1")) {
+                    chargeAmount = amountOrPercentage;
+                } else {
+                    chargeAmount = LoanCharge.percentageOf(principal, 
amountOrPercentage);
+                }
+
+                charges.add(new LoanChargeData(chargeOneId, 
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_1, row),
+                        chargeAmount, chargeOneAmountTypeEnum, 
chargeOneTimeTypeEnum));
             } else {
-                charges.add(new 
LoanChargeData(ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_1, row),
-                        
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_1, row), null));
+                charges.add(new LoanChargeData(chargeOneId, 
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_1, row), null));
             }
         }
 
-        if (charge2 != null) {
+        if (chargeTwoId != null) {
             if (ImportHandlerUtils.readAsDouble(LoanConstants.CHARGE_AMOUNT_2, 
row) != null) {
-                charges.add(new 
LoanChargeData(ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_2, row),
-                        
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_2, row),
-                        
BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanConstants.CHARGE_AMOUNT_2,
 row))));
+                EnumOptionData chargeTwoTimeTypeEnum = ImportHandlerUtils
+                        
.getChargeTimeTypeEmun(workbook.getSheet(TemplatePopulateImportConstants.CHARGE_SHEET_NAME),
 chargeTwoName);
+                EnumOptionData chargeTwoAmountTypeEnum = ImportHandlerUtils
+                        
.getChargeAmountTypeEnum(ImportHandlerUtils.readAsString(LoanConstants.CHARGE_AMOUNT_TYPE_2,
 row));
+
+                BigDecimal chargeAmount;
+                BigDecimal amountOrPercentage = 
BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanConstants.CHARGE_AMOUNT_2,
 row));
+                if (chargeTwoTimeTypeEnum.getValue().equalsIgnoreCase("1")) {
+                    chargeAmount = amountOrPercentage;
+                } else {
+                    chargeAmount = LoanCharge.percentageOf(principal, 
amountOrPercentage);
+                }
+
+                charges.add(new LoanChargeData(chargeTwoId, 
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_2, row),
+                        chargeAmount, chargeTwoAmountTypeEnum, 
chargeTwoTimeTypeEnum));
             } else {
-                charges.add(new 
LoanChargeData(ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_2, row),
-                        
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_2, row), null));
+                charges.add(new LoanChargeData(chargeTwoId, 
ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_2, row), null));
             }
         }
 
@@ -313,6 +349,7 @@ public class LoanImportHandler implements ImportHandler {
         }
 
         statuses.add(status);
+
         if (loanType != null) {
             if (loanType.equals("individual")) {
                 Long clientId = 
ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME),
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ChargeSheetPopulator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ChargeSheetPopulator.java
new file mode 100644
index 0000000..f3ef216
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ChargeSheetPopulator.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.infrastructure.bulkimport.populator;
+
+import java.util.List;
+import org.apache.fineract.infrastructure.bulkimport.constants.ChargeConstants;
+import 
org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.portfolio.charge.data.ChargeData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+public class ChargeSheetPopulator extends AbstractWorkbookPopulator {
+
+    private List<ChargeData> charges;
+
+    private static final int ID_COL = 0;
+
+    public ChargeSheetPopulator(final List<ChargeData> charges) {
+        this.charges = charges;
+    }
+
+    @Override
+    public void populate(final Workbook workbook, String dateFormat) {
+        int rowIndex = 1;
+        Sheet chargeSheet = 
workbook.createSheet(TemplatePopulateImportConstants.CHARGE_SHEET_NAME);
+        setLayout(chargeSheet);
+
+        populateCharges(chargeSheet, rowIndex);
+        chargeSheet.protectSheet("");
+    }
+
+    private void populateCharges(Sheet chargeSheet, int rowIndex) {
+        for (ChargeData charge : charges) {
+            Row row = chargeSheet.createRow(rowIndex);
+            writeLong(ID_COL, row, charge.getId());
+            writeString(ChargeConstants.CHARGE_NAME_COL, row, 
charge.getName().trim().replaceAll("[ )(]", "_"));
+            writeBigDecimal(ChargeConstants.CHARGE_AMOUNT_COL, row, 
charge.getAmount());
+            writeString(ChargeConstants.CHARGE_CALCULATION_TYPE_COL, row, 
charge.getChargeCalculationType().getValue());
+            writeString(ChargeConstants.CHARGE_TIME_TYPE_COL, row, 
charge.getChargeTimeType().getValue());
+            rowIndex++;
+        }
+    }
+
+    private void setLayout(Sheet worksheet) {
+        worksheet.setColumnWidth(ID_COL, 
TemplatePopulateImportConstants.SMALL_COL_SIZE);
+        worksheet.setColumnWidth(ChargeConstants.CHARGE_NAME_COL, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        worksheet.setColumnWidth(ChargeConstants.CHARGE_AMOUNT_COL, 
TemplatePopulateImportConstants.SMALL_COL_SIZE);
+        worksheet.setColumnWidth(ChargeConstants.CHARGE_CALCULATION_TYPE_COL, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        worksheet.setColumnWidth(ChargeConstants.CHARGE_TIME_TYPE_COL, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+
+        Row rowHeader = 
worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+        rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+
+        writeString(ID_COL, rowHeader, "ID");
+        writeString(ChargeConstants.CHARGE_NAME_COL, rowHeader, "Name");
+        writeString(ChargeConstants.CHARGE_AMOUNT_COL, rowHeader, "Charge 
Amount");
+        writeString(ChargeConstants.CHARGE_CALCULATION_TYPE_COL, rowHeader, 
"Charge Calculation Type");
+        writeString(ChargeConstants.CHARGE_TIME_TYPE_COL, rowHeader, "Charge 
Time Type");
+    }
+
+    public Integer getChargesSize() {
+        return charges.size();
+    }
+
+    public List<ChargeData> getCharges() {
+        return charges;
+    }
+
+}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/LoanProductSheetPopulator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/LoanProductSheetPopulator.java
index 894fe4a..465fb29 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/LoanProductSheetPopulator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/LoanProductSheetPopulator.java
@@ -86,7 +86,12 @@ public class LoanProductSheetPopulator extends 
AbstractWorkbookPopulator {
             } else {
                 writeInt(MAX_PRINCIPAL_COL, row, 999999999);
             }
-            writeInt(NO_OF_REPAYMENTS_COL, row, 
product.getNumberOfRepayments());
+            int numberOfRepayments = product.getNumberOfRepayments();
+            if 
(product.getRepaymentFrequencyType().getValue().equalsIgnoreCase("Semi Month")) 
{
+                numberOfRepayments = numberOfRepayments * 
product.getRepaymentEvery();
+            }
+
+            writeInt(NO_OF_REPAYMENTS_COL, row, numberOfRepayments);
             if (product.getMinNumberOfRepayments() != null) {
                 writeInt(MIN_REPAYMENTS_COL, row, 
product.getMinNumberOfRepayments());
             } else {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/charge/ChargeWorkbookPopulator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/charge/ChargeWorkbookPopulator.java
new file mode 100644
index 0000000..53fe915
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/charge/ChargeWorkbookPopulator.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.infrastructure.bulkimport.populator.charge;
+
+import org.apache.fineract.infrastructure.bulkimport.constants.ChargeConstants;
+import 
org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import 
org.apache.fineract.infrastructure.bulkimport.populator.AbstractWorkbookPopulator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+public class ChargeWorkbookPopulator extends AbstractWorkbookPopulator {
+
+    public ChargeWorkbookPopulator() {
+        //
+    }
+
+    @Override
+    public void populate(Workbook workbook, String dateFormat) {
+        Sheet chargeSheet = 
workbook.createSheet(TemplatePopulateImportConstants.CHARGE_SHEET_NAME);
+        setLayout(chargeSheet);
+        // setRules(chargeSheet, dateFormat);
+    }
+
+    private void setLayout(final Sheet worksheet) {
+        Row rowHeader = 
worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+        worksheet.setColumnWidth(0, 
TemplatePopulateImportConstants.SMALL_COL_SIZE);
+        worksheet.setColumnWidth(ChargeConstants.CHARGE_NAME_COL, 
TemplatePopulateImportConstants.SMALL_COL_SIZE);
+        worksheet.setColumnWidth(ChargeConstants.CHARGE_AMOUNT_COL, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        worksheet.setColumnWidth(ChargeConstants.CHARGE_CALCULATION_TYPE_COL, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        // worksheet.setColumnWidth(ChargeConstants.CHARGE_DUE_DATE_COL,
+        // TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        worksheet.setColumnWidth(ChargeConstants.CHARGE_TIME_TYPE_COL, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+
+        writeString(0, rowHeader, "ID");
+        writeString(ChargeConstants.CHARGE_NAME_COL, rowHeader, "Charge 
Name*");
+        writeString(ChargeConstants.CHARGE_AMOUNT_COL, rowHeader, "Charge 
Amount*");
+        writeString(ChargeConstants.CHARGE_CALCULATION_TYPE_COL, rowHeader, 
"Charge Calculation Type*");
+        // writeString(ChargeConstants.CHARGE_DUE_DATE_COL, rowHeader, "Charge 
Due Date*");
+        writeString(ChargeConstants.CHARGE_TIME_TYPE_COL, rowHeader, "Charge 
Time Type*");
+    }
+
+    @SuppressWarnings("unused")
+    private void setRules(Sheet workSheet, final String dateFormat) {
+        // CellRangeAddressList dueDateRange = new CellRangeAddressList(1, 
SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+        // ChargeConstants.CHARGE_DUE_DATE_COL, 
ChargeConstants.CHARGE_DUE_DATE_COL);
+
+        // DataValidationHelper validationHelper = new 
HSSFDataValidationHelper((HSSFSheet) workSheet);
+
+        // DataValidationConstraint dueDateConstraint = validationHelper
+        // 
.createDateConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL, 
"=TODAY()", null, dateFormat);
+
+        // DataValidation dueDateValidation = 
validationHelper.createValidation(dueDateConstraint, dueDateRange);
+
+        // workSheet.addValidationData(dueDateValidation);
+    }
+
+}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/loan/LoanWorkbookPopulator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/loan/LoanWorkbookPopulator.java
index b78c133..a125750 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/loan/LoanWorkbookPopulator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/loan/LoanWorkbookPopulator.java
@@ -22,12 +22,14 @@ import java.util.List;
 import org.apache.fineract.infrastructure.bulkimport.constants.LoanConstants;
 import 
org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.AbstractWorkbookPopulator;
+import 
org.apache.fineract.infrastructure.bulkimport.populator.ChargeSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.ClientSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.ExtrasSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.GroupSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.LoanProductSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.OfficeSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.PersonnelSheetPopulator;
+import org.apache.fineract.portfolio.charge.data.ChargeData;
 import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
 import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
 import org.apache.poi.hssf.usermodel.HSSFSheet;
@@ -46,22 +48,25 @@ import org.apache.poi.ss.util.CellRangeAddressList;
 
 public class LoanWorkbookPopulator extends AbstractWorkbookPopulator {
 
-    private final OfficeSheetPopulator officeSheetPopulator;
-    private final ClientSheetPopulator clientSheetPopulator;
-    private final GroupSheetPopulator groupSheetPopulator;
-    private final PersonnelSheetPopulator personnelSheetPopulator;
-    private final LoanProductSheetPopulator productSheetPopulator;
-    private final ExtrasSheetPopulator extrasSheetPopulator;
+    private OfficeSheetPopulator officeSheetPopulator;
+    private ClientSheetPopulator clientSheetPopulator;
+    private GroupSheetPopulator groupSheetPopulator;
+    private PersonnelSheetPopulator personnelSheetPopulator;
+    private LoanProductSheetPopulator productSheetPopulator;
+    private ChargeSheetPopulator chargeSheetPopulator;
+    private ExtrasSheetPopulator extrasSheetPopulator;
 
     public LoanWorkbookPopulator(OfficeSheetPopulator officeSheetPopulator, 
ClientSheetPopulator clientSheetPopulator,
             GroupSheetPopulator groupSheetPopulator, PersonnelSheetPopulator 
personnelSheetPopulator,
-            LoanProductSheetPopulator productSheetPopulator, 
ExtrasSheetPopulator extrasSheetPopulator) {
+            LoanProductSheetPopulator productSheetPopulator, 
ChargeSheetPopulator chargeSheetPopulator,
+            ExtrasSheetPopulator extrasSheetPopulator) {
         this.officeSheetPopulator = officeSheetPopulator;
         this.clientSheetPopulator = clientSheetPopulator;
         this.groupSheetPopulator = groupSheetPopulator;
         this.personnelSheetPopulator = personnelSheetPopulator;
         this.productSheetPopulator = productSheetPopulator;
         this.extrasSheetPopulator = extrasSheetPopulator;
+        this.chargeSheetPopulator = chargeSheetPopulator;
     }
 
     @Override
@@ -72,6 +77,7 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
         groupSheetPopulator.populate(workbook, dateFormat);
         personnelSheetPopulator.populate(workbook, dateFormat);
         productSheetPopulator.populate(workbook, dateFormat);
+        chargeSheetPopulator.populate(workbook, dateFormat);
         extrasSheetPopulator.populate(workbook, dateFormat);
         setLayout(loanSheet);
         setRules(loanSheet, dateFormat);
@@ -138,6 +144,16 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
                 LoanConstants.LAST_REPAYMENT_DATE_COL, 
LoanConstants.LAST_REPAYMENT_DATE_COL);
         DataValidationHelper validationHelper = new 
HSSFDataValidationHelper((HSSFSheet) worksheet);
 
+        CellRangeAddressList chargeOneNameRange = new CellRangeAddressList(1, 
SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+                LoanConstants.CHARGE_NAME_1, LoanConstants.CHARGE_NAME_1);
+        CellRangeAddressList chargeOneAmountTypeRange = new 
CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+                LoanConstants.CHARGE_AMOUNT_TYPE_1, 
LoanConstants.CHARGE_AMOUNT_TYPE_1);
+
+        CellRangeAddressList chargeTwoNameRange = new CellRangeAddressList(1, 
SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+                LoanConstants.CHARGE_NAME_2, LoanConstants.CHARGE_NAME_2);
+        CellRangeAddressList chargeTwoAmountTypeRange = new 
CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+                LoanConstants.CHARGE_AMOUNT_TYPE_2, 
LoanConstants.CHARGE_AMOUNT_TYPE_2);
+
         setNames(worksheet);
 
         DataValidationConstraint officeNameConstraint = 
validationHelper.createFormulaListConstraint("Office");
@@ -168,9 +184,11 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
                 DataValidationConstraint.OperatorType.BETWEEN, 
"=INDIRECT(CONCATENATE(\"MIN_REPAYMENT_\",$E1))",
                 "=INDIRECT(CONCATENATE(\"MAX_REPAYMENT_\",$E1))");
         DataValidationConstraint frequencyConstraint = validationHelper
+                .createExplicitListConstraint(new String[] { "Days", "Weeks", 
"Months", "Semi Month" });
+        DataValidationConstraint loanTermFrequencyConstraint = validationHelper
                 .createExplicitListConstraint(new String[] { "Days", "Weeks", 
"Months" });
         DataValidationConstraint loanTermConstraint = validationHelper
-                
.createIntegerConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL,
 "=$M1*$N1", null);
+                
.createIntegerConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL,
 "=$M1/$N1", "=$M1*$N1");
         DataValidationConstraint interestFrequencyConstraint = validationHelper
                 
.createFormulaListConstraint("INDIRECT(CONCATENATE(\"INTEREST_FREQUENCY_\",$E1))");
         DataValidationConstraint interestConstraint = 
validationHelper.createDecimalConstraint(
@@ -196,6 +214,14 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
         DataValidationConstraint lastRepaymentDateConstraint = validationHelper
                 
.createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN, "=$I1", 
"=TODAY()", dateFormat);
 
+        DataValidationConstraint chargeOneNameConstraint = 
validationHelper.createFormulaListConstraint("Charges");
+        DataValidationConstraint chargeOneAmountTypeConstraint = 
validationHelper
+                .createExplicitListConstraint(new String[] { "Flat", "% 
Amount" });
+
+        DataValidationConstraint chargeTwoNameConstraint = 
validationHelper.createFormulaListConstraint("Charges");
+        DataValidationConstraint chargeTwoAmountTypeConstraint = 
validationHelper
+                .createExplicitListConstraint(new String[] { "Flat", "% 
Amount" });
+
         DataValidation officeValidation = 
validationHelper.createValidation(officeNameConstraint, officeNameRange);
         DataValidation loanTypeValidation = 
validationHelper.createValidation(loanTypeConstraint, loanTypeRange);
         DataValidation clientValidation = 
validationHelper.createValidation(clientNameConstraint, clientNameRange);
@@ -203,7 +229,7 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
         DataValidation loanOfficerValidation = 
validationHelper.createValidation(loanOfficerNameConstraint, loanOfficerRange);
         DataValidation fundNameValidation = 
validationHelper.createValidation(fundNameConstraint, fundNameRange);
         DataValidation repaidFrequencyValidation = 
validationHelper.createValidation(frequencyConstraint, repaidFrequencyRange);
-        DataValidation loanTermFrequencyValidation = 
validationHelper.createValidation(frequencyConstraint, loanTermFrequencyRange);
+        DataValidation loanTermFrequencyValidation = 
validationHelper.createValidation(loanTermFrequencyConstraint, 
loanTermFrequencyRange);
         DataValidation amortizationValidation = 
validationHelper.createValidation(amortizationConstraint, amortizationRange);
         DataValidation interestMethodValidation = 
validationHelper.createValidation(interestMethodConstraint, 
interestMethodRange);
         DataValidation interestCalculationPeriodValidation = 
validationHelper.createValidation(interestCalculationPeriodConstraint,
@@ -228,6 +254,14 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
                 graceOnInterestChargedRange);
         DataValidation interestFrequencyValidation = 
validationHelper.createValidation(interestFrequencyConstraint, 
interestFrequencyRange);
 
+        DataValidation chargeOneNameValidation = 
validationHelper.createValidation(chargeOneNameConstraint, chargeOneNameRange);
+        DataValidation chargeOneAmountTypeValidation = 
validationHelper.createValidation(chargeOneAmountTypeConstraint,
+                chargeOneAmountTypeRange);
+
+        DataValidation chargeTwoNameValidation = 
validationHelper.createValidation(chargeTwoNameConstraint, chargeTwoNameRange);
+        DataValidation chargeTwoAmountTypeValidation = 
validationHelper.createValidation(chargeTwoAmountTypeConstraint,
+                chargeTwoAmountTypeRange);
+
         interestFrequencyValidation.setSuppressDropDownArrow(true);
 
         worksheet.addValidationData(officeValidation);
@@ -258,6 +292,14 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
         worksheet.addValidationData(lastRepaymentDateValidation);
         worksheet.addValidationData(repaymentTypeValidation);
 
+        worksheet.addValidationData(chargeOneNameValidation);
+        // worksheet.addValidationData(chargeOneAmountValidation);
+        worksheet.addValidationData(chargeOneAmountTypeValidation);
+
+        worksheet.addValidationData(chargeTwoNameValidation);
+        // worksheet.addValidationData(chargeTwoAmountValidation);
+        worksheet.addValidationData(chargeTwoAmountTypeValidation);
+
     }
 
     private void setLayout(Sheet worksheet) {
@@ -299,11 +341,13 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
         worksheet.setColumnWidth(LoanConstants.LOOKUP_CLIENT_EXTERNAL_ID, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
         worksheet.setColumnWidth(LoanConstants.LOOKUP_ACTIVATION_DATE_COL, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
         worksheet.setColumnWidth(LoanConstants.EXTERNAL_ID_COL, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
-        worksheet.setColumnWidth(LoanConstants.CHARGE_ID_1, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        worksheet.setColumnWidth(LoanConstants.CHARGE_NAME_1, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
         worksheet.setColumnWidth(LoanConstants.CHARGE_AMOUNT_1, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        worksheet.setColumnWidth(LoanConstants.CHARGE_AMOUNT_TYPE_1, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
         worksheet.setColumnWidth(LoanConstants.CHARGE_DUE_DATE_1, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
-        worksheet.setColumnWidth(LoanConstants.CHARGE_ID_2, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        worksheet.setColumnWidth(LoanConstants.CHARGE_NAME_2, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
         worksheet.setColumnWidth(LoanConstants.CHARGE_AMOUNT_2, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+        worksheet.setColumnWidth(LoanConstants.CHARGE_AMOUNT_TYPE_2, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
         worksheet.setColumnWidth(LoanConstants.CHARGE_DUE_DATE_2, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
         worksheet.setColumnWidth(LoanConstants.GROUP_ID, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
         worksheet.setColumnWidth(LoanConstants.LINK_ACCOUNT_ID, 
TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
@@ -341,11 +385,13 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
         writeString(LoanConstants.LOOKUP_CLIENT_EXTERNAL_ID, rowHeader, 
"Lookup Client ExternalID");
         writeString(LoanConstants.LOOKUP_ACTIVATION_DATE_COL, rowHeader, 
"Client Activation Date");
         writeString(LoanConstants.EXTERNAL_ID_COL, rowHeader, "External Id");
-        writeString(LoanConstants.CHARGE_ID_1, rowHeader, "Charge Id");
+        writeString(LoanConstants.CHARGE_NAME_1, rowHeader, "Charge Name*");
         writeString(LoanConstants.CHARGE_AMOUNT_1, rowHeader, "Charged 
Amount");
+        writeString(LoanConstants.CHARGE_AMOUNT_TYPE_1, rowHeader, "Charged 
Amount Type");
         writeString(LoanConstants.CHARGE_DUE_DATE_1, rowHeader, "Charged On 
Date");
-        writeString(LoanConstants.CHARGE_ID_2, rowHeader, "Charge Id");
+        writeString(LoanConstants.CHARGE_NAME_2, rowHeader, "Charge Name*");
         writeString(LoanConstants.CHARGE_AMOUNT_2, rowHeader, "Charged 
Amount");
+        writeString(LoanConstants.CHARGE_AMOUNT_TYPE_2, rowHeader, "Charged 
Amount Type");
         writeString(LoanConstants.CHARGE_DUE_DATE_2, rowHeader, "Charged On 
Date");
         writeString(LoanConstants.GROUP_ID, rowHeader, "GROUP ID");
         writeString(LoanConstants.LINK_ACCOUNT_ID, rowHeader, "Linked Account 
No.");
@@ -385,8 +431,11 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
             writeFormula(LoanConstants.NO_OF_REPAYMENTS_COL, row, 
"IF(ISERROR(INDIRECT(CONCATENATE(\"NO_REPAYMENT_\",$E" + (rowNo + 1)
                     + "))),\"\",INDIRECT(CONCATENATE(\"NO_REPAYMENT_\",$E" + 
(rowNo + 1) + ")))");
             writeFormula(LoanConstants.LOAN_TERM_COL, row,
-                    "IF(ISERROR($M" + (rowNo + 1) + "*$N" + (rowNo + 1) + 
"),\"\",$M" + (rowNo + 1) + "*$N" + (rowNo + 1) + ")");
-            writeFormula(LoanConstants.LOAN_TERM_FREQUENCY_COL, row, "$O" + 
(rowNo + 1));
+                    "IF(($O" + (rowNo + 1) + "=\"Semi Month\"), " + 
"(IF(ISERROR($M" + (rowNo + 1) + "/$N" + (rowNo + 1) + "),\"\",$M"
+                            + (rowNo + 1) + "/$N" + (rowNo + 1) + ")), " + 
"(IF(ISERROR($M" + (rowNo + 1) + "*$N" + (rowNo + 1)
+                            + "),\"\",$M" + (rowNo + 1) + "*$N" + (rowNo + 1) 
+ "))" + ")");
+            writeFormula(LoanConstants.LOAN_TERM_FREQUENCY_COL, row,
+                    "IF(($O" + (rowNo + 1) + "=\"Semi Month\"), \"Months\", 
$O" + (rowNo + 1) + ")");
             writeFormula(LoanConstants.NOMINAL_INTEREST_RATE_FREQUENCY_COL, 
row,
                     
"IF(ISERROR(INDIRECT(CONCATENATE(\"INTEREST_FREQUENCY_\",$E" + (rowNo + 1)
                             + 
"))),\"\",INDIRECT(CONCATENATE(\"INTEREST_FREQUENCY_\",$E" + (rowNo + 1) + 
")))");
@@ -408,13 +457,13 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
                     + (rowNo + 1) + 
"))),\"\",INDIRECT(CONCATENATE(\"GRACE_INTEREST_PAYMENT_\",$E" + (rowNo + 1) + 
")))");
             writeFormula(LoanConstants.GRACE_ON_INTEREST_CHARGED_COL, row, 
"IF(ISERROR(INDIRECT(CONCATENATE(\"GRACE_INTEREST_CHARGED_\",$E"
                     + (rowNo + 1) + 
"))),\"\",INDIRECT(CONCATENATE(\"GRACE_INTEREST_CHARGED_\",$E" + (rowNo + 1) + 
")))");
-
         }
     }
 
     private void setNames(Sheet worksheet) {
         Workbook loanWorkbook = worksheet.getWorkbook();
         List<String> officeNames = officeSheetPopulator.getOfficeNames();
+        List<ChargeData> charges = chargeSheetPopulator.getCharges();
         List<LoanProductData> products = productSheetPopulator.getProducts();
 
         // Office Names
@@ -460,6 +509,31 @@ public class LoanWorkbookPopulator extends 
AbstractWorkbookPopulator {
         fundGroup.setRefersToFormula(
                 TemplatePopulateImportConstants.EXTRAS_SHEET_NAME + 
"!$B$2:$B$" + (extrasSheetPopulator.getFundsSize() + 1));
 
+        // Charge Name
+        Name chargeGroup = loanWorkbook.createName();
+        chargeGroup.setNameName("Charges");
+        chargeGroup.setRefersToFormula(
+                TemplatePopulateImportConstants.CHARGE_SHEET_NAME + 
"!$B$2:$B$" + (chargeSheetPopulator.getChargesSize() + 1));
+
+        // Default Charge Name, Charge Amount, Charge Amount Type, Charge Due 
Date
+        for (Integer i = 0; i < charges.size(); i++) {
+            Name chargeColName = loanWorkbook.createName();
+            Name chargeAmount = loanWorkbook.createName();
+            Name chargeAmountType = loanWorkbook.createName();
+
+            String chargeName = charges.get(i).getName().trim().replaceAll("[ 
)(]", "_");
+
+            chargeColName.setNameName("CHARGE_NAME_" + chargeName);
+            
chargeColName.setRefersToFormula(TemplatePopulateImportConstants.CHARGE_SHEET_NAME
 + "!$B$" + (i + 2));
+
+            chargeAmount.setNameName("CHARGE_AMOUNT_" + chargeName);
+            
chargeAmount.setRefersToFormula(TemplatePopulateImportConstants.CHARGE_SHEET_NAME
 + "!$C$" + (i + 2));
+
+            chargeAmountType.setNameName("CHARGE_AMOUNT_TYPE_" + chargeName);
+            
chargeAmountType.setRefersToFormula(TemplatePopulateImportConstants.CHARGE_SHEET_NAME
 + "!$D$" + (i + 2));
+
+        }
+
         // Payment Type Name
         Name paymentTypeGroup = loanWorkbook.createName();
         paymentTypeGroup.setNameName("PaymentTypes");
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportWorkbookPopulatorServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportWorkbookPopulatorServiceImpl.java
index 34b451c..4d0a59d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportWorkbookPopulatorServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportWorkbookPopulatorServiceImpl.java
@@ -29,6 +29,7 @@ import 
org.apache.fineract.accounting.glaccount.service.GLAccountReadPlatformSer
 import 
org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
 import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.CenterSheetPopulator;
+import 
org.apache.fineract.infrastructure.bulkimport.populator.ChargeSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.ClientSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.ExtrasSheetPopulator;
 import 
org.apache.fineract.infrastructure.bulkimport.populator.FixedDepositProductSheetPopulator;
@@ -278,6 +279,11 @@ public class BulkImportWorkbookPopulatorServiceImpl 
implements BulkImportWorkboo
     }
 
     @SuppressWarnings("unchecked")
+    private List<ChargeData> fetchCharges() {
+        return (List) this.chargeReadPlatformService.retrieveAllCharges();
+    }
+
+    @SuppressWarnings("unchecked")
     private List<StaffData> fetchStaff(final Long staffId) {
         List<StaffData> staff = null;
         if (staffId == null) {
@@ -376,13 +382,15 @@ public class BulkImportWorkbookPopulatorServiceImpl 
implements BulkImportWorkboo
         List<StaffData> staff = fetchStaff(staffId);
         List<ClientData> clients = fetchClients(officeId);
         List<GroupGeneralData> groups = fetchGroups(officeId);
+        List<ChargeData> charges = fetchCharges();
         List<LoanProductData> loanproducts = fetchLoanProducts();
         List<FundData> funds = fetchFunds();
         List<PaymentTypeData> paymentTypes = fetchPaymentTypes();
         List<CurrencyData> currencies = fetchCurrencies();
         return new LoanWorkbookPopulator(new OfficeSheetPopulator(offices), 
new ClientSheetPopulator(clients, offices),
                 new GroupSheetPopulator(groups, offices), new 
PersonnelSheetPopulator(staff, offices),
-                new LoanProductSheetPopulator(loanproducts), new 
ExtrasSheetPopulator(funds, paymentTypes, currencies));
+                new LoanProductSheetPopulator(loanproducts), new 
ChargeSheetPopulator(charges),
+                new ExtrasSheetPopulator(funds, paymentTypes, currencies));
     }
 
     private List<CurrencyData> fetchCurrencies() {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
index dd77d5f..230b6d5 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java
@@ -321,6 +321,18 @@ public final class ChargeData implements 
Comparable<ChargeData>, Serializable {
         return name;
     }
 
+    public EnumOptionData getChargeCalculationType() {
+        return chargeCalculationType;
+    }
+
+    public EnumOptionData getChargeTimeType() {
+        return chargeTimeType;
+    }
+
+    public BigDecimal getAmount() {
+        return this.amount;
+    }
+
     public CurrencyData getCurrency() {
         return currency;
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanChargeData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanChargeData.java
index 55663c7..d29a906 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanChargeData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanChargeData.java
@@ -308,6 +308,37 @@ public class LoanChargeData {
         this.amountUnrecognized = chargeData.amountUnrecognized;
     }
 
+    public LoanChargeData(final Long id, final LocalDate dueAsOfDate, final 
BigDecimal amount, final EnumOptionData chargeCalculationType,
+            final EnumOptionData chargeTimeType) {
+        this.id = null;
+        this.chargeId = id;
+        this.name = null;
+        this.currency = null;
+        this.amount = amount;
+        this.amountPaid = null;
+        this.amountWaived = null;
+        this.amountWrittenOff = null;
+        this.amountOutstanding = null;
+        this.chargeTimeType = chargeTimeType;
+        this.dueDate = dueAsOfDate;
+        this.chargeCalculationType = chargeCalculationType;
+        this.percentage = null;
+        this.amountPercentageAppliedTo = null;
+        this.penalty = false;
+        this.chargePaymentMode = null;
+        this.paid = false;
+        this.waived = false;
+        this.amountOrPercentage = null;
+        this.chargeOptions = null;
+        this.chargePayable = false;
+        this.loanId = null;
+        this.minCap = null;
+        this.maxCap = null;
+        this.installmentChargeData = null;
+        this.amountAccrued = null;
+        this.amountUnrecognized = null;
+    }
+
     public LoanChargeData(final Long id, final LocalDate dueAsOfDate, final 
BigDecimal amountOrPercentage) {
         this.id = id;
         this.chargeId = null;
@@ -370,6 +401,10 @@ public class LoanChargeData {
         return isInstalmentFee;
     }
 
+    public EnumOptionData getChargeCalculationType() {
+        return chargeCalculationType;
+    }
+
     public BigDecimal amountOrPercentage() {
         return this.amountOrPercentage;
     }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
index 1692f90..b8a93c1 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
@@ -47,6 +47,7 @@ import 
org.apache.fineract.integrationtests.common.OfficeDomain;
 import org.apache.fineract.integrationtests.common.OfficeHelper;
 import org.apache.fineract.integrationtests.common.PaymentTypeHelper;
 import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.charges.ChargesHelper;
 import org.apache.fineract.integrationtests.common.funds.FundsHelper;
 import org.apache.fineract.integrationtests.common.funds.FundsResourceHandler;
 import 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
@@ -66,6 +67,7 @@ public class LoanImportHandlerTest {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(LoanImportHandlerTest.class);
     private static final String CREATE_CLIENT_URL = 
"/fineract-provider/api/v1/clients?" + Utils.TENANT_IDENTIFIER;
+    private static final String CREATE_CHARGE_URL = 
"/fineract-provider/api/v1/charges?" + Utils.TENANT_IDENTIFIER;
     public static final String DATE_FORMAT = "dd MMMM yyyy";
 
     private ResponseSpecification responseSpec;
@@ -120,6 +122,14 @@ public class LoanImportHandlerTest {
         collateralHashMap.put("quantity", "1");
         collaterals.add(collateralHashMap);
 
+        final String disbursementChargeJsonString = 
ChargesHelper.getLoanDisbursementJSON();
+
+        final Integer disbursementChargeId = 
ChargesHelper.createCharges(this.requestSpec, this.responseSpec, 
disbursementChargeJsonString);
+
+        final JsonPath disbursementChargeJSON = 
JsonPath.from(disbursementChargeJsonString);
+
+        Assertions.assertNotNull(disbursementChargeId, "Could not create 
charge");
+
         // in order to populate helper sheets
         Integer outcome_group_creation = GroupHelper.createGroup(requestSpec, 
responseSpec, true);
         Assertions.assertNotNull(outcome_group_creation, "Could not create 
group");
@@ -200,6 +210,10 @@ public class LoanImportHandlerTest {
         
firstLoanRow.createCell(LoanConstants.REPAYMENT_TYPE_COL).setCellValue(paymentTypeName);
         
firstLoanRow.createCell(LoanConstants.LOAN_COLLATERAL_ID).setCellValue(collaterals.get(0).get("clientCollateralId").toString());
         
firstLoanRow.createCell(LoanConstants.LOAN_COLLATERAL_QUANTITY).setCellValue(collaterals.get(0).get("quantity").toString());
+        
firstLoanRow.createCell(LoanConstants.CHARGE_NAME_1).setCellValue(disbursementChargeJSON.getString("name"));
+        
firstLoanRow.createCell(LoanConstants.CHARGE_AMOUNT_1).setCellValue(disbursementChargeJSON.getFloat("amount"));
+        firstLoanRow.createCell(LoanConstants.CHARGE_AMOUNT_TYPE_1)
+                
.setCellValue(disbursementChargeJSON.getString("chargeCalculationType.value"));
 
         String currentdirectory = new File("").getAbsolutePath();
         File directory = new File(currentdirectory + File.separator + "src" + 
File.separator + "integrationTest" + File.separator

Reply via email to