diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 9a87171cc..c182e6588 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -3601,6 +3601,30 @@
+
+
+ self/clients/{clientId}/images
+ Upload client image (Data URI)
+
+
+
+
+
+
+ self/clients/{clientId}/images
+ Upload client image (Multi-part Form data)
+
+
+
+
+
+
+ self/clients/{clientId}/images
+
+
+
+ Delete client image
+
Loans
self/loans/template?templateType=individual
@@ -3667,10 +3691,26 @@
Savings
+ self/savingsaccounts/template?clientId={clientId}&productId={productId}
+
+ Retrieve Savings Application Template
+
+
+
+
+
+ self/savingsaccounts
+ Submit new Savings Application
+
+
+
+
+
+
self/savingsaccounts/{accountId}
Retrieve a Savings Account
-
+ Update Savings Account
@@ -3697,6 +3737,30 @@
+
+ Share Accounts
+ self/shareaccounts/template?clientId=?productId=?
+
+ Share Accounts Template
+
+
+
+
+
+
+ self/shareaccounts
+ Submit New Share Application
+
+
+
+
+
+
+ self/shareaccounts/{accountId}
+
+ Retrieve a Share Application/Account
+
+
Own Account Transfers
self/accounttransfers/template
@@ -3745,6 +3809,22 @@
+
+ Guarantor and Obligee details
+ self/loans/{loanId}/guarantors
+
+ Guarantors list
+
+
+
+
+
+ self/clients/{clientId}/obligeedetails
+
+ Obligee list
+
+
+
@@ -46695,6 +46775,100 @@ GET https://DomainName/api/v1/self/loans/{loanId}/charges/{chargeId}
+
+
+
+
+
Submit new savings application
+
+
+ Mandatory Fields
+ clientId, productId, submittedOnDate
+
+
+
+ Optional Fields
+ accountNo, externalId, fieldOfficerId
+
+
+
+ Inherited from Product (if not provided)
+ nominalAnnualInterestRate, interestCompoundingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, allowOverdraft, overdraftLimit, withHoldTax
+
+
+
+
+
+
Minimal request: accountNo auto generated, remaining details inherited from savings product.
+
POST https://Domain Name/api/v1/self/savingsaccounts
+
POST self/savingsaccount
+Content-Type: application/json
+Request Body:
+{
+ "productId":3,
+ "clientId":"14",
+ "locale":"en",
+ "dateFormat":"dd MMMM yyyy",
+ "submittedOnDate":"09 July 2018"
+}
+
+
+{
+ "officeId":1,
+ "clientId":14,
+ "savingsId":10,
+ "resourceId":10
+}
+
+
+
Full request:Below details override details from savings product (except currency).
+
POST self/savingsaccount
+Content-Type: application/json
+Request Body:
+{
+ "productId":1,
+ "nominalAnnualInterestRate":9.5,
+ "minRequiredOpeningBalance":1000,
+ "lockinPeriodFrequency":1,
+ "withdrawalFeeForTransfers":true,
+ "allowOverdraft":true,
+ "overdraftLimit":"10000",
+ "nominalAnnualInterestRateOverdraft":"5",
+ "minOverdraftForInterestCalculation":"1000",
+ "enforceMinRequiredBalance":false,
+ "withHoldTax":false,
+ "interestCompoundingPeriodType":1,
+ "interestPostingPeriodType":4,
+ "interestCalculationType":1,
+ "interestCalculationDaysInYearType":365,
+ "lockinPeriodFrequencyType":1,
+ "fieldOfficerId":1,
+ "externalId":"126",
+ "submittedOnDate":"11 July 2018",
+ "locale":"en",
+ "dateFormat":"dd MMMM yyyy",
+ "monthDayFormat":"dd MMM",
+ "charges":[
+ {
+ "chargeId":3,
+ "amount":2
+ }
+ ],
+ "clientId":"14"
+}
+
+
+{
+ "officeId":1,
+ "clientId":14,
+ "savingsId":9,
+ "resourceId":9
+}
+
+
+
+
+
@@ -46785,6 +46959,364 @@ GET https://DomainName/api/v1/self/loans/{loanId}/charges/{chargeId}
+
+
+
+
+
Modify a savings application
+
Savings application can only be modified when in 'Submitted and pending approval' state. Once the application is approved, the details cannot be changed using this method. Specific api endpoints will be created to allow change of interest detail such as rate, compounding period, posting period etc
+
+
+ PUT https://Domain Name/api/v1/self/savingsaccounts/{accountsId}
+ PUT self/savingsaccounts/1
+Content-Type: application/json
+No Request Body:
+{
+ "productId":1,
+ "clientId":14
+}
+
+
+{
+ "officeId": 1,
+ "clientId": 14,
+ "savingsId": 11,
+ "resourceId": 11,
+ "changes": {
+ "productId": 1
+ }
+}
+
+
+
+
+
+
+
+
Retrieve Savings Account Template:
+
Arguments
+
+ clientId
+ Integer mandatory
+ productId
+ Integer optional
+ If entered, productId, productName and selectedProduct fields are returned.
+
+
Example Requests:
+
self/savingsaccounts/template?clientId=14
+
+
self/savingsaccounts/template?clientId=14&productId=2
+
+
+ GET https://Domain Name/api/v1/self/savingsaccounts/template?clientId={clientId}
+
+{
+ "clientId": 14,
+ "clientName": "Bheem",
+ "withdrawalFeeForTransfers": false,
+ "allowOverdraft": false,
+ "enforceMinRequiredBalance": false,
+ "withHoldTax": false,
+ "isDormancyTrackingActive": false,
+ "productOptions": [
+ {
+ "id": 1,
+ "name": "Voluntary savings",
+ "withdrawalFeeForTransfers": false,
+ "allowOverdraft": false,
+ "enforceMinRequiredBalance": false,
+ "withHoldTax": false
+ },
+ {
+ "id": 2,
+ "name": "Savings",
+ "withdrawalFeeForTransfers": false,
+ "allowOverdraft": false,
+ "enforceMinRequiredBalance": false,
+ "withHoldTax": false
+ },
+ {
+ "id": 3,
+ "name": "Savings Product",
+ "withdrawalFeeForTransfers": false,
+ "allowOverdraft": false,
+ "enforceMinRequiredBalance": false,
+ "withHoldTax": false
+ }
+ ],
+ "chargeOptions": [
+ {
+ "id": 3,
+ "name": "Saving Accounts Processing Fee",
+ "active": true,
+ "penalty": false,
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "amount": 2,
+ "chargeTimeType": {
+ "id": 3,
+ "code": "chargeTimeType.savingsActivation",
+ "value": "Savings Activation"
+ },
+ "chargeAppliesTo": {
+ "id": 2,
+ "code": "chargeAppliesTo.savings",
+ "value": "Savings"
+ },
+ "chargeCalculationType": {
+ "id": 1,
+ "code": "chargeCalculationType.flat",
+ "value": "Flat"
+ },
+ "chargePaymentMode": {
+ "id": 0,
+ "code": "chargepaymentmode.regular",
+ "value": "Regular"
+ }
+ }
+ ]
+}
+
+
+
+
+ GET https://Domain Name/api/v1/self/savingsaccounts/template?clientId={clientId}&productId={productId}
+
+{
+ "clientId": 14,
+ "clientName": "Bheem",
+ "savingsProductId": 2,
+ "savingsProductName": "Savings",
+ "timeline": {},
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "inMultiplesOf": 1,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "nominalAnnualInterestRate": 5,
+ "interestCompoundingPeriodType": {
+ "id": 1,
+ "code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
+ "value": "Daily"
+ },
+ "interestPostingPeriodType": {
+ "id": 4,
+ "code": "savings.interest.posting.period.savingsPostingInterestPeriodType.monthly",
+ "value": "Monthly"
+ },
+ "interestCalculationType": {
+ "id": 1,
+ "code": "savingsInterestCalculationType.dailybalance",
+ "value": "Daily Balance"
+ },
+ "interestCalculationDaysInYearType": {
+ "id": 365,
+ "code": "savingsInterestCalculationDaysInYearType.days365",
+ "value": "365 Days"
+ },
+ "minRequiredOpeningBalance": 1000,
+ "withdrawalFeeForTransfers": false,
+ "allowOverdraft": false,
+ "enforceMinRequiredBalance": false,
+ "withHoldTax": false,
+ "isDormancyTrackingActive": false,
+ "charges": [],
+ "productOptions": [
+ {
+ "id": 1,
+ "name": "Voluntary savings",
+ "withdrawalFeeForTransfers": false,
+ "allowOverdraft": false,
+ "enforceMinRequiredBalance": false,
+ "withHoldTax": false
+ },
+ {
+ "id": 2,
+ "name": "Savings",
+ "withdrawalFeeForTransfers": false,
+ "allowOverdraft": false,
+ "enforceMinRequiredBalance": false,
+ "withHoldTax": false
+ },
+ {
+ "id": 3,
+ "name": "Savings Product",
+ "withdrawalFeeForTransfers": false,
+ "allowOverdraft": false,
+ "enforceMinRequiredBalance": false,
+ "withHoldTax": false
+ }
+ ],
+ "fieldOfficerOptions": [
+ {
+ "id": 1,
+ "firstname": "Aliya",
+ "lastname": "A",
+ "displayName": "A, Aliya",
+ "officeId": 1,
+ "officeName": "Head Office",
+ "isLoanOfficer": true,
+ "isActive": true
+ }
+ ],
+ "interestCompoundingPeriodTypeOptions": [
+ {
+ "id": 1,
+ "code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily",
+ "value": "Daily"
+ },
+ {
+ "id": 4,
+ "code": "savings.interest.period.savingsCompoundingInterestPeriodType.monthly",
+ "value": "Monthly"
+ },
+ {
+ "id": 5,
+ "code": "savings.interest.period.savingsCompoundingInterestPeriodType.quarterly",
+ "value": "Quarterly"
+ },
+ {
+ "id": 6,
+ "code": "savings.interest.period.savingsCompoundingInterestPeriodType.biannual",
+ "value": "Semi-Annual"
+ },
+ {
+ "id": 7,
+ "code": "savings.interest.period.savingsCompoundingInterestPeriodType.annual",
+ "value": "Annually"
+ }
+ ],
+ "interestPostingPeriodTypeOptions": [
+ {
+ "id": 4,
+ "code": "savings.interest.posting.period.savingsPostingInterestPeriodType.monthly",
+ "value": "Monthly"
+ },
+ {
+ "id": 5,
+ "code": "savings.interest.posting.period.savingsPostingInterestPeriodType.quarterly",
+ "value": "Quarterly"
+ },
+ {
+ "id": 6,
+ "code": "savings.interest.posting.period.savingsPostingInterestPeriodType.biannual",
+ "value": "BiAnnual"
+ },
+ {
+ "id": 7,
+ "code": "savings.interest.posting.period.savingsPostingInterestPeriodType.annual",
+ "value": "Annually"
+ }
+ ],
+ "interestCalculationTypeOptions": [
+ {
+ "id": 1,
+ "code": "savingsInterestCalculationType.dailybalance",
+ "value": "Daily Balance"
+ },
+ {
+ "id": 2,
+ "code": "savingsInterestCalculationType.averagedailybalance",
+ "value": "Average Daily Balance"
+ }
+ ],
+ "interestCalculationDaysInYearTypeOptions": [
+ {
+ "id": 360,
+ "code": "savingsInterestCalculationDaysInYearType.days360",
+ "value": "360 Days"
+ },
+ {
+ "id": 365,
+ "code": "savingsInterestCalculationDaysInYearType.days365",
+ "value": "365 Days"
+ }
+ ],
+ "lockinPeriodFrequencyTypeOptions": [
+ {
+ "id": 0,
+ "code": "savings.lockin.savingsPeriodFrequencyType.days",
+ "value": "Days"
+ },
+ {
+ "id": 1,
+ "code": "savings.lockin.savingsPeriodFrequencyType.weeks",
+ "value": "Weeks"
+ },
+ {
+ "id": 2,
+ "code": "savings.lockin.savingsPeriodFrequencyType.months",
+ "value": "Months"
+ },
+ {
+ "id": 3,
+ "code": "savings.lockin.savingsPeriodFrequencyType.years",
+ "value": "Years"
+ }
+ ],
+ "withdrawalFeeTypeOptions": [
+ {
+ "id": 1,
+ "code": "savingsWithdrawalFeesType.flat",
+ "value": "Flat"
+ },
+ {
+ "id": 2,
+ "code": "savingsWithdrawalFeesType.percent.of.amount",
+ "value": "% of Amount"
+ }
+ ],
+ "chargeOptions": [
+ {
+ "id": 3,
+ "name": "Saving Accounts Processing Fee",
+ "active": true,
+ "penalty": false,
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "amount": 2,
+ "chargeTimeType": {
+ "id": 3,
+ "code": "chargeTimeType.savingsActivation",
+ "value": "Savings Activation"
+ },
+ "chargeAppliesTo": {
+ "id": 2,
+ "code": "chargeAppliesTo.savings",
+ "value": "Savings"
+ },
+ "chargeCalculationType": {
+ "id": 1,
+ "code": "chargeCalculationType.flat",
+ "value": "Flat"
+ },
+ "chargePaymentMode": {
+ "id": 0,
+ "code": "chargepaymentmode.regular",
+ "value": "Regular"
+ }
+ }
+ ]
+}
+
+
+
@@ -47487,6 +48019,1213 @@ No Request Body:
+
+
+
+
+
Retrieve Share Account Template:
+
This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:
+
+ Field Defaults
+ Allowed Value Lists
+
+
+
Arguments
+
+ clientId
+ Integer mandatory
+ productId
+ Integer optional
+ If entered, productId, productName and selectedProduct fields are returned.
+
+
Example Requests:
+
self/shareaccounts/template?clientId=14
+
+
self/shareaccounts/template?clientId=14&productId=3
+
+
+ GET https://Domain Name/api/v1/self/shareaccounts/template?clientId={clientId}
+
+{
+ "clientId": 14,
+ "productOptions": [
+ {
+ "id": 3,
+ "name": "SP",
+ "shortName": "SP",
+ "totalShares": 1000
+ },
+ {
+ "id": 4,
+ "name": "Product1",
+ "shortName": "test",
+ "totalShares": 1000
+ }
+ ],
+ "chargeOptions": [
+ {
+ "id": 2,
+ "name": "Activation fee",
+ "active": true,
+ "penalty": false,
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "amount": 2,
+ "chargeTimeType": {
+ "id": 14,
+ "code": "chargeTimeType.sharespurchase",
+ "value": "Share Purchase"
+ },
+ "chargeAppliesTo": {
+ "id": 4,
+ "code": "chargeAppliesTo.shares",
+ "value": "Shares"
+ },
+ "chargeCalculationType": {
+ "id": 1,
+ "code": "chargeCalculationType.flat",
+ "value": "Flat"
+ },
+ "chargePaymentMode": {
+ "id": 0,
+ "code": "chargepaymentmode.regular",
+ "value": "Regular"
+ }
+ }
+ ]
+}
+
+
+
+
+ GET https://Domain Name/api/v1/self/shareaccounts/template?clientId={clientId}&productId={productId}
+
+{
+ "clientId": 14,
+ "productOptions": [
+ {
+ "id": 3,
+ "name": "SP",
+ "shortName": "SP",
+ "description": "SP1",
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "inMultiplesOf": 1,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "totalShares": 1000,
+ "totalSharesIssued": 900,
+ "unitPrice": 1,
+ "shareCapital": 900,
+ "minimumShares": 8,
+ "nominalShares": 500,
+ "maximumShares": 500,
+ "marketPrice": [],
+ "charges": [],
+ "allowDividendCalculationForInactiveClients": false,
+ "lockinPeriod": 50,
+ "lockPeriodTypeEnum": {
+ "id": 0,
+ "code": "shares.lockin.sharePeriodFrequencyType.days",
+ "value": "Days"
+ },
+ "minimumActivePeriod": 10,
+ "minimumActivePeriodForDividendsTypeEnum": {
+ "id": 0,
+ "code": "shares.minimumactive.sharePeriodFrequencyType.days",
+ "value": "Days"
+ },
+ "accountingRule": {
+ "id": 2,
+ "code": "accountingRuleType.cash",
+ "value": "CASH BASED"
+ },
+ "accountingMappings": {
+ "shareReferenceId": {
+ "id": 32,
+ "name": "Cash In Hand",
+ "glCode": "20301"
+ },
+ "incomeFromFeeAccountId": {
+ "id": 40,
+ "name": "Other Operating Income",
+ "glCode": "30105"
+ },
+ "shareEquityId": {
+ "id": 56,
+ "name": "Share Equity",
+ "glCode": "00098"
+ },
+ "shareSuspenseId": {
+ "id": 2,
+ "name": "Overpayment Liability",
+ "glCode": "10200"
+ }
+ },
+ "currencyOptions": [
+ {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ }
+ ],
+ "chargeOptions": [
+ {
+ "id": 2,
+ "name": "Activation fee",
+ "active": true,
+ "penalty": false,
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "amount": 2,
+ "chargeTimeType": {
+ "id": 14,
+ "code": "chargeTimeType.sharespurchase",
+ "value": "Share Purchase"
+ },
+ "chargeAppliesTo": {
+ "id": 4,
+ "code": "chargeAppliesTo.shares",
+ "value": "Shares"
+ },
+ "chargeCalculationType": {
+ "id": 1,
+ "code": "chargeCalculationType.flat",
+ "value": "Flat"
+ },
+ "chargePaymentMode": {
+ "id": 0,
+ "code": "chargepaymentmode.regular",
+ "value": "Regular"
+ }
+ }
+ ],
+ "minimumActivePeriodFrequencyTypeOptions": [
+ {
+ "id": 0,
+ "code": "shares.lockin.sharePeriodFrequencyType.days",
+ "value": "Days"
+ }
+ ],
+ "lockinPeriodFrequencyTypeOptions": [
+ {
+ "id": 0,
+ "code": "shares.lockin.sharePeriodFrequencyType.days",
+ "value": "Days"
+ },
+ {
+ "id": 1,
+ "code": "shares.lockin.sharePeriodFrequencyType.weeks",
+ "value": "Weeks"
+ },
+ {
+ "id": 2,
+ "code": "shares.lockin.sharePeriodFrequencyType.months",
+ "value": "Months"
+ },
+ {
+ "id": 3,
+ "code": "shares.lockin.sharePeriodFrequencyType.years",
+ "value": "Years"
+ }
+ ],
+ "accountingMappingOptions": {
+ "liabilityAccountOptions": [
+ {
+ "id": 30,
+ "name": "Recurring Deposits",
+ "parentId": 1,
+ "glCode": "10104",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 2,
+ "code": "accountType.liability",
+ "value": "LIABILITY"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Recurring Deposits",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 2,
+ "name": "Overpayment Liability",
+ "glCode": "10200",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 2,
+ "code": "accountType.liability",
+ "value": "LIABILITY"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "Overpayment Liability",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 55,
+ "name": "Liability Transfer (Temp)",
+ "glCode": "220004-Temp",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 2,
+ "code": "accountType.liability",
+ "value": "LIABILITY"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "description": "Temporary Liability account to track Account Transfers",
+ "nameDecorated": "Liability Transfer (Temp)",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ }
+ ],
+ "assetAccountOptions": [
+ {
+ "id": 31,
+ "name": "Furniture and Fixtures",
+ "parentId": 8,
+ "glCode": "20101",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 1,
+ "code": "accountType.asset",
+ "value": "ASSET"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Furniture and Fixtures",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 32,
+ "name": "Cash In Hand",
+ "parentId": 10,
+ "glCode": "20301",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 1,
+ "code": "accountType.asset",
+ "value": "ASSET"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Cash In Hand",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 33,
+ "name": "Petty Cash",
+ "parentId": 10,
+ "glCode": "20302",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 1,
+ "code": "accountType.asset",
+ "value": "ASSET"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Petty Cash",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 34,
+ "name": "Loans to Customers",
+ "parentId": 12,
+ "glCode": "20501",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 1,
+ "code": "accountType.asset",
+ "value": "ASSET"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Loans to Customers",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 35,
+ "name": "Current Account Overdrafts",
+ "parentId": 12,
+ "glCode": "20502",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 1,
+ "code": "accountType.asset",
+ "value": "ASSET"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Current Account Overdrafts",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 17,
+ "name": "Suspense Account",
+ "glCode": "9999",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 1,
+ "code": "accountType.asset",
+ "value": "ASSET"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "Suspense Account",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ }
+ ],
+ "incomeAccountOptions": [
+ {
+ "id": 54,
+ "name": "Loan Recovery (Temp)",
+ "glCode": "220002-Temp",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 4,
+ "code": "accountType.income",
+ "value": "INCOME"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "description": "Temporary account to track income from Loan recovery",
+ "nameDecorated": "Loan Recovery (Temp)",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 36,
+ "name": "Fees and Charges",
+ "parentId": 18,
+ "glCode": "30101",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 4,
+ "code": "accountType.income",
+ "value": "INCOME"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Fees and Charges",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 37,
+ "name": "Penalties",
+ "parentId": 18,
+ "glCode": "30102",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 4,
+ "code": "accountType.income",
+ "value": "INCOME"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Penalties",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 38,
+ "name": "Interest Received from Borrowers",
+ "parentId": 18,
+ "glCode": "30103",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 4,
+ "code": "accountType.income",
+ "value": "INCOME"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Interest Received from Borrowers",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 39,
+ "name": "Insurance Charges",
+ "parentId": 18,
+ "glCode": "30104",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 4,
+ "code": "accountType.income",
+ "value": "INCOME"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Insurance Charges",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ },
+ {
+ "id": 40,
+ "name": "Other Operating Income",
+ "parentId": 18,
+ "glCode": "30105",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 4,
+ "code": "accountType.income",
+ "value": "INCOME"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Other Operating Income",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ }
+ ],
+ "equityAccountOptions": [
+ {
+ "id": 56,
+ "name": "Share Equity",
+ "parentId": 25,
+ "glCode": "00098",
+ "disabled": false,
+ "manualEntriesAllowed": true,
+ "type": {
+ "id": 3,
+ "code": "accountType.equity",
+ "value": "EQUITY"
+ },
+ "usage": {
+ "id": 1,
+ "code": "accountUsage.detail",
+ "value": "DETAIL"
+ },
+ "nameDecorated": "....Share Equity",
+ "tagId": {
+ "id": 0,
+ "active": false,
+ "mandatory": false
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "chargeOptions": [
+ {
+ "id": 2,
+ "name": "Activation fee",
+ "active": true,
+ "penalty": false,
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "amount": 2,
+ "chargeTimeType": {
+ "id": 14,
+ "code": "chargeTimeType.sharespurchase",
+ "value": "Share Purchase"
+ },
+ "chargeAppliesTo": {
+ "id": 4,
+ "code": "chargeAppliesTo.shares",
+ "value": "Shares"
+ },
+ "chargeCalculationType": {
+ "id": 1,
+ "code": "chargeCalculationType.flat",
+ "value": "Flat"
+ },
+ "chargePaymentMode": {
+ "id": 0,
+ "code": "chargepaymentmode.regular",
+ "value": "Regular"
+ }
+ }
+ ]
+}
+
+
+
+
+
+
+
+
Submit new share application
+
+
+ Mandatory Fields
+ clientId, productId, submittedDate, savingsAccountId, requestedShares, applicationDate
+
+
+
+ Optional Fields
+ accountNo, externalId
+
+
+
+ Inherited from Product (if not provided)
+ minimumActivePeriod, minimumActivePeriodFrequencyType, lockinPeriodFrequency, lockinPeriodFrequencyType
+
+
+
+
+
Minimal request: accountNo auto generated, remaining details inherited from Share product.
+
POST https://Domain Name/api/v1/self/shareaccounts
+
POST Share Account
+Content-Type: application/json
+Request Body:
+{
+ "productId":3,
+ "unitPrice":1,
+ "requestedShares":500,
+ "submittedDate":"31 July 2018",
+ "savingsAccountId":2,
+ "applicationDate":"31 July 2018",
+ "locale":"en",
+ "dateFormat":"dd MMMM yyyy",
+ "charges":[
+ {
+ "chargeId":2,
+ "amount":2
+ }
+ ],
+ "clientId":"14"
+}
+
+
+{
+ "resourceId": 12
+}
+
+
+
+
+
+
+
+
Retrieve a share application/account:
+
+
Example Requests :
+
self/shareaccounts/12
+
+
+ GET https://DomainName/api/v1/self/shareaccounts/{accountId}
+
+{
+ "id": 12,
+ "accountNo": "000000012",
+ "savingsAccountNumber": "000000002",
+ "clientId": 14,
+ "clientName": "Bheem",
+ "productId": 3,
+ "productName": "SP",
+ "status": {
+ "id": 100,
+ "code": "shareAccountStatusType.submitted.and.pending.approval",
+ "value": "Submitted and pending approval",
+ "submittedAndPendingApproval": true,
+ "approved": false,
+ "rejected": false,
+ "active": false,
+ "closed": false
+ },
+ "timeline": {
+ "submittedOnDate": [
+ 2018,
+ 7,
+ 31
+ ],
+ "submittedByUsername": "self",
+ "submittedByFirstname": "self",
+ "submittedByLastname": "self"
+ },
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "inMultiplesOf": 1,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "summary": {
+ "id": 12,
+ "accountNo": "000000012",
+ "totalApprovedShares": 0,
+ "totalPendingForApprovalShares": 500,
+ "productId": 3,
+ "productName": "SP",
+ "status": {
+ "id": 100,
+ "code": "shareAccountStatusType.submitted.and.pending.approval",
+ "value": "Submitted and pending approval",
+ "submittedAndPendingApproval": true,
+ "approved": false,
+ "rejected": false,
+ "active": false,
+ "closed": false
+ },
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "inMultiplesOf": 1,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "timeline": {
+ "submittedOnDate": [
+ 2018,
+ 7,
+ 31
+ ],
+ "submittedByUsername": "self",
+ "submittedByFirstname": "self",
+ "submittedByLastname": "self"
+ }
+ },
+ "purchasedShares": [
+ {
+ "id": 13,
+ "accountId": 12,
+ "purchasedDate": [
+ 2018,
+ 7,
+ 31
+ ],
+ "numberOfShares": 500,
+ "purchasedPrice": 1,
+ "status": {
+ "id": 100,
+ "code": "purchasedSharesStatusType.applied",
+ "value": "Pending Approval"
+ },
+ "type": {
+ "id": 500,
+ "code": "purchasedSharesType.purchased",
+ "value": "Purchase"
+ },
+ "amount": 502,
+ "chargeAmount": 2,
+ "amountPaid": 500
+ }
+ ],
+ "savingsAccountId": 2,
+ "currentMarketPrice": 1,
+ "lockPeriodTypeEnum": {
+ "id": 4,
+ "code": "sharePeriodFrequencyType.invalid",
+ "value": "Invalid"
+ },
+ "minimumActivePeriodTypeEnum": {
+ "id": 4,
+ "code": "sharePeriodFrequencyType.invalid",
+ "value": "Invalid"
+ },
+ "allowDividendCalculationForInactiveClients": false,
+ "charges": [
+ {
+ "id": 9,
+ "chargeId": 2,
+ "accountId": 12,
+ "name": "Activation fee",
+ "chargeTimeType": {
+ "id": 14,
+ "code": "chargeTimeType.sharespurchase",
+ "value": "Share Purchase"
+ },
+ "chargeCalculationType": {
+ "id": 1,
+ "code": "chargeCalculationType.flat",
+ "value": "Flat"
+ },
+ "percentage": 0,
+ "amountPercentageAppliedTo": 0,
+ "currency": {
+ "code": "USD",
+ "name": "US Dollar",
+ "decimalPlaces": 2,
+ "displaySymbol": "$",
+ "nameCode": "currency.USD",
+ "displayLabel": "US Dollar ($)"
+ },
+ "amount": 2,
+ "amountPaid": 0,
+ "amountWaived": 0,
+ "amountWrittenOff": 0,
+ "amountOutstanding": 2,
+ "amountOrPercentage": 2,
+ "isActive": true
+ }
+ ],
+ "dividends": []
+}
+
+
+
+
+
+
+
+
List Guarantors
+
Example Requests:
+
self/loans/33/guarantors
+
+
+
+
+GET https://DomainName/api/v1/self/loans/{loanId}/guarantors
+
+
+[
+ {
+ "id":6,
+ "loanId":33,
+ "guarantorType":{
+ "id":1,
+ "code":"guarantor.existing.customer",
+ "value":"CUSTOMER"
+ },
+ "firstname":"Abhishek v",
+ "lastname":"M",
+ "entityId":12,
+ "officeName":"Head Office",
+ "joinedDate":[
+ 2014,
+ 7,
+ 5
+ ],
+ "guarantorFundingDetails":[
+ {
+ "id":7,
+ "status":{
+ "id":100,
+ "code":"guarantorFundStatusType.active",
+ "value":"ACTIVE"
+ },
+ "savingsAccount":{
+ "id":28,
+ "accountNo":"000000028"
+ },
+ "amount":2000,
+ "amountReleased":0,
+ "amountRemaining":2000,
+ "amountTransfered":0,
+ "guarantorTransactions":[
+ {
+ "id":6,
+ "onHoldTransactionData":{
+ "id":6,
+ "amount":2000,
+ "transactionType":{
+ "id":1,
+ "code":"deposutAccountOnHoldTransactionType.hold",
+ "value":"hold"
+ },
+ "transactionDate":[
+ 2018,
+ 10,
+ 10
+ ],
+ "reversed":false,
+ "savingsId":0,
+ "loanId":0
+ },
+ "reversed":false
+ }
+ ]
+ }
+ ],
+ "status":true
+ },
+ {
+ "id":7,
+ "loanId":33,
+ "clientRelationshipType":{
+ "id":6,
+ "name":"Parent",
+ "active":false,
+ "mandatory":false
+ },
+ "guarantorType":{
+ "id":1,
+ "code":"guarantor.existing.customer",
+ "value":"CUSTOMER"
+ },
+ "firstname":"Bheem",
+ "lastname":"Test",
+ "entityId":14,
+ "officeName":"Head Office",
+ "joinedDate":[
+ 2013,
+ 7,
+ 3
+ ],
+ "guarantorFundingDetails":[
+ {
+ "id":8,
+ "status":{
+ "id":100,
+ "code":"guarantorFundStatusType.active",
+ "value":"ACTIVE"
+ },
+ "savingsAccount":{
+ "id":37,
+ "accountNo":"000000037"
+ },
+ "amount":1000,
+ "amountReleased":0,
+ "amountRemaining":1000,
+ "amountTransfered":0,
+ "guarantorTransactions":[
+ {
+ "id":7,
+ "onHoldTransactionData":{
+ "id":7,
+ "amount":1000,
+ "transactionType":{
+ "id":1,
+ "code":"deposutAccountOnHoldTransactionType.hold",
+ "value":"hold"
+ },
+ "transactionDate":[
+ 2018,
+ 10,
+ 10
+ ],
+ "reversed":false,
+ "savingsId":0,
+ "loanId":0
+ },
+ "reversed":false
+ }
+ ]
+ }
+ ],
+ "status":true
+ }
+]
+
+
+
+
+
+
+
Obligee List
+
Obligee list provides list of clients and other details, to whom the user has agreed to be a guarantor.
+
+
+ Field Descriptions
+
+ clientId
+ The client id of the self service user.
+
+ firstName, lastName, displayName
+ The first name, last name and display name of the obligee
+
+ accountNumber, loanAmount
+ The loan account number and principal amount of the obligee
+
+ guaranteeAmount, amountReleased, amountTransferred
+ Guranteed amount, released and transferred amount of the client
+
+
+
Example Requests:
+
self/clients/14/obligeedetails
+
+
+
+
+GET https://DomainName/api/v1/self/clients/{clientId}/obligeedetails
+
+
+ [
+ {
+ "firstName":"App",
+ "lastName":"Test",
+ "displayName":"App Test",
+ "accountNumber":"000000005",
+ "loanAmount":50000,
+ "guaranteeAmount":10000,
+ "amountReleased":0,
+ "amountTransferred":0
+ },
+ {
+ "firstName":"App",
+ "lastName":"Test",
+ "displayName":"App Test",
+ "accountNumber":"000000005",
+ "loanAmount":50000,
+ "guaranteeAmount":5000,
+ "amountReleased":0,
+ "amountTransferred":0
+ },
+ {
+ "firstName":"App",
+ "lastName":"Test",
+ "displayName":"App Test",
+ "accountNumber":"000000006",
+ "loanAmount":50000,
+ "guaranteeAmount":10000,
+ "amountReleased":0,
+ "amountTransferred":0
+ },
+ {
+ "firstName":"Abhishek v",
+ "lastName":"M",
+ "displayName":"Abhishek v M",
+ "accountNumber":"000000032",
+ "loanAmount":10000,
+ "guaranteeAmount":1000,
+ "amountReleased":1000,
+ "amountTransferred":0
+ },
+ {
+ "firstName":"Abhishek v",
+ "lastName":"M",
+ "displayName":"Abhishek v M",
+ "accountNumber":"000000033",
+ "loanAmount":10000,
+ "guaranteeAmount":1000,
+ "amountReleased":0,
+ "amountTransferred":0
+ }
+]
+
+
+
+
+
+
+
+
Upload client image (Data URI)
+
+
+
+POST https://DomainName/api/v1/self/clients/{clientId}/images
+
+
+POST self/clients/14/images
+Content-Type: text/plain
+Request Body:
+data:image/png;base64,iVBORw0KGgoAA
+AANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0l
+EQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6
+P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC
+
+
+{
+ "resourceId": 14,
+ "changes": {},
+ "resourceIdentifier": "14"
+}
+
+
+
+
+
+
+
+
Upload client image (Multi-part Form data)
+
+
+ Mandatory Fields
+
+
+ file
+
+
+
+
+ The form should contain a required named body part with the
+ name "file".
+ If you are using a HTML form, a snippet like
+ <input type="file" name="file"></input>
+ can be used for uploading the image file
+
+
+
+
+POST https://DomainName/api/v1/self/clients/{clientId}/images
+
+
+POST self/clients/14/images
+Content-Type: multipart/form-data
+Request Body: Not shown
+
+
+{
+ "resourceId": 14,
+ "changes": {},
+ "resourceIdentifier": "14"
+}
+
+
+
+
+
+
+
Delete an client's Image
+
+
+
+DELETE https://DomainName/api/v1/self/clients/{clientId}/images
+
+
+DELETE self/clients/14/images
+Content-Type: application/json
+No Request Body:
+
+
+{
+ "resourceId": 14,
+ "changes": {},
+ "resourceIdentifier": "14"
+}
+
+
+
+
diff --git a/fineract-provider/dependencies.gradle b/fineract-provider/dependencies.gradle
index 131472518..3ceb54df6 100644
--- a/fineract-provider/dependencies.gradle
+++ b/fineract-provider/dependencies.gradle
@@ -85,7 +85,7 @@ dependencies {
[group: 'net.sf.ehcache', name: 'ehcache', version: '2.7.2'],
[group: 'com.github.spullara.mustache.java', name: 'compiler', version: '0.8.12'],
[group: 'com.jayway.jsonpath', name: 'json-path', version: '0.9.1'],
-
+ [group: 'org.apache.tika', name: 'tika-core', version :'1.9'],
// Although fineract (at the time of writing) doesn't have any compile time dep. on this,
// it's useful to have this for the Spring Boot TestRestTemplate http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-rest-templates-test-utility
[group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.5'],
diff --git a/fineract-provider/dev-dependencies.gradle b/fineract-provider/dev-dependencies.gradle
index d12494e0c..325a1a20a 100644
--- a/fineract-provider/dev-dependencies.gradle
+++ b/fineract-provider/dev-dependencies.gradle
@@ -84,7 +84,7 @@ dependencies {
[group: 'net.sf.ehcache', name: 'ehcache', version: '2.7.2'],
[group: 'com.github.spullara.mustache.java', name: 'compiler', version: '0.8.12'],
[group: 'com.jayway.jsonpath', name: 'json-path', version: '0.9.1'],
-
+ [group: 'org.apache.tika', name: 'tika-core', version :'1.9'],
// Although fineract (at the time of writing) doesn't have any compile time dep. on this,
// it's useful to have this for the Spring Boot TestRestTemplate http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-rest-templates-test-utility
[group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.5'],
diff --git a/fineract-provider/fineract-provider.iml b/fineract-provider/fineract-provider.iml
index 98e6d6688..d5c2f047b 100644
--- a/fineract-provider/fineract-provider.iml
+++ b/fineract-provider/fineract-provider.iml
@@ -1,14 +1,1549 @@
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
+
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/AccountNumberPreferencesTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/AccountNumberPreferencesTest.java
index 97c3faccf..12830cd0c 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/AccountNumberPreferencesTest.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/AccountNumberPreferencesTest.java
@@ -373,8 +373,9 @@ public class AccountNumberPreferencesTest {
}
}
- private void validateAccountNumberLengthAndStartsWithPrefix(final String accountNumber, final String prefix) {
+ private void validateAccountNumberLengthAndStartsWithPrefix(final String accountNumber, String prefix) {
if (prefix != null) {
+ prefix = prefix.substring(0, Math.min(prefix.length(), 10));
Assert.assertEquals(accountNumber.length(), prefix.length() + 9);
Assert.assertTrue(accountNumber.startsWith(prefix));
} else {
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
index c516502fa..785dab151 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
@@ -1,5 +1,3 @@
-package org.apache.fineract.integrationtests;
-
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,7 +16,7 @@ package org.apache.fineract.integrationtests;
* specific language governing permissions and limitations
* under the License.
*/
-
+package org.apache.fineract.integrationtests;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.builder.ResponseSpecBuilder;
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/client/ClientEntityImportHandlerTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/client/ClientEntityImportHandlerTest.java
new file mode 100644
index 000000000..ee5e734d1
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/client/ClientEntityImportHandlerTest.java
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.bulkimport.importhandler.client;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.infrastructure.bulkimport.constants.ClientEntityConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.OfficeHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
+import org.apache.fineract.integrationtests.common.system.CodeHelper;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import java.io.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class ClientEntityImportHandlerTest {
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+
+ @Before
+ public void setup() {
+ Utils.initializeRESTAssured();
+ this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+ this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+ }
+
+ @Test
+ public void testClientImport() throws InterruptedException, IOException, ParseException {
+
+ //in order to populate helper sheets
+ StaffHelper staffHelper=new StaffHelper();
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ Integer outcome_staff_creation =staffHelper.createStaff(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create staff",outcome_staff_creation);
+
+ //in order to populate helper sheets
+ OfficeHelper officeHelper=new OfficeHelper(requestSpec,responseSpec);
+ Integer outcome_office_creation=officeHelper.createOffice("02 May 2000");
+ Assert.assertNotNull("Could not create office" ,outcome_office_creation);
+
+ //in order to populate helper columns in client entity sheet
+ CodeHelper codeHelper=new CodeHelper();
+ //create constitution
+ codeHelper.retrieveOrCreateCodeValue(24,requestSpec,responseSpec);
+ //create client classification
+ codeHelper.retrieveOrCreateCodeValue(17,requestSpec,responseSpec);
+ //create client types
+ codeHelper.retrieveOrCreateCodeValue(16,requestSpec,responseSpec);
+ //create Address types
+ codeHelper.retrieveOrCreateCodeValue(29,requestSpec,responseSpec);
+ //create State
+ codeHelper.retrieveOrCreateCodeValue(27,requestSpec,responseSpec);
+ //create Country
+ codeHelper.retrieveOrCreateCodeValue(28,requestSpec,responseSpec);
+ //create Main business line
+ codeHelper.retrieveOrCreateCodeValue(25,requestSpec,responseSpec);
+
+ ClientHelper clientHelper=new ClientHelper(requestSpec,responseSpec);
+ Workbook workbook=clientHelper.getClientEntityWorkbook(GlobalEntityType.CLIENTS_ENTTTY,"dd MMMM yyyy");
+
+ //insert dummy data into client entity sheet
+ Sheet clientEntitySheet = workbook.getSheet(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME);
+ Row firstClientRow=clientEntitySheet.getRow(1);
+ firstClientRow.createCell(ClientEntityConstants.NAME_COL).setCellValue(Utils.randomNameGenerator("C_E_",6));
+ Sheet staffSheet=workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME);
+ firstClientRow.createCell(ClientEntityConstants.OFFICE_NAME_COL).setCellValue(staffSheet.getRow(1).getCell(0).getStringCellValue());
+ firstClientRow.createCell(ClientEntityConstants.STAFF_NAME_COL).setCellValue(staffSheet.getRow(1).getCell(1).getStringCellValue());
+ SimpleDateFormat simpleDateFormat=new SimpleDateFormat("dd MMMM yyyy");
+ Date incoporationDate=simpleDateFormat.parse("14 May 2001");
+ firstClientRow.createCell(ClientEntityConstants.INCOPORATION_DATE_COL).setCellValue(incoporationDate);
+ Date validTill=simpleDateFormat.parse("14 May 2019");
+ firstClientRow.createCell(ClientEntityConstants.INCOPORATION_VALID_TILL_COL).setCellValue(validTill);
+ firstClientRow.createCell(ClientEntityConstants.MOBILE_NO_COL).setCellValue(Utils.randomNumberGenerator(7));
+ firstClientRow.createCell(ClientEntityConstants.CLIENT_TYPE_COL).setCellValue(clientEntitySheet.getRow(1).getCell(ClientEntityConstants.LOOKUP_CLIENT_TYPES).getStringCellValue());
+ firstClientRow.createCell(ClientEntityConstants.CLIENT_CLASSIFICATION_COL).setCellValue(clientEntitySheet.getRow(1).getCell(ClientEntityConstants.LOOKUP_CLIENT_CLASSIFICATION).getStringCellValue());
+ firstClientRow.createCell(ClientEntityConstants.INCOPORATION_NUMBER_COL).setCellValue(Utils.randomNumberGenerator(6));
+ firstClientRow.createCell(ClientEntityConstants.MAIN_BUSINESS_LINE).setCellValue(clientEntitySheet.getRow(1).getCell(ClientEntityConstants.LOOKUP_MAIN_BUSINESS_LINE).getStringCellValue());
+ firstClientRow.createCell(ClientEntityConstants.CONSTITUTION_COL).setCellValue(clientEntitySheet.getRow(1).getCell(ClientEntityConstants.LOOKUP_CONSTITUTION_COL).getStringCellValue());
+ firstClientRow.createCell(ClientEntityConstants.ACTIVE_COL).setCellValue("False");
+ Date submittedDate=simpleDateFormat.parse("28 September 2017");
+ firstClientRow.createCell(ClientEntityConstants.SUBMITTED_ON_COL).setCellValue(submittedDate);
+ firstClientRow.createCell(ClientEntityConstants.ADDRESS_ENABLED).setCellValue("False");
+
+ File directory=new File(System.getProperty("user.home")+File.separator+"Fineract"+File.separator+"bulkimport"+File.separator+"integration_tests"+File.separator+"importhandler"+File.separator+"client") ;
+ if (!directory.exists())
+ directory.mkdirs();
+ File file= new File(directory+File.separator+"ClientEntity.xls");
+ OutputStream outputStream=new FileOutputStream(file);
+ workbook.write(outputStream);
+ outputStream.close();
+
+ String importDocumentId=clientHelper.importClientEntityTemplate(file);
+ file.delete();
+ Assert.assertNotNull(importDocumentId);
+
+ //Wait for the creation of output excel
+ Thread.sleep(3000);
+
+ //check status column of output excel
+ String location=clientHelper.getOutputTemplateLocation(importDocumentId);
+ FileInputStream fileInputStream = new FileInputStream(location);
+ Workbook outputWorkbook=new HSSFWorkbook(fileInputStream);
+ Sheet outputClientEntitySheet = outputWorkbook.getSheet(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME);
+ Row row= outputClientEntitySheet.getRow(1);
+ Assert.assertEquals("Imported",row.getCell(ClientEntityConstants.STATUS_COL).getStringCellValue());
+
+ }
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
new file mode 100644
index 000000000..91bb0bdb2
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java
@@ -0,0 +1,174 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.bulkimport.importhandler.loan;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.infrastructure.bulkimport.constants.LoanConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.integrationtests.common.*;
+import org.apache.fineract.integrationtests.common.funds.FundsResourceHandler;
+import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import java.io.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class LoanImportHandlerTest {
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+
+ @Before
+ public void setup() {
+ Utils.initializeRESTAssured();
+ this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+ this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+ }
+
+ @Test
+ public void testLoanImport() throws InterruptedException, IOException, ParseException {
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ //in order to populate helper sheets
+ OfficeHelper officeHelper=new OfficeHelper(requestSpec,responseSpec);
+ Integer outcome_office_creation=officeHelper.createOffice("02 May 2000");
+ Assert.assertNotNull("Could not create office" ,outcome_office_creation);
+
+ //in order to populate helper sheets
+ ClientHelper clientHelper=new ClientHelper(requestSpec,responseSpec);
+ Integer outcome_client_creation=clientHelper.createClient(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create client" ,outcome_client_creation);
+
+ //in order to populate helper sheets
+ GroupHelper groupHelper=new GroupHelper(requestSpec,responseSpec);
+ Integer outcome_group_creation=groupHelper.createGroup(requestSpec,responseSpec,true);
+ Assert.assertNotNull("Could not create group" ,outcome_group_creation);
+
+ //in order to populate helper sheets
+ StaffHelper staffHelper=new StaffHelper();
+ Integer outcome_staff_creation =staffHelper.createStaff(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create staff",outcome_staff_creation);
+
+ // LoanTransactionHelper ltHelper=new LoanTransactionHelper(requestSpec,responseSpec);
+ // LoanProductTestBuilder loanProductTestBuilder=new LoanProductTestBuilder();
+ // String jsonLoanProduct=loanProductTestBuilder.build(null);
+ // Integer outcome_lp_creaion=ltHelper.getLoanProductId(jsonLoanProduct);
+ // Assert.assertNotNull("Could not create Loan Product" ,outcome_lp_creaion);
+
+ // FundsResourceHandler fundsResourceHandler=new FundsResourceHandler();
+ // String jsonFund="{\n" +
+ // "\t\"name\": \""+Utils.randomNameGenerator("Fund_Name",9)+"\"\n" +
+ // "}";
+ // Integer outcome_fund_creation=fundsResourceHandler.createFund(jsonFund,requestSpec,responseSpec);
+ // Assert.assertNotNull("Could not create Fund" ,outcome_fund_creation);
+
+ // PaymentTypeHelper paymentTypeHelper=new PaymentTypeHelper();
+ // String name = PaymentTypeHelper.randomNameGenerator("P_T", 5);
+ // String description = PaymentTypeHelper.randomNameGenerator("PT_Desc", 15);
+ // Boolean isCashPayment = true;
+ // Integer position = 1;
+ // Integer outcome_payment_creation= paymentTypeHelper.createPaymentType(requestSpec, responseSpec,name,description,isCashPayment,position);
+ // Assert.assertNotNull("Could not create payment type" ,outcome_payment_creation);
+
+ LoanTransactionHelper loanTransactionHelper=new LoanTransactionHelper(requestSpec,responseSpec);
+ Workbook workbook=loanTransactionHelper.getLoanWorkbook("dd MMMM yyyy");
+
+ //insert dummy data into loan Sheet
+ Sheet loanSheet = workbook.getSheet(TemplatePopulateImportConstants.LOANS_SHEET_NAME);
+ Row firstLoanRow=loanSheet.getRow(1);
+ Sheet officeSheet=workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ firstLoanRow.createCell(LoanConstants.OFFICE_NAME_COL).setCellValue(officeSheet.getRow(1).getCell(1).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.LOAN_TYPE_COL).setCellValue("Individual");
+ firstLoanRow.createCell(LoanConstants.CLIENT_NAME_COL).setCellValue(loanSheet.getRow(1).getCell(LoanConstants.LOOKUP_CLIENT_NAME_COL).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.CLIENT_EXTERNAL_ID).setCellValue(loanSheet.getRow(1).getCell(LoanConstants.LOOKUP_CLIENT_EXTERNAL_ID).getStringCellValue());
+ Sheet loanProductSheet=workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME);
+ firstLoanRow.createCell(LoanConstants.PRODUCT_COL).setCellValue(loanProductSheet.getRow(1).getCell(1).getStringCellValue());
+ Sheet staffSheet=workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME);
+ firstLoanRow.createCell(LoanConstants.LOAN_OFFICER_NAME_COL).setCellValue(staffSheet.getRow(1).getCell(1).getStringCellValue());
+ SimpleDateFormat simpleDateFormat=new SimpleDateFormat("dd MMMM yyyy");
+ Date date=simpleDateFormat.parse("13 May 2017");
+ firstLoanRow.createCell(LoanConstants.SUBMITTED_ON_DATE_COL).setCellValue(date);
+ firstLoanRow.createCell(LoanConstants.APPROVED_DATE_COL).setCellValue(date);
+ firstLoanRow.createCell(LoanConstants.DISBURSED_DATE_COL).setCellValue(date);
+ Sheet extrasSheet=workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME);
+ firstLoanRow.createCell(LoanConstants.DISBURSED_PAYMENT_TYPE_COL).setCellValue(extrasSheet.getRow(1).getCell(3).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.FUND_NAME_COL).setCellValue(extrasSheet.getRow(1).getCell(1).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.PRINCIPAL_COL).setCellValue(loanProductSheet.getRow(1).getCell(3).getNumericCellValue());
+ firstLoanRow.createCell(LoanConstants.NO_OF_REPAYMENTS_COL).setCellValue(loanProductSheet.getRow(1).getCell(6).getNumericCellValue());
+ firstLoanRow.createCell(LoanConstants.REPAID_EVERY_COL).setCellValue(loanProductSheet.getRow(1).getCell(9).getNumericCellValue());
+ firstLoanRow.createCell(LoanConstants.REPAID_EVERY_FREQUENCY_COL).setCellValue(loanProductSheet.getRow(1).getCell(10).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.LOAN_TERM_COL).setCellValue(60);
+ firstLoanRow.createCell(LoanConstants.LOAN_TERM_FREQUENCY_COL).setCellValue(loanProductSheet.getRow(1).getCell(10).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.NOMINAL_INTEREST_RATE_COL).setCellValue(loanProductSheet.getRow(1).getCell(11).getNumericCellValue());
+ firstLoanRow.createCell(LoanConstants.NOMINAL_INTEREST_RATE_FREQUENCY_COL).setCellValue(loanProductSheet.getRow(1).getCell(14).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.AMORTIZATION_COL).setCellValue(loanProductSheet.getRow(1).getCell(15).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.INTEREST_METHOD_COL).setCellValue(loanProductSheet.getRow(1).getCell(16).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.INTEREST_CALCULATION_PERIOD_COL).setCellValue(loanProductSheet.getRow(1).getCell(17).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.ARREARS_TOLERANCE_COL).setCellValue(0);
+ firstLoanRow.createCell(LoanConstants.REPAYMENT_STRATEGY_COL).setCellValue(loanProductSheet.getRow(1).getCell(19).getStringCellValue());
+ firstLoanRow.createCell(LoanConstants.GRACE_ON_PRINCIPAL_PAYMENT_COL).setCellValue(0);
+ firstLoanRow.createCell(LoanConstants.GRACE_ON_INTEREST_PAYMENT_COL).setCellValue(0);
+ firstLoanRow.createCell(LoanConstants.GRACE_ON_INTEREST_CHARGED_COL).setCellValue(0);
+ firstLoanRow.createCell(LoanConstants.FIRST_REPAYMENT_COL).setCellValue(date);
+ firstLoanRow.createCell(LoanConstants.TOTAL_AMOUNT_REPAID_COL).setCellValue(6000);
+ firstLoanRow.createCell(LoanConstants.LAST_REPAYMENT_DATE_COL).setCellValue(date);
+ firstLoanRow.createCell(LoanConstants.REPAYMENT_TYPE_COL).setCellValue(extrasSheet.getRow(1).getCell(3).getStringCellValue());
+
+ String currentdirectory = new File("").getAbsolutePath();
+ File directory=new File(currentdirectory+File.separator+"src"+File.separator+"integrationTest"+File.separator+
+ "resources"+File.separator+"bulkimport"+File.separator+"importhandler"+File.separator+"loan") ;
+ if (!directory.exists())
+ directory.mkdirs();
+ File file= new File(directory+File.separator+"Loan.xls");
+ OutputStream outputStream=new FileOutputStream(file);
+ workbook.write(outputStream);
+ outputStream.close();
+
+ String importDocumentId=loanTransactionHelper.importLoanTemplate(file);
+ file.delete();
+ Assert.assertNotNull(importDocumentId);
+
+ //Wait for the creation of output excel
+ Thread.sleep(10000);
+
+ //check status column of output excel
+ String location=loanTransactionHelper.getOutputTemplateLocation(importDocumentId);
+ FileInputStream fileInputStream = new FileInputStream(location);
+ Workbook Outputworkbook=new HSSFWorkbook(fileInputStream);
+ Sheet outputLoanSheet = Outputworkbook.getSheet(TemplatePopulateImportConstants.LOANS_SHEET_NAME);
+ Row row= outputLoanSheet.getRow(1);
+ Assert.assertEquals("Imported",row.getCell(LoanConstants.STATUS_COL).getStringCellValue());
+
+ }
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/office/OfficeImportHandlerTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/office/OfficeImportHandlerTest.java
new file mode 100644
index 000000000..9bd80bc8e
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/office/OfficeImportHandlerTest.java
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.bulkimport.importhandler.office;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.infrastructure.bulkimport.constants.OfficeConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.AbstractWorkbookPopulator;
+import org.apache.fineract.integrationtests.common.OfficeHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.organisation.office.domain.Office;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class OfficeImportHandlerTest {
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+
+ @Before
+ public void setup(){
+ Utils.initializeRESTAssured();
+ this.requestSpec=new RequestSpecBuilder().build();
+ this.requestSpec
+ .header("Authorization",
+ "Basic "
+ + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200)
+ .build();
+ }
+
+ @Test
+ public void testOfficeImport() throws IOException, InterruptedException, NoSuchFieldException, ParseException {
+ OfficeHelper officeHelper=new OfficeHelper(requestSpec,responseSpec);
+ Workbook workbook=officeHelper.getOfficeWorkBook("dd MMMM yyyy");
+
+ //insert dummy data into excel
+ Sheet sheet=workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ Row firstOfficeRow= sheet.getRow(1);
+ firstOfficeRow.createCell(OfficeConstants.OFFICE_NAME_COL).setCellValue(Utils.randomNameGenerator("Test_Off_",6));
+ firstOfficeRow.createCell(OfficeConstants.PARENT_OFFICE_NAME_COL).setCellValue(firstOfficeRow.getCell(OfficeConstants.LOOKUP_OFFICE_COL).getStringCellValue());
+ firstOfficeRow.createCell(OfficeConstants.PARENT_OFFICE_ID_COL).setCellValue(firstOfficeRow.getCell(OfficeConstants.LOOKUP_OFFICE_ID_COL).getNumericCellValue());
+ SimpleDateFormat simpleDateFormat=new SimpleDateFormat("dd MMMM yyyy");
+ Date date=simpleDateFormat.parse("14 May 2001");
+ firstOfficeRow.createCell(OfficeConstants.OPENED_ON_COL).setCellValue(date);
+
+ String currentdirectory = new File("").getAbsolutePath();
+ File directory=new File(currentdirectory+File.separator+"src"+File.separator+"integrationTest"+File.separator+
+ "resources"+File.separator+"bulkimport"+File.separator+"importhandler"+File.separator+"office");
+ if (!directory.exists())
+ directory.mkdirs();
+ File file= new File(directory+File.separator+"Office.xls");
+ OutputStream outputStream=new FileOutputStream(file);
+ workbook.write(outputStream);
+ outputStream.close();
+
+ String importDocumentId=officeHelper.importOfficeTemplate(file);
+ file.delete();
+ Assert.assertNotNull(importDocumentId);
+
+ // Wait for the creation of output excel
+ Thread.sleep(3000);
+
+ //check status column of output excel
+ String location=officeHelper.getOutputTemplateLocation(importDocumentId);
+ FileInputStream fileInputStream = new FileInputStream(location);
+ Workbook outputWorkbook=new HSSFWorkbook(fileInputStream);
+ Sheet officeSheet = outputWorkbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ Row row= officeSheet.getRow(1);
+ Assert.assertEquals("Imported",row.getCell(OfficeConstants.STATUS_COL).getStringCellValue());
+
+ }
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java
new file mode 100644
index 000000000..c22ec1f20
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java
@@ -0,0 +1,153 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.bulkimport.importhandler.savings;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.infrastructure.bulkimport.constants.LoanConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.SavingsConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.GroupHelper;
+import org.apache.fineract.integrationtests.common.OfficeHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
+import org.apache.fineract.template.domain.Template;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import java.io.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class SavingsImportHandlerTest {
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+
+ @Before
+ public void setup() {
+ Utils.initializeRESTAssured();
+ this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+ this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+ }
+
+ @Test
+ public void testSavingsImport() throws InterruptedException, IOException, ParseException {
+
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ //in order to populate helper sheets
+ OfficeHelper officeHelper=new OfficeHelper(requestSpec,responseSpec);
+ Integer outcome_office_creation=officeHelper.createOffice("02 May 2000");
+ Assert.assertNotNull("Could not create office" ,outcome_office_creation);
+
+ //in order to populate helper sheets
+ ClientHelper clientHelper=new ClientHelper(requestSpec,responseSpec);
+ Integer outcome_client_creation=clientHelper.createClient(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create client" ,outcome_client_creation);
+
+ //in order to populate helper sheets
+ GroupHelper groupHelper=new GroupHelper(requestSpec,responseSpec);
+ Integer outcome_group_creation=groupHelper.createGroup(requestSpec,responseSpec,true);
+ Assert.assertNotNull("Could not create group" ,outcome_group_creation);
+
+ //in order to populate helper sheets
+ StaffHelper staffHelper=new StaffHelper();
+ Integer outcome_staff_creation =staffHelper.createStaff(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create staff",outcome_staff_creation);
+
+ SavingsProductHelper savingsProductHelper=new SavingsProductHelper();
+ String jsonSavingsProduct=savingsProductHelper.build();
+ Integer outcome_sp_creaction=savingsProductHelper.createSavingsProduct(jsonSavingsProduct,requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create Savings product",outcome_sp_creaction);
+
+ SavingsAccountHelper savingsAccountHelper=new SavingsAccountHelper(requestSpec,responseSpec);
+ Workbook workbook=savingsAccountHelper.getSavingsWorkbook("dd MMMM yyyy");
+
+ //insert dummy data into Savings sheet
+ Sheet savingsSheet = workbook.getSheet(TemplatePopulateImportConstants.SAVINGS_ACCOUNTS_SHEET_NAME);
+ Row firstSavingsRow=savingsSheet.getRow(1);
+ Sheet officeSheet=workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ firstSavingsRow.createCell(SavingsConstants.OFFICE_NAME_COL).setCellValue(officeSheet.getRow(1).getCell(1).getStringCellValue());
+ firstSavingsRow.createCell(SavingsConstants.SAVINGS_TYPE_COL).setCellValue("Individual");
+ firstSavingsRow.createCell(SavingsConstants.CLIENT_NAME_COL).setCellValue(savingsSheet.getRow(1).getCell(SavingsConstants.LOOKUP_CLIENT_NAME_COL).getStringCellValue());
+ Sheet savingsProductSheet=workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME);
+ firstSavingsRow.createCell(SavingsConstants.PRODUCT_COL).setCellValue(savingsProductSheet.getRow(1).getCell(1).getStringCellValue());
+ Sheet staffSheet=workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME);
+ firstSavingsRow.createCell(SavingsConstants.FIELD_OFFICER_NAME_COL).setCellValue(staffSheet.getRow(1).getCell(1).getStringCellValue());
+ SimpleDateFormat simpleDateFormat=new SimpleDateFormat("dd MMMM yyyy");
+ Date date=simpleDateFormat.parse("13 May 2017");
+ firstSavingsRow.createCell(SavingsConstants.SUBMITTED_ON_DATE_COL).setCellValue(date);
+ firstSavingsRow.createCell(SavingsConstants.APPROVED_DATE_COL).setCellValue(date);
+ firstSavingsRow.createCell(SavingsConstants.ACTIVATION_DATE_COL).setCellValue(date);
+ firstSavingsRow.createCell(SavingsConstants.CURRENCY_COL).setCellValue(savingsProductSheet.getRow(1).getCell(10).getStringCellValue());
+ firstSavingsRow.createCell(SavingsConstants.DECIMAL_PLACES_COL).setCellValue(savingsProductSheet.getRow(1).getCell(11).getNumericCellValue());
+ firstSavingsRow.createCell(SavingsConstants.IN_MULTIPLES_OF_COL).setCellValue(savingsProductSheet.getRow(1).getCell(12).getNumericCellValue());
+ firstSavingsRow.createCell(SavingsConstants.NOMINAL_ANNUAL_INTEREST_RATE_COL).setCellValue(savingsProductSheet.getRow(1).getCell(2).getNumericCellValue());
+ firstSavingsRow.createCell(SavingsConstants.INTEREST_COMPOUNDING_PERIOD_COL).setCellValue(savingsProductSheet.getRow(1).getCell(3).getStringCellValue());
+ firstSavingsRow.createCell(SavingsConstants.INTEREST_POSTING_PERIOD_COL).setCellValue(savingsProductSheet.getRow(1).getCell(4).getStringCellValue());
+ firstSavingsRow.createCell(SavingsConstants.INTEREST_CALCULATION_COL).setCellValue(savingsProductSheet.getRow(1).getCell(5).getStringCellValue());
+ firstSavingsRow.createCell(SavingsConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL).setCellValue(savingsProductSheet.getRow(1).getCell(6).getStringCellValue());
+ firstSavingsRow.createCell(SavingsConstants.MIN_OPENING_BALANCE_COL).setCellValue(1000.0);
+ firstSavingsRow.createCell(SavingsConstants.LOCKIN_PERIOD_COL).setCellValue(1);
+ firstSavingsRow.createCell(SavingsConstants.LOCKIN_PERIOD_FREQUENCY_COL).setCellValue("Weeks");
+ firstSavingsRow.createCell(SavingsConstants.APPLY_WITHDRAWAL_FEE_FOR_TRANSFERS).setCellValue("False");
+ firstSavingsRow.createCell(SavingsConstants.ALLOW_OVER_DRAFT_COL).setCellValue("False");
+ firstSavingsRow.createCell(SavingsConstants.OVER_DRAFT_LIMIT_COL).setCellValue(savingsProductSheet.getRow(1).getCell(15).getNumericCellValue());
+
+ String currentdirectory = new File("").getAbsolutePath();
+ File directory=new File(currentdirectory+File.separator+"src"+File.separator+"integrationTest"+File.separator+
+ "resources"+File.separator+"bulkimport"+File.separator+"importhandler"+File.separator+"savings") ;
+ if (!directory.exists())
+ directory.mkdirs();
+ File file= new File(directory+File.separator+"Savings.xls");
+ OutputStream outputStream=new FileOutputStream(file);
+ workbook.write(outputStream);
+ outputStream.close();
+
+ String importDocumentId=savingsAccountHelper.importSavingsTemplate(file);
+ file.delete();
+ Assert.assertNotNull(importDocumentId);
+
+ //Wait for the creation of output excel
+ Thread.sleep(10000);
+
+ //check status column of output excel
+ String location=savingsAccountHelper.getOutputTemplateLocation(importDocumentId);
+ FileInputStream fileInputStream = new FileInputStream(location);
+ Workbook Outputworkbook=new HSSFWorkbook(fileInputStream);
+ Sheet OutputSavingsSheet = Outputworkbook.getSheet(TemplatePopulateImportConstants.SAVINGS_ACCOUNTS_SHEET_NAME);
+ Row row= OutputSavingsSheet.getRow(1);
+ Assert.assertEquals("Imported",row.getCell(SavingsConstants.STATUS_COL).getStringCellValue());
+ }
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/client/ClientEntityWorkbookPopulatorTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/client/ClientEntityWorkbookPopulatorTest.java
new file mode 100644
index 000000000..27e34b75f
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/client/ClientEntityWorkbookPopulatorTest.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.bulkimport.populator.client;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.OfficeHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+
+public class ClientEntityWorkbookPopulatorTest {
+
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+
+ @Before
+ public void setup(){
+ Utils.initializeRESTAssured();
+ this.requestSpec=new RequestSpecBuilder().build();
+ this.requestSpec
+ .header("Authorization",
+ "Basic "
+ + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200)
+ .build();
+
+
+ }
+
+ @Test
+ public void testClientEntityWorkbookPopulate() throws IOException {
+ //in order to populate helper sheets
+ StaffHelper staffHelper=new StaffHelper();
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ Integer outcome_staff_creation =staffHelper.createStaff(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create staff",outcome_staff_creation);
+
+ //in order to populate helper sheets
+ OfficeHelper officeHelper=new OfficeHelper(requestSpec,responseSpec);
+ Integer outcome_office_creation=officeHelper.createOffice("02 May 2000");
+ Assert.assertNotNull("Could not create office" ,outcome_office_creation);
+
+ ClientHelper clientHelper=new ClientHelper(requestSpec,responseSpec);
+ Workbook workbook=clientHelper.getClientEntityWorkbook(GlobalEntityType.CLIENTS_ENTTTY,"dd MMMM yyyy");
+ Sheet officeSheet=workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ Row firstOfficeRow=officeSheet.getRow(1);
+ Assert.assertNotNull("No offices found for given OfficeId ",firstOfficeRow.getCell(1));
+ Sheet staffSheet=workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME);
+ Row firstStaffRow=staffSheet.getRow(1);
+ Assert.assertNotNull("No staff found for given staffId",firstStaffRow.getCell(1));
+ }
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/loan/LoanWorkbookPopulatorTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/loan/LoanWorkbookPopulatorTest.java
new file mode 100644
index 000000000..b76fac733
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/loan/LoanWorkbookPopulatorTest.java
@@ -0,0 +1,126 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.bulkimport.populator.loan;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
+import org.apache.fineract.integrationtests.common.*;
+import org.apache.fineract.integrationtests.common.funds.FundsResourceHandler;
+import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+
+public class LoanWorkbookPopulatorTest {
+
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+
+ @Before
+ public void setup(){
+ Utils.initializeRESTAssured();
+ this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+ this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+ }
+ @Test
+ public void testLoanWorkbookPopulate() throws IOException {
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ //in order to populate helper sheets
+ OfficeHelper officeHelper=new OfficeHelper(requestSpec,responseSpec);
+ Integer outcome_office_creation=officeHelper.createOffice("02 May 2000");
+ Assert.assertNotNull("Could not create office" ,outcome_office_creation);
+
+ //in order to populate helper sheets
+ ClientHelper clientHelper=new ClientHelper(requestSpec,responseSpec);
+ Integer outcome_client_creation=clientHelper.createClient(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create client" ,outcome_client_creation);
+
+ //in order to populate helper sheets
+ GroupHelper groupHelper=new GroupHelper(requestSpec,responseSpec);
+ Integer outcome_group_creation=groupHelper.createGroup(requestSpec,responseSpec,true);
+ Assert.assertNotNull("Could not create group" ,outcome_group_creation);
+
+ //in order to populate helper sheets
+ StaffHelper staffHelper=new StaffHelper();
+ Integer outcome_staff_creation =staffHelper.createStaff(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create staff",outcome_staff_creation);
+
+ LoanTransactionHelper loanTransactionHelper=new LoanTransactionHelper(requestSpec,responseSpec);
+ LoanProductTestBuilder loanProductTestBuilder=new LoanProductTestBuilder();
+ String jsonLoanProduct=loanProductTestBuilder.build(null);
+ Integer outcome_lp_creaion=loanTransactionHelper.getLoanProductId(jsonLoanProduct);
+ Assert.assertNotNull("Could not create Loan Product" ,outcome_lp_creaion);
+
+ FundsResourceHandler fundsResourceHandler=new FundsResourceHandler();
+ String jsonFund="{\n" +
+ "\t\"name\": \""+Utils.randomNameGenerator("Fund_Name",9)+"\"\n" +
+ "}";
+ Integer outcome_fund_creation=fundsResourceHandler.createFund(jsonFund,requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create Fund" ,outcome_fund_creation);
+
+ PaymentTypeHelper paymentTypeHelper=new PaymentTypeHelper();
+ String name = PaymentTypeHelper.randomNameGenerator("P_T", 5);
+ String description = PaymentTypeHelper.randomNameGenerator("PT_Desc", 15);
+ Boolean isCashPayment = true;
+ Integer position = 1;
+ Integer outcome_payment_creation= paymentTypeHelper.createPaymentType(requestSpec, responseSpec,name,description,isCashPayment,position);
+ Assert.assertNotNull("Could not create payment type" ,outcome_payment_creation);
+
+ Workbook workbook=loanTransactionHelper.getLoanWorkbook("dd MMMM yyyy");
+
+ Sheet officeSheet=workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ Row firstOfficeRow=officeSheet.getRow(1);
+ Assert.assertNotNull("No offices found ",firstOfficeRow.getCell(1));
+
+ Sheet clientSheet=workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME);
+ Row firstClientRow=clientSheet.getRow(1);
+ Assert.assertNotNull("No clients found ",firstClientRow.getCell(1));
+
+ Sheet groupSheet=workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME);
+ Row firstGroupRow=groupSheet.getRow(1);
+ Assert.assertNotNull("No groups found ",firstGroupRow.getCell(1));
+
+ Sheet staffSheet=workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME);
+ Row firstStaffRow=staffSheet.getRow(1);
+ Assert.assertNotNull("No staff found ",firstStaffRow.getCell(1));
+
+ Sheet productSheet=workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME);
+ Row firstProductRow=productSheet.getRow(1);
+ Assert.assertNotNull("No products found ",firstProductRow.getCell(1));
+
+ Sheet extrasSheet=workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME);
+ Row firstExtrasRow=extrasSheet.getRow(1);
+ Assert.assertNotNull("No Extras found ",firstExtrasRow.getCell(1));
+ }
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/office/OfficeWorkBookPopulatorTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/office/OfficeWorkBookPopulatorTest.java
new file mode 100644
index 000000000..b878b4859
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/office/OfficeWorkBookPopulatorTest.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.bulkimport.populator.office;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.infrastructure.bulkimport.constants.OfficeConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.integrationtests.common.OfficeHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class OfficeWorkBookPopulatorTest {
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+
+ @Before
+ public void setup(){
+ Utils.initializeRESTAssured();
+ this.requestSpec=new RequestSpecBuilder().build();
+ this.requestSpec
+ .header("Authorization",
+ "Basic "
+ + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200)
+ .build();
+ }
+
+ @Test
+ public void testOfficeWorkbookPopulate() throws IOException {
+ OfficeHelper officeHelper=new OfficeHelper(requestSpec,responseSpec);
+ Workbook workbook=officeHelper.getOfficeWorkBook("dd MMMM yyyy");
+ Sheet sheet=workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ Row firstRow= sheet.getRow(1);
+ Assert.assertNotNull("No parent offices found",firstRow.getCell(OfficeConstants.LOOKUP_OFFICE_COL).getStringCellValue());
+ Assert.assertEquals(1,firstRow.getCell(OfficeConstants.LOOKUP_OFFICE_ID_COL).getNumericCellValue(),0.0);
+
+ }
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/savings/SavingsWorkbookPopulateTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/savings/SavingsWorkbookPopulateTest.java
new file mode 100644
index 000000000..e1aaeb581
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/bulkimport/populator/savings/SavingsWorkbookPopulateTest.java
@@ -0,0 +1,109 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.bulkimport.populator.savings;
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.GroupHelper;
+import org.apache.fineract.integrationtests.common.OfficeHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
+import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+
+public class SavingsWorkbookPopulateTest {
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+
+ @Before
+ public void setup(){
+ Utils.initializeRESTAssured();
+ this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+ this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+ }
+
+ @Test
+ public void testSavingsWorkbookPopulate() throws IOException {
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ //in order to populate helper sheets
+ OfficeHelper officeHelper=new OfficeHelper(requestSpec,responseSpec);
+ Integer outcome_office_creation=officeHelper.createOffice("02 May 2000");
+ Assert.assertNotNull("Could not create office" ,outcome_office_creation);
+
+ //in order to populate helper sheets
+ ClientHelper clientHelper=new ClientHelper(requestSpec,responseSpec);
+ Integer outcome_client_creation=clientHelper.createClient(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create client" ,outcome_client_creation);
+
+ //in order to populate helper sheets
+ GroupHelper groupHelper=new GroupHelper(requestSpec,responseSpec);
+ Integer outcome_group_creation=groupHelper.createGroup(requestSpec,responseSpec,true);
+ Assert.assertNotNull("Could not create group" ,outcome_group_creation);
+
+ //in order to populate helper sheets
+ StaffHelper staffHelper=new StaffHelper();
+ Integer outcome_staff_creation =staffHelper.createStaff(requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create staff",outcome_staff_creation);
+
+ SavingsProductHelper savingsProductHelper=new SavingsProductHelper();
+ String jsonSavingsProduct=savingsProductHelper.build();
+ Integer outcome_sp_creaction=savingsProductHelper.createSavingsProduct(jsonSavingsProduct,requestSpec,responseSpec);
+ Assert.assertNotNull("Could not create Savings product",outcome_sp_creaction);
+
+ SavingsAccountHelper savingsAccountHelper=new SavingsAccountHelper(requestSpec,responseSpec);
+ Workbook workbook=savingsAccountHelper.getSavingsWorkbook("dd MMMM yyyy");
+
+ Sheet officeSheet=workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ Row firstOfficeRow=officeSheet.getRow(1);
+ Assert.assertNotNull("No offices found ",firstOfficeRow.getCell(1));
+
+ Sheet clientSheet=workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME);
+ Row firstClientRow=clientSheet.getRow(1);
+ Assert.assertNotNull("No clients found ",firstClientRow.getCell(1));
+
+ Sheet groupSheet=workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME);
+ Row firstGroupRow=groupSheet.getRow(1);
+ Assert.assertNotNull("No groups found ",firstGroupRow.getCell(1));
+
+ Sheet staffSheet=workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME);
+ Row firstStaffRow=staffSheet.getRow(1);
+ Assert.assertNotNull("No staff found ",firstStaffRow.getCell(1));
+
+ Sheet productSheet=workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME);
+ Row firstProductRow=productSheet.getRow(1);
+ Assert.assertNotNull("No products found ",firstProductRow.getCell(1));
+
+ }
+}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java
index e79820b82..1fb2b4d28 100755
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/ClientHelper.java
@@ -20,15 +20,25 @@ package org.apache.fineract.integrationtests.common;
import static org.junit.Assert.assertEquals;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
import org.apache.fineract.integrationtests.common.system.CodeHelper;
import com.google.gson.Gson;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
public class ClientHelper {
@@ -591,4 +601,27 @@ public class ClientHelper {
return Utils.performServerGet(requestSpec, responseSpec, CHARGES_URL, "reversed");
}
+ public Workbook getClientEntityWorkbook(GlobalEntityType clientsEntity, String dateFormat) throws IOException {
+ requestSpec.header(HttpHeaders.CONTENT_TYPE,"application/vnd.ms-excel");
+ byte [] byteArray=Utils.performGetBinaryResponse(requestSpec,responseSpec,CLIENT_URL+"/downloadtemplate"+"?"+
+ Utils.TENANT_IDENTIFIER+"&legalFormType="+clientsEntity+"&dateFormat="+dateFormat);
+ InputStream inputStream= new ByteArrayInputStream(byteArray);
+ Workbook workbook=new HSSFWorkbook(inputStream);
+ return workbook;
+ }
+
+ public String getOutputTemplateLocation(final String importDocumentId){
+ requestSpec.header(HttpHeaders.CONTENT_TYPE,MediaType.TEXT_PLAIN);
+ return Utils.performServerOutputTemplateLocationGet(requestSpec,responseSpec,"/fineract-provider/api/v1/imports/getOutputTemplateLocation"+"?"
+ +Utils.TENANT_IDENTIFIER,importDocumentId);
+ }
+
+ public String importClientEntityTemplate(File file){
+ String locale="en";
+ String dateFormat="dd MMMM yyyy";
+ String legalFormType=GlobalEntityType.CLIENTS_ENTTTY.toString();
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA);
+ return Utils.performServerTemplatePost(requestSpec,responseSpec,CLIENT_URL+"/uploadtemplate"+"?"+Utils.TENANT_IDENTIFIER,
+ legalFormType,file,locale,dateFormat);
+ }
}
\ No newline at end of file
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
index efac104a6..a2674bac6 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
@@ -1,5 +1,3 @@
-package org.apache.fineract.integrationtests.common;
-
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,6 +16,7 @@ package org.apache.fineract.integrationtests.common;
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.fineract.integrationtests.common;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/OfficeHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/OfficeHelper.java
index 1571735d5..2940576f3 100755
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/OfficeHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/OfficeHelper.java
@@ -18,6 +18,10 @@
*/
package org.apache.fineract.integrationtests.common;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.HashMap;
import com.google.common.reflect.TypeToken;
@@ -25,6 +29,12 @@ import com.google.gson.Gson;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+
public class OfficeHelper {
private static final String OFFICE_URL = "/fineract-provider/api/v1/offices";
@@ -77,4 +87,27 @@ public class OfficeHelper {
System.out.println("map : " + map);
return new Gson().toJson(map);
}
+
+ public String importOfficeTemplate(File file){
+ String locale="en";
+ String dateFormat="dd MMMM yyyy";
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA);
+ return Utils.performServerTemplatePost(requestSpec,responseSpec,OFFICE_URL+"/uploadtemplate"+"?"+Utils.TENANT_IDENTIFIER,
+ null,file,locale,dateFormat);
+
+ }
+
+ public String getOutputTemplateLocation(final String importDocumentId){
+ requestSpec.header(HttpHeaders.CONTENT_TYPE,MediaType.TEXT_PLAIN);
+ return Utils.performServerOutputTemplateLocationGet(requestSpec,responseSpec,"/fineract-provider/api/v1/imports/getOutputTemplateLocation"+"?"
+ +Utils.TENANT_IDENTIFIER,importDocumentId);
+ }
+ public Workbook getOfficeWorkBook(final String dateFormat) throws IOException {
+ requestSpec.header(HttpHeaders.CONTENT_TYPE,"application/vnd.ms-excel");
+ byte[] byteArray=Utils.performGetBinaryResponse(requestSpec,responseSpec,OFFICE_URL+"/downloadtemplate"+"?"+
+ Utils.TENANT_IDENTIFIER+"&dateFormat="+dateFormat);
+ InputStream inputStream= new ByteArrayInputStream(byteArray);
+ Workbook workbook=new HSSFWorkbook(inputStream);
+ return workbook;
+ }
}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/Utils.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/Utils.java
index 3d173c309..5a7c12743 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/Utils.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/Utils.java
@@ -24,13 +24,11 @@ import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import java.io.File;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Locale;
-import java.util.Random;
-import java.util.TimeZone;
+import java.util.*;
import org.apache.commons.lang.StringUtils;
import org.apache.http.conn.HttpHostConnectException;
@@ -41,7 +39,6 @@ import com.jayway.restassured.RestAssured;
import com.jayway.restassured.path.json.JsonPath;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
-
/**
* Util for RestAssured tests. This class here in src/integrationTest is
* copy/pasted to src/test; please keep them in sync.
@@ -145,6 +142,16 @@ public class Utils {
public static String randomNameGenerator(final String prefix, final int lenOfRandomSuffix) {
return randomStringGenerator(prefix, lenOfRandomSuffix);
}
+ public static Long randomNumberGenerator(final int expectedLength){
+ final String source="1234567890";
+ final int lengthofSource=source.length();
+ final Random random=new Random();
+ StringBuilder stringBuilder=new StringBuilder(expectedLength);
+ for (int i = 0; i < expectedLength; i++) {
+ stringBuilder.append(source.charAt(random.nextInt(lengthofSource)));
+ }
+ return Long.parseLong(stringBuilder.toString());
+ }
public static String convertDateToURLFormat(final Calendar dateToBeConvert) {
DateFormat dateFormat = new SimpleDateFormat("dd MMMMMM yyyy");
@@ -165,4 +172,27 @@ public class Utils {
return TimeZone.getTimeZone(TENANT_TIME_ZONE);
}
+ public static String performServerTemplatePost(final RequestSpecification requestSpec,final ResponseSpecification responseSpec,
+ final String postURL,final String legalFormType,final File file,final String locale,final String dateFormat) {
+
+ final String importDocumentId=given().spec(requestSpec)
+ .queryParam("legalFormType",legalFormType)
+ .multiPart("file",file)
+ .formParam("locale",locale)
+ .formParam("dateFormat",dateFormat)
+ .expect().spec(responseSpec).
+ log().ifError().when().post(postURL)
+ .andReturn().asString();
+ return importDocumentId;
+ }
+
+ public static String performServerOutputTemplateLocationGet(final RequestSpecification requestSpec,final ResponseSpecification responseSpec,
+ final String getURL,final String importDocumentId){
+ final String templateLocation=given().spec(requestSpec).
+ queryParam("importDocumentId",importDocumentId)
+ .expect().spec(responseSpec)
+ .log().ifError().when().get(getURL)
+ .andReturn().asString();
+ return templateLocation.substring(1,templateLocation.length()-1);
+ }
}
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index 57fc3435b..19aa98b32 100755
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -21,18 +21,28 @@ package org.apache.fineract.integrationtests.common.loans;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.LocalDate;
import com.google.gson.Gson;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+
@SuppressWarnings({ "rawtypes", "unchecked" })
public class LoanTransactionHelper {
@@ -41,6 +51,7 @@ public class LoanTransactionHelper {
private static final String CREATE_LOAN_PRODUCT_URL = "/fineract-provider/api/v1/loanproducts?" + Utils.TENANT_IDENTIFIER;
private static final String APPLY_LOAN_URL = "/fineract-provider/api/v1/loans?" + Utils.TENANT_IDENTIFIER;
+ private static final String LOAN_ACCOUNT_URL="/fineract-provider/api/v1/loans";
private static final String APPROVE_LOAN_COMMAND = "approve";
private static final String UNDO_APPROVAL_LOAN_COMMAND = "undoApproval";
private static final String DISBURSE_LOAN_COMMAND = "disburse";
@@ -694,4 +705,29 @@ public class LoanTransactionHelper {
datatablesListMap.add(datatableMap);
return datatablesListMap;
}
+
+ public Workbook getLoanWorkbook(String dateFormat) throws IOException {
+ requestSpec.header(HttpHeaders.CONTENT_TYPE,"application/vnd.ms-excel");
+ byte[] byteArray=Utils.performGetBinaryResponse(requestSpec,responseSpec,LOAN_ACCOUNT_URL+"/downloadtemplate"+"?"+
+ Utils.TENANT_IDENTIFIER+"&dateFormat="+dateFormat);
+ InputStream inputStream= new ByteArrayInputStream(byteArray);
+ Workbook workbook=new HSSFWorkbook(inputStream);
+ return workbook;
+ }
+
+ public String importLoanTemplate(File file) {
+
+ String locale="en";
+ String dateFormat="dd MMMM yyyy";
+ String legalFormType= null;
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA);
+ return Utils.performServerTemplatePost(requestSpec,responseSpec,LOAN_ACCOUNT_URL+"/uploadtemplate"+"?"+Utils.TENANT_IDENTIFIER,
+ legalFormType,file,locale,dateFormat);
+ }
+
+ public String getOutputTemplateLocation(final String importDocumentId){
+ requestSpec.header(HttpHeaders.CONTENT_TYPE,MediaType.TEXT_PLAIN);
+ return Utils.performServerOutputTemplateLocationGet(requestSpec,responseSpec,"/fineract-provider/api/v1/imports/getOutputTemplateLocation"+"?"
+ +Utils.TENANT_IDENTIFIER,importDocumentId);
+ }
}
\ No newline at end of file
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java
index d0752a327..95522ebdb 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java
@@ -18,6 +18,10 @@
*/
package org.apache.fineract.integrationtests.common.savings;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
@@ -27,12 +31,17 @@ import java.util.Locale;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Workbook;
import org.junit.Assert;
import com.google.gson.Gson;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+
@SuppressWarnings({ "rawtypes" })
public class SavingsAccountHelper {
@@ -642,4 +651,28 @@ public class SavingsAccountHelper {
datatablesListMap.add(datatableMap);
return datatablesListMap;
}
+
+ public Workbook getSavingsWorkbook(String dateFormat) throws IOException {
+ requestSpec.header(HttpHeaders.CONTENT_TYPE,"application/vnd.ms-excel");
+ byte[] byteArray=Utils.performGetBinaryResponse(requestSpec,responseSpec,SAVINGS_ACCOUNT_URL+"/downloadtemplate"+"?"+
+ Utils.TENANT_IDENTIFIER+"&dateFormat="+dateFormat);
+ InputStream inputStream= new ByteArrayInputStream(byteArray);
+ Workbook workbook=new HSSFWorkbook(inputStream);
+ return workbook;
+ }
+
+ public String importSavingsTemplate(File file) {
+ String locale="en";
+ String dateFormat="dd MMMM yyyy";
+ String legalFormType= null;
+ requestSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA);
+ return Utils.performServerTemplatePost(requestSpec,responseSpec,SAVINGS_ACCOUNT_URL+"/uploadtemplate"+"?"+Utils.TENANT_IDENTIFIER,
+ legalFormType,file,locale,dateFormat);
+ }
+
+ public String getOutputTemplateLocation(final String importDocumentId){
+ requestSpec.header(HttpHeaders.CONTENT_TYPE,MediaType.TEXT_PLAIN);
+ return Utils.performServerOutputTemplateLocationGet(requestSpec,responseSpec,"/fineract-provider/api/v1/imports/getOutputTemplateLocation"+"?"
+ +Utils.TENANT_IDENTIFIER,importDocumentId);
+ }
}
\ No newline at end of file
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java
index 929e49e1b..a9269ef55 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java
@@ -60,7 +60,7 @@ public class SavingsProductHelper {
private String nameOfSavingsProduct = Utils.randomNameGenerator("SAVINGS_PRODUCT_", 6);
private String shortName = Utils.randomNameGenerator("", 4);
private String description = Utils.randomNameGenerator("", 20);
- private String interestCompoundingPeriodType = "2";
+ private String interestCompoundingPeriodType = "4";
private String interestPostingPeriodType = "4";
private String interestCalculationType = INTEREST_CALCULATION_USING_DAILY_BALANCE;
private String nominalAnnualInterestRate = "10.0";
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/api/GLAccountsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/api/GLAccountsApiResource.java
index 956b01482..f911b7c32 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/api/GLAccountsApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/api/GLAccountsApiResource.java
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.accounting.glaccount.api;
+import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@@ -35,10 +36,13 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import io.swagger.models.parameters.HeaderParameter;
+import com.sun.jersey.core.header.FormDataContentDisposition;
+import com.sun.jersey.multipart.FormDataParam;
import org.apache.fineract.accounting.common.AccountingConstants;
import org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService;
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
@@ -48,6 +52,9 @@ import org.apache.fineract.accounting.journalentry.data.JournalEntryAssociationP
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
+import org.apache.fineract.infrastructure.bulkimport.service.BulkImportWorkbookPopulatorService;
+import org.apache.fineract.infrastructure.bulkimport.service.BulkImportWorkbookService;
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
@@ -81,13 +88,19 @@ public class GLAccountsApiResource {
private final PlatformSecurityContext context;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final CodeValueReadPlatformService codeValueReadPlatformService;
+ private final BulkImportWorkbookService bulkImportWorkbookService;
+ private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
+
+
@Autowired
public GLAccountsApiResource(final PlatformSecurityContext context, final GLAccountReadPlatformService glAccountReadPlatformService,
final DefaultToApiJsonSerializer toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final AccountingDropdownReadPlatformService dropdownReadPlatformService,
- final CodeValueReadPlatformService codeValueReadPlatformService) {
+ final CodeValueReadPlatformService codeValueReadPlatformService,
+ final BulkImportWorkbookService bulkImportWorkbookService,
+ final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService) {
this.context = context;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
@@ -95,6 +108,8 @@ public class GLAccountsApiResource {
this.glAccountReadPlatformService = glAccountReadPlatformService;
this.dropdownReadPlatformService = dropdownReadPlatformService;
this.codeValueReadPlatformService = codeValueReadPlatformService;
+ this.bulkImportWorkbookService=bulkImportWorkbookService;
+ this.bulkImportWorkbookPopulatorService=bulkImportWorkbookPopulatorService;
}
@GET
@@ -236,4 +251,22 @@ public class GLAccountsApiResource {
}
return returnList;
}
+
+ @GET
+ @Path("downloadtemplate")
+ @Produces("application/vnd.ms-excel")
+ public Response getGlAccountsTemplate(@QueryParam("dateFormat") final String dateFormat) {
+ return bulkImportWorkbookPopulatorService.getTemplate(GlobalEntityType.CHART_OF_ACCOUNTS.toString(),null,null,dateFormat);
+ }
+
+ @POST
+ @Path("uploadtemplate")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public String postGlAccountsTemplate(@FormDataParam("file") InputStream uploadedInputStream,
+ @FormDataParam("file") FormDataContentDisposition fileDetail,
+ @FormDataParam("locale") final String locale, @FormDataParam("dateFormat") final String dateFormat){
+ Long importDocumentId= bulkImportWorkbookService.importWorkbook(GlobalEntityType.CHART_OF_ACCOUNTS.toString(), uploadedInputStream,fileDetail,
+ locale,dateFormat);
+ return this.apiJsonSerializerService.serialize(importDocumentId);
+ }
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/data/GLAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/data/GLAccountData.java
index aec22451e..63acf2a77 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/data/GLAccountData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/data/GLAccountData.java
@@ -62,6 +62,55 @@ public class GLAccountData {
final Collection allowedIncomeTagOptions;
final Collection allowedExpensesTagOptions;
+ //import fields
+ private transient Integer rowIndex;
+
+ public static GLAccountData importInstance(String name, Long parentId, String glCode, Boolean manualEntriesAllowed,
+ EnumOptionData type, EnumOptionData usage, String description, CodeValueData tagId,
+ Integer rowIndex){
+ return new GLAccountData(name,parentId,glCode,manualEntriesAllowed,type,
+ usage,description,tagId,rowIndex);
+ }
+
+ private GLAccountData(String name, Long parentId, String glCode, Boolean manualEntriesAllowed,
+ EnumOptionData type, EnumOptionData usage, String description, CodeValueData tagId,
+ Integer rowIndex) {
+
+ this.name = name;
+ this.parentId = parentId;
+ this.glCode = glCode;
+ this.manualEntriesAllowed = manualEntriesAllowed;
+ this.type = type;
+ this.usage = usage;
+ this.description = description;
+ this.tagId = tagId;
+ this.rowIndex = rowIndex;
+ this.id = null;
+ this.disabled = null;
+ this.nameDecorated = null;
+ this.organizationRunningBalance = null;
+ this.accountTypeOptions = null;
+ this.usageOptions = null;
+ this.assetHeaderAccountOptions = null;
+ this.liabilityHeaderAccountOptions = null;
+ this.equityHeaderAccountOptions = null;
+ this.incomeHeaderAccountOptions = null;
+ this.expenseHeaderAccountOptions = null;
+ this.allowedAssetsTagOptions = null;
+ this.allowedLiabilitiesTagOptions = null;
+ this.allowedEquityTagOptions = null;
+ this.allowedIncomeTagOptions = null;
+ this.allowedExpensesTagOptions = null;
+ }
+
+ public Integer getRowIndex() {
+ return rowIndex;
+ }
+
+ public CodeValueData getTagId() {
+ return tagId;
+ }
+
public GLAccountData(final Long id, final String name, final Long parentId, final String glCode, final boolean disabled,
final boolean manualEntriesAllowed, final EnumOptionData type, final EnumOptionData usage, final String description,
final String nameDecorated, final CodeValueData tagId, final Long organizationRunningBalance) {
@@ -195,4 +244,5 @@ public class GLAccountData {
return null;
}
+
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/domain/GLAccountType.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/domain/GLAccountType.java
index b9cf0024d..438faf61c 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/domain/GLAccountType.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/domain/GLAccountType.java
@@ -18,6 +18,8 @@
*/
package org.apache.fineract.accounting.glaccount.domain;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+
import java.util.HashMap;
import java.util.Map;
@@ -60,6 +62,27 @@ public enum GLAccountType {
i = i + 1;
}
}
+ public static EnumOptionData fromString(String accountType){
+ Long accountTypeId=null;
+ if (accountType!=null && accountType.equalsIgnoreCase(ASSET.toString())){
+ accountTypeId=1L;
+ return new EnumOptionData(accountTypeId,null,null);
+ }else if(accountType!=null && accountType.equalsIgnoreCase(LIABILITY.toString())) {
+ accountTypeId = 2L;
+ return new EnumOptionData(accountTypeId, null, null);
+ }else if(accountType!=null && accountType.equalsIgnoreCase(EQUITY.toString())){
+ accountTypeId=3L;
+ return new EnumOptionData(accountTypeId,null,null);
+ }else if(accountType!=null && accountType.equalsIgnoreCase(INCOME.toString())) {
+ accountTypeId = 4L;
+ return new EnumOptionData(accountTypeId, null, null);
+ }else if(accountType!=null && accountType.equalsIgnoreCase(EXPENSE.toString())){
+ accountTypeId=5L;
+ return new EnumOptionData(accountTypeId,null,null);
+ }else {
+ return null;
+ }
+ }
public static GLAccountType fromInt(final int i) {
final GLAccountType type = intToEnumMap.get(Integer.valueOf(i));
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountReadPlatformServiceImpl.java
index 4c008699f..26ad0e273 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountReadPlatformServiceImpl.java
@@ -123,11 +123,13 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
final GLAccountMapper rm = new GLAccountMapper(associationParametersData);
String sql = "select " + rm.schema();
// append SQL statement for fetching account totals
- if (associationParametersData.isRunningBalanceRequired()) {
- sql = sql + " and gl_j.id in (select t1.id from (select t2.account_id, max(t2.id) as id from "
- + "(select id, max(entry_date) as entry_date, account_id from acc_gl_journal_entry where is_running_balance_calculated = 1 "
- + "group by account_id desc) t3 inner join acc_gl_journal_entry t2 on t2.account_id = t3.account_id and t2.entry_date = t3.entry_date "
- + "group by t2.account_id desc) t1)";
+ if (associationParametersData!=null) {
+ if (associationParametersData.isRunningBalanceRequired()) {
+ sql = sql + " and gl_j.id in (select t1.id from (select t2.account_id, max(t2.id) as id from "
+ + "(select id, max(entry_date) as entry_date, account_id from acc_gl_journal_entry where is_running_balance_calculated = 1 "
+ + "group by account_id desc, id) t3 inner join acc_gl_journal_entry t2 on t2.account_id = t3.account_id and t2.entry_date = t3.entry_date "
+ + "group by t2.account_id desc) t1)";
+ }
}
final Object[] paramaterArray = new Object[3];
int arrayPos = 0;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/api/JournalEntriesApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/api/JournalEntriesApiResource.java
index 37f48d286..be2180004 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/api/JournalEntriesApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/api/JournalEntriesApiResource.java
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.accounting.journalentry.api;
+import java.io.InputStream;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
@@ -32,9 +33,12 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
+import com.sun.jersey.core.header.FormDataContentDisposition;
+import com.sun.jersey.multipart.FormDataParam;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.accounting.journalentry.command.JournalEntryCommand;
import org.apache.fineract.accounting.journalentry.command.SingleDebitOrCreditEntryCommand;
@@ -46,6 +50,9 @@ import org.apache.fineract.accounting.producttoaccountmapping.domain.PortfolioPr
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
+import org.apache.fineract.infrastructure.bulkimport.service.BulkImportWorkbookPopulatorService;
+import org.apache.fineract.infrastructure.bulkimport.service.BulkImportWorkbookService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
@@ -76,17 +83,24 @@ public class JournalEntriesApiResource {
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PlatformSecurityContext context;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+ private final BulkImportWorkbookService bulkImportWorkbookService;
+ private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
+
@Autowired
public JournalEntriesApiResource(final PlatformSecurityContext context,
final JournalEntryReadPlatformService journalEntryReadPlatformService,
final DefaultToApiJsonSerializer toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
- final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
+ final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
+ final BulkImportWorkbookService bulkImportWorkbookService,
+ final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService) {
this.context = context;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.apiJsonSerializerService = toApiJsonSerializer;
this.journalEntryReadPlatformService = journalEntryReadPlatformService;
+ this.bulkImportWorkbookService=bulkImportWorkbookService;
+ this.bulkImportWorkbookPopulatorService=bulkImportWorkbookPopulatorService;
}
@GET
@@ -222,4 +236,25 @@ public class JournalEntriesApiResource {
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
}
+
+ @GET
+ @Path("downloadtemplate")
+ @Produces("application/vnd.ms-excel")
+ public Response getJournalEntriesTemplate(@QueryParam("officeId") final Long officeId,
+ @QueryParam("dateFormat") final String dateFormat) {
+ return bulkImportWorkbookPopulatorService.getTemplate(GlobalEntityType.GL_JOURNAL_ENTRIES.toString(),
+ officeId,null,dateFormat);
+ }
+
+ @POST
+ @Path("uploadtemplate")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public String postJournalEntriesTemplate(@FormDataParam("file") InputStream uploadedInputStream,
+ @FormDataParam("file") FormDataContentDisposition fileDetail,
+ @FormDataParam("locale") final String locale,
+ @FormDataParam("dateFormat") final String dateFormat){
+ final Long importDocumentId =this.bulkImportWorkbookService.importWorkbook(GlobalEntityType.GL_JOURNAL_ENTRIES.toString(),
+ uploadedInputStream,fileDetail, locale,dateFormat);
+ return this.apiJsonSerializerService.serialize(importDocumentId);
+ }
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/CreditDebit.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/CreditDebit.java
new file mode 100644
index 000000000..0be9f1a2e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/CreditDebit.java
@@ -0,0 +1,31 @@
+/**
+ * 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.accounting.journalentry.data;
+
+import java.math.BigDecimal;
+
+public class CreditDebit {
+ private final Long glAccountId;
+ private final BigDecimal amount;
+
+ public CreditDebit(Long glAccountId, BigDecimal amount) {
+ this.glAccountId = glAccountId;
+ this.amount = amount;
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/JournalEntryData.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/JournalEntryData.java
index b6bb15dda..4c67d9980 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/JournalEntryData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/JournalEntryData.java
@@ -19,8 +19,10 @@
package org.apache.fineract.accounting.journalentry.data;
import java.math.BigDecimal;
+import java.util.List;
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.joda.time.LocalDate;
@@ -78,6 +80,91 @@ public class JournalEntryData {
@SuppressWarnings("unused")
private final TransactionDetailData transactionDetails;
+ //import fields
+ private transient Integer rowIndex;
+ private String dateFormat;
+ private String locale;
+ private List credits;
+ private List debits;
+ private Long paymentTypeId;
+ private String currencyCode;
+ private String accountNumber;
+ private String checkNumber;
+ private String routingCode;
+ private String receiptNumber;
+ private String bankNumber;
+
+ public static JournalEntryData importInstance(Long officeId,LocalDate transactionDate,String currencyCode, Long paymentTypeId,
+ Integer rowIndex,List credits, Listdebits,
+ String accountNumber,String checkNumber,String routingCode,String receiptNumber,String bankNumber,
+ String comments,String locale,String dateFormat){
+ return new JournalEntryData(officeId, transactionDate, currencyCode,
+ paymentTypeId, rowIndex, credits, debits,accountNumber,checkNumber,routingCode,
+ receiptNumber,bankNumber,comments,locale,dateFormat);
+ }
+ private JournalEntryData(Long officeId,LocalDate transactionDate,String currencyCode, Long paymentTypeId,
+ Integer rowIndex,List credits, Listdebits,
+ String accountNumber,String checkNumber,String routingCode,String receiptNumber,
+ String bankNumber,String comments,String locale,String dateFormat) {
+
+ this.officeId = officeId;
+ this.dateFormat= dateFormat;
+ this.locale= locale;
+ this.transactionDate = transactionDate;
+ this.currencyCode=currencyCode;
+ this.rowIndex = rowIndex;
+ this.credits = credits;
+ this.debits = debits;
+ this.paymentTypeId = paymentTypeId;
+ this.accountNumber=accountNumber;
+ this.checkNumber=checkNumber;
+ this.routingCode=routingCode;
+ this.receiptNumber=receiptNumber;
+ this.bankNumber=bankNumber;
+ this.comments=comments;
+ this.id = null;
+ this.officeName = null;
+ this.glAccountName = null;
+ this.glAccountId = null;
+ this.glAccountCode = null;
+ this.glAccountType = null;
+ this.entryType = null;
+ this.amount = null;
+ this.currency = null;
+ this.transactionId = null;
+ this.manualEntry = null;
+ this.entityType = null;
+ this.entityId = null;
+ this.createdByUserId = null;
+ this.createdDate = null;
+ this.createdByUserName = null;
+ this.reversed = null;
+ this.referenceNumber = null;
+ this.officeRunningBalance = null;
+ this.organizationRunningBalance = null;
+ this.runningBalanceComputed = null;
+ this.transactionDetails = null;
+ }
+
+ public Integer getRowIndex() {
+ return rowIndex;
+ }
+
+ public LocalDate getTransactionDate() {
+ return transactionDate;
+ }
+
+ public void addDebits(CreditDebit debit) {
+
+ this.debits.add(debit);
+ }
+
+
+
+ public void addCredits(CreditDebit credit) {
+ this.credits.add(credit);
+ }
+
public JournalEntryData(final Long id, final Long officeId, final String officeName, final String glAccountName,
final Long glAccountId, final String glAccountCode, final EnumOptionData glAccountClassification,
final LocalDate transactionDate, final EnumOptionData entryType, final BigDecimal amount, final String transactionId,
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryReadPlatformServiceImpl.java
index 49efaa03b..928ed40b7 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryReadPlatformServiceImpl.java
@@ -49,6 +49,7 @@ import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.fineract.organisation.office.service.OfficeReadPlatformService;
@@ -74,18 +75,22 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
private final JdbcTemplate jdbcTemplate;
private final GLAccountReadPlatformService glAccountReadPlatformService;
private final OfficeReadPlatformService officeReadPlatformService;
+ private final ColumnValidator columnValidator;
private final FinancialActivityAccountRepositoryWrapper financialActivityAccountRepositoryWrapper;
private final PaginationHelper paginationHelper = new PaginationHelper<>();
@Autowired
public JournalEntryReadPlatformServiceImpl(final RoutingDataSource dataSource,
- final GLAccountReadPlatformService glAccountReadPlatformService, final OfficeReadPlatformService officeReadPlatformService,
+ final GLAccountReadPlatformService glAccountReadPlatformService,
+ final ColumnValidator columnValidator,
+ final OfficeReadPlatformService officeReadPlatformService,
final FinancialActivityAccountRepositoryWrapper financialActivityAccountRepositoryWrapper) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.glAccountReadPlatformService = glAccountReadPlatformService;
this.officeReadPlatformService = officeReadPlatformService;
this.financialActivityAccountRepositoryWrapper = financialActivityAccountRepositoryWrapper;
+ this.columnValidator = columnValidator;
}
private static final class GLJournalEntryMapper implements RowMapper {
@@ -356,9 +361,11 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
if (searchParameters.isOrderByRequested()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
-
+ this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
+
if (searchParameters.isSortOrderProvided()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
+ this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
}
} else {
sqlBuilder.append(" order by journalEntry.entry_date, journalEntry.id");
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocJsonInputParams.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocJsonInputParams.java
index 0cb33844e..a797a0f98 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocJsonInputParams.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/api/AdHocJsonInputParams.java
@@ -25,7 +25,10 @@ import java.util.Set;
* Enum of all parameters passed in while creating/updating a AdHocQuery
***/
public enum AdHocJsonInputParams {
- ID("id"), NAME("name"),QUERY("query"),TABLENAME("tableName"),TABLEFIELD("tableFields"), ISACTIVE("isActive"),EMAIL("email");
+ ID("id"), NAME("name"),QUERY("query"),TABLENAME("tableName"), TABLEFIELDS("tableFields"), ISACTIVE("isActive"),
+ REPORT_RUN_FREQUENCY("reportRunFrequency"),
+ REPORT_RUN_EVERY("reportRunEvery"),
+ EMAIL("email");
private final String value;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/data/AdHocData.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/data/AdHocData.java
index f0fd7a858..81cfc9199 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/data/AdHocData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/data/AdHocData.java
@@ -18,13 +18,13 @@
*/
package org.apache.fineract.adhocquery.data;
-import java.util.Collection;
-
-import org.apache.fineract.organisation.office.data.OfficeData;
-import org.apache.fineract.useradministration.data.AppUserData;
-import org.apache.fineract.useradministration.data.RoleData;
+import org.apache.fineract.adhocquery.domain.ReportRunFrequency;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
/**
* Immutable data object represent note or case information AdHocData
@@ -32,8 +32,8 @@ import org.joda.time.LocalDate;
*/
public class AdHocData {
-
-
+
+
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
@@ -59,13 +59,19 @@ public class AdHocData {
@SuppressWarnings("unused")
private final String createdBy;
-
-
+ private final List reportRunFrequencies;
- public AdHocData(final Long id, final String name,final String query, final String tableName,final String tableFields,
- final boolean isActive, final DateTime createdOn, final Long createdById,final Long updatedById,
- final DateTime updatedOn,final String createdBy,final String email
- ) {
+ private final Long reportRunFrequency;
+
+ private final Long reportRunEvery;
+
+ private final DateTime lastRun;
+
+ public AdHocData(final Long id, final String name, final String query, final String tableName, final String tableFields,
+ final boolean isActive, final DateTime createdOn, final Long createdById, final Long updatedById,
+ final DateTime updatedOn, final String createdBy, final String email,
+ final List reportRunFrequencies, final Long reportRunFrequency, final Long reportRunEvery,
+ final DateTime lastRun) {
this.id = id;
this.name=name;
this.query=query;
@@ -78,9 +84,17 @@ public class AdHocData {
this.updatedOn=updatedOn;
this.createdBy=createdBy;
this.email=email;
+ this.reportRunFrequencies = reportRunFrequencies;
+ this.reportRunFrequency = reportRunFrequency;
+ this.reportRunEvery = reportRunEvery;
+ this.lastRun = lastRun;
}
public static AdHocData template() {
- AdHocData adHocData = new AdHocData(null,null,null,null,null,false,null,null,null,null,null,null);
+ List reportRunFrequencies = Arrays.stream(ReportRunFrequency.values()).map(rrf -> new EnumOptionData(
+ (long) rrf.getValue(), rrf.getCode(), rrf.getCode()
+ )).collect(Collectors.toList());
+
+ AdHocData adHocData = new AdHocData(null,null,null,null,null,false,null,null,null,null,null,null, reportRunFrequencies, null, null, null);
return adHocData;
}
public Long getId() {
@@ -119,4 +133,16 @@ public class AdHocData {
public String getCreatedBy() {
return this.createdBy;
}
+ public List getReportRunFrequencies() {
+ return this.reportRunFrequencies;
+ }
+ public Long getReportRunFrequency() {
+ return this.reportRunFrequency;
+ }
+ public Long getReportRunEvery() {
+ return this.reportRunEvery;
+ }
+ public DateTime getLastRun() {
+ return this.lastRun;
+ }
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHoc.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHoc.java
index be315ba99..54f98f37d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHoc.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/AdHoc.java
@@ -53,17 +53,24 @@ public class AdHoc extends AbstractAuditableCustom {
@Column(name = "email", length = 500)
private String email;
-
-
+
+ @Column(name = "report_run_frequency_code")
+ private Long reportRunFrequency;
+
+ @Column(name = "report_run_every")
+ private Long reportRunEvery;
+
@Column(name = "IsActive", nullable = false)
private boolean isActive = false;
- private AdHoc(final String name, final String query,final String tableName,final String tableFields ,final String email,final boolean isActive) {
+ private AdHoc(final String name, final String query,final String tableName,final String tableFields ,final String email, final Long reportRunFrequency, final Long reportRunEvery, final boolean isActive) {
this.name = StringUtils.defaultIfEmpty(name, null);
this.query=StringUtils.defaultIfEmpty(query,null);
this.tableName=StringUtils.defaultIfEmpty(tableName,null);
this.tableFields=StringUtils.defaultIfEmpty(tableFields,null);
this.email=StringUtils.defaultIfEmpty(email,null);
+ this.reportRunFrequency = reportRunFrequency;
+ this.reportRunEvery = reportRunEvery;
this.isActive = BooleanUtils.toBooleanDefaultIfNull(isActive, false);
}
@@ -75,10 +82,12 @@ public class AdHoc extends AbstractAuditableCustom {
SQLInjectionValidator.validateAdhocQuery(commandQuery);
final String query = commandQuery;
final String tableName = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLENAME.getValue());
- final String tableFields = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLEFIELD.getValue());
+ final String tableFields = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLEFIELDS.getValue());
final String email = command.stringValueOfParameterNamed(AdHocJsonInputParams.EMAIL.getValue());
+ final Long reportRunFrequency = command.longValueOfParameterNamed(AdHocJsonInputParams.REPORT_RUN_FREQUENCY.getValue());
+ final Long reportRunEvery = command.longValueOfParameterNamed(AdHocJsonInputParams.REPORT_RUN_EVERY.getValue());
final boolean isActive = command.booleanPrimitiveValueOfParameterNamed(AdHocJsonInputParams.ISACTIVE.getValue());
- return new AdHoc(name,query,tableName,tableFields ,email,isActive);
+ return new AdHoc(name,query,tableName,tableFields, email, reportRunFrequency, reportRunEvery, isActive);
}
public Map update(final JsonCommand command) {
@@ -104,7 +113,7 @@ public class AdHoc extends AbstractAuditableCustom {
actualChanges.put(tableName, newValue);
this.tableName = newValue;
}
- final String tableField = "tableField";
+ final String tableField = "tableFields";
if (command.isChangeInStringParameterNamed(tableField, this.tableFields)) {
final String newValue = command.stringValueOfParameterNamed(tableField);
actualChanges.put(tableField, newValue);
@@ -116,6 +125,18 @@ public class AdHoc extends AbstractAuditableCustom {
actualChanges.put(email, newValue);
this.email = newValue;
}
+ final String reportRunFrequency = "reportRunFrequency";
+ if (command.isChangeInLongParameterNamed(reportRunFrequency, this.getReportRunFrequency())) {
+ final Long newValue = command.longValueOfParameterNamed(reportRunFrequency);
+ actualChanges.put(reportRunFrequency, newValue);
+ this.reportRunFrequency = newValue;
+ }
+ final String reportRunEvery = "reportRunEvery";
+ if (command.isChangeInLongParameterNamed(reportRunEvery, this.getReportRunEvery())) {
+ final Long newValue = command.longValueOfParameterNamed(reportRunEvery);
+ actualChanges.put(reportRunEvery, newValue);
+ this.reportRunEvery = newValue;
+ }
final String paramisActive = "isActive";
if (command.isChangeInBooleanParameterNamed(paramisActive, this.isActive)) {
final Boolean newValue = command.booleanObjectValueOfParameterNamed(paramisActive);
@@ -149,5 +170,10 @@ public class AdHoc extends AbstractAuditableCustom {
public void enableActive() {
this.isActive = false;
}
-
+ public Long getReportRunFrequency() {
+ return this.reportRunFrequency;
+ }
+ public Long getReportRunEvery() {
+ return this.reportRunEvery;
+ }
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/ReportRunFrequency.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/ReportRunFrequency.java
new file mode 100644
index 000000000..fc02d4bc7
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/domain/ReportRunFrequency.java
@@ -0,0 +1,55 @@
+/**
+ * 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.adhocquery.domain;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public enum ReportRunFrequency {
+ DAILY(1, "reportRunFrequency.daily"),
+ WEEKLY(2, "reportRunFrequency.weekly"),
+ MONTHLY(3, "reportRunFrequency.monthly"),
+ YEARLY(4, "reportRunFrequency.yearly"),
+ CUSTOM(5, "reportRunFrequency.custom");
+
+ private static final Map MAP = Arrays.stream(ReportRunFrequency.values()).collect(Collectors.toMap(
+ ReportRunFrequency::getValue, e -> e
+ ));
+
+ private final long value;
+ private final String code;
+
+ private ReportRunFrequency(final long value, final String code) {
+ this.value = value;
+ this.code = code;
+ }
+
+ public long getValue() {
+ return this.value;
+ }
+
+ public String getCode() {
+ return this.code;
+ }
+
+ public static ReportRunFrequency fromId(final long id) {
+ return ReportRunFrequency.MAP.get(id);
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocDataValidator.java
index 2cdd294a9..9cb13e8ce 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocDataValidator.java
@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.adhocquery.domain.ReportRunFrequency;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
@@ -44,7 +45,9 @@ public final class AdHocDataValidator {
/**
* The parameters supported for this command.
*/
- private final Set supportedParameters = new HashSet<>(Arrays.asList("name","query","tableName","tableFields","email","isActive"));
+ private final Set supportedParameters = new HashSet<>(Arrays.asList(
+ "name","query","tableName","tableFields","email","isActive", "reportRunFrequency", "reportRunEvery"
+ ));
private final FromJsonHelper fromApiJsonHelper;
@@ -77,7 +80,19 @@ public final class AdHocDataValidator {
baseDataValidator.reset().parameter("tableFields").value(tableFields).notBlank().notExceedingLengthOf(1000);
final String email = this.fromApiJsonHelper.extractStringNamed("email", element);
- baseDataValidator.reset().parameter("email").value(email).notBlank().notExceedingLengthOf(500);
+ baseDataValidator.reset().parameter("email").value(email).ignoreIfNull().notExceedingLengthOf(500);
+
+ final Long reportRunFrequencyCode = this.fromApiJsonHelper.extractLongNamed("reportRunFrequency", element);
+ if (reportRunFrequencyCode != null) {
+ baseDataValidator.reset().parameter("reportRunFrequency").value(reportRunFrequencyCode)
+ .inMinMaxRange((int) ReportRunFrequency.DAILY.getValue(), (int) ReportRunFrequency.CUSTOM.getValue());
+ }
+
+ final Long reportRunEvery = this.fromApiJsonHelper.extractLongNamed("reportRunEvery", element);
+ if (reportRunEvery != null) {
+ baseDataValidator.reset().parameter("reportRunEvery").value(reportRunFrequencyCode).integerGreaterThanZero();
+ }
+
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
@@ -111,7 +126,16 @@ public final class AdHocDataValidator {
}
if (this.fromApiJsonHelper.parameterExists("email", element)) {
final String email = this.fromApiJsonHelper.extractStringNamed("email", element);
- baseDataValidator.reset().parameter("email").value(email).notBlank().notExceedingLengthOf(500);
+ baseDataValidator.reset().parameter("email").value(email).ignoreIfNull().notExceedingLengthOf(500);
+ }
+ if (this.fromApiJsonHelper.parameterExists("reportRunFrequency", element)) {
+ final Long reportRunFrequencyCode = this.fromApiJsonHelper.extractLongNamed("reportRunFrequency", element);
+ baseDataValidator.reset().parameter("reportRunFrequency").value(reportRunFrequencyCode)
+ .inMinMaxRange((int) ReportRunFrequency.DAILY.getValue(), (int) ReportRunFrequency.CUSTOM.getValue());
+ }
+ if (this.fromApiJsonHelper.parameterExists("reportRunEvery", element)) {
+ final Long reportRunEvery = this.fromApiJsonHelper.extractLongNamed("reportRunEvery", element);
+ baseDataValidator.reset().parameter("reportRunEvery").value(reportRunEvery).integerGreaterThanZero();
}
/*if (this.fromApiJsonHelper.parameterExists("isActive", element)) {
final Integer isActive = this.fromApiJsonHelper.extractIntegerNamed("isActive", element, Locale.getDefault());
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformServiceImpl.java
index eb1f6335e..c5c7a0af6 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocReadPlatformServiceImpl.java
@@ -88,13 +88,17 @@ public class AdHocReadPlatformServiceImpl implements AdHocReadPlatformService {
final DateTime updatedOn=JdbcSupport.getDateTime(rs, "updatedOn");
final String createdByUsername=rs.getString("createdBy");
final String email=rs.getString("email");
-
- return new AdHocData(id,name,query, tableName,tableFields,isActive,createdDate,createdById,updatedById,updatedOn,createdByUsername,email);
+ final Long reportRunFrequency=JdbcSupport.getLong(rs, "report_run_frequency_code");
+ final Long reportRunEvery=JdbcSupport.getLong(rs, "report_run_every");
+ final DateTime lastRun = JdbcSupport.getDateTime(rs, "last_run");
+
+ return new AdHocData(id,name,query, tableName,tableFields,isActive,createdDate,createdById,updatedById,updatedOn,createdByUsername,email, AdHocData.template().getReportRunFrequencies(), reportRunFrequency, reportRunEvery, lastRun);
}
public String schema() {
return " r.id as id, r.name as name, r.query as query, r.table_name as tableName,r.table_fields as tableField ,r.IsActive as isActive ,r.email as email ,"
- +" r.created_date as createdDate, r.createdby_id as createdById,cb.username as createdBy,r.lastmodifiedby_id as updatedById ,r.lastmodified_date as updatedOn "
+ + " r.report_run_frequency_code, r.report_run_every, r.last_run, "
+ + " r.created_date as createdDate, r.createdby_id as createdById,cb.username as createdBy,r.lastmodifiedby_id as updatedById ,r.lastmodified_date as updatedOn "
+ " from m_adhoc r left join m_appuser cb on cb.id=r.createdby_id left join m_appuser mb on mb.id=r.lastmodifiedby_id";
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java
index d10cdddec..c92121c98 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/adhocquery/service/AdHocScheduledJobRunnerServiceImpl.java
@@ -18,13 +18,17 @@
*/
package org.apache.fineract.adhocquery.service;
-import java.util.Collection;
-
import org.apache.fineract.adhocquery.data.AdHocData;
+import org.apache.fineract.adhocquery.domain.ReportRunFrequency;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
import org.apache.fineract.infrastructure.jobs.service.JobName;
+import org.joda.time.DateTime;
+import org.joda.time.Days;
+import org.joda.time.LocalDate;
+import org.joda.time.Months;
+import org.joda.time.Years;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -32,6 +36,9 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.util.Collection;
+import java.util.Date;
+
@Service(value = "adHocScheduledJobRunnerService")
public class AdHocScheduledJobRunnerServiceImpl implements AdHocScheduledJobRunnerService {
@@ -47,6 +54,7 @@ public class AdHocScheduledJobRunnerServiceImpl implements AdHocScheduledJobRunn
this.adHocReadPlatformService = adHocReadPlatformService;
}
+
@Transactional
@Override
@CronTarget(jobName = JobName.GENERATE_ADHOCCLIENT_SCEHDULE)
@@ -54,16 +62,56 @@ public class AdHocScheduledJobRunnerServiceImpl implements AdHocScheduledJobRunn
final Collection adhocs = this.adHocReadPlatformService.retrieveAllActiveAdHocQuery();
if(adhocs.size()>0){
adhocs.forEach(adhoc->{
- //jdbcTemplate.execute("truncate table "+adhoc.getTableName());
- final StringBuilder insertSqlBuilder = new StringBuilder(900);
- insertSqlBuilder
- .append("INSERT INTO ")
- .append(adhoc.getTableName()+"(")
- .append(adhoc.getTableFields()+") ")
- .append(adhoc.getQuery());
- if (insertSqlBuilder.length() > 0) {
- final int result = this.jdbcTemplate.update(insertSqlBuilder.toString());
- logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by inserted: " + result);
+ boolean run = true;
+ LocalDate next = null;
+ if (adhoc.getReportRunFrequency() != null) {
+ if (adhoc.getLastRun() != null) {
+ LocalDate start = adhoc.getLastRun().toLocalDate();
+ LocalDate end = new DateTime().toLocalDate();
+ switch (ReportRunFrequency.fromId(adhoc.getReportRunFrequency())) {
+ case DAILY:
+ next = start.plusDays(1);
+ run = Days.daysBetween(start, end).getDays() >= 1;
+ break;
+ case WEEKLY:
+ next = start.plusDays(7);
+ run = Days.daysBetween(start, end).getDays() >= 7;
+ break;
+ case MONTHLY:
+ next = start.plusMonths(1);
+ run = Months.monthsBetween(start, end).getMonths() >= 1;
+ break;
+ case YEARLY:
+ next = start.plusYears(1);
+ run = Years.yearsBetween(start, end).getYears() >= 1;
+ break;
+ case CUSTOM:
+ next = start.plusDays((int) (long) adhoc.getReportRunEvery());
+ run = Days.daysBetween(start, end).getDays() >= adhoc.getReportRunEvery();
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+
+ }
+ }
+
+ if (run) {
+ //jdbcTemplate.execute("truncate table "+adhoc.getTableName());
+ final StringBuilder insertSqlBuilder = new StringBuilder(900);
+ insertSqlBuilder
+ .append("INSERT INTO ")
+ .append(adhoc.getTableName()+"(")
+ .append(adhoc.getTableFields()+") ")
+ .append(adhoc.getQuery());
+ if (insertSqlBuilder.length() > 0) {
+ final int result = this.jdbcTemplate.update(insertSqlBuilder.toString());
+ logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by inserted: " + result);
+
+ this.jdbcTemplate.update("UPDATE m_adhoc SET last_run=? WHERE id=?", new Date(), adhoc.getId());
+ }
+ } else {
+ logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Skipping execution of " + adhoc.getName() + ", scheduled for execution on " + next);
}
});
}else{
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformServiceImpl.java
index 1315055ba..447fbb565 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/AuditReadPlatformServiceImpl.java
@@ -218,12 +218,14 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), extraCriteria);
if (parameters.isOrderByRequested()) {
sqlBuilder.append(' ').append(parameters.orderBySql());
+ this.columnValidator.validateSqlInjection(sqlBuilder.toString(), parameters.orderBySql());
} else {
sqlBuilder.append(' ').append(' ').append(" order by aud.id DESC");
}
if (parameters.isLimited()) {
sqlBuilder.append(' ').append(parameters.limitSql());
+ this.columnValidator.validateSqlInjection(sqlBuilder.toString(), parameters.limitSql());
}
logger.info("sql: " + sqlBuilder.toString());
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/api/BulkImportApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/api/BulkImportApiResource.java
new file mode 100644
index 000000000..854ea7988
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/api/BulkImportApiResource.java
@@ -0,0 +1,114 @@
+/**
+ * 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.api;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
+import org.apache.fineract.infrastructure.bulkimport.data.ImportData;
+import org.apache.fineract.infrastructure.bulkimport.exceptions.ImportTypeNotFoundException;
+import org.apache.fineract.infrastructure.bulkimport.service.BulkImportWorkbookService;
+import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
+import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
+import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import org.apache.fineract.infrastructure.documentmanagement.data.DocumentData;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Path("/imports")
+@Component
+@Scope("singleton")
+public class BulkImportApiResource {
+
+ private final String resourceNameForPermissions = "IMPORT";
+
+ private final PlatformSecurityContext context;
+ private final BulkImportWorkbookService bulkImportWorkbookService;
+ private final DefaultToApiJsonSerializer toApiJsonSerializer;
+ private final ApiRequestParameterHelper apiRequestParameterHelper;
+
+ @Autowired
+ public BulkImportApiResource(final PlatformSecurityContext context,
+ final BulkImportWorkbookService bulkImportWorkbookService,
+ final DefaultToApiJsonSerializer toApiJsonSerializer,
+ final ApiRequestParameterHelper apiRequestParameterHelper) {
+ this.context = context;
+ this.bulkImportWorkbookService = bulkImportWorkbookService;
+ this.toApiJsonSerializer = toApiJsonSerializer;
+ this.apiRequestParameterHelper = apiRequestParameterHelper;
+ }
+
+
+ @GET
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public String retrieveImportDocuments(@Context final UriInfo uriInfo,
+ @QueryParam("entityType") final String entityType) {
+
+ this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
+ Collection importData=new ArrayList<>();
+ if (entityType.equals(GlobalEntityType.CLIENT.getCode())){
+ final Collection importForClientEntity = this.bulkImportWorkbookService.getImports(GlobalEntityType.CLIENTS_ENTTTY);
+ final Collection importForClientPerson=this.bulkImportWorkbookService.getImports(GlobalEntityType.CLIENTS_PERSON);
+ if (importForClientEntity!=null)
+ importData.addAll(importForClientEntity);
+ if (importForClientPerson!=null)
+ importData.addAll(importForClientPerson);
+ }else {
+ final GlobalEntityType type = GlobalEntityType.fromCode(entityType);
+ if (type == null)
+ throw new ImportTypeNotFoundException(entityType);
+ importData = this.bulkImportWorkbookService.getImports(type);
+ }
+ final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+ return this.toApiJsonSerializer.serialize(settings, importData);
+ }
+
+ @GET
+ @Path("getOutputTemplateLocation")
+ public String retriveOutputTemplateLocation(@QueryParam("importDocumentId")final String importDocumentId ){
+ this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
+ final DocumentData documentData =this.bulkImportWorkbookService.getOutputTemplateLocation(importDocumentId);
+ return this.toApiJsonSerializer.serialize(documentData.fileLocation());
+ }
+
+ @GET
+ @Path("downloadOutputTemplate")
+ @Produces("application/vnd.ms-excel")
+ public Response getOutputTemplate(@QueryParam("importDocumentId") final String importDocumentId) {
+ return bulkImportWorkbookService.getOutputTemplate(importDocumentId);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/CenterConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/CenterConstants.java
new file mode 100644
index 000000000..007222118
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/CenterConstants.java
@@ -0,0 +1,51 @@
+/**
+ * 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 class CenterConstants {
+
+ //Column indices
+ public static final int CENTER_NAME_COL = 0;//A
+ public static final int OFFICE_NAME_COL = 1;//B
+ public static final int STAFF_NAME_COL = 2;//C
+ public static final int EXTERNAL_ID_COL = 3;//D
+ public static final int ACTIVE_COL = 4;//E
+ public static final int ACTIVATION_DATE_COL = 5;//F
+ public static final int SUBMITTED_ON_DATE_COL=6;//G
+ public static final int MEETING_START_DATE_COL = 7;//H
+ public static final int IS_REPEATING_COL = 8;//I
+ public static final int FREQUENCY_COL = 9;//J
+ public static final int INTERVAL_COL = 10;//K
+ public static final int REPEATS_ON_DAY_COL = 11;//L
+ public static final int STATUS_COL = 12;//M
+ public static final int CENTER_ID_COL = 13;//N
+ public static final int FAILURE_COL = 14;//O
+ public static final int GROUP_NAMES_STARTING_COL = 15;//P
+ public static final int GROUP_NAMES_ENDING_COL = 250;//IQ
+ public static final int LOOKUP_OFFICE_NAME_COL = 251;
+ public static final int LOOKUP_OFFICE_OPENING_DATE_COL = 252;
+ public static final int LOOKUP_REPEAT_NORMAL_COL = 253;
+ public static final int LOOKUP_REPEAT_MONTHLY_COL = 254;
+ public static final int LOOKUP_IF_REPEAT_WEEKLY_COL = 255;
+
+
+
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ChartOfAcountsConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ChartOfAcountsConstants.java
new file mode 100644
index 000000000..02255c2b1
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ChartOfAcountsConstants.java
@@ -0,0 +1,38 @@
+/**
+ * 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 class ChartOfAcountsConstants {
+ public static final int ACCOUNT_TYPE_COL=0;//A
+ public static final int ACCOUNT_NAME_COL=1;//B
+ public static final int ACCOUNT_USAGE_COL=2;//C
+ public static final int MANUAL_ENTRIES_ALLOWED_COL=3;//D
+ public static final int PARENT_COL=4;//E
+ public static final int PARENT_ID_COL=5;//F
+ public static final int GL_CODE_COL=6;//G
+ public static final int TAG_COL=7;//H
+ public static final int TAG_ID_COL=8;//I
+ public static final int DESCRIPTION_COL=9;//J
+ public static final int LOOKUP_ACCOUNT_TYPE_COL=15;// P
+ public static final int LOOKUP_ACCOUNT_NAME_COL=16; //Q
+ public static final int LOOKUP_ACCOUNT_ID_COL=17;//R
+ public static final int LOOKUP_TAG_COL=18; //S
+ public static final int LOOKUP_TAG_ID_COL=19; //T
+ public static final int STATUS_COL=20;
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ClientEntityConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ClientEntityConstants.java
new file mode 100644
index 000000000..f8ec57387
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ClientEntityConstants.java
@@ -0,0 +1,61 @@
+/**
+ * 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 class ClientEntityConstants {
+
+ public static final int NAME_COL = 0;//A
+ public static final int OFFICE_NAME_COL = 1;//B
+ public static final int STAFF_NAME_COL = 2;//C
+ public static final int INCOPORATION_DATE_COL = 3;//D
+ public static final int INCOPORATION_VALID_TILL_COL = 4; //E
+ public static final int MOBILE_NO_COL=5;//F
+ public static final int CLIENT_TYPE_COL=6;//G
+ public static final int CLIENT_CLASSIFICATION_COL=7;//H
+ public static final int INCOPORATION_NUMBER_COL=8;//I
+ public static final int MAIN_BUSINESS_LINE=9;//J
+ public static final int CONSTITUTION_COL=10;//K
+ public static final int REMARKS_COL=11;//L
+ public static final int EXTERNAL_ID_COL=12;//M
+ public static final int ACTIVE_COL = 13;//N
+ public static final int ACTIVATION_DATE_COL = 14;//O
+ public static final int SUBMITTED_ON_COL=15; //P
+ public static final int ADDRESS_ENABLED=16;//Q
+ public static final int ADDRESS_TYPE_COL=17;//R
+ public static final int STREET_COL=18;//S
+ public static final int ADDRESS_LINE_1_COL=19;//T
+ public static final int ADDRESS_LINE_2_COL=20;//U
+ public static final int ADDRESS_LINE_3_COL=21;//V
+ public static final int CITY_COL =22;//W
+ public static final int STATE_PROVINCE_COL=23;//X
+ public static final int COUNTRY_COL=24;//Y
+ public static final int POSTAL_CODE_COL=25;//Z
+ public static final int IS_ACTIVE_ADDRESS_COL=26;//AA
+ public static final int WARNING_COL = 26;//AA
+ public static final int STATUS_COL = 27;//AB
+ public static final int RELATIONAL_OFFICE_NAME_COL = 35;//AJ
+ public static final int RELATIONAL_OFFICE_OPENING_DATE_COL = 36;//AK
+ public static final int LOOKUP_CONSTITUTION_COL = 37;//AL
+ public static final int LOOKUP_CLIENT_CLASSIFICATION = 38;//AM
+ public static final int LOOKUP_CLIENT_TYPES = 39;//AN
+ public static final int LOOKUP_ADDRESS_TYPE = 40;//AO
+ public static final int LOOKUP_STATE_PROVINCE = 41;//AP
+ public static final int LOOKUP_COUNTRY = 42;//AQ
+ public static final int LOOKUP_MAIN_BUSINESS_LINE=43;//AR
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ClientPersonConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ClientPersonConstants.java
new file mode 100644
index 000000000..5da827019
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/ClientPersonConstants.java
@@ -0,0 +1,58 @@
+/**
+ * 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 class ClientPersonConstants {
+ public static final int FIRST_NAME_COL = 0;//A
+ public static final int LAST_NAME_COL = 1;//B
+ public static final int MIDDLE_NAME_COL = 2;//C
+ public static final int OFFICE_NAME_COL = 3;//D
+ public static final int STAFF_NAME_COL = 4;//E
+ public static final int EXTERNAL_ID_COL = 5;//F
+ public static final int ACTIVE_COL = 6;//G
+ public static final int ACTIVATION_DATE_COL = 7;//H
+ public static final int SUBMITTED_ON_COL=8; //I
+ public static final int MOBILE_NO_COL=9;//J
+ public static final int DOB_COL=10;//K
+ public static final int CLIENT_TYPE_COL=11;//L
+ public static final int GENDER_COL=12;//M
+ public static final int CLIENT_CLASSIFICATION_COL=13;//N
+ public static final int IS_STAFF_COL=14;//O
+ public static final int ADDRESS_ENABLED_COL=15;// P
+ public static final int ADDRESS_TYPE_COL=16;//Q
+ public static final int STREET_COL=17;//R
+ public static final int ADDRESS_LINE_1_COL=18;//S
+ public static final int ADDRESS_LINE_2_COL=19;//T
+ public static final int ADDRESS_LINE_3_COL=20;//U
+ public static final int CITY_COL=21;//V
+ public static final int STATE_PROVINCE_COL=22;//W
+ public static final int COUNTRY_COL=23;//X
+ public static final int POSTAL_CODE_COL=24;//Y
+ public static final int IS_ACTIVE_ADDRESS_COL=25;//Z
+ public static final int WARNING_COL = 26;//AA
+ public static final int STATUS_COL = 27;//AB
+ public static final int RELATIONAL_OFFICE_NAME_COL = 35;//AJ
+ public static final int RELATIONAL_OFFICE_OPENING_DATE_COL = 36;//AK
+ public static final int LOOKUP_GENDER_COL = 37;//AL
+ public static final int LOOKUP_CLIENT_CLASSIFICATION_COL = 38;//AM
+ public static final int LOOKUP_CLIENT_TYPES_COL = 39;//AN
+ public static final int LOOKUP_ADDRESS_TYPE_COL = 40;//AO
+ public static final int LOOKUP_STATE_PROVINCE_COL = 41;//AP
+ public static final int LOOKUP_COUNTRY_COL = 42;//AQ
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/FixedDepositConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/FixedDepositConstants.java
new file mode 100644
index 000000000..d617a077b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/FixedDepositConstants.java
@@ -0,0 +1,55 @@
+/**
+ * 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 class FixedDepositConstants {
+
+ public static final int OFFICE_NAME_COL = 0;
+ public static final int CLIENT_NAME_COL = 1;
+ public static final int PRODUCT_COL = 2;
+ public static final int FIELD_OFFICER_NAME_COL = 3;
+ public static final int SUBMITTED_ON_DATE_COL = 4;
+ public static final int APPROVED_DATE_COL = 5;
+ public static final int ACTIVATION_DATE_COL = 6;
+ public static final int INTEREST_COMPOUNDING_PERIOD_COL = 7;
+ public static final int INTEREST_POSTING_PERIOD_COL = 8;
+ public static final int INTEREST_CALCULATION_COL = 9;
+ public static final int INTEREST_CALCULATION_DAYS_IN_YEAR_COL = 10;
+ public static final int LOCKIN_PERIOD_COL = 11;
+ public static final int LOCKIN_PERIOD_FREQUENCY_COL = 12;
+ public static final int DEPOSIT_AMOUNT_COL = 13;
+ public static final int DEPOSIT_PERIOD_COL = 14;
+ public static final int DEPOSIT_PERIOD_FREQUENCY_COL = 15;
+ public static final int EXTERNAL_ID_COL = 16;
+ public static final int CHARGE_ID_1 = 18;
+ public static final int CHARGE_AMOUNT_1 = 19;
+ public static final int CHARGE_DUE_DATE_1 = 20;
+ public static final int CHARGE_ID_2 = 21;
+ public static final int CHARGE_AMOUNT_2 = 22;
+ public static final int CHARGE_DUE_DATE_2 = 23;
+ public static final int CLOSED_ON_DATE = 24;
+ public static final int ON_ACCOUNT_CLOSURE_ID = 25;
+ public static final int TO_SAVINGS_ACCOUNT_ID = 26;
+ public static final int STATUS_COL = 27;
+ public static final int SAVINGS_ID_COL = 28;
+ public static final int FAILURE_REPORT_COL = 29;
+
+ public static final int LOOKUP_CLIENT_NAME_COL = 31;
+ public static final int LOOKUP_ACTIVATION_DATE_COL = 32;
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/GroupConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/GroupConstants.java
new file mode 100644
index 000000000..02c03260c
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/GroupConstants.java
@@ -0,0 +1,47 @@
+/**
+ * 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 class GroupConstants {
+
+ public static final int NAME_COL = 0; //A
+ public static final int OFFICE_NAME_COL = 1; //B
+ public static final int STAFF_NAME_COL = 2;//C
+
+ public static final int CENTER_NAME_COL = 3;//D
+ public static final int EXTERNAL_ID_COL = 4;//E
+ public static final int ACTIVE_COL = 5;//F
+ public static final int ACTIVATION_DATE_COL = 6;//G
+ public static final int SUBMITTED_ON_DATE_COL=7;//H
+ public static final int MEETING_START_DATE_COL = 8;//I
+ public static final int IS_REPEATING_COL = 9;//J
+ public static final int FREQUENCY_COL = 10;//K
+ public static final int INTERVAL_COL = 11;//L
+ public static final int REPEATS_ON_DAY_COL = 12;//M
+ public static final int STATUS_COL = 13;//N
+ public static final int GROUP_ID_COL = 14;//O
+ public static final int FAILURE_COL = 15;//P
+ public static final int CLIENT_NAMES_STARTING_COL = 16;//Q
+ public static final int CLIENT_NAMES_ENDING_COL = 250;//IQ
+ public static final int LOOKUP_OFFICE_NAME_COL = 251;//IR
+ public static final int LOOKUP_OFFICE_OPENING_DATE_COL = 252;//IS
+ public static final int LOOKUP_REPEAT_NORMAL_COL = 253;//IT
+ public static final int LOOKUP_REPEAT_MONTHLY_COL = 254;//IU
+ public static final int LOOKUP_IF_REPEAT_WEEKLY_COL = 255;//IV
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/GuarantorConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/GuarantorConstants.java
new file mode 100644
index 000000000..b37195bd2
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/GuarantorConstants.java
@@ -0,0 +1,45 @@
+/**
+ * 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 class GuarantorConstants {
+
+ public static final int OFFICE_NAME_COL = 0;
+ public static final int CLIENT_NAME_COL = 1;
+ public static final int LOAN_ACCOUNT_NO_COL = 2;
+ public static final int GUARANTO_TYPE_COL =3;
+ public static final int CLIENT_RELATIONSHIP_TYPE_COL =4;
+ public static final int ENTITY_OFFICE_NAME_COL = 5;
+ public static final int ENTITY_ID_COL = 6;
+ public static final int FIRST_NAME_COL = 7;
+ public static final int LAST_NAME_COL = 8;
+ public static final int ADDRESS_LINE_1_COL= 9;
+ public static final int ADDRESS_LINE_2_COL = 10;
+ public static final int CITY_COL = 11;
+ public static final int DOB_COL = 12;
+ public static final int ZIP_COL = 13;
+ public static final int SAVINGS_ID_COL=14;
+ public static final int AMOUNT=15;
+ public static final int STATUS_COL = 18;
+ public static final int LOOKUP_CLIENT_NAME_COL=81;
+ public static final int LOOKUP_ACCOUNT_NO_COL=82;
+ public static final int LOOKUP_SAVINGS_CLIENT_NAME_COL=83;
+ public static final int LOOKUP_SAVINGS_ACCOUNT_NO_COL=84;
+ public static final int LOOKUP_GUARANTOR_RELATIONSHIPS=85;
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/JournalEntryConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/JournalEntryConstants.java
new file mode 100644
index 000000000..e54f19b88
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/JournalEntryConstants.java
@@ -0,0 +1,49 @@
+/**
+ * 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 class JournalEntryConstants {
+
+ public static final int OFFICE_NAME_COL = 0;
+
+ public static final int TRANSACION_ON_DATE_COL = 1;
+
+ public static final int CURRENCY_NAME_COL = 2;
+
+ public static final int PAYMENT_TYPE_ID_COL = 3;
+
+ public static final int TRANSACTION_ID_COL = 4;
+
+ public static final int GL_ACCOUNT_ID_CREDIT_COL = 5;
+
+ public static final int AMOUNT_CREDIT_COL = 6;
+
+ public static final int GL_ACCOUNT_ID_DEBIT_COL = 7;
+
+ public static final int AMOUNT_DEBIT_COL = 8;
+
+ public static final int STATUS_COL = 9;
+
+ public static final int ACCOUNT_NO_COL = 10;
+ public static final int CHECK_NO_COL = 11;
+ public static final int ROUTING_CODE_COL = 12;
+ public static final int RECEIPT_NO_COL = 13;
+ public static final int BANK_NO_COL = 14;
+ public static final int COMMENTS_COL=15;
+}
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
new file mode 100644
index 000000000..2e5b38fd0
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java
@@ -0,0 +1,75 @@
+/**
+ * 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 class LoanConstants {
+
+ public static final int OFFICE_NAME_COL = 0;//A
+ public static final int LOAN_TYPE_COL = 1;//B
+ public static final int CLIENT_NAME_COL = 2;//C
+ public static final int CLIENT_EXTERNAL_ID=3;//D
+ public static final int PRODUCT_COL = 4;//E
+ public static final int LOAN_OFFICER_NAME_COL = 5;//F
+ public static final int SUBMITTED_ON_DATE_COL = 6;//G
+ public static final int APPROVED_DATE_COL = 7;//H
+ public static final int DISBURSED_DATE_COL = 8;//I
+ public static final int DISBURSED_PAYMENT_TYPE_COL = 9;//J
+ public static final int FUND_NAME_COL = 10;//K
+ public static final int PRINCIPAL_COL = 11;//L
+ public static final int NO_OF_REPAYMENTS_COL = 12;//M
+ public static final int REPAID_EVERY_COL = 13;//N
+ public static final int REPAID_EVERY_FREQUENCY_COL = 14;//O
+ public static final int LOAN_TERM_COL = 15;//P
+ public static final int LOAN_TERM_FREQUENCY_COL = 16;//Q
+ public static final int NOMINAL_INTEREST_RATE_COL = 17;//R
+ public static final int NOMINAL_INTEREST_RATE_FREQUENCY_COL = 18;//S
+ public static final int AMORTIZATION_COL = 19;//T
+ public static final int INTEREST_METHOD_COL = 20;//U
+ public static final int INTEREST_CALCULATION_PERIOD_COL = 21;//V
+ public static final int ARREARS_TOLERANCE_COL = 22;//W
+ public static final int REPAYMENT_STRATEGY_COL = 23;//X
+ public static final int GRACE_ON_PRINCIPAL_PAYMENT_COL = 24;//Y
+ public static final int GRACE_ON_INTEREST_PAYMENT_COL = 25;//Z
+ public static final int GRACE_ON_INTEREST_CHARGED_COL = 26;//AA
+ public static final int INTEREST_CHARGED_FROM_COL = 27;//AB
+ public static final int FIRST_REPAYMENT_COL = 28;//AC
+ public static final int TOTAL_AMOUNT_REPAID_COL = 29;//AD
+ public static final int LAST_REPAYMENT_DATE_COL = 30;//AE
+ public static final int REPAYMENT_TYPE_COL = 31;//AF
+ public static final int STATUS_COL = 32;//AG
+ 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_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_AMOUNT_2 = 40;//AO
+ public static final int CHARGE_DUE_DATE_2 = 41;//AP
+ public static final int GROUP_ID = 42;//AQ
+ public static final int LOOKUP_CLIENT_NAME_COL = 43;//AR
+ 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 String LOAN_TYPE_INDIVIDUAL="Individual";
+ public static final String LOAN_TYPE_GROUP="Group";
+ public static final String LOAN_TYPE_JLG="JLG" ;
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanRepaymentConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanRepaymentConstants.java
new file mode 100644
index 000000000..4a35d9461
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanRepaymentConstants.java
@@ -0,0 +1,44 @@
+/**
+ * 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 class LoanRepaymentConstants {
+
+ public static final int OFFICE_NAME_COL = 0;//A
+ public static final int CLIENT_NAME_COL = 1;//B
+ public static final int CLIENT_EXTERNAL_ID=2;//C
+ public static final int LOAN_ACCOUNT_NO_COL = 3;//D
+ public static final int PRODUCT_COL = 4;//E
+ public static final int PRINCIPAL_COL = 5;//F
+ public static final int AMOUNT_COL = 6;//G
+ public static final int REPAID_ON_DATE_COL = 7;//H
+ public static final int REPAYMENT_TYPE_COL = 8;//I
+ public static final int ACCOUNT_NO_COL = 9;//J
+ public static final int CHECK_NO_COL = 10;//K
+ public static final int ROUTING_CODE_COL = 11;//L
+ public static final int RECEIPT_NO_COL = 12;//M
+ public static final int BANK_NO_COL = 13;//N
+ public static final int STATUS_COL = 14;//O
+ public static final int LOOKUP_CLIENT_NAME_COL = 15;//P
+ public static final int LOOKUP_CLIENT_EXTERNAL_ID = 16;//Q
+ public static final int LOOKUP_ACCOUNT_NO_COL = 17;//R
+ public static final int LOOKUP_PRODUCT_COL = 18;//S
+ public static final int LOOKUP_PRINCIPAL_COL = 19;//T
+ public static final int LOOKUP_LOAN_DISBURSEMENT_DATE_COL = 20;//U
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/OfficeConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/OfficeConstants.java
new file mode 100644
index 000000000..f1fe3a386
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/OfficeConstants.java
@@ -0,0 +1,33 @@
+/**
+ * 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 class OfficeConstants {
+
+ //Column indices
+ public static final int OFFICE_NAME_COL = 0;
+ public static final int PARENT_OFFICE_NAME_COL = 1;
+ public static final int PARENT_OFFICE_ID_COL=2;
+ public static final int OPENED_ON_COL = 3;
+ public static final int EXTERNAL_ID_COL = 4;
+ public static final int LOOKUP_OFFICE_COL=7;
+ public static final int LOOKUP_OFFICE_ID_COL=8;
+ public static final int STATUS_COL=10;
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/RecurringDepositConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/RecurringDepositConstants.java
new file mode 100644
index 000000000..0cd58d087
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/RecurringDepositConstants.java
@@ -0,0 +1,60 @@
+/**
+ * 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 class RecurringDepositConstants {
+
+ public static final int OFFICE_NAME_COL = 0;
+ public static final int CLIENT_NAME_COL = 1;
+ public static final int PRODUCT_COL = 2;
+ public static final int FIELD_OFFICER_NAME_COL = 3;
+ public static final int SUBMITTED_ON_DATE_COL = 4;
+ public static final int APPROVED_DATE_COL = 5;
+ public static final int ACTIVATION_DATE_COL = 6;
+ public static final int INTEREST_COMPOUNDING_PERIOD_COL = 7;
+ public static final int INTEREST_POSTING_PERIOD_COL = 8;
+ public static final int INTEREST_CALCULATION_COL = 9;
+ public static final int INTEREST_CALCULATION_DAYS_IN_YEAR_COL = 10;
+ public static final int LOCKIN_PERIOD_COL = 11;
+ public static final int LOCKIN_PERIOD_FREQUENCY_COL = 12;
+ public static final int RECURRING_DEPOSIT_AMOUNT_COL = 13;
+ public static final int DEPOSIT_PERIOD_COL = 14;
+ public static final int DEPOSIT_PERIOD_FREQUENCY_COL = 15;
+ public static final int DEPOSIT_FREQUENCY_COL = 16;
+ public static final int DEPOSIT_FREQUENCY_TYPE_COL = 17;
+ public static final int DEPOSIT_START_DATE_COL = 18;
+ public static final int IS_MANDATORY_DEPOSIT_COL = 19;
+ public static final int ALLOW_WITHDRAWAL_COL = 20;
+ public static final int FREQ_SAME_AS_GROUP_CENTER_COL = 21;
+ public static final int ADJUST_ADVANCE_PAYMENTS_COL = 22;
+ public static final int EXTERNAL_ID_COL = 23;
+ public static final int STATUS_COL = 24;
+ public static final int SAVINGS_ID_COL = 25;
+ public static final int FAILURE_REPORT_COL = 26;
+ public static final int CHARGE_ID_1 = 28;
+ public static final int CHARGE_AMOUNT_1 = 29;
+ public static final int CHARGE_DUE_DATE_1 = 30;
+ public static final int CHARGE_ID_2 = 33;
+ public static final int CHARGE_AMOUNT_2 = 34;
+ public static final int CHARGE_DUE_DATE_2 = 35;
+
+
+ public static final int LOOKUP_CLIENT_NAME_COL = 31;
+ public static final int LOOKUP_ACTIVATION_DATE_COL = 32;
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/SavingsConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/SavingsConstants.java
new file mode 100644
index 000000000..72b544a81
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/SavingsConstants.java
@@ -0,0 +1,57 @@
+/**
+ * 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 class SavingsConstants {
+
+ public static final int OFFICE_NAME_COL = 0;
+ public static final int SAVINGS_TYPE_COL = 1;
+ public static final int CLIENT_NAME_COL = 2;
+ public static final int PRODUCT_COL = 3;
+ public static final int FIELD_OFFICER_NAME_COL = 4;
+ public static final int SUBMITTED_ON_DATE_COL = 5;
+ public static final int APPROVED_DATE_COL = 6;
+ public static final int ACTIVATION_DATE_COL = 7;
+ public static final int CURRENCY_COL = 8;
+ public static final int DECIMAL_PLACES_COL = 9;
+ public static final int IN_MULTIPLES_OF_COL = 10;
+ public static final int NOMINAL_ANNUAL_INTEREST_RATE_COL = 11;
+ public static final int INTEREST_COMPOUNDING_PERIOD_COL = 12;
+ public static final int INTEREST_POSTING_PERIOD_COL = 13;
+ public static final int INTEREST_CALCULATION_COL = 14;
+ public static final int INTEREST_CALCULATION_DAYS_IN_YEAR_COL = 15;
+ public static final int MIN_OPENING_BALANCE_COL = 16;
+ public static final int LOCKIN_PERIOD_COL = 17;
+ public static final int LOCKIN_PERIOD_FREQUENCY_COL = 18;
+ public static final int APPLY_WITHDRAWAL_FEE_FOR_TRANSFERS = 19;
+ public static final int ALLOW_OVER_DRAFT_COL = 20;
+ public static final int OVER_DRAFT_LIMIT_COL= 21;
+ public static final int EXTERNAL_ID_COL = 22;
+ public static final int STATUS_COL = 23;
+ public static final int SAVINGS_ID_COL = 24;
+ public static final int FAILURE_REPORT_COL = 25;
+ public static final int LOOKUP_CLIENT_NAME_COL = 31;
+ public static final int LOOKUP_ACTIVATION_DATE_COL = 32;
+ public static final int CHARGE_ID_1 = 34;
+ public static final int CHARGE_AMOUNT_1 = 35;
+ public static final int CHARGE_DUE_DATE_1 = 36;
+ public static final int CHARGE_ID_2 = 37;
+ public static final int CHARGE_AMOUNT_2 = 38;
+ public static final int CHARGE_DUE_DATE_2 = 39;
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/SharedAccountsConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/SharedAccountsConstants.java
new file mode 100644
index 000000000..c3d8e61a3
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/SharedAccountsConstants.java
@@ -0,0 +1,45 @@
+/**
+ * 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 class SharedAccountsConstants {
+
+ public static final int CLIENT_NAME_COL=0;
+ public static final int PRODUCT_COL=1;
+ public static final int SUBMITTED_ON_COL=2;
+ public static final int EXTERNAL_ID_COL=3;
+ public static final int CURRENCY_COL=4;
+ public static final int DECIMAL_PLACES_COL=5;
+ public static final int TOTAL_NO_SHARES_COL=6;
+ public static final int TODAYS_PRICE_COL=7;
+ public static final int CURRENCY_IN_MULTIPLES_COL=8;
+ public static final int DEFAULT_SAVINGS_AC_COL=9;
+ public static final int MINIMUM_ACTIVE_PERIOD_IN_DAYS_COL=10;
+ public static final int LOCK_IN_PERIOD_COL=11;
+ public static final int LOCK_IN_PERIOD_FREQUENCY_TYPE=12;
+ public static final int APPLICATION_DATE_COL=13;
+ public static final int ALLOW_DIVIDEND_CALCULATION_FOR_INACTIVE_CLIENTS_COL=14;
+ public static final int CHARGES_NAME_1_COL=15;
+ public static final int CHARGES_AMOUNT_1_COL=16;
+ public static final int CHARGES_NAME_2_COL=17;
+ public static final int CHARGES_AMOUNT_2_COL=18;
+ public static final int CHARGES_NAME_3_COL=19;
+ public static final int CHARGES_AMOUNT_3_COL=20;
+ public static final int STATUS_COL=25;
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/StaffConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/StaffConstants.java
new file mode 100644
index 000000000..f1d7d6a3a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/StaffConstants.java
@@ -0,0 +1,32 @@
+/**
+ * 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 class StaffConstants {
+
+ public static final int OFFICE_NAME_COL = 0;//A
+ public static final int FIRST_NAME_COL = 1;//B
+ public static final int LAST_NAME_COL = 2;//C
+ public static final int IS_LOAN_OFFICER = 3;//D
+ public static final int MOBILE_NO_COL=4;//E
+ public static final int JOINED_ON_COL =5;//F
+ public static final int EXTERNAL_ID_COL =6;//G
+ public static final int IS_ACTIVE_COL =7;//h
+ public static final int STATUS_COL=8;//H
+}
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
new file mode 100644
index 000000000..ba7ad96ae
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/TemplatePopulateImportConstants.java
@@ -0,0 +1,143 @@
+/**
+ * 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 class TemplatePopulateImportConstants {
+
+ //columns sizes
+ public final static int SMALL_COL_SIZE =4000;
+ public final static int MEDIUM_COL_SIZE =6000;
+ public final static int LARGE_COL_SIZE=8000;
+ public final static int EXTRALARGE_COL_SIZE=10000;
+
+ //Sheet names
+ public static final String OFFICE_SHEET_NAME ="Offices";
+ 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 CHART_OF_ACCOUNTS_SHEET_NAME="ChartOfAccounts";
+ public static final String CLIENT_ENTITY_SHEET_NAME="ClientEntity";
+ public static final String CLIENT_PERSON_SHEET_NAME="ClientPerson";
+ public static final String CLIENT_SHEET_NAME="Clients";
+ public static final String FIXED_DEPOSIT_SHEET_NAME="FixedDeposit";
+ public static final String FIXED_DEPOSIT_TRANSACTION_SHEET_NAME="FixedDepositTransactions";
+ public static final String PRODUCT_SHEET_NAME="Products";
+ public static final String GUARANTOR_SHEET_NAME="guarantor";
+ public static final String EXTRAS_SHEET_NAME="Extras";
+ public static final String GL_ACCOUNTS_SHEET_NAME="GlAccounts";
+ public static final String SAVINGS_ACCOUNTS_SHEET_NAME="SavingsAccounts";
+ public static final String SHARED_PRODUCTS_SHEET_NAME="SharedProducts";
+ public static final String JOURNAL_ENTRY_SHEET_NAME="AddJournalEntries";
+ public static final String LOANS_SHEET_NAME="Loans";
+ public static final String LOAN_REPAYMENT_SHEET_NAME="LoanRepayment";
+ public static final String RECURRING_DEPOSIT_SHEET_NAME="RecurringDeposit";
+ public static final String SAVINGS_TRANSACTION_SHEET_NAME="SavingsTransaction";
+ public static final String SHARED_ACCOUNTS_SHEET_NAME="SharedAccounts";
+ public static final String EMPLOYEE_SHEET_NAME="Employee";
+ public static final String ROLES_SHEET_NAME="Roles";
+ public static final String USER_SHEET_NAME="Users";
+
+ public final static int ROWHEADER_INDEX=0;
+ public final static short ROW_HEADER_HEIGHT =500;
+ public final static int FIRST_COLUMN_INDEX=0;
+
+ //Status column
+ public final static String STATUS_CELL_IMPORTED="Imported";
+ public final static String STATUS_CREATION_FAILED="Creation failed";
+ public final static String STATUS_APPROVAL_FAILED="Approval failed";
+ public final static String STATUS_ACTIVATION_FAILED="Activation failed";
+ public final static String STATUS_MEETING_FAILED="Meeting failed";
+ public final static String STATUS_DISBURSAL_FAILED="Disbursal failed";
+ public final static String STATUS_DISBURSAL_REPAYMENT_FAILED="Repayment failed";
+ public final static String STATUS_COLUMN_HEADER="Status";
+
+ //Frequency Calender
+ public static final String FREQUENCY_DAILY="Daily";
+ public static final String FREQUENCY_WEEKLY="Weekly";
+ public static final String FREQUENCY_MONTHLY="Monthly";
+ public static final String FREQUENCY_YEARLY= "Yearly";
+
+ //InterestCompoundingPeriod
+ public static final String INTEREST_COMPOUNDING_PERIOD_DAILY="Daily";
+ public static final String INTEREST_COMPOUNDING_PERIOD_MONTHLY="Monthly";
+ public static final String INTEREST_COMPOUNDING_PERIOD_QUARTERLY="Quarterly";
+ public static final String INTEREST_COMPOUNDING_PERIOD_SEMI_ANNUALLY="Semi-Annual";
+ public static final String INTEREST_COMPOUNDING_PERIOD_ANNUALLY="Annually";
+
+ //InterestPostingPeriod
+ public static final String INTEREST_POSTING_PERIOD_MONTHLY="Monthly";
+ public static final String INTEREST_POSTING_PERIOD_QUARTERLY="Quarterly";
+ public static final String INTEREST_POSTING_PERIOD_BIANUALLY="BiAnnual";
+ public static final String INTEREST_POSTING_PERIOD_ANNUALLY="Annually";
+
+ //InterestCalculation
+ public static final String INTEREST_CAL_DAILY_BALANCE="Daily Balance";
+ public static final String INTEREST_CAL_AVG_BALANCE="Average Daily Balance";
+
+ //InterestCalculation Day in Year
+ public static final String INTEREST_CAL_DAYS_IN_YEAR_360="360 Days";
+ public static final String INTEREST_CAL_DAYS_IN_YEAR_365="365 Days";
+
+ //Frequency
+ public static final String FREQUENCY_DAYS="Days";
+ public static final String FREQUENCY_WEEKS="Weeks";
+ public static final String FREQUENCY_MONTHS="Months";
+ public static final String FREQUENCY_YEARS="Years";
+
+ //Day Of Week
+ public static final String MONDAY ="Mon";
+ public static final String TUESDAY ="Tue";
+ public static final String WEDNESDAY ="Wed";
+ public static final String THURSDAY ="Thu";
+ public static final String FRIDAY ="Fri";
+ public static final String SATURDAY ="Sat";
+ public static final String SUNDAY ="Sun";
+
+ //Entity types
+ public static final String CENTER_ENTITY_TYPE="CENTER";
+ public static final String OFFICE_ENTITY_TYPE="OFFICE";
+ public static final String STAFF_ENTITY_TYPE="STAFF";
+ public static final String USER_ENTITY_TYPE="USER";
+ public static final String GROUP_ENTITY_TYPE="GROUP";
+ public static final String CLIENT_ENTITY_TYPE="CLIENT";
+ public static final String LOAN_PRODUCT_ENTITY_TYPE="LOANPRODUCT";
+ public static final String FUNDS_ENTITY_TYPE="FUNDS";
+ public static final String PAYMENT_TYPE_ENTITY_TYPE="PAYMENTTYPE";
+ public static final String CURRENCY_ENTITY_TYPE="CURRENCY";
+ public static final String GL_ACCOUNT_ENTITY_TYPE="GLACCOUNT";
+ public static final String SHARED_ACCOUNT_ENTITY_TYPE="SHAREDACCOUNT";
+ public static final String SAVINGS_PRODUCT_ENTITY_TYPE="SAVINGSPRODUCT";
+ public static final String RECURRING_DEPOSIT_PRODUCT_ENTITY_TYPE="RECURRINGDEPOSITPRODUCT";
+ public static final String FIXED_DEPOSIT_PRODUCT_ENTITY_TYPE="FIXEDDEPOSITPRODUCT";
+
+ //ReportHeader Values
+ public static final String STATUS_COL_REPORT_HEADER="Status";
+ public static final String CENTERID_COL_REPORT_HEADER="Center Id";
+ public static final String SAVINGS_ID_COL_REPORT_HEADER="Savings ID";
+ public static final String GROUP_ID_COL_REPORT_HEADER="Group ID";
+ public static final String FAILURE_COL_REPORT_HEADER="Failure Report";
+
+ //Guarantor Types
+ public static final String GUARANTOR_INTERNAL="Internal";
+ public static final String GUARANTOR_EXTERNAL="External";
+
+ //Loan Account/Loan repayment Client External Id
+ public static final Boolean CONTAINS_CLIENT_EXTERNAL_ID=true;
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/TransactionConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/TransactionConstants.java
new file mode 100644
index 000000000..acfa73efd
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/TransactionConstants.java
@@ -0,0 +1,43 @@
+/**
+ * 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 class TransactionConstants {
+
+ public static final int OFFICE_NAME_COL = 0;
+ public static final int CLIENT_NAME_COL = 1;
+ public static final int SAVINGS_ACCOUNT_NO_COL = 2;
+ public static final int PRODUCT_COL = 3;
+ public static final int OPENING_BALANCE_COL = 4;
+ public static final int TRANSACTION_TYPE_COL = 5;
+ public static final int AMOUNT_COL = 6;
+ public static final int TRANSACTION_DATE_COL = 7;
+ public static final int PAYMENT_TYPE_COL = 8;
+ public static final int ACCOUNT_NO_COL = 9;
+ public static final int CHECK_NO_COL = 10;
+ public static final int ROUTING_CODE_COL = 11;
+ public static final int RECEIPT_NO_COL = 12;
+ public static final int BANK_NO_COL = 13;
+ public static final int STATUS_COL = 14;
+ public static final int LOOKUP_CLIENT_NAME_COL = 15;
+ public static final int LOOKUP_ACCOUNT_NO_COL = 16;
+ public static final int LOOKUP_PRODUCT_COL = 17;
+ public static final int LOOKUP_OPENING_BALANCE_COL = 18;
+ public static final int LOOKUP_SAVINGS_ACTIVATION_DATE_COL = 19;
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/UserConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/UserConstants.java
new file mode 100644
index 000000000..b9b6c4c51
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/UserConstants.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 class UserConstants {
+ public static final int OFFICE_NAME_COL=0;
+ public static final int STAFF_NAME_COL=1;
+ public static final int USER_NAME_COL=2;
+ public static final int FIRST_NAME_COL=3;
+ public static final int LAST_NAME_COL=4;
+ public static final int EMAIL_COL=5;
+ public static final int AUTO_GEN_PW_COL=6;
+ public static final int OVERRIDE_PW_EXPIRY_POLICY_COL=7;
+ public static final int STATUS_COL=8;
+ public static final int ROLE_NAME_START_COL=9;
+ public static final int ROLE_NAME_END_COL=14;
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/BulkImportEvent.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/BulkImportEvent.java
new file mode 100644
index 000000000..0a493663d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/BulkImportEvent.java
@@ -0,0 +1,71 @@
+/**
+ * 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.data;
+
+import org.apache.poi.ss.usermodel.Workbook;
+import org.springframework.context.ApplicationEvent;
+
+public class BulkImportEvent extends ApplicationEvent {
+
+ private final String tenantIdentifier;
+
+ private final Workbook workbook;
+
+ private final Long importId;
+
+ private final String locale;
+
+ private final String dateFormat;
+
+ private BulkImportEvent(final String tenantIdentifier, final Workbook workbook,
+ final Long importId, final String locale, final String dateFormat) {
+ super(BulkImportEvent.class);
+ this.tenantIdentifier = tenantIdentifier;
+ this.workbook = workbook;
+ this.importId = importId;
+ this.locale = locale;
+ this.dateFormat = dateFormat;
+ }
+
+ public static BulkImportEvent instance(final String tenantIdentifier, final Workbook workbook,
+ final Long importId, final String locale, final String dateFormat) {
+ return new BulkImportEvent(tenantIdentifier, workbook, importId, locale, dateFormat);
+ }
+
+ public String getTenantIdentifier() {
+ return tenantIdentifier;
+ }
+
+ public Workbook getWorkbook() {
+ return workbook;
+ }
+
+ public Long getImportId() {
+ return importId;
+ }
+
+ public String getDateFormat() {
+ return dateFormat;
+ }
+
+ public String getLocale() {
+ return locale;
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/Count.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/Count.java
new file mode 100644
index 000000000..c4926c19b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/Count.java
@@ -0,0 +1,45 @@
+/**
+ * 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.data;
+
+public class Count {
+
+ private Integer successCount;
+ private Integer errorCount;
+
+ public static Count instance(final Integer successCount,
+ final Integer errorCount) {
+ return new Count(successCount, errorCount);
+ }
+
+ private Count(final Integer successCount,
+ final Integer errorCount) {
+ this.successCount = successCount;
+ this.errorCount = errorCount;
+ }
+
+ public Integer getSuccessCount() {
+ return successCount;
+ }
+
+ public Integer getErrorCount() {
+ return errorCount;
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/GlobalEntityType.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/GlobalEntityType.java
new file mode 100644
index 000000000..bb99a544a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/GlobalEntityType.java
@@ -0,0 +1,118 @@
+/**
+ * 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.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum GlobalEntityType {
+
+
+ INVALID(0, "invalid"),
+ CLIENTS_PERSON(1, "clients.person"),
+ CLIENTS_ENTTTY(2,"clients.entity"),
+ GROUPS(3, "groups"),
+ CENTERS(4, "centers"),
+ OFFICES(5, "offices"),
+ STAFF(6, "staff"),
+ USERS(7, "users"),
+ SMS(8, "sms"),
+ DOCUMENTS(9, "documents"),
+ TEMPLATES(10, "templates"),
+ NOTES(11, "templates"),
+ CALENDAR(12, "calendar"),
+ MEETINGS(13, "meetings"),
+ HOLIDAYS(14, "holidays"),
+ LOANS(15, "loans"),
+ LOAN_PRODUCTS(16,"loancharges"),
+ LOAN_TRANSACTIONS(18, "loantransactions"),
+ GUARANTORS(19, "guarantors"),
+ COLLATERALS(20, "collaterals"),
+ FUNDS(21, "funds"),
+ CURRENCY(22, "currencies"),
+ SAVINGS_ACCOUNT(23, "savingsaccount"),
+ SAVINGS_CHARGES(24, "savingscharges"),
+ SAVINGS_TRANSACTIONS(25, "savingstransactions"),
+ SAVINGS_PRODUCTS(26, "savingsproducts"),
+ GL_JOURNAL_ENTRIES(27, "gljournalentries"),
+ CODE_VALUE(28, "codevalue"),
+ CODE(29, "code"),
+ CHART_OF_ACCOUNTS(30,"chartofaccounts"),
+ FIXED_DEPOSIT_ACCOUNTS(31,"fixeddepositaccounts"),
+ FIXED_DEPOSIT_TRANSACTIONS(32,"fixeddeposittransactions"),
+ SHARE_ACCOUNTS(33,"shareaccounts"),
+ RECURRING_DEPOSIT_ACCOUNTS(34,"recurringdeposits"),
+ RECURRING_DEPOSIT_ACCOUNTS_TRANSACTIONS(35,"recurringdepositstransactions"),
+ CLIENT(36,"client");
+
+ private final Integer value;
+ private final String code;
+
+ private static final Map intToEnumMap = new HashMap<>();
+ private static final Map stringToEnumMap = new HashMap<>();
+ private static int minValue;
+ private static int maxValue;
+
+ static {
+ int i = 0;
+ for (final GlobalEntityType entityType : GlobalEntityType.values()) {
+ if (i == 0) {
+ minValue = entityType.value;
+ }
+ intToEnumMap.put(entityType.value, entityType);
+ stringToEnumMap.put(entityType.code, entityType);
+ if (minValue >= entityType.value) {
+ minValue = entityType.value;
+ }
+ if (maxValue < entityType.value) {
+ maxValue = entityType.value;
+ }
+ i = i + 1;
+ }
+ }
+
+ private GlobalEntityType(final Integer value, final String code) {
+ this.value = value;
+ this.code = code;
+ }
+
+ public Integer getValue() {
+ return this.value;
+ }
+
+ public String getCode() {
+ return this.code;
+ }
+
+ public static GlobalEntityType fromInt(final int i) {
+ final GlobalEntityType entityType = intToEnumMap.get(Integer.valueOf(i));
+ return entityType;
+ }
+
+ public static GlobalEntityType fromCode(final String key) {
+ final GlobalEntityType entityType = stringToEnumMap.get(key);
+ return entityType;
+ }
+
+ @Override
+ public String toString() {
+ return name().toString();
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/ImportData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/ImportData.java
new file mode 100644
index 000000000..635a6a94a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/ImportData.java
@@ -0,0 +1,80 @@
+/**
+ * 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.data;
+
+import org.joda.time.LocalDate;
+
+public class ImportData {
+
+ @SuppressWarnings("unused")
+ private Long importId;
+ @SuppressWarnings("unused")
+ private Long documentId;
+ @SuppressWarnings("unused")
+ private String name;
+ @SuppressWarnings("unused")
+ private LocalDate importTime;
+ @SuppressWarnings("unused")
+ private LocalDate endTime;
+ @SuppressWarnings("unused")
+ private Boolean completed;
+ @SuppressWarnings("unused")
+ private Long createdBy;
+ @SuppressWarnings("unused")
+ private Integer totalRecords;
+ @SuppressWarnings("unused")
+ private Integer successCount;
+ @SuppressWarnings("unused")
+ private Integer failureCount;
+
+ public static ImportData instance(final Long importId, final Long documentId,
+ final LocalDate importTime, final LocalDate endTime,
+ final Boolean completed, final String name,
+ final Long createdBy, final Integer totalRecords, final Integer successCount,
+ final Integer failureCount) {
+ return new ImportData(importId, documentId, importTime, endTime,
+ completed, name, createdBy, totalRecords, successCount,
+ failureCount);
+ }
+
+ public static ImportData instance(final Long importId){
+ return new ImportData(importId,null,null,
+ null,null,null,null,null,
+ null,null);
+ }
+
+ private ImportData(final Long importId, final Long documentId,
+ final LocalDate importTime, final LocalDate endTime,
+ final Boolean completed, final String name,
+ final Long createdBy, final Integer totalRecords, final Integer successCount,
+ final Integer failureCount) {
+ this.importId = importId;
+ this.documentId = documentId;
+ this.name = name;
+ this.importTime = importTime;
+ this.endTime = endTime;
+ this.completed = completed;
+ this.createdBy = createdBy;
+ this.totalRecords = totalRecords;
+ this.successCount = successCount;
+ this.failureCount = failureCount;
+ }
+
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/ImportFormatType.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/ImportFormatType.java
new file mode 100644
index 000000000..29bbe61a9
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/data/ImportFormatType.java
@@ -0,0 +1,49 @@
+/**
+ * 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.data;
+
+import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
+
+public enum ImportFormatType {
+
+ XLSX ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
+ XLS ("application/vnd.ms-excel"),
+ ODS ("application/vnd.oasis.opendocument.spreadsheet");
+
+
+ private final String format;
+
+ private ImportFormatType(String format) {
+ this.format= format;
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+ public static ImportFormatType of(String name) {
+ for(ImportFormatType type : ImportFormatType.values()) {
+ if(type.name().equalsIgnoreCase(name)) {
+ return type;
+ }
+ }
+ throw new GeneralPlatformDomainRuleException("error.msg.invalid.file.extension",
+ "Uploaded file extension is not recognized.");
+ }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocument.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocument.java
new file mode 100644
index 000000000..5e65be248
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocument.java
@@ -0,0 +1,124 @@
+/**
+ * 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.domain;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import org.apache.fineract.infrastructure.documentmanagement.domain.Document;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+
+@Entity
+@Table(name = "m_import_document")
+public class ImportDocument extends AbstractPersistableCustom{
+
+ @OneToOne
+ @JoinColumn(name = "document_id")
+ private Document document;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "import_time")
+ private Date importTime;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "end_time")
+ private Date endTime;
+
+ @Column(name = "completed", nullable = false)
+ private Boolean completed;
+
+ @Column(name = "entity_type")
+ private Integer entity_type;
+
+ @ManyToOne
+ @JoinColumn(name = "createdby_id")
+ private AppUser createdBy;
+
+ @Column(name = "total_records", nullable = true)
+ private Integer totalRecords;
+
+ @Column(name = "success_count", nullable = true)
+ private Integer successCount;
+
+ @Column(name = "failure_count", nullable = true)
+ private Integer failureCount;
+
+ protected ImportDocument() {
+
+ }
+
+ public static ImportDocument instance(final Document document, final LocalDateTime importTime,
+ final Integer entity_type, final AppUser createdBy, final Integer totalRecords) {
+
+ final Boolean completed = Boolean.FALSE;
+ final Integer successCount = 0;
+ final Integer failureCount = 0;
+ final LocalDateTime endTime = LocalDateTime.now();
+
+ return new ImportDocument(document, importTime, endTime, completed, entity_type,
+ createdBy, totalRecords, successCount, failureCount);
+ }
+
+ private ImportDocument(final Document document, final LocalDateTime importTime,
+ final LocalDateTime endTime, Boolean completed, final Integer entity_type,
+ final AppUser createdBy, final Integer totalRecords, final Integer successCount,
+ final Integer failureCount) {
+ this.document = document;
+ this.importTime = importTime.toDate();
+ this.endTime = endTime.toDate();
+ this.completed = completed;
+ this.entity_type = entity_type;
+ this.createdBy = createdBy;
+ this.totalRecords = totalRecords;
+ this.successCount = successCount;
+ this.failureCount = failureCount;
+
+ }
+
+ public void update(final LocalDateTime endTime, final Integer successCount,
+ final Integer errorCount) {
+ this.endTime = endTime.toDate();
+ this.completed = Boolean.TRUE;
+ this.successCount = successCount;
+ this.failureCount = errorCount;
+ }
+
+ public Document getDocument() {
+ return this.document;
+ }
+
+ public Integer getEntityType() {
+ return this.entity_type;
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocumentRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocumentRepository.java
new file mode 100644
index 000000000..18e0d3d73
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/domain/ImportDocumentRepository.java
@@ -0,0 +1,27 @@
+/**
+ * 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.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface ImportDocumentRepository
+ extends JpaRepository, JpaSpecificationExecutor {
+ // no added behaviour
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/exceptions/ImportTypeNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/exceptions/ImportTypeNotFoundException.java
new file mode 100644
index 000000000..2754c2ac7
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/exceptions/ImportTypeNotFoundException.java
@@ -0,0 +1,29 @@
+/**
+ * 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.exceptions;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+public class ImportTypeNotFoundException extends AbstractPlatformResourceNotFoundException {
+
+ public ImportTypeNotFoundException(final String entityType) {
+ super("error.msg.entity.type.invalid", "Entity type " + entityType + " does not exist", entityType);
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandler.java
new file mode 100644
index 000000000..e185d3888
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandler.java
@@ -0,0 +1,27 @@
+/**
+ * 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.importhandler;
+
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.poi.ss.usermodel.Workbook;
+
+public interface ImportHandler {
+ public Count process(Workbook workbook, String locale, String dateFormat);
+}
+
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
new file mode 100644
index 000000000..c396f9835
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/ImportHandlerUtils.java
@@ -0,0 +1,355 @@
+/**
+ * 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.importhandler;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+public class ImportHandlerUtils {
+
+ public static Integer getNumberOfRows(Sheet sheet, int primaryColumn) {
+ Integer noOfEntries = 0;
+ // getLastRowNum and getPhysicalNumberOfRows showing false values
+ // sometimes
+ while (sheet.getRow(noOfEntries+1) !=null && sheet.getRow(noOfEntries+1).getCell(primaryColumn) != null) {
+ noOfEntries++;
+ }
+
+ return noOfEntries;
+ }
+
+ public static boolean isNotImported(Row row, int statusColumn) {
+ if (readAsString(statusColumn,row)!=null) {
+ return !readAsString(statusColumn, row).equals(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ }else {
+ return true;
+ }
+ }
+
+ public static Long readAsLong(int colIndex, Row row) {
+ Cell c = row.getCell(colIndex);
+ if (c == null || c.getCellType() == Cell.CELL_TYPE_BLANK)
+ return null;
+ FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
+ if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
+ if(eval!=null) {
+ CellValue val = eval.evaluate(c);
+ return ((Double) val.getNumberValue()).longValue();
+ }
+ }
+ else if (c.getCellType()==Cell.CELL_TYPE_NUMERIC){
+ return ((Double) c.getNumericCellValue()).longValue();
+ }
+ else {
+ return Long.parseLong(row.getCell(colIndex).getStringCellValue());
+ }
+ return null;
+ }
+
+
+ public static String readAsString(int colIndex, Row row) {
+
+ Cell c = row.getCell(colIndex);
+ if (c == null || c.getCellType() == Cell.CELL_TYPE_BLANK)
+ return null;
+ FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
+ if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
+ if (eval!=null) {
+ CellValue val = eval.evaluate(c);
+ String res = trimEmptyDecimalPortion(val.getStringValue());
+ if (res!=null) {
+ if (!res.equals("")) {
+ return res.trim();
+ } else {
+ return null;
+ }
+ }else {
+ return null;
+ }
+ }else {
+ return null;
+ }
+ }else if(c.getCellType()==Cell.CELL_TYPE_STRING) {
+ String res = trimEmptyDecimalPortion(c.getStringCellValue().trim());
+ return res.trim();
+
+ }else if(c.getCellType()==Cell.CELL_TYPE_NUMERIC) {
+ return ((Double) row.getCell(colIndex).getNumericCellValue()).intValue() + "";
+ }else if (c.getCellType()==Cell.CELL_TYPE_BOOLEAN){
+ return c.getBooleanCellValue()+"";
+ }else {
+ return null;
+ }
+ }
+
+
+ public static String trimEmptyDecimalPortion(String result) {
+ if(result != null && result.endsWith(".0"))
+ return result.split("\\.")[0];
+ else
+ return result;
+ }
+
+ public static LocalDate readAsDate(int colIndex, Row row) {
+ Cell c = row.getCell(colIndex);
+ if(c == null || c.getCellType() == Cell.CELL_TYPE_BLANK)
+ return null;
+
+ LocalDate localDate=new LocalDate(c.getDateCellValue());
+ return localDate;
+ }
+
+ public static Boolean readAsBoolean(int colIndex, Row row) {
+ Cell c = row.getCell(colIndex);
+ if(c == null || c.getCellType() == Cell.CELL_TYPE_BLANK)
+ return false;
+ FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
+ if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
+ if(eval!=null) {
+ CellValue val = eval.evaluate(c);
+ return val.getBooleanValue();
+ }
+ return false;
+ }else if(c.getCellType()==Cell.CELL_TYPE_BOOLEAN)
+ return c.getBooleanCellValue();
+ else {
+ String booleanString = row.getCell(colIndex).getStringCellValue().trim();
+ if (booleanString.equalsIgnoreCase("TRUE"))
+ return true;
+ else
+ return false;
+ }
+ }
+
+ public static Integer readAsInt(int colIndex, Row row) {
+ Cell c = row.getCell(colIndex);
+ if (c == null || c.getCellType() == Cell.CELL_TYPE_BLANK)
+ return null;
+ FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
+ if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
+ if(eval!=null) {
+ CellValue val = eval.evaluate(c);
+ return ((Double) val.getNumberValue()).intValue();
+ }
+ return null;
+ }else if (c.getCellType()==Cell.CELL_TYPE_NUMERIC) {
+ return ((Double) c.getNumericCellValue()).intValue();
+ }else {
+ return Integer.parseInt(row.getCell(colIndex).getStringCellValue());
+ }
+ }
+
+ public static Double readAsDouble(int colIndex, Row row) {
+ Cell c = row.getCell(colIndex);
+ if (c == null || c.getCellType() == Cell.CELL_TYPE_BLANK)
+ return 0.0;
+ FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
+ if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
+ if (eval!=null) {
+ CellValue val = eval.evaluate(c);
+ return val.getNumberValue();
+ }else {
+ return 0.0;
+ }
+ } else if (c.getCellType()==Cell.CELL_TYPE_NUMERIC) {
+ return row.getCell(colIndex).getNumericCellValue();
+ }else {
+ return Double.parseDouble(row.getCell(colIndex).getStringCellValue());
+ }
+ }
+
+ public static void writeString(int colIndex, Row row, String value) {
+ if(value!=null)
+ row.createCell(colIndex).setCellValue(value);
+ }
+
+ public static CellStyle getCellStyle(Workbook workbook, IndexedColors color) {
+ CellStyle style = workbook.createCellStyle();
+ style.setFillForegroundColor(color.getIndex());
+ style.setFillPattern(CellStyle.SOLID_FOREGROUND);
+ return style;
+ }
+
+ public static String getDefaultUserMessages(List ApiParameterErrorList){
+ StringBuffer defaultUserMessages=new StringBuffer();
+ for (ApiParameterError error:ApiParameterErrorList) {
+ defaultUserMessages=defaultUserMessages.append(error.getDefaultUserMessage()+'\t');
+ }
+ return defaultUserMessages.toString();
+ }
+ public static String getErrorList(List errorList){
+ StringBuffer errors=new StringBuffer();
+ for (String error: errorList) {
+ errors=errors.append(error);
+ }
+ return errors.toString();
+ }
+
+ public static void writeErrorMessage(Sheet sheet,Integer rowIndex,String errorMessage,int statusColumn){
+ Cell statusCell = sheet.getRow(rowIndex).createCell(statusColumn);
+ statusCell.setCellValue(errorMessage);
+ statusCell.setCellStyle(getCellStyle(sheet.getWorkbook(), IndexedColors.RED));
+ }
+
+ public static String getErrorMessage(RuntimeException re) {
+ if (re instanceof AbstractPlatformDomainRuleException){
+ AbstractPlatformDomainRuleException abstractPlatformDomainRuleException= (AbstractPlatformDomainRuleException) re;
+ return abstractPlatformDomainRuleException.getDefaultUserMessage();
+ }else if (re instanceof AbstractPlatformResourceNotFoundException){
+ AbstractPlatformResourceNotFoundException abstractPlatformResourceNotFoundException= (AbstractPlatformResourceNotFoundException) re;
+ return abstractPlatformResourceNotFoundException.getDefaultUserMessage();
+ }else if (re instanceof AbstractPlatformServiceUnavailableException) {
+ AbstractPlatformServiceUnavailableException abstractPlatformServiceUnavailableException = (AbstractPlatformServiceUnavailableException) re;
+ return abstractPlatformServiceUnavailableException.getDefaultUserMessage();
+ }else if (re instanceof PlatformDataIntegrityException){
+ PlatformDataIntegrityException platformDataIntegrityException= (PlatformDataIntegrityException) re;
+ return platformDataIntegrityException.getDefaultUserMessage();
+ }else if (re instanceof PlatformApiDataValidationException){
+ PlatformApiDataValidationException platformApiDataValidationException=(PlatformApiDataValidationException) re;
+ return getDefaultUserMessages(platformApiDataValidationException.getErrors());
+ }else if (re instanceof UnsupportedParameterException ){
+ UnsupportedParameterException unsupportedParameterException= (UnsupportedParameterException) re;
+ return getErrorList(unsupportedParameterException.getUnsupportedParameters());
+ }else {
+ if (re.getMessage()!=null) {
+ return re.getMessage();
+ }else {
+ return re.getClass().getCanonicalName();
+ }
+ }
+ }
+
+ public static Long getIdByName (Sheet sheet, String name) {
+ String sheetName = sheet.getSheetName();
+ if(!sheetName.equals(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME)) {
+ for (Row row : sheet) {
+ for (Cell cell : row) {
+ if(name!=null) {
+ if (cell.getCellType() == Cell.CELL_TYPE_STRING && cell.getRichStringCellValue().getString().trim().equals(name)) {
+ if (sheetName.equals(TemplatePopulateImportConstants.OFFICE_SHEET_NAME) ||
+ sheetName.equals(TemplatePopulateImportConstants.GL_ACCOUNTS_SHEET_NAME) ||
+ sheetName.equals(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME) ||
+ sheetName.equals(TemplatePopulateImportConstants.SHARED_PRODUCTS_SHEET_NAME)||
+ sheetName.equals(TemplatePopulateImportConstants.ROLES_SHEET_NAME)) {
+ if (row.getCell(cell.getColumnIndex() - 1).getCellType() == Cell.CELL_TYPE_NUMERIC)
+ return ((Double) row.getCell(cell.getColumnIndex() - 1).getNumericCellValue()).longValue();
+ return 0L;
+ } else if (sheetName.equals(TemplatePopulateImportConstants.CLIENT_SHEET_NAME) ||
+ sheetName.equals(TemplatePopulateImportConstants.CENTER_SHEET_NAME) ||
+ sheetName.equals(TemplatePopulateImportConstants.GROUP_SHEET_NAME) ||
+ sheetName.equals(TemplatePopulateImportConstants.STAFF_SHEET_NAME))
+ if (row.getCell(cell.getColumnIndex() + 1).getCellType() == Cell.CELL_TYPE_NUMERIC)
+ return ((Double) row.getCell(cell.getColumnIndex() + 1).getNumericCellValue()).longValue();
+ return 0L;
+ }
+ }else {
+ return 0L;
+ }
+ }
+ }
+ } else if (sheetName.equals(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME)) {
+ for(Row row : sheet) {
+ for(int i = 0; i < 2; i++) {
+ if (name != null) {
+ Cell cell = row.getCell(i);
+ if (cell.getCellType() == Cell.CELL_TYPE_STRING && cell.getRichStringCellValue().getString().trim().equals(name)) {
+ return ((Double) row.getCell(cell.getColumnIndex() - 1).getNumericCellValue()).longValue();
+ }
+ }else {
+ return 0L;
+ }
+ }
+ }
+ }
+ return 0L;
+ }
+ public static String getCodeByName(Sheet sheet, String name) {
+ String sheetName = sheet.getSheetName();
+ sheetName.equals(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME);
+ {
+ for (Row row : sheet) {
+ for (Cell cell : row) {
+ if (name!=null) {
+ if (cell.getCellType() == Cell.CELL_TYPE_STRING
+ && cell.getRichStringCellValue().getString().trim()
+ .equals(name)) {
+ return row.getCell(cell.getColumnIndex() - 1)
+ .getStringCellValue().toString();
+
+ }
+ }
+ }
+ }
+ }
+ return "";
+ }
+
+ public static String getFrequencyId(String frequency) {
+ if (frequency!=null) {
+ if (frequency.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_DAILY))
+ frequency = "1";
+ else if (frequency.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_WEEKLY))
+ frequency = "2";
+ else if (frequency.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_MONTHLY))
+ frequency = "3";
+ else if (frequency.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_YEARLY))
+ frequency = "4";
+ return frequency;
+ }else {
+ return null;
+ }
+ }
+
+ public static String getRepeatsOnDayId(String repeatsOnDay) {
+ if (repeatsOnDay!=null) {
+ if (repeatsOnDay.equalsIgnoreCase(TemplatePopulateImportConstants.MONDAY))
+ repeatsOnDay = "1";
+ else if (repeatsOnDay.equalsIgnoreCase(TemplatePopulateImportConstants.TUESDAY))
+ repeatsOnDay = "2";
+ else if (repeatsOnDay.equalsIgnoreCase(TemplatePopulateImportConstants.WEDNESDAY))
+ repeatsOnDay = "3";
+ else if (repeatsOnDay.equalsIgnoreCase(TemplatePopulateImportConstants.THURSDAY))
+ repeatsOnDay = "4";
+ else if (repeatsOnDay.equalsIgnoreCase(TemplatePopulateImportConstants.FRIDAY))
+ repeatsOnDay = "5";
+
+ else if (repeatsOnDay.equalsIgnoreCase(TemplatePopulateImportConstants.SATURDAY))
+ repeatsOnDay = "6";
+ else if (repeatsOnDay.equalsIgnoreCase(TemplatePopulateImportConstants.SUNDAY))
+ repeatsOnDay = "7";
+ return repeatsOnDay;
+ }else {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/center/CenterImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/center/CenterImportHandler.java
new file mode 100644
index 000000000..958f1ddd1
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/center/CenterImportHandler.java
@@ -0,0 +1,259 @@
+/**
+ * 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.importhandler.center;
+
+import com.google.common.reflect.TypeToken;
+import com.google.gson.GsonBuilder;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.CenterConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOptionDataValueSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.GroupIdSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.calendar.data.CalendarData;
+import org.apache.fineract.portfolio.group.data.CenterData;
+import org.apache.fineract.portfolio.group.data.GroupGeneralData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+@Service
+public class CenterImportHandler implements ImportHandler {
+
+
+ private List centers;
+ private List meetings;
+ private Liststatuses;
+ private Workbook workbook;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public CenterImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.centers=new ArrayList<>();
+ this.meetings=new ArrayList<>();
+ this.statuses=new ArrayList<>();
+ this.workbook=workbook;
+ readExcelFile(locale, dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+
+ Sheet centersSheet = workbook.getSheet(TemplatePopulateImportConstants.CENTER_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(centersSheet, TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex = 1; rowIndex <=noOfEntries; rowIndex++) {
+ Row row;
+ row = centersSheet.getRow(rowIndex);
+ if(ImportHandlerUtils.isNotImported(row, CenterConstants.STATUS_COL)) {
+ centers.add(readCenter(row,locale,dateFormat));
+ meetings.add(readMeeting(row,locale,dateFormat));
+ }
+ }
+ }
+
+ private CalendarData readMeeting(Row row,final String locale, final String dateFormat) {
+ LocalDate meetingStartDate = ImportHandlerUtils.readAsDate(CenterConstants.MEETING_START_DATE_COL, row);
+ Boolean isRepeating = ImportHandlerUtils.readAsBoolean(CenterConstants.IS_REPEATING_COL, row);
+ String frequency = ImportHandlerUtils.readAsString(CenterConstants.FREQUENCY_COL, row);
+ EnumOptionData frequencyEnum=new EnumOptionData(null,null,ImportHandlerUtils.getFrequencyId(frequency));
+ Integer interval = ImportHandlerUtils.readAsInt(CenterConstants.INTERVAL_COL, row);
+ String repeatsOnDay = ImportHandlerUtils.readAsString(CenterConstants.REPEATS_ON_DAY_COL, row);
+ EnumOptionData repeatsOnDayEnum=new EnumOptionData(null,null,ImportHandlerUtils.getRepeatsOnDayId(repeatsOnDay));
+ if(meetingStartDate==null)
+ return null;
+ else {
+ if(repeatsOnDay==null)
+ return CalendarData.importInstanceNoRepeatsOnDay(meetingStartDate, isRepeating,
+ frequencyEnum, interval, row.getRowNum(),locale,dateFormat);
+ else
+ return CalendarData.importInstanceWithRepeatsOnDay(meetingStartDate, isRepeating,
+ frequencyEnum, interval, repeatsOnDayEnum, row.getRowNum(),locale,dateFormat);
+ }
+ }
+
+ private CenterData readCenter(Row row,final String locale, final String dateFormat) {
+ String status = ImportHandlerUtils.readAsString(CenterConstants.STATUS_COL, row);
+ String officeName = ImportHandlerUtils.readAsString(CenterConstants.OFFICE_NAME_COL, row);
+ Long officeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME), officeName);
+ String staffName = ImportHandlerUtils.readAsString(CenterConstants.STAFF_NAME_COL, row);
+ Long staffId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), staffName);
+
+ String externalId = ImportHandlerUtils.readAsString(CenterConstants.EXTERNAL_ID_COL, row);
+ Boolean active = ImportHandlerUtils.readAsBoolean(CenterConstants.ACTIVE_COL, row);
+ LocalDate submittedOn=ImportHandlerUtils.readAsDate(CenterConstants.SUBMITTED_ON_DATE_COL,row);
+ LocalDate activationDate = null;
+ if (active){
+ activationDate=ImportHandlerUtils.readAsDate(CenterConstants.ACTIVATION_DATE_COL, row);
+ }else {
+ activationDate=submittedOn;
+ }
+ String centerName = ImportHandlerUtils.readAsString(CenterConstants.CENTER_NAME_COL, row);
+ if(centerName==null||centerName.equals("")) {
+ throw new IllegalArgumentException("Name is blank");
+ }
+ List groupMembers = new ArrayList();
+ for (int cellNo =CenterConstants. GROUP_NAMES_STARTING_COL; cellNo < CenterConstants.GROUP_NAMES_ENDING_COL; cellNo++) {
+ String groupName = ImportHandlerUtils.readAsString(cellNo, row);
+ if (groupName==null||groupName.equals(""))
+ break;
+ Long groupId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME), groupName);
+ GroupGeneralData group = new GroupGeneralData(groupId);
+ if (!containsGroupId(groupMembers,groupId)) {
+ groupMembers.add(group);
+ }
+ }
+
+ statuses.add(status);
+ return CenterData.importInstance(centerName,groupMembers,activationDate, active,submittedOn, externalId,
+ officeId, staffId, row.getRowNum(),dateFormat,locale);
+ }
+
+ private boolean containsGroupId(List groupMembers,Long groupId){
+ for (GroupGeneralData group: groupMembers) {
+ if (group.getId()==groupId){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet centerSheet = workbook.getSheet(TemplatePopulateImportConstants.CENTER_SHEET_NAME);
+ int progressLevel = 0;
+ String centerId = "";
+ int successCount = 0;
+ int errorCount = 0;
+ String errorMessage = "";
+ for (int i = 0; i < centers.size(); i++) {
+ Row row = centerSheet.getRow(centers.get(i).getRowIndex());
+ Cell errorReportCell = row.createCell(CenterConstants.FAILURE_COL);
+ Cell statusCell = row.createCell(CenterConstants.STATUS_COL);
+ CommandProcessingResult result = null;
+ try {
+ String status = statuses.get(i);
+ progressLevel = getProgressLevel(status);
+
+ if (progressLevel == 0) {
+ result = importCenter(i, dateFormat);
+ centerId = result.getGroupId().toString();
+ progressLevel = 1;
+ } else
+ centerId = ImportHandlerUtils.readAsInt(CenterConstants.CENTER_ID_COL, centerSheet.getRow(centers.get(i).getRowIndex())).toString();
+
+ if (meetings.get(i) != null)
+ progressLevel = importCenterMeeting(result, i, dateFormat);
+ successCount++;
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ writeCenterErrorMessage(centerId,errorMessage,progressLevel,statusCell,errorReportCell,row);
+ }
+ }
+ setReportHeaders(centerSheet);
+ return Count.instance(successCount, errorCount);
+ }
+
+ private void writeCenterErrorMessage(String centerId,String errorMessage,int progressLevel,Cell statusCell,Cell errorReportCell,Row row){
+ String status = "";
+ if (progressLevel == 0)
+ status = TemplatePopulateImportConstants.STATUS_CREATION_FAILED;
+ else if (progressLevel == 1)
+ status = TemplatePopulateImportConstants.STATUS_MEETING_FAILED;
+ statusCell.setCellValue(status);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.RED));
+
+ if (progressLevel > 0)
+ row.createCell(CenterConstants.CENTER_ID_COL).setCellValue(Integer.parseInt(centerId));
+ errorReportCell.setCellValue(errorMessage);
+ }
+
+ private int getProgressLevel(String status) {
+
+ if(status==null || status.equals(TemplatePopulateImportConstants.STATUS_CREATION_FAILED))
+ return 0;
+ else if(status.equals(TemplatePopulateImportConstants.STATUS_MEETING_FAILED))
+ return 1;
+ return 0;
+ }
+ private CommandProcessingResult importCenter(int rowIndex,String dateFormat) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ Type groupCollectionType = new TypeToken>() {}.getType();
+ gsonBuilder.registerTypeAdapter(groupCollectionType,new GroupIdSerializer());
+ String payload= gsonBuilder.create().toJson(centers.get(rowIndex));;
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createCenter() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ return result;
+ }
+
+ private void setReportHeaders(Sheet sheet) {
+ ImportHandlerUtils.writeString(CenterConstants.STATUS_COL, sheet.getRow(0), TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ ImportHandlerUtils.writeString(CenterConstants.CENTER_ID_COL, sheet.getRow(0), TemplatePopulateImportConstants.CENTERID_COL_REPORT_HEADER);
+ ImportHandlerUtils.writeString(CenterConstants.FAILURE_COL, sheet.getRow(0), TemplatePopulateImportConstants.FAILURE_COL_REPORT_HEADER);
+ }
+
+ private Integer importCenterMeeting(CommandProcessingResult result, int rowIndex,String dateFormat) {
+ CalendarData calendarData=meetings.get(rowIndex);
+ calendarData.setTitle("centers_" + result.getGroupId().toString() + "_CollectionMeeting");
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(EnumOptionData.class,new EnumOptionDataValueSerializer());
+
+ String payload = gsonBuilder.create().toJson(calendarData);
+ CommandWrapper commandWrapper=new CommandWrapper(result.getOfficeId(),result.getGroupId(),result.getClientId(),
+ result.getLoanId(),result.getSavingsId(),null,null,null,null,
+ null,payload,result.getTransactionId(),result.getProductId(),null,null,
+ null);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createCalendar(commandWrapper,TemplatePopulateImportConstants.CENTER_ENTITY_TYPE,result.getGroupId()) //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult meetingresult = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ return 2;
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/chartofaccounts/ChartOfAccountsImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/chartofaccounts/ChartOfAccountsImportHandler.java
new file mode 100644
index 000000000..c31099ad9
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/chartofaccounts/ChartOfAccountsImportHandler.java
@@ -0,0 +1,143 @@
+/**
+ * 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.importhandler.chartofaccounts;
+
+import com.google.gson.GsonBuilder;
+import org.apache.fineract.accounting.glaccount.data.GLAccountData;
+import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
+import org.apache.fineract.accounting.glaccount.domain.GLAccountUsage;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.ChartOfAcountsConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.CodeValueDataIdSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOptionDataIdSerializer;
+import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.poi.ss.usermodel.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class ChartOfAccountsImportHandler implements ImportHandler {
+ private List glAccounts;
+ private Workbook workbook;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public ChartOfAccountsImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.glAccounts=new ArrayList<>();
+ this.workbook=workbook;
+ readExcelFile();
+ return importEntity();
+ }
+
+ public void readExcelFile() {
+
+ Sheet chartOfAccountsSheet=workbook.getSheet(TemplatePopulateImportConstants.CHART_OF_ACCOUNTS_SHEET_NAME);
+ Integer noOfEntries= ImportHandlerUtils.getNumberOfRows(chartOfAccountsSheet,TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex=1;rowIndex<=noOfEntries;rowIndex++){
+ Row row;
+ row=chartOfAccountsSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, ChartOfAcountsConstants.STATUS_COL)){
+ glAccounts.add(readGlAccounts(row));
+ }
+ }
+ }
+
+ private GLAccountData readGlAccounts(Row row) {
+ String accountType=ImportHandlerUtils.readAsString(ChartOfAcountsConstants.ACCOUNT_TYPE_COL,row);
+ EnumOptionData accountTypeEnum=GLAccountType.fromString(accountType);
+ String accountName=ImportHandlerUtils.readAsString(ChartOfAcountsConstants.ACCOUNT_NAME_COL,row);
+ String usage=ImportHandlerUtils.readAsString(ChartOfAcountsConstants.ACCOUNT_USAGE_COL,row);
+ Long usageId=null;
+ EnumOptionData usageEnum=null;
+ if (usage!=null&& usage.equals(GLAccountUsage.DETAIL.toString())){
+ usageId=1L;
+ usageEnum=new EnumOptionData(usageId,null,null);
+ }else if (usage!=null&&usage.equals(GLAccountUsage.HEADER.toString())){
+ usageId=2L;
+ usageEnum=new EnumOptionData(usageId,null,null);
+ }
+ Boolean manualEntriesAllowed=ImportHandlerUtils.readAsBoolean(ChartOfAcountsConstants.MANUAL_ENTRIES_ALLOWED_COL,row);
+ Long parentId=null;
+ if (ImportHandlerUtils.readAsString(ChartOfAcountsConstants.PARENT_ID_COL,row)!=null) {
+ parentId = Long.parseLong(ImportHandlerUtils.readAsString(ChartOfAcountsConstants.PARENT_ID_COL,row));
+ }
+ String glCode=ImportHandlerUtils.readAsString(ChartOfAcountsConstants.GL_CODE_COL,row);
+ Long tagId=null;
+ if(ImportHandlerUtils.readAsString(ChartOfAcountsConstants.TAG_ID_COL,row)!=null)
+ tagId=Long.parseLong(ImportHandlerUtils.readAsString(ChartOfAcountsConstants.TAG_ID_COL,row));
+ CodeValueData tagIdCodeValueData=new CodeValueData(tagId);
+ String description=ImportHandlerUtils.readAsString(ChartOfAcountsConstants.DESCRIPTION_COL,row);
+ return GLAccountData.importInstance(accountName,parentId,glCode,manualEntriesAllowed,accountTypeEnum,
+ usageEnum,description,tagIdCodeValueData,row.getRowNum());
+ }
+
+ public Count importEntity() {
+ Sheet chartOfAccountsSheet=workbook.getSheet(TemplatePopulateImportConstants.CHART_OF_ACCOUNTS_SHEET_NAME);
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(EnumOptionData.class, new EnumOptionDataIdSerializer());
+ gsonBuilder.registerTypeAdapter(CodeValueData.class, new CodeValueDataIdSerializer());
+ int successCount = 0;
+ int errorCount = 0;
+ String errorMessage = "";
+ for (GLAccountData glAccount: glAccounts) {
+ try {
+ String payload=gsonBuilder.create().toJson(glAccount);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createGLAccount() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = chartOfAccountsSheet.getRow(glAccount.getRowIndex()).createCell(ChartOfAcountsConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(chartOfAccountsSheet,glAccount.getRowIndex(),errorMessage,ChartOfAcountsConstants.STATUS_COL);
+ }
+ }
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(ChartOfAcountsConstants.STATUS_COL, chartOfAccountsSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX),
+ TemplatePopulateImportConstants.STATUS_COLUMN_HEADER);
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientEntityImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientEntityImportHandler.java
new file mode 100644
index 000000000..36fb4cdb8
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientEntityImportHandler.java
@@ -0,0 +1,212 @@
+/**
+ * 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.importhandler.client;
+
+import com.google.gson.GsonBuilder;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.ClientEntityConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.address.data.AddressData;
+import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.client.data.ClientNonPersonData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class ClientEntityImportHandler implements ImportHandler {
+
+ private Workbook workbook;
+ private List clients;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public ClientEntityImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook = workbook;
+ this.clients=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+ Sheet clientSheet=workbook.getSheet(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME);
+ Integer noOfEntries= ImportHandlerUtils.getNumberOfRows(clientSheet,0);
+ for (int rowIndex=1;rowIndex<=noOfEntries;rowIndex++){
+ Row row;
+ row=clientSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, ClientEntityConstants.STATUS_COL)){
+ clients.add(readClient(row,locale,dateFormat));
+ }
+ }
+ }
+
+ private ClientData readClient(Row row,final String locale, final String dateFormat) {
+ Long legalFormId=2L;
+ String name = ImportHandlerUtils.readAsString(ClientEntityConstants.NAME_COL, row);
+ String officeName = ImportHandlerUtils.readAsString(ClientEntityConstants.OFFICE_NAME_COL, row);
+ Long officeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME), officeName);
+ String staffName = ImportHandlerUtils.readAsString(ClientEntityConstants.STAFF_NAME_COL, row);
+ Long staffId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), staffName);
+ LocalDate incorportionDate=ImportHandlerUtils.readAsDate(ClientEntityConstants.INCOPORATION_DATE_COL,row);
+ LocalDate incorporationTill=ImportHandlerUtils.readAsDate(ClientEntityConstants.INCOPORATION_VALID_TILL_COL,row);
+ String mobileNo=null;
+ if (ImportHandlerUtils.readAsLong(ClientEntityConstants.MOBILE_NO_COL, row)!=null)
+ mobileNo = ImportHandlerUtils.readAsLong(ClientEntityConstants.MOBILE_NO_COL, row).toString();
+
+ String clientType=ImportHandlerUtils.readAsString(ClientEntityConstants.CLIENT_TYPE_COL, row);
+ Long clientTypeId = null;
+ if (clientType!=null) {
+ String clientTypeAr[] =clientType .split("-");
+ if (clientTypeAr[1] != null) {
+ clientTypeId = Long.parseLong(clientTypeAr[1]);
+ }
+ }
+ String clientClassification= ImportHandlerUtils.readAsString(ClientEntityConstants.CLIENT_CLASSIFICATION_COL, row);
+ Long clientClassicationId = null;
+ if (clientClassification!=null) {
+ String clientClassificationAr[] =clientClassification.split("-");
+ if (clientClassificationAr[1] != null)
+ clientClassicationId = Long.parseLong(clientClassificationAr[1]);
+ }
+ String incorporationNo=ImportHandlerUtils.readAsString(ClientEntityConstants.INCOPORATION_NUMBER_COL,row);
+
+ String mainBusinessLine=ImportHandlerUtils.readAsString(ClientEntityConstants.MAIN_BUSINESS_LINE,row);
+ Long mainBusinessId = null;
+ if (mainBusinessLine!=null) {
+ String mainBusinessLineAr[] = ImportHandlerUtils.readAsString(ClientEntityConstants.MAIN_BUSINESS_LINE, row).split("-");
+ if (mainBusinessLineAr[1] != null)
+ mainBusinessId = Long.parseLong(mainBusinessLineAr[1]);
+ }
+ String constitution= ImportHandlerUtils.readAsString(ClientEntityConstants.CONSTITUTION_COL,row);
+ Long constitutionId = null;
+ if (constitution!=null) {
+ String constitutionAr[] = constitution.split("-");
+ if (constitutionAr[1] != null)
+ constitutionId = Long.parseLong(constitutionAr[1]);
+ }
+ String remarks = ImportHandlerUtils.readAsString(ClientEntityConstants.REMARKS_COL, row);
+
+ ClientNonPersonData clientNonPersonData= ClientNonPersonData.importInstance(incorporationNo,incorporationTill,remarks,
+ mainBusinessId,constitutionId,locale,dateFormat);
+
+ String externalId= ImportHandlerUtils.readAsString(ClientEntityConstants.EXTERNAL_ID_COL, row);
+
+ Boolean active = ImportHandlerUtils.readAsBoolean(ClientEntityConstants.ACTIVE_COL, row);
+
+ LocalDate submittedOn=ImportHandlerUtils.readAsDate(ClientEntityConstants.SUBMITTED_ON_COL,row);
+
+ LocalDate activationDate = ImportHandlerUtils.readAsDate(ClientEntityConstants.ACTIVATION_DATE_COL, row);
+ if (!active){
+ activationDate=submittedOn;
+ }
+ AddressData addressDataObj=null;
+ if (ImportHandlerUtils.readAsBoolean(ClientEntityConstants.ADDRESS_ENABLED,row)) {
+ String addressType = ImportHandlerUtils.readAsString(ClientEntityConstants.ADDRESS_TYPE_COL, row);
+ Long addressTypeId = null;
+ if (addressType!=null) {
+ String addressTypeAr[] = addressType.split("-");
+ if (addressTypeAr[1] != null)
+ addressTypeId = Long.parseLong(addressTypeAr[1]);
+ }
+ String street = ImportHandlerUtils.readAsString(ClientEntityConstants.STREET_COL, row);
+ String addressLine1 = ImportHandlerUtils.readAsString(ClientEntityConstants.ADDRESS_LINE_1_COL, row);
+ String addressLine2 = ImportHandlerUtils.readAsString(ClientEntityConstants.ADDRESS_LINE_2_COL, row);
+ String addressLine3 = ImportHandlerUtils.readAsString(ClientEntityConstants.ADDRESS_LINE_3_COL, row);
+ String city = ImportHandlerUtils.readAsString(ClientEntityConstants.CITY_COL, row);
+
+ String postalCode = ImportHandlerUtils.readAsString(ClientEntityConstants.POSTAL_CODE_COL, row);
+ Boolean isActiveAddress = ImportHandlerUtils.readAsBoolean(ClientEntityConstants.IS_ACTIVE_ADDRESS_COL, row);
+
+ String stateProvince=ImportHandlerUtils.readAsString(ClientEntityConstants.STATE_PROVINCE_COL, row);
+ Long stateProvinceId = null;
+ if (stateProvince!=null) {
+ String stateProvinceAr[] = stateProvince.split("-");
+ if (stateProvinceAr[1] != null)
+ stateProvinceId = Long.parseLong(stateProvinceAr[1]);
+ }
+ String country= ImportHandlerUtils.readAsString(ClientEntityConstants.COUNTRY_COL, row);
+ Long countryId = null;
+ if (country!=null) {
+ String countryAr[] = country.split("-");
+ if (countryAr[1] != null)
+ countryId = Long.parseLong(countryAr[1]);
+ }
+ addressDataObj = new AddressData(addressTypeId, street, addressLine1, addressLine2, addressLine3,
+ city, postalCode, isActiveAddress, stateProvinceId, countryId);
+ }
+ return ClientData.importClientEntityInstance(legalFormId,row.getRowNum(),name,officeId,clientTypeId,clientClassicationId,
+ staffId,active,activationDate,submittedOn, externalId,incorportionDate,mobileNo,clientNonPersonData,addressDataObj,locale,dateFormat);
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet clientSheet=workbook.getSheet(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME);
+
+ int successCount = 0;
+ int errorCount = 0;
+ String errorMessage = "";
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+
+ for (ClientData client: clients) {
+ try {
+ String payload=gsonBuilder.create().toJson(client);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createClient() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = clientSheet.getRow(client.getRowIndex()).createCell(ClientEntityConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(clientSheet,client.getRowIndex(),errorMessage,ClientEntityConstants.STATUS_COL);
+ }
+ }
+ clientSheet.setColumnWidth(ClientEntityConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(ClientEntityConstants.STATUS_COL, clientSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX),
+ TemplatePopulateImportConstants.STATUS_COLUMN_HEADER);
+
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientPersonImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientPersonImportHandler.java
new file mode 100644
index 000000000..34e0fae47
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientPersonImportHandler.java
@@ -0,0 +1,197 @@
+/**
+ * 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.importhandler.client;
+
+import com.google.gson.GsonBuilder;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.ClientPersonConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.address.data.AddressData;
+import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class ClientPersonImportHandler implements ImportHandler {
+
+ private Workbook workbook;
+ private List clients;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public ClientPersonImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook = workbook;
+ this.clients=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+ Sheet clientSheet=workbook.getSheet(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME);
+ Integer noOfEntries= ImportHandlerUtils.getNumberOfRows(clientSheet,0);
+ for (int rowIndex=1;rowIndex<=noOfEntries;rowIndex++){
+ Row row;
+ row=clientSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, ClientPersonConstants.STATUS_COL)){
+ clients.add(readClient(row,locale,dateFormat));
+ }
+ }
+ }
+
+ private ClientData readClient(Row row,final String locale, final String dateFormat) {
+ Long legalFormId=1L;
+ String firstName = ImportHandlerUtils.readAsString(ClientPersonConstants.FIRST_NAME_COL, row);
+ String lastName = ImportHandlerUtils.readAsString(ClientPersonConstants.LAST_NAME_COL, row);
+ String middleName = ImportHandlerUtils.readAsString(ClientPersonConstants.MIDDLE_NAME_COL, row);
+ String officeName = ImportHandlerUtils.readAsString(ClientPersonConstants.OFFICE_NAME_COL, row);
+ Long officeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME), officeName);
+ String staffName = ImportHandlerUtils.readAsString(ClientPersonConstants.STAFF_NAME_COL, row);
+ Long staffId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), staffName);
+ String externalId = ImportHandlerUtils.readAsString(ClientPersonConstants.EXTERNAL_ID_COL, row);
+ LocalDate submittedOn=ImportHandlerUtils.readAsDate(ClientPersonConstants.SUBMITTED_ON_COL,row);
+ LocalDate activationDate = ImportHandlerUtils.readAsDate(ClientPersonConstants.ACTIVATION_DATE_COL, row);
+ Boolean active = ImportHandlerUtils.readAsBoolean(ClientPersonConstants.ACTIVE_COL, row);
+ if (!active){
+ activationDate=submittedOn;
+ }
+ String mobileNo=null;
+ if (ImportHandlerUtils.readAsLong(ClientPersonConstants.MOBILE_NO_COL, row)!=null)
+ mobileNo = ImportHandlerUtils.readAsLong(ClientPersonConstants.MOBILE_NO_COL, row).toString();
+ LocalDate dob = ImportHandlerUtils.readAsDate(ClientPersonConstants.DOB_COL, row);
+
+ String clientType=ImportHandlerUtils.readAsString(ClientPersonConstants.CLIENT_TYPE_COL, row);
+ Long clientTypeId = null;
+ if (clientType!=null) {
+ String clientTypeAr[] = clientType.split("-");
+ if (clientTypeAr[1] != null) {
+ clientTypeId = Long.parseLong(clientTypeAr[1]);
+ }
+ }
+ String gender=ImportHandlerUtils.readAsString(ClientPersonConstants.GENDER_COL, row);
+ Long genderId = null;
+ if (gender!=null) {
+ String genderAr[] = gender.split("-");
+ if (genderAr[1] != null)
+ genderId = Long.parseLong(genderAr[1]);
+ }
+ String clientClassification= ImportHandlerUtils.readAsString(ClientPersonConstants.CLIENT_CLASSIFICATION_COL, row);
+ Long clientClassicationId = null;
+ if (clientClassification!=null) {
+ String clientClassificationAr[] = clientClassification.split("-");
+ if (clientClassificationAr[1] != null)
+ clientClassicationId = Long.parseLong(clientClassificationAr[1]);
+ }
+ Boolean isStaff = ImportHandlerUtils.readAsBoolean(ClientPersonConstants.IS_STAFF_COL, row);
+
+ AddressData addressDataObj=null;
+ if (ImportHandlerUtils.readAsBoolean(ClientPersonConstants.ADDRESS_ENABLED_COL,row)) {
+ String addressType=ImportHandlerUtils.readAsString(ClientPersonConstants.ADDRESS_TYPE_COL, row);
+ Long addressTypeId = null;
+ if (addressType!=null) {
+ String addressTypeAr[] = addressType.split("-");
+
+ if (addressTypeAr[1] != null)
+ addressTypeId = Long.parseLong(addressTypeAr[1]);
+ }
+ String street = ImportHandlerUtils.readAsString(ClientPersonConstants.STREET_COL, row);
+ String addressLine1 = ImportHandlerUtils.readAsString(ClientPersonConstants.ADDRESS_LINE_1_COL, row);
+ String addressLine2 = ImportHandlerUtils.readAsString(ClientPersonConstants.ADDRESS_LINE_2_COL, row);
+ String addressLine3 = ImportHandlerUtils.readAsString(ClientPersonConstants.ADDRESS_LINE_3_COL, row);
+ String city = ImportHandlerUtils.readAsString(ClientPersonConstants.CITY_COL, row);
+
+ String postalCode = ImportHandlerUtils.readAsString(ClientPersonConstants.POSTAL_CODE_COL, row);
+ Boolean isActiveAddress = ImportHandlerUtils.readAsBoolean(ClientPersonConstants.IS_ACTIVE_ADDRESS_COL, row);
+
+ String stateProvince=ImportHandlerUtils.readAsString(ClientPersonConstants.STATE_PROVINCE_COL, row);
+ Long stateProvinceId = null;
+ if (stateProvince!=null) {
+ String stateProvinceAr[] = stateProvince.split("-");
+ if (stateProvinceAr[1] != null)
+ stateProvinceId = Long.parseLong(stateProvinceAr[1]);
+ }
+ String country=ImportHandlerUtils.readAsString(ClientPersonConstants.COUNTRY_COL, row);
+ Long countryId=null;
+ if (country!=null) {
+ String countryAr[] = country.split("-");
+ if (countryAr[1] != null)
+ countryId = Long.parseLong(countryAr[1]);
+ }
+ addressDataObj = new AddressData(addressTypeId, street, addressLine1, addressLine2, addressLine3,
+ city, postalCode, isActiveAddress, stateProvinceId, countryId);
+ }
+ return ClientData.importClientPersonInstance(legalFormId,row.getRowNum(),firstName,lastName,middleName,submittedOn,activationDate,active,externalId,
+ officeId,staffId,mobileNo,dob,clientTypeId,genderId,clientClassicationId,isStaff,addressDataObj,locale,dateFormat);
+
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet clientSheet=workbook.getSheet(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ for (ClientData client: clients) {
+ try {
+ String payload=gsonBuilder.create().toJson(client);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createClient() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = clientSheet.getRow(client.getRowIndex()).createCell(ClientPersonConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(clientSheet,client.getRowIndex(),errorMessage,ClientPersonConstants.STATUS_COL);
+ }
+ }
+ clientSheet.setColumnWidth(ClientPersonConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(ClientPersonConstants.STATUS_COL, clientSheet.
+ getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX), TemplatePopulateImportConstants.STATUS_COLUMN_HEADER);
+
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/fixeddeposits/FixedDepositImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/fixeddeposits/FixedDepositImportHandler.java
new file mode 100644
index 000000000..10118a5b2
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/fixeddeposits/FixedDepositImportHandler.java
@@ -0,0 +1,390 @@
+/**
+ * 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.importhandler.fixeddeposits;
+
+import com.google.gson.*;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.FixedDepositConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOptionDataIdSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.savings.data.*;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class FixedDepositImportHandler implements ImportHandler {
+
+ private Workbook workbook;
+
+ private List savings;
+ private List approvalDates;
+ private List activationDates;
+ private List closedOnDate;
+ private List statuses;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public FixedDepositImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook = workbook;
+ savings=new ArrayList<>();
+ approvalDates=new ArrayList<>();
+ activationDates=new ArrayList<>();
+ closedOnDate=new ArrayList<>();
+ statuses=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+ Sheet savingsSheet = workbook.getSheet(TemplatePopulateImportConstants.FIXED_DEPOSIT_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(savingsSheet, TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = savingsSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, FixedDepositConstants.STATUS_COL)) {
+ savings.add(readSavings(row,locale,dateFormat));
+ approvalDates.add(readSavingsApproval(row,locale,dateFormat));
+ activationDates.add(readSavingsActivation(row,locale,dateFormat));
+ closedOnDate.add(readSavingsClosed(row,locale,dateFormat));
+ }
+ }
+
+ }
+
+ private ClosingOfSavingsAccounts readSavingsClosed(Row row,String locale,String dateFormat) {
+ LocalDate closedOnDate = ImportHandlerUtils.readAsDate(FixedDepositConstants.CLOSED_ON_DATE, row);
+ Long onAccountClosureId = ImportHandlerUtils.readAsLong(FixedDepositConstants.ON_ACCOUNT_CLOSURE_ID, row);
+ Long toSavingsAccountId = ImportHandlerUtils.readAsLong(FixedDepositConstants.TO_SAVINGS_ACCOUNT_ID, row);
+ if (closedOnDate!=null)
+ return ClosingOfSavingsAccounts.importInstance(null, closedOnDate,onAccountClosureId,toSavingsAccountId, null,
+ row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private SavingsActivation readSavingsActivation(Row row,String locale,String dateFormat) {
+ LocalDate activationDate = ImportHandlerUtils.readAsDate(FixedDepositConstants.ACTIVATION_DATE_COL, row);
+ if (activationDate!=null)
+ return SavingsActivation.importInstance(activationDate, row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private SavingsApproval readSavingsApproval(Row row,String locale,String dateFormat) {
+ LocalDate approvalDate = ImportHandlerUtils.readAsDate(FixedDepositConstants.APPROVED_DATE_COL, row);
+ if (approvalDate!=null)
+ return SavingsApproval.importInstance(approvalDate, row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private FixedDepositAccountData readSavings(Row row,String locale,String dateFormat) {
+
+ String productName = ImportHandlerUtils.readAsString(FixedDepositConstants.PRODUCT_COL, row);
+ Long productId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME), productName);
+ String fieldOfficerName = ImportHandlerUtils.readAsString(FixedDepositConstants.FIELD_OFFICER_NAME_COL, row);
+ Long fieldOfficerId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), fieldOfficerName);
+ LocalDate submittedOnDate = ImportHandlerUtils.readAsDate(FixedDepositConstants.SUBMITTED_ON_DATE_COL, row);
+ String interestCompoundingPeriodType = ImportHandlerUtils.readAsString(FixedDepositConstants.INTEREST_COMPOUNDING_PERIOD_COL, row);
+ Long interestCompoundingPeriodTypeId = null;
+ EnumOptionData interestCompoundingPeriodTypeEnum=null;
+ if (interestCompoundingPeriodType!=null) {
+ if (interestCompoundingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_DAILY))
+ interestCompoundingPeriodTypeId = 1L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_MONTHLY))
+ interestCompoundingPeriodTypeId = 4L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_QUARTERLY))
+ interestCompoundingPeriodTypeId = 5L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_SEMI_ANNUALLY))
+ interestCompoundingPeriodTypeId = 6L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_ANNUALLY))
+ interestCompoundingPeriodTypeId = 7L;
+ interestCompoundingPeriodTypeEnum = new EnumOptionData(interestCompoundingPeriodTypeId, null, null);
+ }
+ String interestPostingPeriodType = ImportHandlerUtils.readAsString(FixedDepositConstants.INTEREST_POSTING_PERIOD_COL, row);
+ Long interestPostingPeriodTypeId = null;
+
+ EnumOptionData interestPostingPeriodTypeEnum=null;
+ if (interestCompoundingPeriodType!=null) {
+ if (interestPostingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_POSTING_PERIOD_MONTHLY))
+ interestPostingPeriodTypeId = 4L;
+ else if (interestPostingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_POSTING_PERIOD_QUARTERLY))
+ interestPostingPeriodTypeId = 5L;
+ else if (interestPostingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_ANNUALLY))
+ interestPostingPeriodTypeId = 7L;
+ else if (interestPostingPeriodType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_POSTING_PERIOD_BIANUALLY))
+ interestPostingPeriodTypeId = 6L;
+ interestPostingPeriodTypeEnum = new EnumOptionData(interestPostingPeriodTypeId, null, null);
+ }
+ String interestCalculationType = ImportHandlerUtils.readAsString(FixedDepositConstants.INTEREST_CALCULATION_COL, row);
+ EnumOptionData interestCalculationTypeEnum=null;
+ if (interestCalculationType!=null) {
+ Long interestCalculationTypeId = null;
+ if (interestCalculationType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_CAL_DAILY_BALANCE))
+ interestCalculationTypeId = 1L;
+ else if (interestCalculationType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_CAL_AVG_BALANCE))
+ interestCalculationTypeId = 2L;
+ interestCalculationTypeEnum = new EnumOptionData(interestCalculationTypeId, null, null);
+ }
+ String interestCalculationDaysInYearType = ImportHandlerUtils.readAsString(FixedDepositConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL, row);
+ Long interestCalculationDaysInYearTypeId = null;
+ EnumOptionData interestCalculationDaysInYearTypeEnum=null;
+ if (interestCalculationDaysInYearType!=null) {
+ if (interestCalculationDaysInYearType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_CAL_DAYS_IN_YEAR_360))
+ interestCalculationDaysInYearTypeId = 360L;
+ else if (interestCalculationDaysInYearType.equalsIgnoreCase(TemplatePopulateImportConstants.INTEREST_CAL_DAYS_IN_YEAR_365))
+ interestCalculationDaysInYearTypeId = 365L;
+ interestCalculationDaysInYearTypeEnum = new EnumOptionData(interestCalculationDaysInYearTypeId, null, null);
+ }
+ Integer lockinPeriodFrequency = ImportHandlerUtils.readAsInt(FixedDepositConstants.LOCKIN_PERIOD_COL, row);
+ String lockinPeriodFrequencyType = ImportHandlerUtils.readAsString(FixedDepositConstants.LOCKIN_PERIOD_FREQUENCY_COL, row);
+
+ Long lockinPeriodFrequencyTypeId =null;
+ EnumOptionData lockinPeriodFrequencyTypeEnum=null;
+ if (lockinPeriodFrequencyType!=null) {
+ if (lockinPeriodFrequencyType.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_DAYS))
+ lockinPeriodFrequencyTypeId = 0L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_WEEKS))
+ lockinPeriodFrequencyTypeId = 1L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_MONTHS))
+ lockinPeriodFrequencyTypeId = 2L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_YEARS))
+ lockinPeriodFrequencyTypeId = 3L;
+ lockinPeriodFrequencyTypeEnum = new EnumOptionData(lockinPeriodFrequencyTypeId, null, null);
+ }
+ BigDecimal depositAmount=null;
+ if (ImportHandlerUtils.readAsDouble(FixedDepositConstants.DEPOSIT_AMOUNT_COL, row)!=null) {
+ depositAmount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(FixedDepositConstants.DEPOSIT_AMOUNT_COL, row));
+ }
+ Integer depositPeriod = ImportHandlerUtils.readAsInt(FixedDepositConstants.DEPOSIT_PERIOD_COL, row);
+
+ String depositPeriodFrequency = ImportHandlerUtils.readAsString(FixedDepositConstants.DEPOSIT_PERIOD_FREQUENCY_COL, row);
+ Long depositPeriodFrequencyId = null;
+ if (depositPeriodFrequency!=null) {
+ if (depositPeriodFrequency.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_DAYS))
+ depositPeriodFrequencyId = 0L;
+ else if (depositPeriodFrequency.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_WEEKS))
+ depositPeriodFrequencyId = 1L;
+ else if (depositPeriodFrequency.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_MONTHS))
+ depositPeriodFrequencyId = 2L;
+ else if (depositPeriodFrequency.equalsIgnoreCase(TemplatePopulateImportConstants.FREQUENCY_YEARS))
+ depositPeriodFrequencyId = 3L;
+ }
+ String externalId = ImportHandlerUtils.readAsString(FixedDepositConstants.EXTERNAL_ID_COL, row);
+ String clientName = ImportHandlerUtils.readAsString(FixedDepositConstants.CLIENT_NAME_COL, row);
+
+ List charges = new ArrayList();
+
+ String charge1 = ImportHandlerUtils.readAsString(FixedDepositConstants.CHARGE_ID_1, row);
+ String charge2 = ImportHandlerUtils.readAsString(FixedDepositConstants.CHARGE_ID_2, row);
+
+ if (charge1!=null) {
+ if (ImportHandlerUtils.readAsDouble(FixedDepositConstants.CHARGE_AMOUNT_1, row)!=null)
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(FixedDepositConstants.CHARGE_ID_1, row),
+ BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(FixedDepositConstants.CHARGE_AMOUNT_1, row)),
+ ImportHandlerUtils.readAsDate(FixedDepositConstants.CHARGE_DUE_DATE_1, row)));
+ }else {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(FixedDepositConstants.CHARGE_ID_1, row),
+ null,
+ ImportHandlerUtils.readAsDate(FixedDepositConstants.CHARGE_DUE_DATE_1, row)));
+ }
+
+ if (charge2!=null) {
+ if (ImportHandlerUtils.readAsDouble(FixedDepositConstants.CHARGE_AMOUNT_2, row)!=null) {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(FixedDepositConstants.CHARGE_ID_2, row),
+ BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(FixedDepositConstants.CHARGE_AMOUNT_2, row)),
+ ImportHandlerUtils.readAsDate(FixedDepositConstants.CHARGE_DUE_DATE_2, row)));
+ }else {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(FixedDepositConstants.CHARGE_ID_2, row),
+ null,
+ ImportHandlerUtils.readAsDate(FixedDepositConstants.CHARGE_DUE_DATE_2, row)));
+ }
+ }
+ String status = ImportHandlerUtils.readAsString(FixedDepositConstants.STATUS_COL, row);
+ statuses.add(status);
+ Long clientId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME), clientName);
+ return FixedDepositAccountData.importInstance (clientId, productId, fieldOfficerId, submittedOnDate,
+ interestCompoundingPeriodTypeEnum, interestPostingPeriodTypeEnum, interestCalculationTypeEnum,
+ interestCalculationDaysInYearTypeEnum, lockinPeriodFrequency, lockinPeriodFrequencyTypeEnum,
+ depositAmount, depositPeriod, depositPeriodFrequencyId, externalId, charges,row.getRowNum(),locale,dateFormat);
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet savingsSheet = workbook.getSheet(TemplatePopulateImportConstants.FIXED_DEPOSIT_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ int progressLevel = 0;
+ Long savingsId=null;
+ for (int i = 0; i < savings.size(); i++) {
+ Row row = savingsSheet.getRow(savings.get(i).getRowIndex());
+ Cell statusCell = row.createCell(FixedDepositConstants.STATUS_COL);
+ Cell errorReportCell = row.createCell(FixedDepositConstants.FAILURE_REPORT_COL);
+ try {
+ String status = statuses.get(i);
+ progressLevel = getProgressLevel(status);
+
+ if (progressLevel == 0) {
+ CommandProcessingResult result= importSavings(i,dateFormat);
+ savingsId = result.getSavingsId();
+ progressLevel = 1;
+ } else
+ savingsId = ImportHandlerUtils.readAsLong(FixedDepositConstants.SAVINGS_ID_COL, savingsSheet.getRow(savings.get(i).getRowIndex()));
+
+ if (progressLevel <= 1) progressLevel = importSavingsApproval(savingsId, i,dateFormat);
+
+ if (progressLevel <= 2) progressLevel = importSavingsActivation(savingsId, i,dateFormat);
+
+ if (progressLevel <= 3) progressLevel = importSavingsClosing(savingsId, i,dateFormat);
+
+ successCount++;
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ writeFixedDepositErrorMessage(savingsId,errorMessage,progressLevel,statusCell,errorReportCell,row);
+ }
+
+ }
+ setReportHeaders(savingsSheet);
+ return Count.instance(successCount,errorCount);
+ }
+ private void writeFixedDepositErrorMessage(Long savingsId,String errorMessage,int progressLevel,Cell statusCell,Cell errorReportCell,Row row){
+ String status = "";
+ if (progressLevel == 0)
+ status = TemplatePopulateImportConstants.STATUS_CREATION_FAILED;
+ else if (progressLevel == 1)
+ status = TemplatePopulateImportConstants.STATUS_APPROVAL_FAILED;
+ else if (progressLevel == 2) status = TemplatePopulateImportConstants.STATUS_ACTIVATION_FAILED;
+ statusCell.setCellValue(status);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.RED));
+
+ if (progressLevel > 0) row.createCell(FixedDepositConstants.SAVINGS_ID_COL).setCellValue(savingsId);
+ errorReportCell.setCellValue(errorMessage);
+ }
+
+ private int importSavingsClosing(Long savingsId, int i,String dateFormat) {
+ if(closedOnDate.get(i)!=null) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ String payload = gsonBuilder.create().toJson(closedOnDate.get(i));
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .closeFixedDepositAccount(savingsId)//
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ }
+ return 4;
+ }
+
+ private CommandProcessingResult importSavings(int i,String dateFormat) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(EnumOptionData.class,new EnumOptionDataIdSerializer());
+ JsonObject savingsJsonob=gsonBuilder.create().toJsonTree(savings.get(i)).getAsJsonObject();
+ savingsJsonob.remove("withdrawalFeeForTransfers");
+ JsonArray chargesJsonAr=savingsJsonob.getAsJsonArray("charges");
+ for (int j=0;j savingsTransactions;
+ private String savingsAccountId = "";
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+ @Autowired
+ public FixedDepositTransactionImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.savingsTransactions=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+ Sheet savingsTransactionSheet = workbook.getSheet(TemplatePopulateImportConstants.FIXED_DEPOSIT_TRANSACTION_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(savingsTransactionSheet, TransactionConstants.AMOUNT_COL);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = savingsTransactionSheet.getRow(rowIndex);
+ if(ImportHandlerUtils.isNotImported(row, TransactionConstants.STATUS_COL))
+ savingsTransactions.add(readSavingsTransaction(row,locale,dateFormat));
+ }
+ }
+
+ private SavingsAccountTransactionData readSavingsTransaction(Row row,String locale,String dateFormat) {
+ String savingsAccountIdCheck=null;
+ if (ImportHandlerUtils.readAsLong(TransactionConstants.SAVINGS_ACCOUNT_NO_COL, row)!=null)
+ savingsAccountIdCheck = ImportHandlerUtils.readAsLong(TransactionConstants.SAVINGS_ACCOUNT_NO_COL, row).toString();
+ if(savingsAccountIdCheck!=null)
+ savingsAccountId = savingsAccountIdCheck;
+ String transactionType = ImportHandlerUtils.readAsString(TransactionConstants.TRANSACTION_TYPE_COL, row);
+ SavingsAccountTransactionEnumData savingsAccountTransactionEnumData=new SavingsAccountTransactionEnumData(null,null,transactionType);
+
+ BigDecimal amount=null;
+ if (ImportHandlerUtils.readAsDouble(TransactionConstants.AMOUNT_COL, row)!=null)
+ amount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(TransactionConstants.AMOUNT_COL, row));
+
+ LocalDate transactionDate = ImportHandlerUtils.readAsDate(TransactionConstants.TRANSACTION_DATE_COL, row);
+ String paymentType = ImportHandlerUtils.readAsString(TransactionConstants.PAYMENT_TYPE_COL, row);
+ Long paymentTypeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME), paymentType);
+ String accountNumber = ImportHandlerUtils.readAsString(TransactionConstants.ACCOUNT_NO_COL, row);
+ String checkNumber = ImportHandlerUtils.readAsString(TransactionConstants.CHECK_NO_COL, row);
+ String routingCode = ImportHandlerUtils.readAsString(TransactionConstants.ROUTING_CODE_COL, row);
+ String receiptNumber = ImportHandlerUtils.readAsString(TransactionConstants.RECEIPT_NO_COL, row);
+ String bankNumber = ImportHandlerUtils.readAsString(TransactionConstants.BANK_NO_COL, row);
+ return SavingsAccountTransactionData.importInstance(amount, transactionDate, paymentTypeId, accountNumber,
+ checkNumber, routingCode, receiptNumber, bankNumber, Long.parseLong(savingsAccountId), savingsAccountTransactionEnumData, row.getRowNum(),locale,dateFormat);
+
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet savingsTransactionSheet = workbook.getSheet(TemplatePopulateImportConstants.FIXED_DEPOSIT_TRANSACTION_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(SavingsAccountTransactionEnumData.class
+ ,new SavingsAccountTransactionEnumValueSerialiser());
+
+ for (SavingsAccountTransactionData transaction : savingsTransactions) {
+ try {
+ JsonObject savingsTransactionJsonob=gsonBuilder.create().toJsonTree(transaction).getAsJsonObject();
+ savingsTransactionJsonob.remove("transactionType");
+ savingsTransactionJsonob.remove("reversed");
+ savingsTransactionJsonob.remove("interestedPostedAsOn");
+ String payload= savingsTransactionJsonob.toString();
+ CommandWrapper commandRequest=null;
+ if (transaction.getTransactionType().getValue().equals("Withdrawal")) {
+ commandRequest = new CommandWrapperBuilder() //
+ .fixedDepositAccountWithdrawal(transaction.getSavingsAccountId()) //
+ .withJson(payload) //
+ .build(); //
+
+ }else if (transaction.getTransactionType().getValue().equals("Deposit")){
+ commandRequest = new CommandWrapperBuilder() //
+ .fixedDepositAccountDeposit(transaction.getSavingsAccountId()) //
+ .withJson(payload) //
+ .build();
+ }
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = savingsTransactionSheet.getRow(transaction.getRowIndex()).createCell(TransactionConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(savingsTransactionSheet,transaction.getRowIndex(),errorMessage,TransactionConstants.STATUS_COL);
+ }
+ }
+ savingsTransactionSheet.setColumnWidth(TransactionConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(TransactionConstants.STATUS_COL, savingsTransactionSheet.getRow(TransactionConstants.STATUS_COL), TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/group/GroupImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/group/GroupImportHandler.java
new file mode 100644
index 000000000..ada465d58
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/group/GroupImportHandler.java
@@ -0,0 +1,257 @@
+/**
+ * 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.importhandler.group;
+
+import com.google.common.reflect.TypeToken;
+import com.google.gson.GsonBuilder;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.GroupConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.ClientIdSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOptionDataValueSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.calendar.data.CalendarData;
+import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.group.data.GroupGeneralData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+@Service
+public class GroupImportHandler implements ImportHandler {
+ private List groups;
+ private List meetings;
+ private Workbook workbook;
+ private Liststatuses;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public GroupImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ groups=new ArrayList<>();
+ meetings=new ArrayList<>();
+ statuses=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(String locale, String dateFormat) {
+ Sheet groupsSheet = workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(groupsSheet, TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = groupsSheet.getRow(rowIndex);
+ if(ImportHandlerUtils.isNotImported(row, GroupConstants.STATUS_COL)) {
+ groups.add(readGroup(row,locale,dateFormat));
+ meetings.add(readMeeting(row,locale,dateFormat));
+ }
+ }
+ }
+
+ private CalendarData readMeeting(Row row,String locale,String dateFormat) {
+ LocalDate meetingStartDate = ImportHandlerUtils.readAsDate(GroupConstants.MEETING_START_DATE_COL, row);
+ Boolean isRepeating = ImportHandlerUtils.readAsBoolean(GroupConstants.IS_REPEATING_COL, row);
+ String frequency = ImportHandlerUtils.readAsString(GroupConstants.FREQUENCY_COL, row);
+ EnumOptionData frequencyEnum=new EnumOptionData(null,null,ImportHandlerUtils.getFrequencyId(frequency));
+ Integer interval = ImportHandlerUtils.readAsInt(GroupConstants.INTERVAL_COL, row);
+ String repeatsOnDay = ImportHandlerUtils.readAsString(GroupConstants.REPEATS_ON_DAY_COL, row);
+ EnumOptionData repeatsOnDayEnum=new EnumOptionData(null,null,ImportHandlerUtils.getRepeatsOnDayId(repeatsOnDay));
+ if(meetingStartDate==null)
+ return null;
+ else {
+ if(repeatsOnDay==null)
+ return CalendarData.importInstanceNoRepeatsOnDay(meetingStartDate, isRepeating, frequencyEnum, interval, row.getRowNum(),locale,dateFormat);
+ else
+ return CalendarData.importInstanceWithRepeatsOnDay(meetingStartDate, isRepeating, frequencyEnum, interval, repeatsOnDayEnum, row.getRowNum(),locale,dateFormat);
+ }
+ }
+ private GroupGeneralData readGroup(Row row,String locale,String dateFormat) {
+ String status = ImportHandlerUtils.readAsString(GroupConstants.STATUS_COL, row);
+ String officeName = ImportHandlerUtils.readAsString(GroupConstants.OFFICE_NAME_COL, row);
+ Long officeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME), officeName);
+ String staffName = ImportHandlerUtils.readAsString(GroupConstants.STAFF_NAME_COL, row);
+ Long staffId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), staffName);
+ String centerName = ImportHandlerUtils.readAsString(GroupConstants.CENTER_NAME_COL, row);
+ Long centerId=null;
+ if(centerName!=null)
+ centerId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CENTER_SHEET_NAME), centerName);
+ String externalId = ImportHandlerUtils.readAsString(GroupConstants.EXTERNAL_ID_COL, row);
+ Boolean active = ImportHandlerUtils.readAsBoolean(GroupConstants.ACTIVE_COL, row);
+ LocalDate submittedOnDate=ImportHandlerUtils.readAsDate(GroupConstants.SUBMITTED_ON_DATE_COL,row);
+ LocalDate activationDate=null;
+ if(active) {
+ activationDate = ImportHandlerUtils.readAsDate(GroupConstants.ACTIVATION_DATE_COL, row);
+ }else {
+ activationDate=submittedOnDate;
+ }
+ String groupName = ImportHandlerUtils.readAsString(GroupConstants.NAME_COL, row);
+ if (groupName == null || groupName.equals("")) {
+ throw new IllegalArgumentException("Name is blank");
+ }
+ List clientMembers = new ArrayList<>();
+ for (int cellNo = GroupConstants.CLIENT_NAMES_STARTING_COL; cellNo clientMembers,Long clientId){
+ for (ClientData client: clientMembers) {
+ if (client.getId()==clientId){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet groupSheet = workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ int progressLevel = 0;
+ String groupId = "";
+ String errorMessage="";
+ for (int i = 0; i < groups.size(); i++) {
+ Row row = groupSheet.getRow(groups.get(i).getRowIndex());
+ Cell errorReportCell = row.createCell(GroupConstants.FAILURE_COL);
+ Cell statusCell = row.createCell(GroupConstants.STATUS_COL);
+ CommandProcessingResult result=null;
+ try {
+ String status = statuses.get(i);
+ progressLevel = getProgressLevel(status);
+
+ if(progressLevel == 0)
+ {
+ result = importGroup(i,dateFormat);
+ groupId = result.getGroupId().toString();
+ progressLevel = 1;
+ } else
+ groupId = ImportHandlerUtils.readAsInt(GroupConstants.GROUP_ID_COL, groupSheet.getRow(groups.get(i).getRowIndex())).toString();
+
+ if(meetings.get(i) != null && groups.get(i).getCenterId() == null)
+ progressLevel = importGroupMeeting(result, i,dateFormat);
+
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ writeGroupErrorMessage(groupId,errorMessage,progressLevel,statusCell,errorReportCell,row);
+ }
+ }
+ setReportHeaders(groupSheet);
+ return Count.instance(successCount,errorCount);
+ }
+ private void writeGroupErrorMessage(String groupId,String errorMessage,int progressLevel,Cell statusCell,Cell errorReportCell,Row row){
+ String status = "";
+ if(progressLevel == 0)
+ status = TemplatePopulateImportConstants.STATUS_CREATION_FAILED;
+ else if(progressLevel == 1)
+ status =TemplatePopulateImportConstants.STATUS_MEETING_FAILED ;
+ statusCell.setCellValue(status);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.RED));
+
+ if(progressLevel>0)
+ row.createCell(GroupConstants.GROUP_ID_COL).setCellValue(Integer.parseInt(groupId));
+ errorReportCell.setCellValue(errorMessage);
+ }
+ private void setReportHeaders(Sheet groupSheet) {
+ ImportHandlerUtils.writeString(GroupConstants.STATUS_COL, groupSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX),
+ TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ ImportHandlerUtils.writeString(GroupConstants.GROUP_ID_COL, groupSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX),
+ TemplatePopulateImportConstants.GROUP_ID_COL_REPORT_HEADER);
+ ImportHandlerUtils.writeString(GroupConstants.FAILURE_COL, groupSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX),
+ TemplatePopulateImportConstants.FAILURE_COL_REPORT_HEADER);
+ }
+
+ private Integer importGroupMeeting(CommandProcessingResult result, int rowIndex, String dateFormat) {
+ CalendarData calendarData=meetings.get(rowIndex);
+ calendarData.setTitle("group_" + result.getGroupId().toString() + "_CollectionMeeting");
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(EnumOptionData.class,new EnumOptionDataValueSerializer());
+
+ String payload = gsonBuilder.create().toJson(calendarData);
+ CommandWrapper commandWrapper=new CommandWrapper(result.getOfficeId(),result.getGroupId(),
+ result.getClientId(),result.getLoanId(),result.getSavingsId(),null,
+ null,null,null,null,payload,result.getTransactionId(),
+ result.getProductId(),null,null,null);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createCalendar(commandWrapper,TemplatePopulateImportConstants.CENTER_ENTITY_TYPE,result.getGroupId()) //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult meetingresult = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ return 2;
+ }
+
+ private CommandProcessingResult importGroup(int rowIndex, String dateFormat) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ Type clientCollectionType = new TypeToken>() {}.getType();
+ gsonBuilder.registerTypeAdapter(clientCollectionType,new ClientIdSerializer());
+ String payload= gsonBuilder.create().toJson(groups.get(rowIndex));;
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createGroup() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ return result;
+ }
+
+ private int getProgressLevel(String status) {
+ if(status==null || status.equals(TemplatePopulateImportConstants.STATUS_CREATION_FAILED))
+ return 0;
+ else if(status.equals(TemplatePopulateImportConstants.STATUS_MEETING_FAILED))
+ return 1;
+ return 0;
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/guarantor/GuarantorImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/guarantor/GuarantorImportHandler.java
new file mode 100644
index 000000000..e97443f0e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/guarantor/GuarantorImportHandler.java
@@ -0,0 +1,151 @@
+/**
+ * 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.importhandler.guarantor;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.GuarantorConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class GuarantorImportHandler implements ImportHandler {
+ private Workbook workbook;
+ private List guarantors;
+ private Long loanAccountId ;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+@Autowired
+ public GuarantorImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.guarantors=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+ Sheet addGuarantorSheet = workbook.getSheet(TemplatePopulateImportConstants.GUARANTOR_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(addGuarantorSheet, GuarantorConstants.LOAN_ACCOUNT_NO_COL);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = addGuarantorSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, GuarantorConstants.STATUS_COL))
+ guarantors.add(ReadGuarantor(row,locale,dateFormat));
+
+ }
+ }
+
+ private GuarantorData ReadGuarantor(Row row,String locale,String dateFormat) {
+ String loanaccountInfo=ImportHandlerUtils.readAsString(GuarantorConstants.LOAN_ACCOUNT_NO_COL, row);
+ if (loanaccountInfo!=null){
+ String loanAccountAr[]=loanaccountInfo.split("-");
+ loanAccountId=Long.parseLong(loanAccountAr[0]);
+ }
+ String guarantorType = ImportHandlerUtils.readAsString(GuarantorConstants.GUARANTO_TYPE_COL, row);
+
+ Integer guarantorTypeId = null;
+ if (guarantorType!=null) {
+ if (guarantorType.equalsIgnoreCase(TemplatePopulateImportConstants.GUARANTOR_INTERNAL))
+ guarantorTypeId = 1;
+ else if (guarantorType.equalsIgnoreCase(TemplatePopulateImportConstants.GUARANTOR_EXTERNAL))
+ guarantorTypeId = 3;
+ }
+ String clientName = ImportHandlerUtils.readAsString(GuarantorConstants.ENTITY_ID_COL, row);
+ Long entityId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME), clientName);
+ String clientRelationshipTypeInfo=ImportHandlerUtils.readAsString(GuarantorConstants.CLIENT_RELATIONSHIP_TYPE_COL, row);
+ Integer clientRelationshipTypeId=null;
+ if (clientRelationshipTypeInfo!=null){
+ String clientRelationshipTypeAr[]=clientRelationshipTypeInfo.split("-");
+ clientRelationshipTypeId=Integer.parseInt(clientRelationshipTypeAr[1]);
+ }
+ String firstname = ImportHandlerUtils.readAsString(GuarantorConstants.FIRST_NAME_COL, row);
+ String lastname = ImportHandlerUtils.readAsString(GuarantorConstants.LAST_NAME_COL, row);
+ String addressLine1 = ImportHandlerUtils.readAsString(GuarantorConstants.ADDRESS_LINE_1_COL, row);
+ String addressLine2 = ImportHandlerUtils.readAsString(GuarantorConstants.ADDRESS_LINE_2_COL, row);
+ String city = ImportHandlerUtils.readAsString(GuarantorConstants.CITY_COL, row);
+ LocalDate dob = ImportHandlerUtils.readAsDate(GuarantorConstants.DOB_COL, row);
+ String zip = ImportHandlerUtils.readAsString(GuarantorConstants.ZIP_COL, row);
+ Integer savingsId = ImportHandlerUtils.readAsInt(GuarantorConstants.SAVINGS_ID_COL, row);
+ BigDecimal amount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(GuarantorConstants.AMOUNT, row));
+
+ return GuarantorData.importInstance(guarantorTypeId,clientRelationshipTypeId,entityId,firstname,
+ lastname,addressLine1, addressLine2,city,dob,zip,savingsId,amount, row.getRowNum(), loanAccountId,locale,dateFormat);
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet addGuarantorSheet = workbook.getSheet(TemplatePopulateImportConstants.GUARANTOR_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ GsonBuilder gsonBuilder=new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ for (GuarantorData guarantor : guarantors) {
+ try {
+ JsonObject guarantorJsonob=gsonBuilder.create().toJsonTree(guarantor).getAsJsonObject();
+ guarantorJsonob.remove("status");
+ String payload = guarantorJsonob.toString();
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createGuarantor(guarantor.getAccountId()) //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = addGuarantorSheet.getRow(guarantor.getRowIndex()).createCell(GuarantorConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(addGuarantorSheet,guarantor.getRowIndex(),errorMessage,GuarantorConstants.STATUS_COL);
+ }
+
+ }
+ addGuarantorSheet.setColumnWidth(GuarantorConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(GuarantorConstants.STATUS_COL, addGuarantorSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX),
+ TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/ClientIdSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/ClientIdSerializer.java
new file mode 100644
index 000000000..0dbe28ca9
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/ClientIdSerializer.java
@@ -0,0 +1,38 @@
+/**
+ * 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.importhandler.helper;
+
+import com.google.gson.*;
+import org.apache.fineract.portfolio.client.data.ClientData;
+
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+public class ClientIdSerializer implements JsonSerializer> {
+
+ @Override
+ public JsonElement serialize(Collection src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonArray clientIdJsonArray=new JsonArray();
+ for (ClientData client:src) {
+ JsonElement clientIdElment=new JsonPrimitive(client.id().toString());
+ clientIdJsonArray.add(clientIdElment);
+ }
+ return clientIdJsonArray;
+ }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/CodeValueDataIdSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/CodeValueDataIdSerializer.java
new file mode 100644
index 000000000..d5f4ef0f5
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/CodeValueDataIdSerializer.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.importhandler.helper;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+
+import java.lang.reflect.Type;
+
+public class CodeValueDataIdSerializer implements JsonSerializer {
+ @Override
+ public JsonElement serialize(CodeValueData src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(src.getId());
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/CurrencyDateCodeSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/CurrencyDateCodeSerializer.java
new file mode 100644
index 000000000..c784bae95
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/CurrencyDateCodeSerializer.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.importhandler.helper;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+
+import java.lang.reflect.Type;
+
+public class CurrencyDateCodeSerializer implements JsonSerializer{
+ @Override
+ public JsonElement serialize(CurrencyData src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(src.code());
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/DateSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/DateSerializer.java
new file mode 100644
index 000000000..c7b7bc593
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/DateSerializer.java
@@ -0,0 +1,41 @@
+/**
+ * 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.importhandler.helper;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import org.joda.time.LocalDate;
+
+import java.lang.reflect.Type;
+
+public class DateSerializer implements JsonSerializer {
+
+ private final String dateFormat;
+
+ public DateSerializer(String dateFormat) {
+ this.dateFormat = dateFormat;
+ }
+
+ @Override
+ public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(src.toString(dateFormat));
+ }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/EnumOptionDataIdSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/EnumOptionDataIdSerializer.java
new file mode 100644
index 000000000..e95e2cb55
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/EnumOptionDataIdSerializer.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.importhandler.helper;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+
+import java.lang.reflect.Type;
+
+public class EnumOptionDataIdSerializer implements JsonSerializer {
+ @Override
+ public JsonElement serialize(EnumOptionData src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(src.getId());
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/EnumOptionDataValueSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/EnumOptionDataValueSerializer.java
new file mode 100644
index 000000000..41b6ce31c
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/EnumOptionDataValueSerializer.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.importhandler.helper;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+
+import java.lang.reflect.Type;
+
+public class EnumOptionDataValueSerializer implements JsonSerializer {
+ @Override
+ public JsonElement serialize(EnumOptionData src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(src.getValue());
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/GroupIdSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/GroupIdSerializer.java
new file mode 100644
index 000000000..07306a02a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/GroupIdSerializer.java
@@ -0,0 +1,37 @@
+/**
+ * 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.importhandler.helper;
+
+import com.google.gson.*;
+import org.apache.fineract.portfolio.group.data.GroupGeneralData;
+
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+public class GroupIdSerializer implements JsonSerializer> {
+ @Override
+ public JsonElement serialize(Collection src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonArray groupIdJsonArray=new JsonArray();
+ for (GroupGeneralData group:src) {
+ JsonElement groupIdElement=new JsonPrimitive(group.getId().toString());
+ groupIdJsonArray.add(groupIdElement);
+ }
+ return groupIdJsonArray;
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/SavingsAccountTransactionEnumValueSerialiser.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/SavingsAccountTransactionEnumValueSerialiser.java
new file mode 100644
index 000000000..4942d2daf
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/helper/SavingsAccountTransactionEnumValueSerialiser.java
@@ -0,0 +1,35 @@
+/**
+ * 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.importhandler.helper;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
+
+import java.lang.reflect.Type;
+
+public class SavingsAccountTransactionEnumValueSerialiser implements JsonSerializer {
+
+ @Override
+ public JsonElement serialize(SavingsAccountTransactionEnumData src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(src.getValue());
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/journalentry/JournalEntriesImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/journalentry/JournalEntriesImportHandler.java
new file mode 100644
index 000000000..ad7b8a91d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/journalentry/JournalEntriesImportHandler.java
@@ -0,0 +1,226 @@
+/**
+ * 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.importhandler.journalentry;
+
+import com.google.gson.GsonBuilder;
+import org.apache.fineract.accounting.journalentry.data.CreditDebit;
+import org.apache.fineract.accounting.journalentry.data.JournalEntryData;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.ChartOfAcountsConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.JournalEntryConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.CurrencyDateCodeSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class JournalEntriesImportHandler implements ImportHandler {
+ private Workbook workbook;
+ private List gltransaction;
+ private LocalDate transactionDate;
+
+ List credits = new ArrayList<>();
+ List debits = new ArrayList<>();
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public JournalEntriesImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ gltransaction=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+ String currentTransactionId = null;
+ String prevTransactionId = null;
+ JournalEntryData journalEntry = null;
+
+ Sheet addJournalEntriesSheet = workbook.getSheet(TemplatePopulateImportConstants.JOURNAL_ENTRY_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(addJournalEntriesSheet, 4);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = addJournalEntriesSheet.getRow(rowIndex);
+
+ currentTransactionId = ImportHandlerUtils.readAsString(JournalEntryConstants.TRANSACTION_ID_COL, row);
+
+ if (currentTransactionId.equals(prevTransactionId)) {
+ if (journalEntry != null) {
+
+ String creditGLAcct = ImportHandlerUtils.readAsString(
+ JournalEntryConstants.GL_ACCOUNT_ID_CREDIT_COL, row);
+ Long glAccountIdCredit = ImportHandlerUtils.getIdByName(
+ workbook.getSheet(TemplatePopulateImportConstants.GL_ACCOUNTS_SHEET_NAME), creditGLAcct);
+
+ String debitGLAcct = ImportHandlerUtils.readAsString(
+ JournalEntryConstants. GL_ACCOUNT_ID_DEBIT_COL, row);
+
+ Long glAccountIdDebit = ImportHandlerUtils.getIdByName(
+ workbook.getSheet(TemplatePopulateImportConstants.GL_ACCOUNTS_SHEET_NAME), debitGLAcct);
+
+ BigDecimal creditAmt=null;
+ if (ImportHandlerUtils.readAsDouble(JournalEntryConstants.AMOUNT_CREDIT_COL, row)!=null)
+ creditAmt = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(JournalEntryConstants.AMOUNT_CREDIT_COL, row));
+ BigDecimal debitAmount=null;
+ if (ImportHandlerUtils.readAsDouble(JournalEntryConstants.AMOUNT_DEBIT_COL, row)!=null)
+ debitAmount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(JournalEntryConstants.AMOUNT_DEBIT_COL, row));
+
+ if (creditGLAcct!=null) {
+
+ CreditDebit credit = new CreditDebit(
+ glAccountIdCredit, creditAmt);
+ journalEntry.addCredits(credit);
+ }
+ if (debitGLAcct!=null) {
+ CreditDebit debit = new CreditDebit(
+ glAccountIdDebit, debitAmount);
+
+ journalEntry.addDebits(debit);
+ }
+ }
+ } else {
+
+ if (journalEntry != null) {
+ gltransaction.add(journalEntry);
+ journalEntry = null;
+ }
+
+ journalEntry = readAddJournalEntries(row,locale,dateFormat);
+
+ }
+ prevTransactionId = currentTransactionId;
+ }
+ // Adding last JE
+ gltransaction.add(journalEntry);
+ }
+
+ private JournalEntryData readAddJournalEntries(Row row,String locale,String dateFormat) {
+ LocalDate transactionDateCheck = ImportHandlerUtils.readAsDate(JournalEntryConstants.TRANSACION_ON_DATE_COL, row);
+ if (transactionDateCheck!=null)
+ transactionDate = transactionDateCheck;
+
+ String officeName = ImportHandlerUtils.readAsString(JournalEntryConstants.OFFICE_NAME_COL, row);
+ Long officeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME), officeName);
+ String paymentType = ImportHandlerUtils.readAsString(JournalEntryConstants.PAYMENT_TYPE_ID_COL, row);
+ Long paymentTypeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME),
+ paymentType);
+ String currencyName = ImportHandlerUtils.readAsString(JournalEntryConstants.CURRENCY_NAME_COL, row);
+ String currencyCode = ImportHandlerUtils.getCodeByName(workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME),
+ currencyName).toString();
+ String glAccountNameCredit = ImportHandlerUtils.readAsString(JournalEntryConstants.GL_ACCOUNT_ID_CREDIT_COL, row);
+ Long glAccountIdCredit = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GL_ACCOUNTS_SHEET_NAME),
+ glAccountNameCredit);
+ String glAccountNameDebit = ImportHandlerUtils.readAsString(JournalEntryConstants.GL_ACCOUNT_ID_DEBIT_COL, row);
+ Long glAccountIdDebit = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GL_ACCOUNTS_SHEET_NAME),
+ glAccountNameDebit);
+
+ credits = new ArrayList<>();
+ debits = new ArrayList<>();
+
+ // String credit = readAsString(JournalEntryConstants.GL_ACCOUNT_ID_CREDIT_COL, row);
+ // String debit = readAsString(JournalEntryConstants.GL_ACCOUNT_ID_DEBIT_COL, row);
+
+ if (glAccountNameCredit!=null) {
+ if (ImportHandlerUtils.readAsDouble(JournalEntryConstants.AMOUNT_CREDIT_COL, row) != null){
+ credits.add(new CreditDebit(glAccountIdCredit, BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(
+ JournalEntryConstants.AMOUNT_CREDIT_COL, row))));
+ }else {
+ credits.add(new CreditDebit(glAccountIdCredit,null));
+ }
+ }
+
+ if (glAccountNameDebit!=null) {
+ if (ImportHandlerUtils.readAsDouble(JournalEntryConstants.AMOUNT_DEBIT_COL, row)!=null) {
+ debits.add(new CreditDebit(glAccountIdDebit, BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(
+ JournalEntryConstants.AMOUNT_DEBIT_COL, row))));
+ }else {
+ debits.add(new CreditDebit(glAccountIdDebit, null));
+ }
+ }
+ String accountNo=ImportHandlerUtils.readAsString(JournalEntryConstants.ACCOUNT_NO_COL,row);
+ String chequeNo=ImportHandlerUtils.readAsString(JournalEntryConstants.CHECK_NO_COL,row);
+ String routingCode=ImportHandlerUtils.readAsString(JournalEntryConstants.ROUTING_CODE_COL,row);
+ String receiptNo=ImportHandlerUtils.readAsString(JournalEntryConstants.RECEIPT_NO_COL,row);
+ String bankNo=ImportHandlerUtils.readAsString(JournalEntryConstants.BANK_NO_COL,row);
+ String comments=ImportHandlerUtils.readAsString(JournalEntryConstants.COMMENTS_COL,row);
+
+ return JournalEntryData.importInstance(officeId, transactionDate, currencyCode,
+ paymentTypeId, row.getRowNum(), credits, debits,accountNo,chequeNo,routingCode,receiptNo,bankNo,comments,locale,dateFormat);
+
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet addJournalEntriesSheet = workbook.getSheet(TemplatePopulateImportConstants.JOURNAL_ENTRY_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(CurrencyData.class,new CurrencyDateCodeSerializer());
+
+ for (JournalEntryData transaction : gltransaction) {
+ try {
+ String payload =gsonBuilder.create().toJson(transaction);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createJournalEntry() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = addJournalEntriesSheet.getRow(
+ transaction.getRowIndex()).createCell(JournalEntryConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook,
+ IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(addJournalEntriesSheet,transaction.getRowIndex(),errorMessage, JournalEntryConstants.STATUS_COL);
+ }
+
+ }
+ addJournalEntriesSheet.setColumnWidth(JournalEntryConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(JournalEntryConstants.STATUS_COL, addJournalEntriesSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX), TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
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
new file mode 100644
index 000000000..2199fa783
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java
@@ -0,0 +1,463 @@
+/**
+ * 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.importhandler.loan;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.LoanConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOptionDataValueSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.portfolio.loanaccount.data.*;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+@Service
+public class LoanImportHandler implements ImportHandler {
+ private Workbook workbook;
+ private List loans;
+ private List approvalDates;
+ private List loanRepayments;
+ private List disbursalDates;
+ private List statuses;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public LoanImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.loans = new ArrayList<>();
+ this.approvalDates = new ArrayList<>();
+ this.loanRepayments = new ArrayList<>();
+ this.disbursalDates = new ArrayList<>();
+ this.statuses=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+ Sheet loanSheet = workbook.getSheet(TemplatePopulateImportConstants.LOANS_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(loanSheet, TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = loanSheet.getRow(rowIndex);
+ if ( ImportHandlerUtils.isNotImported(row, LoanConstants.STATUS_COL)) {
+ loans.add(readLoan(row,locale,dateFormat));
+ approvalDates.add(readLoanApproval(row,locale,dateFormat));
+ disbursalDates.add(readDisbursalData(row,locale,dateFormat));
+ loanRepayments.add(readLoanRepayment(row,locale,dateFormat));
+ }
+ }
+
+ }
+
+ private LoanTransactionData readLoanRepayment(Row row,String locale,String dateFormat) {
+ BigDecimal repaymentAmount=null;
+ if (ImportHandlerUtils.readAsDouble(LoanConstants.TOTAL_AMOUNT_REPAID_COL, row)!=null)
+ repaymentAmount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanConstants.TOTAL_AMOUNT_REPAID_COL, row));
+ LocalDate lastRepaymentDate = ImportHandlerUtils.readAsDate(LoanConstants.LAST_REPAYMENT_DATE_COL, row);
+ String repaymentType = ImportHandlerUtils.readAsString(LoanConstants.REPAYMENT_TYPE_COL, row);
+ Long repaymentTypeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME), repaymentType);
+ if (repaymentAmount!=null&&lastRepaymentDate!=null&&repaymentType!=null&&repaymentTypeId!=null)
+ return LoanTransactionData.importInstance(repaymentAmount, lastRepaymentDate, repaymentTypeId, row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private DisbursementData readDisbursalData(Row row,String locale,String dateFormat) {
+ LocalDate disbursedDate = ImportHandlerUtils.readAsDate(LoanConstants.DISBURSED_DATE_COL, row);
+ String linkAccountId=null;
+ if ( ImportHandlerUtils.readAsLong(LoanConstants.LINK_ACCOUNT_ID, row)!=null)
+ linkAccountId = ImportHandlerUtils.readAsLong(LoanConstants.LINK_ACCOUNT_ID, row).toString();
+
+ if (disbursedDate!=null) {
+ return DisbursementData.importInstance(disbursedDate,linkAccountId,row.getRowNum(),locale,dateFormat);
+ }
+ return null;
+ }
+
+ private LoanApprovalData readLoanApproval(Row row,String locale,String dateFormat) {
+ LocalDate approvedDate = ImportHandlerUtils.readAsDate(LoanConstants.APPROVED_DATE_COL, row);
+ if (approvedDate!=null)
+ return LoanApprovalData.importInstance(approvedDate, row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private LoanAccountData readLoan(Row row,String locale,String dateFormat) {
+ String externalId = ImportHandlerUtils.readAsString(LoanConstants.EXTERNAL_ID_COL, row);
+ String status = ImportHandlerUtils.readAsString(LoanConstants.STATUS_COL, row);
+ String productName = ImportHandlerUtils.readAsString(LoanConstants.PRODUCT_COL, row);
+ Long productId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME), productName);
+ String loanOfficerName = ImportHandlerUtils.readAsString(LoanConstants.LOAN_OFFICER_NAME_COL, row);
+ Long loanOfficerId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), loanOfficerName);
+ LocalDate submittedOnDate = ImportHandlerUtils.readAsDate(LoanConstants.SUBMITTED_ON_DATE_COL, row);
+ String fundName = ImportHandlerUtils.readAsString(LoanConstants.FUND_NAME_COL, row);
+ Long fundId;
+ if (fundName == null)
+ fundId = null;
+ else
+ fundId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME), fundName);
+
+ BigDecimal principal = null;
+ if ( ImportHandlerUtils.readAsDouble(LoanConstants.PRINCIPAL_COL, row) != null)
+ principal = BigDecimal.valueOf( ImportHandlerUtils.readAsDouble(LoanConstants.PRINCIPAL_COL, row));
+ Integer numberOfRepayments = ImportHandlerUtils.readAsInt(LoanConstants.NO_OF_REPAYMENTS_COL, row);
+ Integer repaidEvery = ImportHandlerUtils.readAsInt(LoanConstants.REPAID_EVERY_COL, row);
+ String repaidEveryFrequency = ImportHandlerUtils.readAsString(LoanConstants.REPAID_EVERY_FREQUENCY_COL, row);
+ String repaidEveryFrequencyId = "";
+ EnumOptionData repaidEveryFrequencyEnums = null;
+ if (repaidEveryFrequency != null) {
+ if (repaidEveryFrequency.equalsIgnoreCase("Days"))
+ repaidEveryFrequencyId = "0";
+ else if (repaidEveryFrequency.equalsIgnoreCase("Weeks"))
+ repaidEveryFrequencyId = "1";
+ else if (repaidEveryFrequency.equalsIgnoreCase("Months")) repaidEveryFrequencyId = "2";
+ 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);
+ EnumOptionData loanTermFrequencyEnum = null;
+ if (loanTermFrequency != null) {
+ String loanTermFrequencyId = "";
+ if (loanTermFrequency.equalsIgnoreCase("Days"))
+ loanTermFrequencyId = "0";
+ else if (loanTermFrequency.equalsIgnoreCase("Weeks"))
+ loanTermFrequencyId = "1";
+ else if (loanTermFrequency.equalsIgnoreCase("Months"))
+ loanTermFrequencyId = "2";
+ loanTermFrequencyEnum = new EnumOptionData(null, null, loanTermFrequencyId);
+ }
+ BigDecimal nominalInterestRate = null;
+ if ( ImportHandlerUtils.readAsDouble(LoanConstants.NOMINAL_INTEREST_RATE_COL, row) != null)
+ nominalInterestRate = BigDecimal.valueOf( ImportHandlerUtils.readAsDouble(LoanConstants.NOMINAL_INTEREST_RATE_COL, row));
+ String amortization = ImportHandlerUtils.readAsString(LoanConstants.AMORTIZATION_COL, row);
+ String amortizationId = "";
+ EnumOptionData amortizationEnumOption = null;
+ if (amortization != null) {
+ if (amortization.equalsIgnoreCase("Equal principal payments"))
+ amortizationId = "0";
+ else if (amortization.equalsIgnoreCase("Equal installments")) amortizationId = "1";
+ amortizationEnumOption = new EnumOptionData(null, null, amortizationId);
+ }
+ String interestMethod = ImportHandlerUtils.readAsString(LoanConstants.INTEREST_METHOD_COL, row);
+ String interestMethodId = "";
+ EnumOptionData interestMethodEnum = null;
+ if (interestMethod != null) {
+ if (interestMethod.equalsIgnoreCase("Flat"))
+ interestMethodId = "1";
+ else if (interestMethod.equalsIgnoreCase("Declining Balance")) interestMethodId = "0";
+ interestMethodEnum = new EnumOptionData(null, null, interestMethodId);
+ }
+ String interestCalculationPeriod = ImportHandlerUtils.readAsString(LoanConstants.INTEREST_CALCULATION_PERIOD_COL, row);
+ String interestCalculationPeriodId = "";
+ EnumOptionData interestCalculationPeriodEnum = null;
+ if (interestCalculationPeriod != null) {
+ if (interestCalculationPeriod.equalsIgnoreCase("Daily"))
+ interestCalculationPeriodId = "0";
+ else if (interestCalculationPeriod.equalsIgnoreCase("Same as repayment period"))
+ interestCalculationPeriodId = "1";
+ interestCalculationPeriodEnum = new EnumOptionData(null, null, interestCalculationPeriodId);
+
+ }
+ BigDecimal arrearsTolerance = null;
+ if ( ImportHandlerUtils.readAsDouble(LoanConstants.ARREARS_TOLERANCE_COL, row) != null)
+ arrearsTolerance = BigDecimal.valueOf( ImportHandlerUtils.readAsDouble(LoanConstants.ARREARS_TOLERANCE_COL, row));
+ String repaymentStrategy = ImportHandlerUtils.readAsString(LoanConstants.REPAYMENT_STRATEGY_COL, row);
+ Long repaymentStrategyId = null;
+ if (repaymentStrategy!=null) {
+ if (repaymentStrategy.equalsIgnoreCase("Penalties, Fees, Interest, Principal order"))
+ repaymentStrategyId = 1L;
+ else if (repaymentStrategy.equalsIgnoreCase("HeavensFamily Unique"))
+ repaymentStrategyId = 2L;
+ else if (repaymentStrategy.equalsIgnoreCase("Creocore Unique"))
+ repaymentStrategyId = 3L;
+ else if (repaymentStrategy.equalsIgnoreCase("Overdue/Due Fee/Int,Principal"))
+ repaymentStrategyId = 4L;
+ else if (repaymentStrategy.equalsIgnoreCase("Principal, Interest, Penalties, Fees Order"))
+ repaymentStrategyId = 5L;
+ else if (repaymentStrategy.equalsIgnoreCase("Interest, Principal, Penalties, Fees Order"))
+ repaymentStrategyId = 6L;
+ else if (repaymentStrategy.equalsIgnoreCase("Early Repayment Strategy"))
+ repaymentStrategyId = 7L;
+ }
+ Integer graceOnPrincipalPayment = ImportHandlerUtils.readAsInt(LoanConstants.GRACE_ON_PRINCIPAL_PAYMENT_COL, row);
+ Integer graceOnInterestPayment = ImportHandlerUtils.readAsInt(LoanConstants.GRACE_ON_INTEREST_PAYMENT_COL, row);
+ Integer graceOnInterestCharged = ImportHandlerUtils.readAsInt(LoanConstants.GRACE_ON_INTEREST_CHARGED_COL, row);
+ LocalDate interestChargedFromDate = ImportHandlerUtils.readAsDate(LoanConstants.INTEREST_CHARGED_FROM_COL, row);
+ LocalDate firstRepaymentOnDate = ImportHandlerUtils.readAsDate(LoanConstants.FIRST_REPAYMENT_COL, row);
+ String loanType=null;
+ EnumOptionData loanTypeEnumOption=null;
+ if ( ImportHandlerUtils.readAsString(LoanConstants.LOAN_TYPE_COL, row)!=null) {
+ loanType = ImportHandlerUtils.readAsString(LoanConstants.LOAN_TYPE_COL, row).toLowerCase(Locale.ENGLISH);
+
+ loanTypeEnumOption = new EnumOptionData(null, null, loanType);
+ }
+
+ String clientOrGroupName = ImportHandlerUtils.readAsString(LoanConstants.CLIENT_NAME_COL, row);
+
+ List charges = new ArrayList<>();
+
+ Long charge1 = ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_1, row);
+ Long charge2 = ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_2, row);
+
+ Long groupId = ImportHandlerUtils.readAsLong(LoanConstants.GROUP_ID, row);
+
+ String linkAccountId = ImportHandlerUtils.readAsString(LoanConstants.LINK_ACCOUNT_ID, row);
+
+ if (charge1!=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))));
+ }else {
+ charges.add(new LoanChargeData( ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_1, row),
+ ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_1, row),null));
+ }
+ }
+
+ if (charge2!=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))));
+ }else {
+ charges.add(new LoanChargeData( ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_2, row),
+ ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_2, row),
+ null));
+ }
+ }
+ statuses.add(status);
+ if (loanType!=null) {
+ if (loanType.equals("individual")) {
+ Long clientId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME), clientOrGroupName);
+ return LoanAccountData.importInstanceIndividual(loanTypeEnumOption, clientId, productId, loanOfficerId, submittedOnDate, fundId,
+ principal, numberOfRepayments,
+ repaidEvery, repaidEveryFrequencyEnums, loanTerm, loanTermFrequencyEnum, nominalInterestRate, submittedOnDate,
+ amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum, arrearsTolerance, repaymentStrategyId,
+ graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, firstRepaymentOnDate,
+ row.getRowNum(), externalId, null, charges, linkAccountId,locale,dateFormat);
+ } else if (loanType.equals("jlg")) {
+ Long clientId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME), clientOrGroupName);
+ return LoanAccountData.importInstanceIndividual(loanTypeEnumOption, clientId, productId, loanOfficerId, submittedOnDate, fundId,
+ principal, numberOfRepayments,
+ repaidEvery, repaidEveryFrequencyEnums, loanTerm, loanTermFrequencyEnum, nominalInterestRate, submittedOnDate,
+ amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum, arrearsTolerance, repaymentStrategyId,
+ graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, firstRepaymentOnDate,
+ row.getRowNum(), externalId, groupId, charges, linkAccountId,locale,dateFormat);
+ } else {
+ Long groupIdforGroupLoan = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME), clientOrGroupName);
+ return LoanAccountData.importInstanceGroup(loanTypeEnumOption, groupIdforGroupLoan, productId, loanOfficerId, submittedOnDate, fundId,
+ principal, numberOfRepayments,
+ repaidEvery, repaidEveryFrequencyEnums, loanTerm, loanTermFrequencyEnum, nominalInterestRate,
+ amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum, arrearsTolerance,
+ repaymentStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
+ interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(), externalId, linkAccountId,locale,dateFormat);
+ }
+ }else {
+ return null;
+ }
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet loanSheet = workbook.getSheet(TemplatePopulateImportConstants.LOANS_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ int progressLevel = 0;
+ String loanId;
+ String errorMessage="";
+ for (int i = 0; i < loans.size(); i++) {
+ Row row = loanSheet.getRow(loans.get(i).getRowIndex());
+ Cell errorReportCell = row.createCell(LoanConstants.FAILURE_REPORT_COL);
+ Cell statusCell = row.createCell(LoanConstants.STATUS_COL);
+ CommandProcessingResult result=null;
+ loanId="";
+ try {
+ String status = statuses.get(i);;
+ progressLevel = getProgressLevel(status);
+
+ if (progressLevel == 0&& loans.get(i)!=null) {
+ result = importLoan(i,dateFormat);
+ loanId = result.getLoanId().toString();
+ progressLevel = 1;
+ } else
+ loanId = ImportHandlerUtils.readAsString(LoanConstants.LOAN_ID_COL, loanSheet.getRow(loans.get(i).getRowIndex()));
+
+ if (progressLevel <= 1 && approvalDates.get(i)!=null) progressLevel = importLoanApproval(result, i,dateFormat);
+
+ if (progressLevel <= 2 && disbursalDates.get(i)!=null) progressLevel = importDisbursalData(result, i,dateFormat);
+
+ if (loanRepayments.get(i) != null) progressLevel = importLoanRepayment(result, i,dateFormat);
+
+ successCount++;
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ writeLoanErrorMessage(loanId,errorMessage,progressLevel,statusCell,errorReportCell,row);
+ }
+
+ }
+ setReportHeaders(loanSheet);
+ return Count.instance(successCount,errorCount);
+ }
+
+ private void writeLoanErrorMessage(String loanId,String errorMessage,int progressLevel,Cell statusCell,Cell errorReportCell,Row row){
+ String status = "";
+ if (progressLevel == 0)
+ status = TemplatePopulateImportConstants.STATUS_CREATION_FAILED;
+ else if (progressLevel == 1)
+ status = TemplatePopulateImportConstants.STATUS_APPROVAL_FAILED;
+ else if (progressLevel == 2)
+ status = TemplatePopulateImportConstants.STATUS_DISBURSAL_FAILED;
+ else if (progressLevel == 3) status = TemplatePopulateImportConstants.STATUS_DISBURSAL_REPAYMENT_FAILED;
+ statusCell.setCellValue(status);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.RED));
+
+ if (progressLevel > 0) row.createCell(LoanConstants.LOAN_ID_COL).setCellValue(Integer.parseInt(loanId));
+ errorReportCell.setCellValue(errorMessage);
+ }
+ private void setReportHeaders(Sheet sheet) {
+ sheet.setColumnWidth(LoanConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ Row rowHeader = sheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ ImportHandlerUtils.writeString(LoanConstants.STATUS_COL, rowHeader, "Status");
+ ImportHandlerUtils.writeString(LoanConstants.LOAN_ID_COL, rowHeader, "Loan ID");
+ ImportHandlerUtils.writeString(LoanConstants.FAILURE_REPORT_COL, rowHeader, "Report");
+ }
+
+ private Integer importLoanRepayment(CommandProcessingResult result, int rowIndex,String dateFormat) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ JsonObject loanRepaymentJsonob=gsonBuilder.create().toJsonTree(loanRepayments.get(rowIndex)).getAsJsonObject();
+ loanRepaymentJsonob.remove("manuallyReversed");
+ String payload=loanRepaymentJsonob.toString();
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .loanRepaymentTransaction(result.getLoanId()) //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult loanRepaymentResult = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ return 4;
+ }
+
+ private Integer importDisbursalData(CommandProcessingResult result, int rowIndex, String dateFormat) {
+ if (approvalDates.get(rowIndex) != null && disbursalDates.get(rowIndex) != null) {
+
+ DisbursementData disbusalData = disbursalDates.get(rowIndex);
+ String linkAccountId = disbusalData.getLinkAccountId();
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ if (linkAccountId != null && linkAccountId != "") {
+ String payload =gsonBuilder.create().toJson(disbusalData);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .disburseLoanToSavingsApplication(result.getLoanId()) //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult loanDisburseToSavingsResult = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ } else {
+ String payload = gsonBuilder.create().toJson(disbusalData);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .disburseLoanApplication(result.getLoanId()) //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult loanDisburseResult = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ }
+ }
+ return 3;
+ }
+
+ private Integer importLoanApproval(CommandProcessingResult result, int rowIndex,String dateFormat) {
+ if (approvalDates.get(rowIndex) != null) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ String payload = gsonBuilder.create().toJson(approvalDates.get(rowIndex));
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .approveLoanApplication(result.getLoanId()) //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult loanapprovalresult = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ }
+ return 2;
+ }
+
+ private CommandProcessingResult importLoan(int rowIndex,String dateFormat) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(EnumOptionData.class,new EnumOptionDataValueSerializer());
+ JsonObject loanJsonOb = gsonBuilder.create().toJsonTree(loans.get(rowIndex)).getAsJsonObject();
+ loanJsonOb.remove("isLoanProductLinkedToFloatingRate");
+ loanJsonOb.remove("isInterestRecalculationEnabled");
+ loanJsonOb.remove("isFloatingInterestRate");
+ JsonArray chargesJsonAr=loanJsonOb.getAsJsonArray("charges");
+ if (chargesJsonAr!=null) {
+ for (int i = 0; i < chargesJsonAr.size(); i++) {
+ JsonElement chargesJsonElement = chargesJsonAr.get(i);
+ JsonObject chargeJsonOb = chargesJsonElement.getAsJsonObject();
+ chargeJsonOb.remove("penalty");
+ chargeJsonOb.remove("paid");
+ chargeJsonOb.remove("waived");
+ chargeJsonOb.remove("chargePayable");
+ }
+ }
+ loanJsonOb.remove("isTopup");
+ String payload=loanJsonOb.toString();
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createLoanApplication() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ return result;
+ }
+
+ private int getProgressLevel(String status) {
+ if (status==null || status.equals(TemplatePopulateImportConstants.STATUS_CREATION_FAILED))
+ return 0;
+ else if (status.equals(TemplatePopulateImportConstants.STATUS_APPROVAL_FAILED))
+ return 1;
+ else if (status.equals(TemplatePopulateImportConstants.STATUS_DISBURSAL_FAILED))
+ return 2;
+ else if (status.equals(TemplatePopulateImportConstants.STATUS_DISBURSAL_REPAYMENT_FAILED)) return 3;
+ return 0;
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loanrepayment/LoanRepaymentImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loanrepayment/LoanRepaymentImportHandler.java
new file mode 100644
index 000000000..8134bc666
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loanrepayment/LoanRepaymentImportHandler.java
@@ -0,0 +1,134 @@
+/**
+ * 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.importhandler.loanrepayment;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.LoanRepaymentConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class LoanRepaymentImportHandler implements ImportHandler {
+ private Workbook workbook;
+ private List loanRepayments;
+ private Integer loanAccountId;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+ @Autowired
+ public LoanRepaymentImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.loanRepayments=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+ public void readExcelFile(String locale, String dateFormat) {
+ Sheet loanRepaymentSheet = workbook.getSheet(TemplatePopulateImportConstants.LOAN_REPAYMENT_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(loanRepaymentSheet, LoanRepaymentConstants.AMOUNT_COL);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = loanRepaymentSheet.getRow(rowIndex);
+ if(ImportHandlerUtils.isNotImported(row, LoanRepaymentConstants.STATUS_COL))
+ loanRepayments.add(readLoanRepayment(row,locale,dateFormat));
+ }
+ }
+
+ private LoanTransactionData readLoanRepayment(Row row,String locale, String dateFormat) {
+ String loanaccountInfo=ImportHandlerUtils.readAsString(LoanRepaymentConstants.LOAN_ACCOUNT_NO_COL, row);
+ if (loanaccountInfo!=null){
+ String loanAccountAr[]=loanaccountInfo.split("-");
+ loanAccountId=Integer.parseInt(loanAccountAr[0]);
+ }
+ BigDecimal repaymentAmount=null;
+ if (ImportHandlerUtils.readAsDouble(LoanRepaymentConstants.AMOUNT_COL, row)!=null)
+ repaymentAmount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanRepaymentConstants.AMOUNT_COL, row));
+ LocalDate repaymentDate = ImportHandlerUtils.readAsDate(LoanRepaymentConstants.REPAID_ON_DATE_COL, row);
+ String repaymentType = ImportHandlerUtils.readAsString(LoanRepaymentConstants.REPAYMENT_TYPE_COL, row);
+ Long repaymentTypeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME), repaymentType);
+ String accountNumber = ImportHandlerUtils.readAsString(LoanRepaymentConstants.ACCOUNT_NO_COL, row);
+ Integer checkNumber = ImportHandlerUtils.readAsInt(LoanRepaymentConstants.CHECK_NO_COL, row);
+ Integer routingCode = ImportHandlerUtils.readAsInt(LoanRepaymentConstants.ROUTING_CODE_COL, row);
+ Integer receiptNumber = ImportHandlerUtils.readAsInt(LoanRepaymentConstants.RECEIPT_NO_COL, row);
+ Integer bankNumber = ImportHandlerUtils.readAsInt(LoanRepaymentConstants.BANK_NO_COL, row);
+ return LoanTransactionData.importInstance(repaymentAmount, repaymentDate, repaymentTypeId, accountNumber,
+ checkNumber, routingCode, receiptNumber, bankNumber, loanAccountId, "", row.getRowNum(),locale,dateFormat);
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet loanRepaymentSheet = workbook.getSheet(TemplatePopulateImportConstants.LOAN_REPAYMENT_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+
+ for (LoanTransactionData loanRepayment : loanRepayments) {
+ try {
+
+ JsonObject loanRepaymentJsonob=gsonBuilder.create().toJsonTree(loanRepayment).getAsJsonObject();
+ loanRepaymentJsonob.remove("manuallyReversed");
+ String payload=loanRepaymentJsonob.toString();
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .loanRepaymentTransaction(loanRepayment.getAccountId().longValue()) //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = loanRepaymentSheet.getRow(loanRepayment.getRowIndex()).createCell(LoanRepaymentConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(loanRepaymentSheet,loanRepayment.getRowIndex(),errorMessage,LoanRepaymentConstants.STATUS_COL);
+ }
+
+ }
+ loanRepaymentSheet.setColumnWidth(LoanRepaymentConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(LoanRepaymentConstants.STATUS_COL,
+ loanRepaymentSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX),
+ TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/office/OfficeImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/office/OfficeImportHandler.java
new file mode 100644
index 000000000..7a3aa009e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/office/OfficeImportHandler.java
@@ -0,0 +1,123 @@
+/**
+ * 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.importhandler.office;
+
+import com.google.gson.GsonBuilder;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.OfficeConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class OfficeImportHandler implements ImportHandler {
+ private List offices;
+ private Workbook workbook;
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public OfficeImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(final Workbook workbook, final String locale, final String dateFormat) {
+ this.offices=new ArrayList<>();
+ this.workbook=workbook;
+ readExcelFile(locale, dateFormat);
+ return importEntity (dateFormat);
+ }
+
+
+
+ public void readExcelFile(final String locale, final String dateFormat) {
+ Sheet officeSheet=workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(officeSheet,0);
+ for (int rowIndex=1;rowIndex<=noOfEntries;rowIndex++) {
+ Row row;
+ row=officeSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, OfficeConstants.STATUS_COL)){
+ offices.add(readOffice(row, locale, dateFormat));
+ }
+ }
+ }
+
+ private OfficeData readOffice(Row row, final String locale, final String dateFormat) {
+ String officeName = ImportHandlerUtils.readAsString(OfficeConstants.OFFICE_NAME_COL,row);
+ Long parentId= ImportHandlerUtils.readAsLong(OfficeConstants.PARENT_OFFICE_ID_COL,row);
+ LocalDate openedDate= ImportHandlerUtils.readAsDate(OfficeConstants.OPENED_ON_COL,row);
+ String externalId= ImportHandlerUtils.readAsString(OfficeConstants.EXTERNAL_ID_COL,row);
+ OfficeData office = OfficeData.importInstance(officeName,parentId,openedDate,externalId);
+ office.setImportFields(row.getRowNum(), locale, dateFormat);
+ return office;
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet officeSheet = workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+
+ int successCount = 0;
+ int errorCount = 0;
+ String errorMessage="";
+ for (OfficeData office: offices) {
+ try {
+ String payload = gsonBuilder.create().toJson(office);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createOffice() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount ++;
+ Cell statusCell = officeSheet.getRow(office.getRowIndex()).createCell(OfficeConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(officeSheet,office.getRowIndex(),errorMessage,OfficeConstants.STATUS_COL);
+ }
+ }
+ officeSheet.setColumnWidth(OfficeConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(OfficeConstants.STATUS_COL, officeSheet.getRow(0), TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ return Count.instance(successCount, errorCount);
+ }
+
+ public List getOffices() {
+ return offices;
+ }
+}
+
+
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/recurringdeposit/RecurringDepositImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/recurringdeposit/RecurringDepositImportHandler.java
new file mode 100644
index 000000000..0c2cb827b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/recurringdeposit/RecurringDepositImportHandler.java
@@ -0,0 +1,372 @@
+/**
+ * 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.importhandler.recurringdeposit;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.RecurringDepositConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOptionDataIdSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.savings.data.RecurringDepositAccountData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
+import org.apache.fineract.portfolio.savings.data.SavingsActivation;
+import org.apache.fineract.portfolio.savings.data.SavingsApproval;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class RecurringDepositImportHandler implements ImportHandler {
+
+ private Workbook workbook;
+ private List savings;
+ private List approvalDates;
+ private List activationDates;
+ private List statuses;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public RecurringDepositImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+
+ }
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ savings=new ArrayList<>();
+ approvalDates=new ArrayList<>();
+ activationDates=new ArrayList<>();
+ statuses=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(String locale, String dateFormat) {
+ Sheet savingsSheet = workbook.getSheet(TemplatePopulateImportConstants.RECURRING_DEPOSIT_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(savingsSheet, TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = savingsSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, RecurringDepositConstants.STATUS_COL)) {
+ savings.add(readSavings(row,locale,dateFormat));
+ approvalDates.add(readSavingsApproval(row,locale,dateFormat));
+ activationDates.add(readSavingsActivation(row,locale,dateFormat));
+ }
+ }
+
+ }
+
+ private SavingsActivation readSavingsActivation(Row row,String locale, String dateFormat) {
+ LocalDate activationDate = ImportHandlerUtils.readAsDate(RecurringDepositConstants.ACTIVATION_DATE_COL, row);
+ if (activationDate!=null)
+ return SavingsActivation.importInstance(activationDate, row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private SavingsApproval readSavingsApproval(Row row,String locale, String dateFormat) {
+ LocalDate approvalDate = ImportHandlerUtils.readAsDate(RecurringDepositConstants.APPROVED_DATE_COL, row);
+ if (approvalDate!=null)
+ return SavingsApproval.importInstance(approvalDate, row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private RecurringDepositAccountData readSavings(Row row,String locale, String dateFormat) {
+
+ String productName = ImportHandlerUtils.readAsString(RecurringDepositConstants.PRODUCT_COL, row);
+ Long productId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME), productName);
+ String fieldOfficerName = ImportHandlerUtils.readAsString(RecurringDepositConstants.FIELD_OFFICER_NAME_COL, row);
+ Long fieldOfficerId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), fieldOfficerName);
+ LocalDate submittedOnDate = ImportHandlerUtils.readAsDate(RecurringDepositConstants.SUBMITTED_ON_DATE_COL, row);
+ String interestCompoundingPeriodType = ImportHandlerUtils.readAsString(RecurringDepositConstants.INTEREST_COMPOUNDING_PERIOD_COL, row);
+ Long interestCompoundingPeriodTypeId = null;
+ EnumOptionData interestCompoundingPeriodTypeEnum=null;
+ if (interestCompoundingPeriodType!=null) {
+ if (interestCompoundingPeriodType.equalsIgnoreCase("Daily"))
+ interestCompoundingPeriodTypeId = 1L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase("Monthly"))
+ interestCompoundingPeriodTypeId = 4L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase("Quarterly"))
+ interestCompoundingPeriodTypeId = 5L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase("Semi-Annual"))
+ interestCompoundingPeriodTypeId = 6L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase("Annually"))
+ interestCompoundingPeriodTypeId = 7L;
+ interestCompoundingPeriodTypeEnum = new EnumOptionData(interestCompoundingPeriodTypeId, null, null);
+ }
+ String interestPostingPeriodType = ImportHandlerUtils.readAsString(RecurringDepositConstants.INTEREST_POSTING_PERIOD_COL, row);
+ Long interestPostingPeriodTypeId = null;
+ EnumOptionData interestPostingPeriodTypeEnum=null;
+ if (interestPostingPeriodType!=null) {
+ if (interestPostingPeriodType.equalsIgnoreCase("Monthly"))
+ interestPostingPeriodTypeId = 4L;
+ else if (interestPostingPeriodType.equalsIgnoreCase("Quarterly"))
+ interestPostingPeriodTypeId = 5L;
+ else if (interestPostingPeriodType.equalsIgnoreCase("Annually"))
+ interestPostingPeriodTypeId = 7L;
+ else if (interestPostingPeriodType.equalsIgnoreCase("BiAnnual"))
+ interestPostingPeriodTypeId = 6L;
+ interestPostingPeriodTypeEnum = new EnumOptionData(interestPostingPeriodTypeId, null, null);
+ }
+
+ String interestCalculationType = ImportHandlerUtils.readAsString(RecurringDepositConstants.INTEREST_CALCULATION_COL, row);
+ Long interestCalculationTypeId = null;
+ EnumOptionData interestCalculationTypeEnum=null;
+ if (interestCalculationType!=null) {
+ if (interestCalculationType.equalsIgnoreCase("Daily Balance"))
+ interestCalculationTypeId = 1L;
+ else if (interestCalculationType.equalsIgnoreCase("Average Daily Balance"))
+ interestCalculationTypeId = 2L;
+ interestCalculationTypeEnum = new EnumOptionData(interestCalculationTypeId, null, null);
+ }
+ String interestCalculationDaysInYearType = ImportHandlerUtils.readAsString(RecurringDepositConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL, row);
+ EnumOptionData interestCalculationDaysInYearTypeEnum=null;
+ Long interestCalculationDaysInYearTypeId = null;
+ if (interestCalculationDaysInYearType!=null) {
+ if (interestCalculationDaysInYearType.equalsIgnoreCase("360 Days"))
+ interestCalculationDaysInYearTypeId = 360L;
+ else if (interestCalculationDaysInYearType.equalsIgnoreCase("365 Days"))
+ interestCalculationDaysInYearTypeId = 365L;
+ interestCalculationDaysInYearTypeEnum = new EnumOptionData(interestCalculationDaysInYearTypeId, null, null);
+ }
+ Integer lockinPeriodFrequency = ImportHandlerUtils.readAsInt(RecurringDepositConstants.LOCKIN_PERIOD_COL, row);
+ String lockinPeriodFrequencyType = ImportHandlerUtils.readAsString(RecurringDepositConstants.LOCKIN_PERIOD_FREQUENCY_COL, row);
+ Long lockinPeriodFrequencyTypeId = null;
+ EnumOptionData lockinPeriodFrequencyTypeEnum=null;
+ if (lockinPeriodFrequencyType!=null) {
+ if (lockinPeriodFrequencyType.equalsIgnoreCase("Days"))
+ lockinPeriodFrequencyTypeId = 0L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase("Weeks"))
+ lockinPeriodFrequencyTypeId = 1L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase("Months"))
+ lockinPeriodFrequencyTypeId = 2L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase("Years"))
+ lockinPeriodFrequencyTypeId = 3L;
+ lockinPeriodFrequencyTypeEnum = new EnumOptionData(lockinPeriodFrequencyTypeId, null, null);
+ }
+ BigDecimal depositAmount=null;
+ if (ImportHandlerUtils.readAsDouble(RecurringDepositConstants.RECURRING_DEPOSIT_AMOUNT_COL, row)!=null)
+ depositAmount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(RecurringDepositConstants.RECURRING_DEPOSIT_AMOUNT_COL, row));
+ Integer depositPeriod = ImportHandlerUtils.readAsInt(RecurringDepositConstants.DEPOSIT_PERIOD_COL, row);
+ String depositPeriodFrequency = ImportHandlerUtils.readAsString(RecurringDepositConstants.DEPOSIT_PERIOD_FREQUENCY_COL, row);
+ Long depositPeriodFrequencyId = null;
+ if (depositPeriodFrequency!=null) {
+ if (depositPeriodFrequency.equalsIgnoreCase("Days"))
+ depositPeriodFrequencyId = 0L;
+ else if (depositPeriodFrequency.equalsIgnoreCase("Weeks"))
+ depositPeriodFrequencyId = 1L;
+ else if (depositPeriodFrequency.equalsIgnoreCase("Months"))
+ depositPeriodFrequencyId = 2L;
+ else if (depositPeriodFrequency.equalsIgnoreCase("Years"))
+ depositPeriodFrequencyId = 3L;
+ }
+ Integer recurringFrequency = ImportHandlerUtils.readAsInt(RecurringDepositConstants.DEPOSIT_FREQUENCY_COL, row);
+ String recurringFrequencyType = ImportHandlerUtils.readAsString(RecurringDepositConstants.DEPOSIT_FREQUENCY_TYPE_COL, row);
+ Long recurringFrequencyTypeId = null;
+ EnumOptionData recurringFrequencyTypeEnum=null;
+ if (recurringFrequencyType!=null) {
+ if (recurringFrequencyType.equalsIgnoreCase("Days"))
+ recurringFrequencyTypeId = 0L;
+ else if (recurringFrequencyType.equalsIgnoreCase("Weeks"))
+ recurringFrequencyTypeId = 1L;
+ else if (recurringFrequencyType.equalsIgnoreCase("Months"))
+ recurringFrequencyTypeId = 2L;
+ else if (recurringFrequencyType.equalsIgnoreCase("Years"))
+ recurringFrequencyTypeId = 3L;
+ recurringFrequencyTypeEnum = new EnumOptionData(recurringFrequencyTypeId, null, null);
+ }
+ LocalDate depositStartDate = ImportHandlerUtils.readAsDate(RecurringDepositConstants.DEPOSIT_START_DATE_COL, row);
+ Boolean allowWithdrawal = ImportHandlerUtils.readAsBoolean(RecurringDepositConstants.ALLOW_WITHDRAWAL_COL, row);
+ Boolean isMandatoryDeposit = ImportHandlerUtils.readAsBoolean(RecurringDepositConstants.IS_MANDATORY_DEPOSIT_COL, row);
+ Boolean inheritCalendar = ImportHandlerUtils.readAsBoolean(RecurringDepositConstants.FREQ_SAME_AS_GROUP_CENTER_COL, row);
+ Boolean adjustAdvancePayments = ImportHandlerUtils.readAsBoolean(RecurringDepositConstants.ADJUST_ADVANCE_PAYMENTS_COL, row);
+ String clientName = ImportHandlerUtils.readAsString(RecurringDepositConstants.CLIENT_NAME_COL, row);
+ String externalId = ImportHandlerUtils.readAsString(RecurringDepositConstants.EXTERNAL_ID_COL, row);
+ List charges = new ArrayList<>();
+
+ String charge1 = ImportHandlerUtils.readAsString(RecurringDepositConstants.CHARGE_ID_1, row);
+ String charge2 = ImportHandlerUtils.readAsString(RecurringDepositConstants.CHARGE_ID_2, row);
+
+ if (charge1!=null) {
+ if (ImportHandlerUtils.readAsDouble(RecurringDepositConstants.CHARGE_AMOUNT_1, row)!=null) {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(RecurringDepositConstants.CHARGE_ID_1, row),
+ BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(RecurringDepositConstants.CHARGE_AMOUNT_1, row)),
+ ImportHandlerUtils.readAsDate(RecurringDepositConstants.CHARGE_DUE_DATE_1, row)));
+ }else {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(RecurringDepositConstants.CHARGE_ID_1, row),
+ null,
+ ImportHandlerUtils.readAsDate(RecurringDepositConstants.CHARGE_DUE_DATE_1, row)));
+ }
+ }
+
+ if (charge2!=null) {
+ if (ImportHandlerUtils.readAsDouble(RecurringDepositConstants.CHARGE_AMOUNT_2, row)!=null) {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(RecurringDepositConstants.CHARGE_ID_2, row),
+ BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(RecurringDepositConstants.CHARGE_AMOUNT_2, row)),
+ ImportHandlerUtils.readAsDate(RecurringDepositConstants.CHARGE_DUE_DATE_2, row)));
+ }else {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(RecurringDepositConstants.CHARGE_ID_2, row),
+ null,
+ ImportHandlerUtils.readAsDate(RecurringDepositConstants.CHARGE_DUE_DATE_2, row)));
+ }
+ }
+ String status = ImportHandlerUtils.readAsString(RecurringDepositConstants.STATUS_COL, row);
+ statuses.add(status);
+ Long clientId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME), clientName);
+ return RecurringDepositAccountData.importInstance(clientId, productId, fieldOfficerId, submittedOnDate,
+ interestCompoundingPeriodTypeEnum,interestPostingPeriodTypeEnum,interestCalculationTypeEnum,
+ interestCalculationDaysInYearTypeEnum, lockinPeriodFrequency, lockinPeriodFrequencyTypeEnum,
+ depositAmount, depositPeriod, depositPeriodFrequencyId, depositStartDate,
+ recurringFrequency, recurringFrequencyTypeEnum, inheritCalendar, isMandatoryDeposit,
+ allowWithdrawal, adjustAdvancePayments, externalId,charges, row.getRowNum(),locale,dateFormat);
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet savingsSheet = workbook.getSheet(TemplatePopulateImportConstants.RECURRING_DEPOSIT_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ int progressLevel = 0;
+ Long savingsId=null;
+ String errorMessage="";
+ for (int i = 0; i < savings.size(); i++) {
+ Row row = savingsSheet.getRow(savings.get(i).getRowIndex());
+ Cell statusCell = row.createCell(RecurringDepositConstants.STATUS_COL);
+ Cell errorReportCell = row.createCell(RecurringDepositConstants.FAILURE_REPORT_COL);
+ try {
+ String status = statuses.get(i);
+ progressLevel = getProgressLevel(status);
+
+ if (progressLevel == 0) {
+ CommandProcessingResult result= importSavings(i,dateFormat);
+ savingsId = result.getSavingsId();
+ progressLevel = 1;
+ } else
+ savingsId = ImportHandlerUtils.readAsLong(RecurringDepositConstants.SAVINGS_ID_COL, savingsSheet.getRow(savings.get(i).getRowIndex()));
+
+ if (progressLevel <= 1) progressLevel = importSavingsApproval(savingsId, i,dateFormat);
+
+ if (progressLevel <= 2) progressLevel = importSavingsActivation(savingsId, i,dateFormat);
+ successCount++;
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ writeRecurringDepositErrorMessage(savingsId,errorMessage,progressLevel,statusCell,errorReportCell,row);
+ }
+ }
+ setReportHeaders(savingsSheet);
+ return Count.instance(successCount,errorCount);
+ }
+
+ private void writeRecurringDepositErrorMessage(Long savingsId,String errorMessage,int progressLevel,Cell statusCell,Cell errorReportCell,Row row){
+ String status = "";
+ if (progressLevel == 0)
+ status = TemplatePopulateImportConstants.STATUS_CREATION_FAILED;
+ else if (progressLevel == 1)
+ status = TemplatePopulateImportConstants.STATUS_APPROVAL_FAILED;
+ else if (progressLevel == 2) status = TemplatePopulateImportConstants.STATUS_ACTIVATION_FAILED;
+ statusCell.setCellValue(status);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.RED));
+
+ if (progressLevel > 0) row.createCell(RecurringDepositConstants.SAVINGS_ID_COL).setCellValue(savingsId);
+
+ errorReportCell.setCellValue(errorMessage);
+ }
+
+ private void setReportHeaders(Sheet savingsSheet) {
+ savingsSheet.setColumnWidth(RecurringDepositConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ Row rowHeader = savingsSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ ImportHandlerUtils.writeString(RecurringDepositConstants.STATUS_COL, rowHeader, "Status");
+ ImportHandlerUtils.writeString(RecurringDepositConstants.SAVINGS_ID_COL, rowHeader, "Savings ID");
+ ImportHandlerUtils.writeString(RecurringDepositConstants.FAILURE_REPORT_COL, rowHeader, "Report");
+ }
+
+ private int importSavingsActivation(Long savingsId, int i,String dateFormat) {
+ if(activationDates.get(i)!=null) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ String payload = gsonBuilder.create().toJson(activationDates.get(i));
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .recurringDepositAccountActivation(savingsId)//
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ }
+ return 3;
+ }
+
+ private int importSavingsApproval(Long savingsId, int i, String dateFormat) {
+ if(approvalDates.get(i)!=null) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ String payload = gsonBuilder.create().toJson(approvalDates.get(i));
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .approveRecurringDepositAccountApplication(savingsId)//
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ }
+ return 2;
+ }
+
+ private CommandProcessingResult importSavings(int i, String dateFormat) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(EnumOptionData.class,new EnumOptionDataIdSerializer());
+ JsonObject savingsJsonob=gsonBuilder.create().toJsonTree(savings.get(i)).getAsJsonObject();
+ savingsJsonob.remove("withdrawalFeeForTransfers");
+ String payload=savingsJsonob.toString();
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createRecurringDepositAccount() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ return result;
+ }
+
+ private int getProgressLevel(String status) {
+ if (status==null || status.equals(TemplatePopulateImportConstants.STATUS_CREATION_FAILED))
+ return 0;
+ else if (status.equals(TemplatePopulateImportConstants.STATUS_APPROVAL_FAILED))
+ return 1;
+ else if (status.equals(TemplatePopulateImportConstants.STATUS_ACTIVATION_FAILED)) return 2;
+ return 0;
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/recurringdeposit/RecurringDepositTransactionImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/recurringdeposit/RecurringDepositTransactionImportHandler.java
new file mode 100644
index 000000000..3715dbd25
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/recurringdeposit/RecurringDepositTransactionImportHandler.java
@@ -0,0 +1,157 @@
+/**
+ * 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.importhandler.recurringdeposit;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TransactionConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.SavingsAccountTransactionEnumValueSerialiser;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class RecurringDepositTransactionImportHandler implements ImportHandler {
+
+ private Workbook workbook;
+ private List savingsTransactions;
+ private String savingsAccountId = "";
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+ @Autowired
+ public RecurringDepositTransactionImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.savingsTransactions=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(String locale, String dateFormat) {
+ Sheet savingsTransactionSheet = workbook.getSheet(TemplatePopulateImportConstants.SAVINGS_TRANSACTION_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(savingsTransactionSheet, TransactionConstants.AMOUNT_COL);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = savingsTransactionSheet.getRow(rowIndex);
+ if(ImportHandlerUtils.isNotImported(row, TransactionConstants.STATUS_COL))
+ savingsTransactions.add(readSavingsTransaction(row,locale,dateFormat));
+ }
+ }
+
+ private SavingsAccountTransactionData readSavingsTransaction(Row row,String locale, String dateFormat) {
+ String savingsAccountIdCheck=null;
+ if (ImportHandlerUtils.readAsLong(TransactionConstants.SAVINGS_ACCOUNT_NO_COL, row)!=null)
+ savingsAccountIdCheck = ImportHandlerUtils.readAsLong(TransactionConstants.SAVINGS_ACCOUNT_NO_COL, row).toString();
+ if(savingsAccountIdCheck!=null)
+ savingsAccountId = savingsAccountIdCheck;
+ String transactionType = ImportHandlerUtils.readAsString(TransactionConstants.TRANSACTION_TYPE_COL, row);
+ SavingsAccountTransactionEnumData savingsAccountTransactionEnumData=new SavingsAccountTransactionEnumData(null,null,transactionType);
+
+ BigDecimal amount=null;
+ if (ImportHandlerUtils.readAsDouble(TransactionConstants.AMOUNT_COL, row)!=null)
+ amount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(TransactionConstants.AMOUNT_COL, row));
+
+ LocalDate transactionDate = ImportHandlerUtils.readAsDate(TransactionConstants.TRANSACTION_DATE_COL, row);
+ String paymentType = ImportHandlerUtils.readAsString(TransactionConstants.PAYMENT_TYPE_COL, row);
+ Long paymentTypeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME), paymentType);
+ String accountNumber = ImportHandlerUtils.readAsString(TransactionConstants.ACCOUNT_NO_COL, row);
+ String checkNumber = ImportHandlerUtils.readAsString(TransactionConstants.CHECK_NO_COL, row);
+ String routingCode = ImportHandlerUtils.readAsString(TransactionConstants.ROUTING_CODE_COL, row);
+ String receiptNumber = ImportHandlerUtils.readAsString(TransactionConstants.RECEIPT_NO_COL, row);
+ String bankNumber = ImportHandlerUtils.readAsString(TransactionConstants.BANK_NO_COL, row);
+ return SavingsAccountTransactionData.importInstance(amount, transactionDate, paymentTypeId, accountNumber,
+ checkNumber, routingCode, receiptNumber, bankNumber, Long.parseLong(savingsAccountId), savingsAccountTransactionEnumData, row.getRowNum(),locale,dateFormat);
+
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet savingsTransactionSheet = workbook.getSheet(TemplatePopulateImportConstants.SAVINGS_TRANSACTION_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(SavingsAccountTransactionEnumData.class
+ ,new SavingsAccountTransactionEnumValueSerialiser());
+
+ for (SavingsAccountTransactionData transaction : savingsTransactions) {
+ try {
+ JsonObject savingsTransactionJsonob=gsonBuilder.create().toJsonTree(transaction).getAsJsonObject();
+ savingsTransactionJsonob.remove("transactionType");
+ savingsTransactionJsonob.remove("reversed");
+ savingsTransactionJsonob.remove("interestedPostedAsOn");
+ String payload= savingsTransactionJsonob.toString();
+ CommandWrapper commandRequest=null;
+ if (transaction.getTransactionType().getValue().equals("Withdrawal")) {
+ commandRequest = new CommandWrapperBuilder() //
+ .recurringAccountWithdrawal(transaction.getSavingsAccountId()) //
+ .withJson(payload) //
+ .build(); //
+
+ }else if (transaction.getTransactionType().getValue().equals("Deposit")){
+ commandRequest = new CommandWrapperBuilder() //
+ .recurringAccountDeposit(transaction.getSavingsAccountId()) //
+ .withJson(payload) //
+ .build();
+ }
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = savingsTransactionSheet.getRow(transaction.getRowIndex()).createCell(TransactionConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ } catch (AbstractPlatformDomainRuleException e) {
+ errorCount++;
+ e.printStackTrace();
+ errorMessage = e.getDefaultUserMessage();
+ ImportHandlerUtils.writeErrorMessage(savingsTransactionSheet,transaction.getRowIndex(),errorMessage,TransactionConstants.STATUS_COL);
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(savingsTransactionSheet,transaction.getRowIndex(),errorMessage,TransactionConstants.STATUS_COL);
+ }
+ }
+ savingsTransactionSheet.setColumnWidth(TransactionConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(TransactionConstants.STATUS_COL, savingsTransactionSheet.getRow(TransactionConstants.STATUS_COL), TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsImportHandler.java
new file mode 100644
index 000000000..13c0f54dc
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsImportHandler.java
@@ -0,0 +1,364 @@
+/**
+ * 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.importhandler.savings;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.SavingsConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOptionDataIdSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
+import org.apache.fineract.portfolio.savings.data.SavingsActivation;
+import org.apache.fineract.portfolio.savings.data.SavingsApproval;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+@Service
+public class SavingsImportHandler implements ImportHandler {
+
+ private Workbook workbook;
+ private List savings;
+ private List approvalDates;
+ private List activationDates;
+ private Liststatuses;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public SavingsImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.savings=new ArrayList<>();
+ this.approvalDates=new ArrayList<>();
+ this.activationDates=new ArrayList<>();
+ this.statuses=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+ public void readExcelFile(String locale, String dateFormat) {
+ Sheet savingsSheet = workbook.getSheet(TemplatePopulateImportConstants.SAVINGS_ACCOUNTS_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(savingsSheet, TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = savingsSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, SavingsConstants.STATUS_COL)) {
+ savings.add(readSavings(row,locale,dateFormat));
+ approvalDates.add(readSavingsApproval(row,locale,dateFormat));
+ activationDates.add(readSavingsActivation(row,locale,dateFormat));
+ }
+ }
+ }
+
+ private SavingsActivation readSavingsActivation(Row row,String locale, String dateFormat) {
+ LocalDate activationDate = ImportHandlerUtils.readAsDate( SavingsConstants.ACTIVATION_DATE_COL, row);
+ if (activationDate!=null)
+ return SavingsActivation.importInstance(activationDate, row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private SavingsApproval readSavingsApproval(Row row,String locale, String dateFormat) {
+ LocalDate approvalDate = ImportHandlerUtils.readAsDate( SavingsConstants.APPROVED_DATE_COL, row);
+ if (approvalDate!=null)
+ return SavingsApproval.importInstance(approvalDate, row.getRowNum(),locale,dateFormat);
+ else
+ return null;
+ }
+
+ private SavingsAccountData readSavings(Row row,String locale, String dateFormat) {
+ String productName = ImportHandlerUtils.readAsString( SavingsConstants.PRODUCT_COL, row);
+ Long productId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME), productName);
+ String fieldOfficerName = ImportHandlerUtils.readAsString(SavingsConstants.FIELD_OFFICER_NAME_COL, row);
+ Long fieldOfficerId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), fieldOfficerName);
+ LocalDate submittedOnDate = ImportHandlerUtils.readAsDate(SavingsConstants.SUBMITTED_ON_DATE_COL, row);
+
+ BigDecimal nominalAnnualInterestRate=null;
+ if (ImportHandlerUtils.readAsDouble(SavingsConstants.NOMINAL_ANNUAL_INTEREST_RATE_COL, row)!=null) {
+ nominalAnnualInterestRate = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(SavingsConstants.NOMINAL_ANNUAL_INTEREST_RATE_COL, row));
+ }
+ String interestCompoundingPeriodType = ImportHandlerUtils.readAsString(SavingsConstants.INTEREST_COMPOUNDING_PERIOD_COL, row);
+ Long interestCompoundingPeriodTypeId = null;
+ EnumOptionData interestCompoundingPeriodTypeEnum=null;
+ if (interestCompoundingPeriodType!=null) {
+ if (interestCompoundingPeriodType.equalsIgnoreCase("Daily"))
+ interestCompoundingPeriodTypeId = 1L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase("Monthly"))
+ interestCompoundingPeriodTypeId = 4L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase("Quarterly"))
+ interestCompoundingPeriodTypeId = 5L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase("Semi-Annual"))
+ interestCompoundingPeriodTypeId = 6L;
+ else if (interestCompoundingPeriodType.equalsIgnoreCase("Annually"))
+ interestCompoundingPeriodTypeId = 7L;
+ interestCompoundingPeriodTypeEnum = new EnumOptionData(interestCompoundingPeriodTypeId, null, null);
+ }
+ String interestPostingPeriodType = ImportHandlerUtils.readAsString(SavingsConstants.INTEREST_POSTING_PERIOD_COL, row);
+ Long interestPostingPeriodTypeId = null;
+ EnumOptionData interestPostingPeriodTypeEnum=null;
+ if (interestPostingPeriodType!=null) {
+ if (interestPostingPeriodType.equalsIgnoreCase("Monthly"))
+ interestPostingPeriodTypeId = 4L;
+ else if (interestPostingPeriodType.equalsIgnoreCase("Quarterly"))
+ interestPostingPeriodTypeId = 5L;
+ else if (interestPostingPeriodType.equalsIgnoreCase("Annually"))
+ interestPostingPeriodTypeId = 7L;
+ else if (interestPostingPeriodType.equalsIgnoreCase("BiAnnual"))
+ interestPostingPeriodTypeId = 6L;
+ interestPostingPeriodTypeEnum = new EnumOptionData(interestPostingPeriodTypeId, null, null);
+ }
+ String interestCalculationType = ImportHandlerUtils.readAsString(SavingsConstants.INTEREST_CALCULATION_COL, row);
+ Long interestCalculationTypeId = null;
+ EnumOptionData interestCalculationTypeEnum=null;
+ if (interestCalculationType!=null) {
+ if (interestCalculationType.equalsIgnoreCase("Daily Balance"))
+ interestCalculationTypeId = 1L;
+ else if (interestCalculationType.equalsIgnoreCase("Average Daily Balance"))
+ interestCalculationTypeId = 2L;
+ interestCalculationTypeEnum = new EnumOptionData(interestCalculationTypeId, null, null);
+ }
+ String interestCalculationDaysInYearType = ImportHandlerUtils.readAsString(SavingsConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL, row);
+ EnumOptionData interestCalculationDaysInYearTypeEnum=null;
+ Long interestCalculationDaysInYearTypeId = null;
+ if (interestCalculationDaysInYearType!=null) {
+ if (interestCalculationDaysInYearType.equalsIgnoreCase("360 Days"))
+ interestCalculationDaysInYearTypeId = 360L;
+ else if (interestCalculationDaysInYearType.equalsIgnoreCase("365 Days"))
+ interestCalculationDaysInYearTypeId = 365L;
+ interestCalculationDaysInYearTypeEnum = new EnumOptionData(interestCalculationDaysInYearTypeId, null, null);
+ }
+ BigDecimal minRequiredOpeningBalance=null;
+ if (ImportHandlerUtils.readAsDouble(SavingsConstants.MIN_OPENING_BALANCE_COL, row)!=null) {
+ minRequiredOpeningBalance = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(SavingsConstants.MIN_OPENING_BALANCE_COL, row));
+ }
+ Integer lockinPeriodFrequency = ImportHandlerUtils.readAsInt(SavingsConstants.LOCKIN_PERIOD_COL, row);
+ String lockinPeriodFrequencyType = ImportHandlerUtils.readAsString(SavingsConstants.LOCKIN_PERIOD_FREQUENCY_COL, row);
+ Long lockinPeriodFrequencyTypeId = null;
+ EnumOptionData lockinPeriodFrequencyTypeEnum=null;
+ if (lockinPeriodFrequencyType!=null) {
+ if (lockinPeriodFrequencyType.equalsIgnoreCase("Days"))
+ lockinPeriodFrequencyTypeId = 0L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase("Weeks"))
+ lockinPeriodFrequencyTypeId = 1L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase("Months"))
+ lockinPeriodFrequencyTypeId = 2L;
+ else if (lockinPeriodFrequencyType.equalsIgnoreCase("Years"))
+ lockinPeriodFrequencyTypeId = 3L;
+ lockinPeriodFrequencyTypeEnum = new EnumOptionData(lockinPeriodFrequencyTypeId, null, null);
+ }
+ Boolean applyWithdrawalFeeForTransfers = ImportHandlerUtils.readAsBoolean(SavingsConstants.APPLY_WITHDRAWAL_FEE_FOR_TRANSFERS, row);
+
+ String savingsType=null;
+ if (ImportHandlerUtils.readAsString(SavingsConstants.SAVINGS_TYPE_COL, row)!=null)
+ savingsType = ImportHandlerUtils.readAsString(SavingsConstants.SAVINGS_TYPE_COL, row).toLowerCase(Locale.ENGLISH);
+
+ String clientOrGroupName = ImportHandlerUtils.readAsString(SavingsConstants.CLIENT_NAME_COL, row);
+
+ String externalId = ImportHandlerUtils.readAsString(SavingsConstants.EXTERNAL_ID_COL, row);
+ List charges = new ArrayList<>();
+
+
+ Boolean allowOverdraft = ImportHandlerUtils.readAsBoolean(SavingsConstants.ALLOW_OVER_DRAFT_COL, row);
+ BigDecimal overdraftLimit = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(SavingsConstants.OVER_DRAFT_LIMIT_COL, row));
+
+ String charge1 = ImportHandlerUtils.readAsString(SavingsConstants.CHARGE_ID_1, row);
+ String charge2 = ImportHandlerUtils.readAsString(SavingsConstants.CHARGE_ID_2, row);
+
+ if (charge1!=null) {
+ if (ImportHandlerUtils.readAsDouble(SavingsConstants.CHARGE_AMOUNT_1, row)!=null) {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(SavingsConstants.CHARGE_ID_1, row),
+ BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(SavingsConstants.CHARGE_AMOUNT_1, row)),
+ ImportHandlerUtils.readAsDate(SavingsConstants.CHARGE_DUE_DATE_1, row)));
+ }else {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(SavingsConstants.CHARGE_ID_1, row),
+ null,
+ ImportHandlerUtils.readAsDate(SavingsConstants.CHARGE_DUE_DATE_1, row)));
+ }
+ }
+
+ if (charge2!=null) {
+ if (ImportHandlerUtils.readAsDouble(SavingsConstants.CHARGE_AMOUNT_2, row)!=null) {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(SavingsConstants.CHARGE_ID_2, row),
+ BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(SavingsConstants.CHARGE_AMOUNT_2, row)),
+ ImportHandlerUtils.readAsDate(SavingsConstants.CHARGE_DUE_DATE_2, row)));
+ }else {
+ charges.add(new SavingsAccountChargeData(ImportHandlerUtils.readAsLong(SavingsConstants.CHARGE_ID_2, row),
+ null,
+ ImportHandlerUtils.readAsDate(SavingsConstants.CHARGE_DUE_DATE_2, row)));
+ }
+ }
+ String status = ImportHandlerUtils.readAsString(SavingsConstants.STATUS_COL, row);
+ statuses.add(status);
+ if (savingsType!=null) {
+ if (savingsType.equals("individual")) {
+ Long clientId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME), clientOrGroupName);
+ return SavingsAccountData.importInstanceIndividual(clientId, productId, fieldOfficerId, submittedOnDate, nominalAnnualInterestRate,
+ interestCompoundingPeriodTypeEnum, interestPostingPeriodTypeEnum, interestCalculationTypeEnum,
+ interestCalculationDaysInYearTypeEnum, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyTypeEnum,
+ applyWithdrawalFeeForTransfers, row.getRowNum(), externalId, charges, allowOverdraft, overdraftLimit,locale,dateFormat);
+ }
+ Long groupId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME), clientOrGroupName);
+ return SavingsAccountData.importInstanceGroup(groupId, productId, fieldOfficerId, submittedOnDate, nominalAnnualInterestRate,
+ interestCompoundingPeriodTypeEnum, interestPostingPeriodTypeEnum, interestCalculationTypeEnum,
+ interestCalculationDaysInYearTypeEnum, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyTypeEnum,
+ applyWithdrawalFeeForTransfers, row.getRowNum(), externalId, charges, allowOverdraft, overdraftLimit,locale,dateFormat);
+ }else {
+ return null;
+ }
+
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet savingsSheet = workbook.getSheet(TemplatePopulateImportConstants.SAVINGS_ACCOUNTS_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ int progressLevel = 0;
+ String errorMessage="";
+ Long savingsId=null;
+ for (int i = 0; i < savings.size(); i++) {
+ Row row = savingsSheet.getRow(savings.get(i).getRowIndex());
+ Cell statusCell = row.createCell(SavingsConstants.STATUS_COL);
+ Cell errorReportCell = row.createCell(SavingsConstants.FAILURE_REPORT_COL);
+ try {
+ String status = statuses.get(i);
+ progressLevel = getProgressLevel(status);
+
+ if (progressLevel == 0) {
+ CommandProcessingResult result = importSavings(i,dateFormat);
+ savingsId = result.getSavingsId();;
+ progressLevel = 1;
+ } else
+ savingsId = ImportHandlerUtils.readAsLong(SavingsConstants.SAVINGS_ID_COL, savingsSheet.getRow(savings.get(i).getRowIndex()));
+
+ if (progressLevel <= 1) progressLevel = importSavingsApproval(savingsId, i,dateFormat);
+
+ if (progressLevel <= 2) progressLevel = importSavingsActivation(savingsId, i,dateFormat);
+ successCount++;
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ writeSavingsErrorMessage(savingsId,errorMessage,progressLevel,statusCell,errorReportCell,row);
+ }
+ }
+ setReportHeaders(savingsSheet);
+ return Count.instance(successCount,errorCount);
+ }
+
+ private void writeSavingsErrorMessage(Long savingsId,String errorMessage,int progressLevel,Cell statusCell,Cell errorReportCell,Row row){
+ String status = "";
+
+ if (progressLevel == 0)
+ status = TemplatePopulateImportConstants.STATUS_CREATION_FAILED;
+ else if (progressLevel == 1)
+ status = TemplatePopulateImportConstants.STATUS_APPROVAL_FAILED;
+ else if (progressLevel == 2) status = TemplatePopulateImportConstants.STATUS_ACTIVATION_FAILED;
+ statusCell.setCellValue(status);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.RED));
+
+ if (progressLevel > 0) row.createCell(SavingsConstants.SAVINGS_ID_COL).setCellValue(savingsId);
+
+ errorReportCell.setCellValue(errorMessage);
+ }
+ private void setReportHeaders(Sheet savingsSheet) {
+ savingsSheet.setColumnWidth(SavingsConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ Row rowHeader = savingsSheet.getRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ ImportHandlerUtils.writeString(SavingsConstants.STATUS_COL, rowHeader, TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ ImportHandlerUtils.writeString(SavingsConstants.SAVINGS_ID_COL, rowHeader, TemplatePopulateImportConstants.SAVINGS_ID_COL_REPORT_HEADER);
+ ImportHandlerUtils.writeString(SavingsConstants.FAILURE_REPORT_COL, rowHeader, TemplatePopulateImportConstants.FAILURE_COL_REPORT_HEADER);
+ }
+
+ private int importSavingsActivation(Long savingsId, int i, String dateFormat) {
+ if(activationDates.get(i)!=null) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ String payload = gsonBuilder.create().toJson(activationDates.get(i));
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .savingsAccountActivation(savingsId)//
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ }
+ return 3;
+ }
+
+ private int importSavingsApproval(Long savingsId, int i,
+ String dateFormat) {
+ if(approvalDates.get(i)!=null) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ String payload = gsonBuilder.create().toJson(approvalDates.get(i));
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .approveSavingsAccountApplication(savingsId)//
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ }
+ return 2;
+ }
+
+ private CommandProcessingResult importSavings(int i,String dateFormat) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(EnumOptionData.class,new EnumOptionDataIdSerializer());
+ JsonObject savingsJsonob=gsonBuilder.create().toJsonTree(savings.get(i)).getAsJsonObject();
+ savingsJsonob.remove("isDormancyTrackingActive");
+ String payload= savingsJsonob.toString();
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createSavingsAccount() //
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ return result;
+ }
+
+ private int getProgressLevel(String status) {
+ if (status==null || status.equals(TemplatePopulateImportConstants.STATUS_CREATION_FAILED))
+ return 0;
+ else if (status.equals(TemplatePopulateImportConstants.STATUS_APPROVAL_FAILED))
+ return 1;
+ else if (status.equals(TemplatePopulateImportConstants.STATUS_ACTIVATION_FAILED)) return 2;
+ return 0;
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsTransactionImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsTransactionImportHandler.java
new file mode 100644
index 000000000..dfd562f9e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsTransactionImportHandler.java
@@ -0,0 +1,152 @@
+/**
+ * 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.importhandler.savings;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TransactionConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.SavingsAccountTransactionEnumValueSerialiser;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class SavingsTransactionImportHandler implements ImportHandler {
+ private Workbook workbook;
+ private List savingsTransactions;
+ private String savingsAccountId = "";
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public SavingsTransactionImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.savingsTransactions=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile(String locale, String dateFormat) {
+ Sheet savingsTransactionSheet = workbook.getSheet(TemplatePopulateImportConstants.SAVINGS_TRANSACTION_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(savingsTransactionSheet, TransactionConstants.AMOUNT_COL);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = savingsTransactionSheet.getRow(rowIndex);
+ if(ImportHandlerUtils.isNotImported(row, TransactionConstants.STATUS_COL))
+ savingsTransactions.add(readSavingsTransaction(row,locale,dateFormat));
+ }
+ }
+
+ private SavingsAccountTransactionData readSavingsTransaction(Row row,String locale, String dateFormat) {
+ String savingsAccountIdCheck=null;
+ if (ImportHandlerUtils.readAsLong(TransactionConstants.SAVINGS_ACCOUNT_NO_COL, row)!=null)
+ savingsAccountIdCheck = ImportHandlerUtils.readAsLong(TransactionConstants.SAVINGS_ACCOUNT_NO_COL, row).toString();
+ if(savingsAccountIdCheck!=null)
+ savingsAccountId = savingsAccountIdCheck;
+ String transactionType = ImportHandlerUtils.readAsString(TransactionConstants.TRANSACTION_TYPE_COL, row);
+ SavingsAccountTransactionEnumData savingsAccountTransactionEnumData=new SavingsAccountTransactionEnumData(null,null,transactionType);
+
+ BigDecimal amount=null;
+ if (ImportHandlerUtils.readAsDouble(TransactionConstants.AMOUNT_COL, row)!=null)
+ amount = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(TransactionConstants.AMOUNT_COL, row));
+
+ LocalDate transactionDate = ImportHandlerUtils.readAsDate(TransactionConstants.TRANSACTION_DATE_COL, row);
+ String paymentType = ImportHandlerUtils.readAsString(TransactionConstants.PAYMENT_TYPE_COL, row);
+ Long paymentTypeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME), paymentType);
+ String accountNumber = ImportHandlerUtils.readAsString(TransactionConstants.ACCOUNT_NO_COL, row);
+ String checkNumber = ImportHandlerUtils.readAsString(TransactionConstants.CHECK_NO_COL, row);
+ String routingCode = ImportHandlerUtils.readAsString(TransactionConstants.ROUTING_CODE_COL, row);
+ String receiptNumber = ImportHandlerUtils.readAsString(TransactionConstants.RECEIPT_NO_COL, row);
+ String bankNumber = ImportHandlerUtils.readAsString(TransactionConstants.BANK_NO_COL, row);
+ return SavingsAccountTransactionData.importInstance(amount, transactionDate, paymentTypeId, accountNumber,
+ checkNumber, routingCode, receiptNumber, bankNumber, Long.parseLong(savingsAccountId), savingsAccountTransactionEnumData, row.getRowNum(),locale,dateFormat);
+
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet savingsTransactionSheet = workbook.getSheet(TemplatePopulateImportConstants.SAVINGS_TRANSACTION_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ gsonBuilder.registerTypeAdapter(SavingsAccountTransactionEnumData.class
+ ,new SavingsAccountTransactionEnumValueSerialiser());
+
+ for (SavingsAccountTransactionData transaction : savingsTransactions) {
+ try {
+ JsonObject savingsTransactionJsonob=gsonBuilder.create().toJsonTree(transaction).getAsJsonObject();
+ savingsTransactionJsonob.remove("transactionType");
+ savingsTransactionJsonob.remove("reversed");
+ savingsTransactionJsonob.remove("interestedPostedAsOn");
+ String payload= savingsTransactionJsonob.toString();
+ CommandWrapper commandRequest=null;
+ if (transaction.getTransactionType().getValue().equals("Withdrawal")) {
+ commandRequest = new CommandWrapperBuilder() //
+ .savingsAccountWithdrawal(transaction.getSavingsAccountId()) //
+ .withJson(payload) //
+ .build(); //
+
+ }else if (transaction.getTransactionType().getValue().equals("Deposit")){
+ commandRequest = new CommandWrapperBuilder() //
+ .savingsAccountDeposit(transaction.getSavingsAccountId()) //
+ .withJson(payload) //
+ .build();
+ }
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = savingsTransactionSheet.getRow(transaction.getRowIndex()).createCell(TransactionConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(savingsTransactionSheet,transaction.getRowIndex(),errorMessage,TransactionConstants.STATUS_COL);
+ }
+ }
+ savingsTransactionSheet.setColumnWidth(TransactionConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(TransactionConstants.STATUS_COL, savingsTransactionSheet.getRow(TransactionConstants.STATUS_COL), TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/sharedaccount/SharedAccountImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/sharedaccount/SharedAccountImportHandler.java
new file mode 100644
index 000000000..63ce1c292
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/sharedaccount/SharedAccountImportHandler.java
@@ -0,0 +1,174 @@
+/**
+ * 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.importhandler.sharedaccount;
+
+import com.google.gson.GsonBuilder;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.SharedAccountsConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountChargeData;
+import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountData;
+import org.apache.poi.ss.usermodel.*;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class SharedAccountImportHandler implements ImportHandler {
+ private Workbook workbook;
+ private List shareAccountDataList;
+ private Liststatuses;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public SharedAccountImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.shareAccountDataList=new ArrayList<>();
+ statuses=new ArrayList();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+ public void readExcelFile(String locale, String dateFormat) {
+ Sheet sharedAccountsSheet=workbook.getSheet(TemplatePopulateImportConstants.SHARED_ACCOUNTS_SHEET_NAME);
+ Integer noOfEntries= ImportHandlerUtils.getNumberOfRows(sharedAccountsSheet, TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex=1;rowIndex<=noOfEntries;rowIndex++){
+ Row row;
+ row=sharedAccountsSheet.getRow(rowIndex);
+ if (ImportHandlerUtils.isNotImported(row, SharedAccountsConstants.STATUS_COL)){
+ shareAccountDataList.add(readSharedAccount(row,locale,dateFormat));
+ }
+ }
+ }
+
+ private ShareAccountData readSharedAccount(Row row,String locale, String dateFormat) {
+ String clientName = ImportHandlerUtils.readAsString(SharedAccountsConstants.CLIENT_NAME_COL, row);
+ Long clientId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME), clientName);
+
+ String productName = ImportHandlerUtils.readAsString(SharedAccountsConstants.PRODUCT_COL, row);
+ Long productId=ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.SHARED_PRODUCTS_SHEET_NAME),productName);
+
+ LocalDate submittedOnDate=ImportHandlerUtils.readAsDate(SharedAccountsConstants.SUBMITTED_ON_COL,row);
+
+ String externalId = ImportHandlerUtils.readAsString(SharedAccountsConstants.EXTERNAL_ID_COL, row);
+
+ Integer totNoOfShares=ImportHandlerUtils.readAsInt(SharedAccountsConstants.TOTAL_NO_SHARES_COL,row);
+
+ Long defaultSavingsAccountId=ImportHandlerUtils.readAsLong(SharedAccountsConstants.DEFAULT_SAVINGS_AC_COL,row);
+
+ Integer minimumActivePeriodDays=ImportHandlerUtils.readAsInt(SharedAccountsConstants.MINIMUM_ACTIVE_PERIOD_IN_DAYS_COL,row);
+ Integer minimumActivePeriodFrequencyType=0;
+
+ Integer lockInPeriod=ImportHandlerUtils.readAsInt(SharedAccountsConstants.LOCK_IN_PERIOD_COL,row);
+
+ Integer lockPeriodFrequencyType=null;
+
+ if (ImportHandlerUtils.readAsString(SharedAccountsConstants.LOCK_IN_PERIOD_FREQUENCY_TYPE,row)!=null) {
+ if (ImportHandlerUtils.readAsString(SharedAccountsConstants.LOCK_IN_PERIOD_FREQUENCY_TYPE, row)
+ .equals(TemplatePopulateImportConstants.FREQUENCY_DAYS)) {
+ lockPeriodFrequencyType = 0;
+ } else if (ImportHandlerUtils.readAsString(SharedAccountsConstants.LOCK_IN_PERIOD_FREQUENCY_TYPE, row)
+ .equals(TemplatePopulateImportConstants.FREQUENCY_WEEKS)) {
+ lockPeriodFrequencyType = 1;
+ } else if (ImportHandlerUtils.readAsString(SharedAccountsConstants.LOCK_IN_PERIOD_FREQUENCY_TYPE, row)
+ .equals(TemplatePopulateImportConstants.FREQUENCY_MONTHS)) {
+ lockPeriodFrequencyType = 2;
+ } else if (ImportHandlerUtils.readAsString(SharedAccountsConstants.LOCK_IN_PERIOD_FREQUENCY_TYPE, row)
+ .equals(TemplatePopulateImportConstants.FREQUENCY_YEARS)) {
+ lockPeriodFrequencyType = 3;
+ }
+ }
+ LocalDate applicationDate=ImportHandlerUtils.readAsDate(SharedAccountsConstants.APPLICATION_DATE_COL,row);
+ Boolean allowDividendCalc=ImportHandlerUtils.readAsBoolean(SharedAccountsConstants.ALLOW_DIVIDEND_CALCULATION_FOR_INACTIVE_CLIENTS_COL,row);
+
+ List charges=new ArrayList<>();
+ for (int cellNo=SharedAccountsConstants.CHARGES_NAME_1_COL;cellNo staffList;
+ private Workbook workbook;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public StaffImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ this.staffList=new ArrayList<>();
+ readExcelFile(locale,dateFormat);
+ return importEntity(dateFormat);
+ }
+ public void readExcelFile(String locale, String dateFormat) {
+ Sheet staffSheet=workbook.getSheet(TemplatePopulateImportConstants.EMPLOYEE_SHEET_NAME);
+ Integer noOfEntries= ImportHandlerUtils.getNumberOfRows(staffSheet,TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex=1;rowIndex<=noOfEntries;rowIndex++){
+ Row row;
+ row=staffSheet.getRow(rowIndex);
+ if ( ImportHandlerUtils.isNotImported(row, StaffConstants.STATUS_COL)){
+ staffList.add(readStaff(row,locale,dateFormat));
+ }
+
+ }
+ }
+
+ private StaffData readStaff(Row row,String locale, String dateFormat) {
+ String officeName = ImportHandlerUtils.readAsString( StaffConstants.OFFICE_NAME_COL, row);
+ Long officeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME), officeName);
+ String firstName = ImportHandlerUtils.readAsString(StaffConstants.FIRST_NAME_COL, row);
+ String lastName = ImportHandlerUtils.readAsString(StaffConstants.LAST_NAME_COL, row);
+ Boolean isLoanOfficer=ImportHandlerUtils.readAsBoolean(StaffConstants.IS_LOAN_OFFICER,row);
+ String mobileNo=null;
+ if (ImportHandlerUtils.readAsLong(StaffConstants.MOBILE_NO_COL,row)!=null)
+ mobileNo=ImportHandlerUtils.readAsLong(StaffConstants.MOBILE_NO_COL,row).toString();
+ LocalDate joinedOnDate=ImportHandlerUtils.readAsDate(StaffConstants.JOINED_ON_COL,row);
+ String externalId=ImportHandlerUtils.readAsString(StaffConstants.EXTERNAL_ID_COL,row);
+ Boolean isActive=ImportHandlerUtils.readAsBoolean(StaffConstants.IS_ACTIVE_COL,row);
+
+ return StaffData.importInstance(externalId,firstName,lastName,mobileNo,officeId,isLoanOfficer,isActive,
+ joinedOnDate,row.getRowNum(),locale,dateFormat);
+ }
+
+ public Count importEntity(String dateFormat) {
+ Sheet staffSheet=workbook.getSheet(TemplatePopulateImportConstants.EMPLOYEE_SHEET_NAME);
+ int successCount=0;
+ int errorCount=0;
+ String errorMessage="";
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat));
+ for (StaffData staff: staffList) {
+ try {
+ String payload=gsonBuilder.create().toJson(staff);
+ final CommandWrapper commandRequest = new CommandWrapperBuilder() //
+ .createStaff()//
+ .withJson(payload) //
+ .build(); //
+ final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ successCount++;
+ Cell statusCell = staffSheet.getRow(staff.getRowIndex()).createCell(StaffConstants.STATUS_COL);
+ statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
+ statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
+ }catch (RuntimeException ex){
+ errorCount++;
+ ex.printStackTrace();
+ errorMessage=ImportHandlerUtils.getErrorMessage(ex);
+ ImportHandlerUtils.writeErrorMessage(staffSheet,staff.getRowIndex(),errorMessage,StaffConstants.STATUS_COL);
+ }
+ }
+ staffSheet.setColumnWidth(StaffConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ ImportHandlerUtils.writeString(StaffConstants.STATUS_COL, staffSheet.getRow(0), TemplatePopulateImportConstants.STATUS_COL_REPORT_HEADER);
+ return Count.instance(successCount,errorCount);
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/users/UserImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/users/UserImportHandler.java
new file mode 100644
index 000000000..c1ec6396b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/users/UserImportHandler.java
@@ -0,0 +1,137 @@
+/**
+ * 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.importhandler.users;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.UserConstants;
+import org.apache.fineract.infrastructure.bulkimport.data.Count;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
+import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.exception.*;
+import org.apache.fineract.useradministration.data.AppUserData;
+import org.apache.poi.ss.usermodel.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+@Service
+public class UserImportHandler implements ImportHandler{
+ private Workbook workbook;
+ private List users;
+ private List statuses;
+
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+
+ @Autowired
+ public UserImportHandler(final PortfolioCommandSourceWritePlatformService
+ commandsSourceWritePlatformService) {
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ }
+
+ @Override
+ public Count process(Workbook workbook, String locale, String dateFormat) {
+ this.workbook=workbook;
+ users=new ArrayList<>();
+ statuses=new ArrayList<>();
+ readExcelFile();
+ return importEntity(dateFormat);
+ }
+
+ public void readExcelFile() {
+ Sheet usersSheet = workbook.getSheet(TemplatePopulateImportConstants.USER_SHEET_NAME);
+ Integer noOfEntries = ImportHandlerUtils.getNumberOfRows(usersSheet, TemplatePopulateImportConstants.FIRST_COLUMN_INDEX);
+ for (int rowIndex = 1; rowIndex <= noOfEntries; rowIndex++) {
+ Row row;
+ row = usersSheet.getRow(rowIndex);
+ if(ImportHandlerUtils.isNotImported(row, UserConstants.STATUS_COL)) {
+ users.add(readUsers(row));
+ }
+ }
+ }
+
+ private AppUserData readUsers(Row row) {
+ String officeName = ImportHandlerUtils.readAsString(UserConstants.OFFICE_NAME_COL, row);
+ Long officeId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME), officeName);
+ String staffName = ImportHandlerUtils.readAsString(UserConstants.STAFF_NAME_COL, row);
+ Long staffId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME), staffName);
+ String userName=ImportHandlerUtils.readAsString(UserConstants.USER_NAME_COL,row);
+ String firstName=ImportHandlerUtils.readAsString(UserConstants.FIRST_NAME_COL,row);
+ String lastName=ImportHandlerUtils.readAsString(UserConstants.LAST_NAME_COL,row);
+ String email=ImportHandlerUtils.readAsString(UserConstants.EMAIL_COL,row);
+ Boolean autoGenPw=ImportHandlerUtils.readAsBoolean(UserConstants.AUTO_GEN_PW_COL,row);
+ Boolean overridepw=ImportHandlerUtils.readAsBoolean(UserConstants.OVERRIDE_PW_EXPIRY_POLICY_COL,row);
+ String status=ImportHandlerUtils.readAsString(UserConstants.STATUS_COL,row);
+ statuses.add(status);
+
+ List rolesIds=new ArrayList<>();
+ for (int cellNo=UserConstants.ROLE_NAME_START_COL;cellNo offices, int officeNameCol,
+ int activationDateCol,String dateFormat) {
+ if(offices!=null){
+ Workbook workbook = sheet.getWorkbook();
+ CellStyle dateCellStyle = workbook.createCellStyle();
+ short df = workbook.createDataFormat().getFormat(dateFormat);
+ dateCellStyle.setDataFormat(df);
+ int rowIndex = 0;
+ for (OfficeData office : offices) {
+ Row row = sheet.createRow(++rowIndex);
+ writeString(officeNameCol, row, office.name().trim().replaceAll("[ )(]", "_"));
+ writeDate(activationDateCol, row,
+ "" + office.getOpeningDate().getDayOfMonth() + "/"
+ + office.getOpeningDate().getMonthOfYear() + "/" + office.getOpeningDate().getYear(),
+ dateCellStyle,dateFormat);
+
+ }
+ }
+ }
+
+ protected void setClientAndGroupDateLookupTable(Sheet sheet, List clients,
+ List groups, int nameCol, int activationDateCol,boolean containsClientExtId,
+ String dateFormat) {
+ Workbook workbook = sheet.getWorkbook();
+ CellStyle dateCellStyle = workbook.createCellStyle();
+ short df = workbook.createDataFormat().getFormat(dateFormat);
+ dateCellStyle.setDataFormat(df);
+ int rowIndex = 0;
+ SimpleDateFormat outputFormat = new SimpleDateFormat(dateFormat);
+ SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd");
+ Date date = null;
+ try {
+ if (clients != null){
+ for (ClientData client : clients) {
+ Row row = sheet.getRow(++rowIndex);
+ if (row == null)
+ row = sheet.createRow(rowIndex);
+ writeString(nameCol, row, client.displayName().replaceAll("[ )(] ", "_") + "(" + client.id() + ")");
+
+ if (client.getActivationDate() != null) {
+ date = inputFormat.parse(client.getActivationDate().toString());
+ writeDate(activationDateCol, row, outputFormat.format(date), dateCellStyle,dateFormat);
+ }
+ if (containsClientExtId){
+ if (client.getExternalId()!=null){
+ writeString(nameCol+1,row,client.getExternalId());
+ }
+ }
+
+ }
+ }
+ if (groups!=null){
+ for (GroupGeneralData group : groups) {
+ Row row = sheet.getRow(++rowIndex);
+ if (row == null)
+ row = sheet.createRow(rowIndex);
+ writeString(nameCol, row, group.getName().replaceAll("[ )(] ", "_"));
+
+ date = inputFormat.parse(group.getActivationDate().toString());
+ writeDate(activationDateCol, row, outputFormat.format(date), dateCellStyle,dateFormat);
+ }
+ }
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/CenterSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/CenterSheetPopulator.java
new file mode 100644
index 000000000..bf828b403
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/CenterSheetPopulator.java
@@ -0,0 +1,123 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.fineract.portfolio.group.data.CenterData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CenterSheetPopulator extends AbstractWorkbookPopulator {
+ private List allCenters;
+ private List offices;
+
+ private Map> officeToCenters;
+ private Map officeNameToBeginEndIndexesOfCenters;
+ private Map centerNameToCenterId;
+
+ private static final int OFFICE_NAME_COL = 0;
+ private static final int CENTER_NAME_COL = 1;
+ private static final int CENTER_ID_COL = 2;
+
+ public CenterSheetPopulator(List centers, List offices) {
+ this.allCenters = centers;
+ this.offices = offices;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet centerSheet = workbook.createSheet(TemplatePopulateImportConstants.CENTER_SHEET_NAME);
+ setLayout(centerSheet);
+ setOfficeToCentersMap();
+ centerNameToCenterIdMap();
+ populateCentersByOfficeName(centerSheet);
+ centerSheet.protectSheet("");
+ }
+
+ private void centerNameToCenterIdMap() {
+ centerNameToCenterId = new HashMap();
+ for (CenterData centerData : allCenters) {
+ centerNameToCenterId.put(centerData.getName(), centerData.getId());
+ }
+ }
+
+ private void populateCentersByOfficeName(Sheet centerSheet) {
+ int rowIndex = 1, officeIndex = 0, startIndex = 1;
+ officeNameToBeginEndIndexesOfCenters = new HashMap();
+ Row row = centerSheet.createRow(rowIndex);
+ for (OfficeData office : offices) {
+ startIndex = rowIndex + 1;
+ writeString(OFFICE_NAME_COL, row, office.name());
+ ArrayList centersList = new ArrayList();
+
+ if (officeToCenters.containsKey(office.name().trim().replaceAll("[ )(]", "_"))){
+ centersList = officeToCenters.get(office.name().trim().replaceAll("[ )(]", "_"));
+ if (!centersList.isEmpty()) {
+ for (String centerName : centersList) {
+ writeString(CENTER_NAME_COL, row, centerName);
+ writeLong(CENTER_ID_COL, row, centerNameToCenterId.get(centerName));
+ row = centerSheet.createRow(++rowIndex);
+ }
+ officeNameToBeginEndIndexesOfCenters.put(officeIndex++, new Integer[] { startIndex, rowIndex });
+ } else {
+ officeNameToBeginEndIndexesOfCenters.put(officeIndex++, new Integer[] { startIndex, rowIndex + 1 });
+ }
+ }
+ }
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ for (int colIndex = 0; colIndex <= 10; colIndex++)
+ worksheet.setColumnWidth(colIndex, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(OFFICE_NAME_COL, rowHeader, "Office Names");
+ writeString(CENTER_NAME_COL, rowHeader, "Center Names");
+ writeString(CENTER_ID_COL, rowHeader, "Center ID");
+ }
+
+ private void setOfficeToCentersMap() {
+ officeToCenters = new HashMap<>();
+ for (CenterData center : allCenters) {
+ add(center.getOfficeName().trim().replaceAll("[ )(]", "_"), center.getName().trim());
+ }
+ }
+
+ // Guava Multi-map can reduce this.
+ private void add(String key, String value) {
+ ArrayList values = officeToCenters.get(key);
+ if (values == null) {
+ values = new ArrayList<>();
+ }
+ values.add(value);
+ officeToCenters.put(key, values);
+ }
+
+ public Map getOfficeNameToBeginEndIndexesOfCenters() {
+ return officeNameToBeginEndIndexesOfCenters;
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ClientSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ClientSheetPopulator.java
new file mode 100644
index 000000000..69c4ba4d8
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ClientSheetPopulator.java
@@ -0,0 +1,144 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ClientSheetPopulator extends AbstractWorkbookPopulator {
+ private List allClients;
+ private List officesDataList;
+
+ private Map> officeToClients;
+ private Map officeNameToBeginEndIndexesOfClients;
+ private Map clientNameToClientId;
+ private Map clientNameToSavingsAccountIds;
+
+ private static final int OFFICE_NAME_COL = 0;
+ private static final int CLIENT_NAME_COL = 1;
+ private static final int CLIENT_ID_COL = 2;
+
+ public ClientSheetPopulator(final List clients, final List Offices) {
+ this.allClients = clients;
+ this.officesDataList = Offices;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet clientSheet = workbook.createSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME);
+ setLayout(clientSheet);
+ setOfficeToClientsMap();
+ setClientNameToClientIdMap();
+ populateClientsByOfficeName(clientSheet);
+ clientSheet.protectSheet("");
+ setClientNameToSavingsAccountsIdsMap();
+ }
+
+ private void setClientNameToClientIdMap() {
+ clientNameToClientId = new HashMap<>();
+ for (ClientData clientData : allClients) {
+ clientNameToClientId.put(clientData.displayName().trim() + "(" + clientData.id() + ")",
+ clientData.id());
+ }
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ for (int colIndex = 1; colIndex <= 10; colIndex++)
+ worksheet.setColumnWidth(colIndex, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(OFFICE_NAME_COL, rowHeader, "Office Names");
+ writeString(CLIENT_NAME_COL, rowHeader, "Client Names");
+ writeString(CLIENT_ID_COL, rowHeader, "Client ID");
+ }
+
+ private void setOfficeToClientsMap() {
+ officeToClients = new HashMap<>();
+ for (ClientData person : allClients) {
+ addToOfficeClientMap(person.getOfficeName().trim().replaceAll("[ )(]", "_"),
+ person.displayName().trim() + "(" + person.id() + ")");
+ }
+ }
+
+ private void setClientNameToSavingsAccountsIdsMap(){
+ clientNameToSavingsAccountIds=new HashMap<>();
+ for (ClientData client: allClients) {
+ clientNameToSavingsAccountIds.put(client.displayName().trim() + "(" + client.id() + ")",client.getSavingsAccountId());
+ }
+
+ }
+
+ // Guava Multi-map can reduce this.
+ private void addToOfficeClientMap(String key, String value) {
+ ArrayList values = officeToClients.get(key);
+ if (values == null) {
+ values = new ArrayList();
+ }
+ values.add(value);
+ officeToClients.put(key, values);
+ }
+
+ private void populateClientsByOfficeName(Sheet clientSheet) {
+ int rowIndex = 1, startIndex = 1, officeIndex = 0;
+ officeNameToBeginEndIndexesOfClients = new HashMap<>();
+ Row row = clientSheet.createRow(rowIndex);
+ for (OfficeData office : officesDataList) {
+ startIndex = rowIndex + 1;
+ writeString(OFFICE_NAME_COL, row, office.name());
+ ArrayList clientList = new ArrayList();
+ if (officeToClients.containsKey(office.name().trim().replaceAll("[ )(]", "_")))
+ clientList = officeToClients.get(office.name().trim().replaceAll("[ )(]", "_"));
+ if (!clientList.isEmpty()) {
+ for (String clientName : clientList) {
+ writeString(CLIENT_NAME_COL, row, clientName);
+ writeLong(CLIENT_ID_COL, row, clientNameToClientId.get(clientName));
+ row = clientSheet.createRow(++rowIndex);
+ }
+ officeNameToBeginEndIndexesOfClients.put(officeIndex++, new Integer[] { startIndex, rowIndex });
+ } else
+ officeIndex++;
+ }
+ }
+
+ public List getClients() {
+ return allClients;
+ }
+
+ public Integer getClientsSize() {
+ return allClients.size();
+ }
+
+ public Map getOfficeNameToBeginEndIndexesOfClients() {
+ return officeNameToBeginEndIndexesOfClients;
+ }
+
+ public Map getClientNameToSavingsAccountIds() {
+ return clientNameToSavingsAccountIds;
+ }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ExtrasSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ExtrasSheetPopulator.java
new file mode 100644
index 000000000..e97eb7aeb
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ExtrasSheetPopulator.java
@@ -0,0 +1,116 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.fineract.portfolio.fund.data.FundData;
+import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.List;
+
+public class ExtrasSheetPopulator extends AbstractWorkbookPopulator {
+
+ private List funds;
+ private List paymentTypes;
+ private List currencies;
+
+ private static final int FUND_ID_COL = 0;
+ private static final int FUND_NAME_COL = 1;
+ private static final int PAYMENT_TYPE_ID_COL = 2;
+ private static final int PAYMENT_TYPE_NAME_COL = 3;
+ private static final int CURRENCY_CODE_COL = 4;
+ private static final int CURRENCY_NAME_COL = 5;
+
+
+ public ExtrasSheetPopulator(List funds, List paymentTypes,
+ List currencies) {
+ this.funds = funds;
+ this.paymentTypes = paymentTypes;
+ this.currencies = currencies;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ int fundRowIndex = 1;
+ Sheet extrasSheet = workbook.createSheet(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME);
+ setLayout(extrasSheet);
+ for (FundData fund : funds) {
+ Row row = extrasSheet.createRow(fundRowIndex++);
+ writeLong(FUND_ID_COL, row, fund.getId());
+ writeString(FUND_NAME_COL, row, fund.getName());
+ }
+ int paymentTypeRowIndex = 1;
+ for (PaymentTypeData paymentType : paymentTypes) {
+ Row row;
+ if (paymentTypeRowIndex < fundRowIndex)
+ row = extrasSheet.getRow(paymentTypeRowIndex++);
+ else
+ row = extrasSheet.createRow(paymentTypeRowIndex++);
+ writeLong(PAYMENT_TYPE_ID_COL, row, paymentType.getId());
+ writeString(PAYMENT_TYPE_NAME_COL, row, paymentType.getName().trim().replaceAll("[ )(]", "_"));
+ }
+ int currencyCodeRowIndex = 1;
+ for (CurrencyData currencies : currencies) {
+ Row row;
+ if (currencyCodeRowIndex < paymentTypeRowIndex)
+ row = extrasSheet.getRow(currencyCodeRowIndex++);
+ else
+ row = extrasSheet.createRow(currencyCodeRowIndex++);
+
+ writeString(CURRENCY_NAME_COL, row, currencies.getName().trim().replaceAll("[ )(]", "_"));
+ writeString(CURRENCY_CODE_COL, row, currencies.code());
+ }
+ extrasSheet.protectSheet("");
+
+ }
+
+ private void setLayout(Sheet worksheet) {
+ worksheet.setColumnWidth(FUND_ID_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(FUND_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(PAYMENT_TYPE_ID_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(PAYMENT_TYPE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(CURRENCY_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(CURRENCY_CODE_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ writeString(FUND_ID_COL, rowHeader, "Fund ID");
+ writeString(FUND_NAME_COL, rowHeader, "Name");
+ writeString(PAYMENT_TYPE_ID_COL, rowHeader, "Payment Type ID");
+ writeString(PAYMENT_TYPE_NAME_COL, rowHeader, "Payment Type Name");
+ writeString(CURRENCY_NAME_COL, rowHeader, "Currency Type ");
+ writeString(CURRENCY_CODE_COL, rowHeader, "Currency Code ");
+ }
+ public Integer getFundsSize() {
+ return funds.size();
+ }
+ public Integer getPaymentTypesSize() {
+ return paymentTypes.size();
+ }
+
+ public Integer getCurrenciesSize() {
+ return currencies.size();
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/FixedDepositProductSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/FixedDepositProductSheetPopulator.java
new file mode 100644
index 000000000..0e2185b39
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/FixedDepositProductSheetPopulator.java
@@ -0,0 +1,173 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.fineract.portfolio.savings.data.FixedDepositProductData;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.List;
+
+public class FixedDepositProductSheetPopulator extends AbstractWorkbookPopulator {
+ List products;
+
+ private static final int ID_COL = 0;
+ private static final int NAME_COL = 1;
+ private static final int SHORT_NAME_COL = 2;
+ private static final int NOMINAL_ANNUAL_INTEREST_RATE_COL = 3;
+ private static final int INTEREST_COMPOUNDING_PERIOD_COL = 4;
+ private static final int INTEREST_POSTING_PERIOD_COL = 5;
+ private static final int INTEREST_CALCULATION_COL = 6;
+ private static final int INTEREST_CALCULATION_DAYS_IN_YEAR_COL = 7;
+ private static final int LOCKIN_PERIOD_COL = 8;
+ private static final int LOCKIN_PERIOD_FREQUENCY_COL = 9;
+ private static final int CURRENCY_COL = 10;
+ private static final int MIN_DEPOSIT_COL = 11;
+ private static final int MAX_DEPOSIT_COL = 12;
+ private static final int DEPOSIT_COL = 13;
+ private static final int MIN_DEPOSIT_TERM_COL = 14;
+ private static final int MIN_DEPOSIT_TERM_TYPE_COL = 15;
+ private static final int MAX_DEPOSIT_TERM_COL = 16;
+ private static final int MAX_DEPOSIT_TERM_TYPE_COL = 17;
+ private static final int PRECLOSURE_PENAL_APPLICABLE_COL = 18;
+ private static final int PRECLOSURE_PENAL_INTEREST_COL = 19;
+ private static final int PRECLOSURE_INTEREST_TYPE_COL = 20;
+ private static final int IN_MULTIPLES_OF_DEPOSIT_TERM_COL = 21;
+ private static final int IN_MULTIPLES_OF_DEPOSIT_TERM_TYPE_COL = 22;
+
+ public FixedDepositProductSheetPopulator(List fixedDepositProducts) {
+ this.products =fixedDepositProducts;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ int rowIndex = 1;
+ Sheet productSheet = workbook.createSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME);
+ setLayout(productSheet);
+ CellStyle dateCellStyle = workbook.createCellStyle();
+ short df = workbook.createDataFormat().getFormat(dateFormat);
+ dateCellStyle.setDataFormat(df);
+ for(FixedDepositProductData product : products) {
+ Row row = productSheet.createRow(rowIndex++);
+ writeLong(ID_COL, row, product.getId());
+ writeString(NAME_COL, row, product.getName().trim().replaceAll("[ )(]", "_"));
+ writeString(SHORT_NAME_COL, row, product.getShortName().trim().replaceAll("[ )(]", "_"));
+ writeBigDecimal(NOMINAL_ANNUAL_INTEREST_RATE_COL, row, product.getNominalAnnualInterestRate());
+ writeString(INTEREST_COMPOUNDING_PERIOD_COL, row, product.getInterestCompoundingPeriodType().getValue());
+ writeString(INTEREST_POSTING_PERIOD_COL, row, product.getInterestPostingPeriodType().getValue());
+ writeString(INTEREST_CALCULATION_COL, row, product.getInterestCalculationType().getValue());
+ writeString(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, row, product.getInterestCalculationDaysInYearType().getValue());
+
+ writeBoolean(PRECLOSURE_PENAL_APPLICABLE_COL, row, product.isPreClosurePenalApplicable());
+ writeInt(MIN_DEPOSIT_TERM_COL, row, product.getMinDepositTerm());
+ writeString(MIN_DEPOSIT_TERM_TYPE_COL, row, product.getMinDepositTermType().getValue());
+
+ if(product.getMinDepositAmount() != null)
+ writeBigDecimal(MIN_DEPOSIT_COL, row, product.getMinDepositAmount());
+ if(product.getMaxDepositAmount() != null)
+ writeBigDecimal(MAX_DEPOSIT_COL, row, product.getMaxDepositAmount());
+ if(product.getDepositAmount() != null)
+ writeBigDecimal(DEPOSIT_COL, row, product.getDepositAmount());
+ if(product.getMaxDepositTerm() != null)
+ writeInt(MAX_DEPOSIT_TERM_COL, row, product.getMaxDepositTerm());
+ if(product.getInMultiplesOfDepositTerm() != null)
+ writeInt(IN_MULTIPLES_OF_DEPOSIT_TERM_COL, row, product.getInMultiplesOfDepositTerm());
+ if(product.getPreClosurePenalInterest() != null)
+ writeBigDecimal(PRECLOSURE_PENAL_INTEREST_COL, row, product.getPreClosurePenalInterest());
+ if(product.getMaxDepositTermType() != null)
+ writeString(MAX_DEPOSIT_TERM_TYPE_COL, row, product.getMaxDepositTermType().getValue());
+ if(product.getPreClosurePenalInterestOnType() != null)
+ writeString(PRECLOSURE_INTEREST_TYPE_COL, row, product.getPreClosurePenalInterestOnType().getValue());
+ if(product.getInMultiplesOfDepositTermType() != null)
+ writeString(IN_MULTIPLES_OF_DEPOSIT_TERM_TYPE_COL, row, product.getInMultiplesOfDepositTermType().getValue());
+
+ if(product.getLockinPeriodFrequency() != null)
+ writeInt(LOCKIN_PERIOD_COL, row, product.getLockinPeriodFrequency());
+ if(product.getLockinPeriodFrequencyType() != null)
+ writeString(LOCKIN_PERIOD_FREQUENCY_COL, row, product.getLockinPeriodFrequencyType().getValue());
+ CurrencyData currency = product.getCurrency();
+ writeString(CURRENCY_COL, row, currency.code());
+ }
+ productSheet.protectSheet("");
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(SHORT_NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(NOMINAL_ANNUAL_INTEREST_RATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_COMPOUNDING_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_POSTING_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_CALCULATION_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(LOCKIN_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(LOCKIN_PERIOD_FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CURRENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_DEPOSIT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_DEPOSIT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(DEPOSIT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_DEPOSIT_TERM_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_DEPOSIT_TERM_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_DEPOSIT_TERM_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_DEPOSIT_TERM_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(PRECLOSURE_PENAL_APPLICABLE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(PRECLOSURE_PENAL_INTEREST_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(PRECLOSURE_INTEREST_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(IN_MULTIPLES_OF_DEPOSIT_TERM_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(IN_MULTIPLES_OF_DEPOSIT_TERM_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+
+ writeString(ID_COL, rowHeader, "ID");
+ writeString(NAME_COL, rowHeader, "Name");
+ writeString(SHORT_NAME_COL, rowHeader, "Short Name");
+ writeString(NOMINAL_ANNUAL_INTEREST_RATE_COL, rowHeader, "Interest");
+ writeString(INTEREST_COMPOUNDING_PERIOD_COL, rowHeader, "Interest Compounding Period");
+ writeString(INTEREST_POSTING_PERIOD_COL, rowHeader, "Interest Posting Period");
+ writeString(INTEREST_CALCULATION_COL, rowHeader, "Interest Calculated Using");
+ writeString(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, rowHeader, "# Days In Year");
+ writeString(LOCKIN_PERIOD_COL, rowHeader, "Locked In For");
+ writeString(LOCKIN_PERIOD_FREQUENCY_COL, rowHeader, "Frequency");
+ writeString(CURRENCY_COL, rowHeader, "Currency");
+ writeString(MIN_DEPOSIT_COL, rowHeader, "Min Deposit");
+ writeString(MAX_DEPOSIT_COL, rowHeader, "Max Deposit");
+ writeString(DEPOSIT_COL, rowHeader, "Deposit");
+ writeString(MIN_DEPOSIT_TERM_COL, rowHeader, "Min Deposit Term");
+ writeString(MAX_DEPOSIT_TERM_COL, rowHeader, "Max Deposit Term");
+ writeString(MIN_DEPOSIT_TERM_TYPE_COL, rowHeader, "Min Deposit Term Type");
+ writeString(MAX_DEPOSIT_TERM_TYPE_COL, rowHeader, "Max Deposit Term Type");
+ writeString(PRECLOSURE_PENAL_APPLICABLE_COL, rowHeader, "Preclosure Penal Applicable");
+ writeString(PRECLOSURE_PENAL_INTEREST_COL, rowHeader, "Penal Interest");
+ writeString(PRECLOSURE_INTEREST_TYPE_COL, rowHeader, "Penal Interest Type");
+ writeString(IN_MULTIPLES_OF_DEPOSIT_TERM_COL, rowHeader, "Multiples of Deposit Term");
+ writeString(IN_MULTIPLES_OF_DEPOSIT_TERM_TYPE_COL, rowHeader, "Multiples of Deposit Term Type");
+ }
+
+ public List getProducts() {
+ return products;
+ }
+
+ public Integer getProductsSize() {
+ return products.size();
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/GlAccountSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/GlAccountSheetPopulator.java
new file mode 100644
index 000000000..04390c1af
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/GlAccountSheetPopulator.java
@@ -0,0 +1,71 @@
+/**
+ * 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 org.apache.fineract.accounting.glaccount.data.GLAccountData;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.List;
+
+public class GlAccountSheetPopulator extends AbstractWorkbookPopulator {
+ private List allGlAccounts;
+
+ private static final int ID_COL = 0;
+ private static final int ACCOUNT_NAME_COL = 1;
+
+ public GlAccountSheetPopulator(List glAccounts) {
+ this.allGlAccounts = glAccounts;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ int rowIndex = 1;
+ Sheet glAccountSheet = workbook.createSheet(TemplatePopulateImportConstants.GL_ACCOUNTS_SHEET_NAME);
+ setLayout(glAccountSheet);
+ populateglAccounts(glAccountSheet, rowIndex);
+ glAccountSheet.protectSheet("");
+
+ }
+
+ private void setLayout(Sheet worksheet) {
+ worksheet.setColumnWidth(ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ACCOUNT_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ writeString(ID_COL, rowHeader, "Gl Account ID");
+ writeString(ACCOUNT_NAME_COL, rowHeader, "Gl Account Name");
+ }
+
+ private void populateglAccounts(Sheet GlAccountSheet, int rowIndex) {
+ for (GLAccountData glAccount : allGlAccounts) {
+ Row row = GlAccountSheet.createRow(rowIndex);
+ writeLong(ID_COL, row, glAccount.getId());
+ writeString(ACCOUNT_NAME_COL, row, glAccount.getName().trim().replaceAll("[ )(]", "_"));
+ rowIndex++;
+ }
+ }
+
+ public Integer getGlAccountNamesSize() {
+ return allGlAccounts.size();
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/GroupSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/GroupSheetPopulator.java
new file mode 100644
index 000000000..4d6e1b38d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/GroupSheetPopulator.java
@@ -0,0 +1,126 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.fineract.portfolio.group.data.GroupGeneralData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+public class GroupSheetPopulator extends AbstractWorkbookPopulator {
+ private List groups;
+ private List offices;
+
+ private Map> officeToGroups;
+ private Map officeNameToBeginEndIndexesOfGroups;
+ private Map groupNameToGroupId;
+
+ private static final int OFFICE_NAME_COL = 0;
+ private static final int GROUP_NAME_COL = 1;
+ private static final int GROUP_ID_COL = 2;
+
+ public GroupSheetPopulator(final List groups, final List offices) {
+ this.groups = groups;
+ this.offices = offices;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet groupSheet = workbook.createSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME);
+ setLayout(groupSheet);
+ setGroupNameToGroupIdMap();
+ setOfficeToGroupsMap();
+ populateGroupsByOfficeName(groupSheet);
+ groupSheet.protectSheet("");
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ for (int colIndex = 0; colIndex <= 10; colIndex++)
+ worksheet.setColumnWidth(colIndex, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(OFFICE_NAME_COL, rowHeader, "Office Names");
+ writeString(GROUP_NAME_COL, rowHeader, "Group Names");
+ writeString(GROUP_ID_COL, rowHeader, "Group ID");
+ }
+
+ private void setOfficeToGroupsMap() {
+ officeToGroups = new HashMap<>();
+ for (GroupGeneralData group : groups) {
+ add(group.getOfficeName().trim().replaceAll("[ )(]", "_"), group.getName().trim());
+ }
+ }
+ //Guava Multi-map can reduce this.
+ private void add(String key, String value) {
+ ArrayList values = officeToGroups.get(key);
+ if (values == null) {
+ values = new ArrayList<>();
+ }
+ values.add(value);
+ officeToGroups.put(key, values);
+ }
+ private void populateGroupsByOfficeName(Sheet groupSheet) {
+ int rowIndex = 1, officeIndex = 0, startIndex = 1;
+ officeNameToBeginEndIndexesOfGroups = new HashMap<>();
+ Row row = groupSheet.createRow(rowIndex);
+ for(OfficeData office : offices) {
+ startIndex = rowIndex+1;
+ writeString(OFFICE_NAME_COL, row, office.name());
+ ArrayList groupsList = new ArrayList<>();
+
+ if(officeToGroups.containsKey(office.name().trim().replaceAll("[ )(]", "_")))
+ groupsList = officeToGroups.get(office.name().trim().replaceAll("[ )(]", "_"));
+
+ if(!groupsList.isEmpty()) {
+ for(String groupName : groupsList) {
+ writeString(GROUP_NAME_COL, row, groupName);
+ writeLong(GROUP_ID_COL, row, groupNameToGroupId.get(groupName));
+ row = groupSheet.createRow(++rowIndex);
+ }
+ officeNameToBeginEndIndexesOfGroups.put(officeIndex++, new Integer[]{startIndex, rowIndex});
+ }
+ else {
+ officeNameToBeginEndIndexesOfGroups.put(officeIndex++, new Integer[]{startIndex, rowIndex+1});
+ }
+ }
+ }
+ public List getGroups() {
+ return groups;
+ }
+ public Integer getGroupsSize() {
+ return groups.size();
+ }
+ public Map getOfficeNameToBeginEndIndexesOfGroups() {
+ return officeNameToBeginEndIndexesOfGroups;
+ }
+ private void setGroupNameToGroupIdMap(){
+ groupNameToGroupId=new HashMap();
+ for (GroupGeneralData group : groups) {
+ groupNameToGroupId.put(group.getName().trim(), group.getId());
+ }
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 000000000..93de8841d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/LoanProductSheetPopulator.java
@@ -0,0 +1,199 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.List;
+
+
+public class LoanProductSheetPopulator extends AbstractWorkbookPopulator {
+
+ private List products;
+
+ private static final int ID_COL = 0;
+ private static final int NAME_COL = 1;
+ private static final int FUND_NAME_COL = 2;
+ private static final int PRINCIPAL_COL = 3;
+ private static final int MIN_PRINCIPAL_COL = 4;
+ private static final int MAX_PRINCIPAL_COL = 5;
+ private static final int NO_OF_REPAYMENTS_COL = 6;
+ private static final int MIN_REPAYMENTS_COL = 7;
+ private static final int MAX_REPAYMENTS_COL = 8;
+ private static final int REPAYMENT_EVERY_COL = 9;
+ private static final int REPAYMENT_FREQUENCY_COL = 10;
+ private static final int INTEREST_RATE_COL = 11;
+ private static final int MIN_INTEREST_RATE_COL = 12;
+ private static final int MAX_INTEREST_RATE_COL = 13;
+ private static final int INTEREST_RATE_FREQUENCY_COL = 14;
+ private static final int AMORTIZATION_TYPE_COL = 15;
+ private static final int INTEREST_TYPE_COL = 16;
+ private static final int INTEREST_CALCULATION_PERIOD_TYPE_COL = 17;
+ private static final int IN_ARREARS_TOLERANCE_COL = 18;
+ private static final int TRANSACTION_PROCESSING_STRATEGY_NAME_COL = 19;
+ private static final int GRACE_ON_PRINCIPAL_PAYMENT_COL = 20;
+ private static final int GRACE_ON_INTEREST_PAYMENT_COL = 21;
+ private static final int GRACE_ON_INTEREST_CHARGED_COL = 22;
+ private static final int START_DATE_COL = 23;
+ private static final int CLOSE_DATE_COL = 24;
+
+
+
+ public LoanProductSheetPopulator(List products) {
+ this.products = products;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ int rowIndex = 1;
+ Sheet productSheet = workbook.createSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME);
+ setLayout(productSheet);
+ CellStyle dateCellStyle = workbook.createCellStyle();
+ short df = workbook.createDataFormat().getFormat(dateFormat);
+ dateCellStyle.setDataFormat(df);
+ for (LoanProductData product : products) {
+ Row row = productSheet.createRow(rowIndex++);
+ writeLong(ID_COL, row, product.getId());
+ writeString(NAME_COL, row, product.getName().trim().replaceAll("[ )(]", "_"));
+ if (product.getFundName() != null)
+ writeString(FUND_NAME_COL, row, product.getFundName());
+ writeBigDecimal(PRINCIPAL_COL, row, product.getPrincipal());
+ if (product.getMinPrincipal() != null)
+ writeBigDecimal(MIN_PRINCIPAL_COL, row, product.getMinPrincipal());
+ else
+ writeInt(MIN_PRINCIPAL_COL, row, 1);
+ if (product.getMaxPrincipal() != null)
+ writeBigDecimal(MAX_PRINCIPAL_COL, row, product.getMaxPrincipal());
+ else
+ writeInt(MAX_PRINCIPAL_COL, row, 999999999);
+ writeInt(NO_OF_REPAYMENTS_COL, row, product.getNumberOfRepayments());
+ if (product.getMinNumberOfRepayments() != null)
+ writeInt(MIN_REPAYMENTS_COL, row, product.getMinNumberOfRepayments());
+ else
+ writeInt(MIN_REPAYMENTS_COL, row, 1);
+ if (product.getMaxNumberOfRepayments() != null)
+ writeInt(MAX_REPAYMENTS_COL, row, product.getMaxNumberOfRepayments());
+ else
+ writeInt(MAX_REPAYMENTS_COL, row, 999999999);
+ writeInt(REPAYMENT_EVERY_COL, row, product.getRepaymentEvery());
+ writeString(REPAYMENT_FREQUENCY_COL, row, product.getRepaymentFrequencyType().getValue());
+ writeBigDecimal(INTEREST_RATE_COL, row, product.getInterestRatePerPeriod());
+ if (product.getMinInterestRatePerPeriod() != null)
+ writeBigDecimal(MIN_INTEREST_RATE_COL, row, product.getMinInterestRatePerPeriod());
+ else
+ writeInt(MIN_INTEREST_RATE_COL, row, 1);
+ if (product.getMaxInterestRatePerPeriod() != null)
+ writeBigDecimal(MAX_INTEREST_RATE_COL, row, product.getMaxInterestRatePerPeriod());
+ else
+ writeInt(MAX_INTEREST_RATE_COL, row, 999999999);
+ writeString(INTEREST_RATE_FREQUENCY_COL, row, product.getInterestRateFrequencyType().getValue());
+ writeString(AMORTIZATION_TYPE_COL, row, product.getAmortizationType().getValue());
+ writeString(INTEREST_TYPE_COL, row, product.getInterestType().getValue());
+ writeString(INTEREST_CALCULATION_PERIOD_TYPE_COL, row,
+ product.getInterestCalculationPeriodType().getValue());
+ if (product.getInArrearsTolerance() != null)
+ writeBigDecimal(IN_ARREARS_TOLERANCE_COL, row, product.getInArrearsTolerance());
+ writeString(TRANSACTION_PROCESSING_STRATEGY_NAME_COL, row, product.getTransactionProcessingStrategyName());
+ if (product.getGraceOnPrincipalPayment() != null)
+ writeInt(GRACE_ON_PRINCIPAL_PAYMENT_COL, row, product.getGraceOnPrincipalPayment());
+ if (product.getGraceOnInterestPayment() != null)
+ writeInt(GRACE_ON_INTEREST_PAYMENT_COL, row, product.getGraceOnInterestPayment());
+ if (product.getGraceOnInterestCharged() != null)
+ writeInt(GRACE_ON_INTEREST_CHARGED_COL, row, product.getGraceOnInterestCharged());
+ if (product.getStartDate() != null)
+ writeDate(START_DATE_COL, row, product.getStartDate().toString(), dateCellStyle,dateFormat);
+ else
+ writeDate(START_DATE_COL, row, "1/1/1970", dateCellStyle,dateFormat);
+ if (product.getCloseDate() != null)
+ writeDate(CLOSE_DATE_COL, row, product.getCloseDate().toString(), dateCellStyle,dateFormat);
+ else
+ writeDate(CLOSE_DATE_COL, row, "1/1/2040", dateCellStyle,dateFormat);
+ productSheet.protectSheet("");
+ }
+
+ }
+
+ private void setLayout(Sheet worksheet) {
+ worksheet.setColumnWidth(ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FUND_NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(PRINCIPAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_PRINCIPAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_PRINCIPAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(NO_OF_REPAYMENTS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_REPAYMENTS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_REPAYMENTS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(REPAYMENT_EVERY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(REPAYMENT_FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_RATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_INTEREST_RATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_INTEREST_RATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_RATE_FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(AMORTIZATION_TYPE_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_CALCULATION_PERIOD_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(IN_ARREARS_TOLERANCE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(TRANSACTION_PROCESSING_STRATEGY_NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GRACE_ON_PRINCIPAL_PAYMENT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GRACE_ON_INTEREST_PAYMENT_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(GRACE_ON_INTEREST_CHARGED_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(START_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CLOSE_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ writeString(ID_COL, rowHeader, "ID");
+ writeString(NAME_COL, rowHeader, "Name");
+ writeString(FUND_NAME_COL, rowHeader, "Fund");
+ writeString(PRINCIPAL_COL, rowHeader, "Principal");
+ writeString(MIN_PRINCIPAL_COL, rowHeader, "Min Principal");
+ writeString(MAX_PRINCIPAL_COL, rowHeader, "Max Principal");
+ writeString(NO_OF_REPAYMENTS_COL, rowHeader, "# of Repayments");
+ writeString(MIN_REPAYMENTS_COL, rowHeader, "Min Repayments");
+ writeString(MAX_REPAYMENTS_COL, rowHeader, "Max Repayments");
+ writeString(REPAYMENT_EVERY_COL, rowHeader, "Repayment Every");
+ writeString(REPAYMENT_FREQUENCY_COL, rowHeader, "Frequency");
+ writeString(INTEREST_RATE_COL, rowHeader, "Interest");
+ writeString(MIN_INTEREST_RATE_COL, rowHeader, "Min Interest");
+ writeString(MAX_INTEREST_RATE_COL, rowHeader, "Max Interest");
+ writeString(INTEREST_RATE_FREQUENCY_COL, rowHeader, "Frequency");
+ writeString(AMORTIZATION_TYPE_COL, rowHeader, "Amortization Type");
+ writeString(INTEREST_TYPE_COL, rowHeader, "Interest Type");
+ writeString(INTEREST_CALCULATION_PERIOD_TYPE_COL, rowHeader, "Interest Calculation Period");
+ writeString(IN_ARREARS_TOLERANCE_COL, rowHeader, "In Arrears Tolerance");
+ writeString(TRANSACTION_PROCESSING_STRATEGY_NAME_COL, rowHeader, "Transaction Processing Strategy");
+ writeString(GRACE_ON_PRINCIPAL_PAYMENT_COL, rowHeader, "Grace On Principal Payment");
+ writeString(GRACE_ON_INTEREST_PAYMENT_COL, rowHeader, "Grace on Interest Payment");
+ writeString(GRACE_ON_INTEREST_CHARGED_COL, rowHeader, "Grace on Interest Charged");
+ writeString(START_DATE_COL, rowHeader, "Start Date");
+ writeString(CLOSE_DATE_COL, rowHeader, "End Date");
+ }
+ public List getProducts(){
+ return products;
+
+ }
+ public Integer getProductsSize() {
+ return products.size();
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/OfficeSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/OfficeSheetPopulator.java
new file mode 100644
index 000000000..a2ff62070
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/OfficeSheetPopulator.java
@@ -0,0 +1,82 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class OfficeSheetPopulator extends AbstractWorkbookPopulator {
+
+ private List offices;
+
+ private static final int ID_COL = 0;
+ private static final int OFFICE_NAME_COL = 1;
+
+ public OfficeSheetPopulator(final List offices) {
+ this.offices = offices;
+ }
+
+
+ @Override
+ public void populate(final Workbook workbook,String dateFormat) {
+ int rowIndex = 1;
+ Sheet officeSheet = workbook.createSheet(TemplatePopulateImportConstants.OFFICE_SHEET_NAME);
+ setLayout(officeSheet);
+
+ populateOffices(officeSheet, rowIndex);
+ officeSheet.protectSheet("");
+ }
+
+ private void populateOffices(Sheet officeSheet, int rowIndex) {
+ for (OfficeData office : offices) {
+ Row row = officeSheet.createRow(rowIndex);
+ writeLong(ID_COL, row, office.getId());
+ writeString(OFFICE_NAME_COL, row, office.name().trim().replaceAll("[ )(]", "_"));
+ rowIndex++;
+ }
+ }
+
+ private void setLayout(Sheet worksheet) {
+ worksheet.setColumnWidth(ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ writeString(ID_COL, rowHeader, "ID");
+ writeString(OFFICE_NAME_COL, rowHeader, "Name");
+ }
+
+ public List getOffices() {
+ return offices;
+ }
+
+ public List getOfficeNames() {
+ List officeNames=new ArrayList<>();
+ for (OfficeData office : offices) {
+ officeNames.add(office.name());
+ }
+ return officeNames;
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/PersonnelSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/PersonnelSheetPopulator.java
new file mode 100644
index 000000000..2894616bc
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/PersonnelSheetPopulator.java
@@ -0,0 +1,131 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.fineract.organisation.staff.data.StaffData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+//import org.apache.commons.collections.CollectionUtils;
+
+public class PersonnelSheetPopulator extends AbstractWorkbookPopulator {
+
+ private List personnel;
+ private List offices;
+
+ // Maintaining the one to many relationship
+ private Map> officeToPersonnel;
+
+ /*
+ * Guava Multimap would make this more readable. The value Integer[] contains the beginIndex and
+ * endIndex for the staff list of each office. Required for applying names in excel.
+ */
+ private Map officeNameToBeginEndIndexesOfStaff;
+
+ private static final int OFFICE_NAME_COL = 0;
+ private static final int STAFF_NAME_COL = 1;
+ private static final int STAFF_ID_COL = 2;
+
+ public PersonnelSheetPopulator(List personnel, List offices) {
+ this.personnel = personnel;
+ this.offices = offices;
+ }
+
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet staffSheet = workbook.createSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME);
+ setLayout(staffSheet);
+
+ /*
+ * This piece of code could have been avoided by making multiple trips to the database for the
+ * staff of each office but this is more performance efficient
+ */
+ setOfficeToPersonnelMap();
+
+ populateStaffByOfficeName(staffSheet);
+ staffSheet.protectSheet("");
+ }
+
+
+ private void populateStaffByOfficeName(Sheet staffSheet) {
+ int rowIndex = 1, startIndex = 1, officeIndex = 0;
+ officeNameToBeginEndIndexesOfStaff = new HashMap<>();
+ Row row = staffSheet.createRow(rowIndex);
+ for (OfficeData office : offices) {
+ startIndex = rowIndex + 1;
+ writeString(OFFICE_NAME_COL, row, office.name().trim().replaceAll("[ )(]", "_"));
+
+ List staffList =
+ officeToPersonnel.get(office.name().trim().replaceAll("[ )(]", "_"));
+
+ if (staffList!=null){
+ if (!staffList.isEmpty()) {
+ for (StaffData staff : staffList) {
+ writeString(STAFF_NAME_COL, row, staff.getDisplayName());
+ writeLong(STAFF_ID_COL, row, staff.getId());
+ row = staffSheet.createRow(++rowIndex);
+ }
+ officeNameToBeginEndIndexesOfStaff.put(officeIndex++, new Integer[]{startIndex, rowIndex});
+ }
+ }else
+ officeIndex++;
+ }
+ }
+
+ private void setOfficeToPersonnelMap() {
+ officeToPersonnel = new HashMap<>();
+ for (StaffData person : personnel) {
+ add(person.getOfficeName().trim().replaceAll("[ )(]", "_"), person);
+ }
+ }
+
+ // Guava Multi-map can reduce this.
+ private void add(String key, StaffData value) {
+ List values = officeToPersonnel.get(key);
+ if (values == null) {
+ values = new ArrayList<>();
+ }
+ values.add(value);
+ officeToPersonnel.put(key, values);
+ }
+
+ private void setLayout(Sheet worksheet) {
+ for (Integer i = 0; i < 3; i++)
+ worksheet.setColumnWidth(i, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ writeString(OFFICE_NAME_COL, rowHeader, "Office Name");
+ writeString(STAFF_NAME_COL, rowHeader, "Staff List");
+ writeString(STAFF_ID_COL, rowHeader, "Staff ID");
+ }
+
+ public Map getOfficeNameToBeginEndIndexesOfStaff() {
+ return officeNameToBeginEndIndexesOfStaff;
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/RecurringDepositProductSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/RecurringDepositProductSheetPopulator.java
new file mode 100644
index 000000000..32af96db5
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/RecurringDepositProductSheetPopulator.java
@@ -0,0 +1,190 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.fineract.portfolio.savings.data.RecurringDepositProductData;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.List;
+
+public class RecurringDepositProductSheetPopulator extends AbstractWorkbookPopulator {
+
+ private List products;
+
+ private static final int ID_COL = 0;
+ private static final int NAME_COL = 1;
+ private static final int SHORT_NAME_COL = 2;
+ private static final int NOMINAL_ANNUAL_INTEREST_RATE_COL = 3;
+ private static final int INTEREST_COMPOUNDING_PERIOD_COL = 4;
+ private static final int INTEREST_POSTING_PERIOD_COL = 5;
+ private static final int INTEREST_CALCULATION_COL = 6;
+ private static final int INTEREST_CALCULATION_DAYS_IN_YEAR_COL = 7;
+ private static final int LOCKIN_PERIOD_COL = 8;
+ private static final int LOCKIN_PERIOD_FREQUENCY_COL = 9;
+ private static final int CURRENCY_COL = 10;
+ private static final int MIN_DEPOSIT_COL = 11;
+ private static final int MAX_DEPOSIT_COL = 12;
+ private static final int DEPOSIT_COL = 13;
+ private static final int MIN_DEPOSIT_TERM_COL = 14;
+ private static final int MIN_DEPOSIT_TERM_TYPE_COL = 15;
+ private static final int MAX_DEPOSIT_TERM_COL = 16;
+ private static final int MAX_DEPOSIT_TERM_TYPE_COL = 17;
+ private static final int PRECLOSURE_PENAL_APPLICABLE_COL = 18;
+ private static final int PRECLOSURE_PENAL_INTEREST_COL = 19;
+ private static final int PRECLOSURE_INTEREST_TYPE_COL = 20;
+ private static final int IN_MULTIPLES_OF_DEPOSIT_TERM_COL = 21;
+ private static final int IN_MULTIPLES_OF_DEPOSIT_TERM_TYPE_COL = 22;
+ private static final int IS_MANDATORY_DEPOSIT_COL = 23;
+ private static final int ALLOW_WITHDRAWAL_COL = 24;
+ private static final int ADJUST_ADVANCE_COL = 25;
+
+ public RecurringDepositProductSheetPopulator(List recurringDepositProducts) {
+ this.products=recurringDepositProducts;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ int rowIndex = 1;
+ Sheet productSheet = workbook.createSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME);
+ setLayout(productSheet);
+ CellStyle dateCellStyle = workbook.createCellStyle();
+ short df = workbook.createDataFormat().getFormat(dateFormat);
+ dateCellStyle.setDataFormat(df);
+ for(RecurringDepositProductData product : products) {
+ Row row = productSheet.createRow(rowIndex++);
+ writeLong(ID_COL, row, product.getId());
+ writeString(NAME_COL, row, product.getName().trim().replaceAll("[ )(]", "_"));
+ writeString(SHORT_NAME_COL, row, product.getShortName().trim().replaceAll("[ )(]", "_"));
+ writeBigDecimal(NOMINAL_ANNUAL_INTEREST_RATE_COL, row, product.getNominalAnnualInterestRate());
+ writeString(INTEREST_COMPOUNDING_PERIOD_COL, row, product.getInterestCompoundingPeriodType().getValue());
+ writeString(INTEREST_POSTING_PERIOD_COL, row, product.getInterestPostingPeriodType().getValue());
+ writeString(INTEREST_CALCULATION_COL, row, product.getInterestCalculationType().getValue());
+ writeString(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, row, product.getInterestCalculationDaysInYearType().getValue());
+ writeBoolean(PRECLOSURE_PENAL_APPLICABLE_COL, row, product.isPreClosurePenalApplicable());
+ writeString(MIN_DEPOSIT_TERM_TYPE_COL, row, product.getMinDepositTermType().getValue());
+
+ if(product.getMinDepositAmount() != null)
+ writeBigDecimal(MIN_DEPOSIT_COL, row, product.getMinDepositAmount());
+ if(product.getMaxDepositAmount() != null)
+ writeBigDecimal(MAX_DEPOSIT_COL, row, product.getMaxDepositAmount());
+ if(product.getDepositAmount() != null)
+ writeBigDecimal(DEPOSIT_COL, row, product.getDepositAmount());
+ if(product.getMaxDepositTerm() != null)
+ writeInt(MAX_DEPOSIT_TERM_COL, row, product.getMaxDepositTerm());
+
+ if(product.getMinDepositTerm() != null)
+ writeInt(MIN_DEPOSIT_TERM_COL, row, product.getMinDepositTerm());
+
+
+ if(product.getInMultiplesOfDepositTerm() != null)
+ writeInt(IN_MULTIPLES_OF_DEPOSIT_TERM_COL, row, product.getInMultiplesOfDepositTerm());
+ if(product.getPreClosurePenalInterest() != null)
+ writeBigDecimal(PRECLOSURE_PENAL_INTEREST_COL, row, product.getPreClosurePenalInterest());
+ if(product.getMaxDepositTermType() != null)
+ writeString(MAX_DEPOSIT_TERM_TYPE_COL, row, product.getMaxDepositTermType().getValue());
+ if(product.getPreClosurePenalInterestOnType() != null)
+ writeString(PRECLOSURE_INTEREST_TYPE_COL, row, product.getPreClosurePenalInterestOnType().getValue());
+ if(product.getInMultiplesOfDepositTermType() != null)
+ writeString(IN_MULTIPLES_OF_DEPOSIT_TERM_TYPE_COL, row, product.getInMultiplesOfDepositTermType().getValue());
+ writeBoolean(ALLOW_WITHDRAWAL_COL, row, product.isAllowWithdrawal());
+ writeBoolean(ADJUST_ADVANCE_COL, row, product.isAdjustAdvanceTowardsFuturePayments());
+ writeBoolean(IS_MANDATORY_DEPOSIT_COL, row, product.isMandatoryDeposit());
+ if(product.getLockinPeriodFrequency() != null)
+ writeInt(LOCKIN_PERIOD_COL, row, product.getLockinPeriodFrequency());
+ if(product.getLockinPeriodFrequencyType() != null)
+ writeString(LOCKIN_PERIOD_FREQUENCY_COL, row, product.getLockinPeriodFrequencyType().getValue());
+ CurrencyData currency = product.getCurrency();
+ writeString(CURRENCY_COL, row, currency.code());
+ }
+ productSheet.protectSheet("");
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(SHORT_NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(NOMINAL_ANNUAL_INTEREST_RATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_COMPOUNDING_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_POSTING_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_CALCULATION_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(LOCKIN_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(LOCKIN_PERIOD_FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CURRENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_DEPOSIT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_DEPOSIT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(DEPOSIT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_DEPOSIT_TERM_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_DEPOSIT_TERM_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_DEPOSIT_TERM_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MAX_DEPOSIT_TERM_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(PRECLOSURE_PENAL_APPLICABLE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(PRECLOSURE_PENAL_INTEREST_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(PRECLOSURE_INTEREST_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(IN_MULTIPLES_OF_DEPOSIT_TERM_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(IN_MULTIPLES_OF_DEPOSIT_TERM_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(IS_MANDATORY_DEPOSIT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ALLOW_WITHDRAWAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ADJUST_ADVANCE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+
+ writeString(ID_COL, rowHeader, "ID");
+ writeString(NAME_COL, rowHeader, "Name");
+ writeString(SHORT_NAME_COL, rowHeader, "Short Name");
+ writeString(NOMINAL_ANNUAL_INTEREST_RATE_COL, rowHeader, "Interest");
+ writeString(INTEREST_COMPOUNDING_PERIOD_COL, rowHeader, "Interest Compounding Period");
+ writeString(INTEREST_POSTING_PERIOD_COL, rowHeader, "Interest Posting Period");
+ writeString(INTEREST_CALCULATION_COL, rowHeader, "Interest Calculated Using");
+ writeString(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, rowHeader, "# Days In Year");
+ writeString(LOCKIN_PERIOD_COL, rowHeader, "Locked In For");
+ writeString(LOCKIN_PERIOD_FREQUENCY_COL, rowHeader, "Frequency");
+ writeString(CURRENCY_COL, rowHeader, "Currency");
+ writeString(MIN_DEPOSIT_COL, rowHeader, "Min Deposit");
+ writeString(MAX_DEPOSIT_COL, rowHeader, "Max Deposit");
+ writeString(DEPOSIT_COL, rowHeader, "Deposit");
+ writeString(MIN_DEPOSIT_TERM_COL, rowHeader, "Min Deposit Term");
+ writeString(MAX_DEPOSIT_TERM_COL, rowHeader, "Max Deposit Term");
+ writeString(MIN_DEPOSIT_TERM_TYPE_COL, rowHeader, "Min Deposit Term Type");
+ writeString(MAX_DEPOSIT_TERM_TYPE_COL, rowHeader, "Max Deposit Term Type");
+ writeString(PRECLOSURE_PENAL_APPLICABLE_COL, rowHeader, "Preclosure Penal Applicable");
+ writeString(PRECLOSURE_PENAL_INTEREST_COL, rowHeader, "Penal Interest");
+ writeString(PRECLOSURE_INTEREST_TYPE_COL, rowHeader, "Penal Interest Type");
+ writeString(IN_MULTIPLES_OF_DEPOSIT_TERM_COL, rowHeader, "Multiples of Deposit Term");
+ writeString(IN_MULTIPLES_OF_DEPOSIT_TERM_TYPE_COL, rowHeader, "Multiples of Deposit Term Type");
+ writeString(IS_MANDATORY_DEPOSIT_COL, rowHeader, "Is Mandatory Deposit?");
+ writeString(ALLOW_WITHDRAWAL_COL, rowHeader, "Allow Withdrawal?");
+ writeString(ADJUST_ADVANCE_COL, rowHeader, "Adjust Advance Towards Future Payments?");
+ }
+
+ public List getProducts() {
+ return products;
+ }
+
+ public Integer getProductsSize() {
+ return products.size();
+ }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/RoleSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/RoleSheetPopulator.java
new file mode 100644
index 000000000..a7717f86f
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/RoleSheetPopulator.java
@@ -0,0 +1,67 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.useradministration.data.RoleData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.List;
+
+public class RoleSheetPopulator extends AbstractWorkbookPopulator {
+ private ListrolesList;
+
+ private static final int ID_COL=0;
+ private static final int ROLE_NAME=1;
+
+ public RoleSheetPopulator(List roles) {
+ this.rolesList=roles;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ int rowIndex = 1;
+ Sheet rolesSheet = workbook.createSheet(TemplatePopulateImportConstants.ROLES_SHEET_NAME);
+ setLayout(rolesSheet);
+ populateRoles(rolesSheet, rowIndex);
+ rolesSheet.protectSheet("");
+ }
+
+ private void populateRoles(Sheet rolesSheet, int rowIndex) {
+ for (RoleData role : rolesList) {
+ Row row = rolesSheet.createRow(rowIndex);
+ writeLong(ID_COL, row, role.getId());
+ writeString(ROLE_NAME, row, role.getName().trim().replaceAll("[ )(]", "_"));
+ rowIndex++;
+ }
+ }
+
+ private void setLayout(Sheet rolesSheet) {
+ rolesSheet.setColumnWidth(ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ rolesSheet.setColumnWidth(ROLE_NAME, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ Row rowHeader = rolesSheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ writeString(ID_COL, rowHeader, "ID");
+ writeString(ROLE_NAME, rowHeader, "Role Name");
+ }
+
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SavingsAccountSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SavingsAccountSheetPopulator.java
new file mode 100644
index 000000000..e2a9c77fb
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SavingsAccountSheetPopulator.java
@@ -0,0 +1,84 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
+import org.apache.fineract.template.domain.Template;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.List;
+import java.util.Map;
+
+public class SavingsAccountSheetPopulator extends AbstractWorkbookPopulator {
+
+ private List savingsAccountDataList;
+ private Map> clientToSavingsMap;
+
+ private static final int SAVINGS_ACCOUNT_ID_COL=0;
+ private static final int SAVING_ACCOUNT_NO=1;
+ private static final int CURRENCY_COL=2;
+ private static final int CLIENT_NAME=3;
+
+
+ public SavingsAccountSheetPopulator(List savingsAccountDataList) {
+ this.savingsAccountDataList=savingsAccountDataList;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet savingsSheet=workbook.createSheet(TemplatePopulateImportConstants.SAVINGS_ACCOUNTS_SHEET_NAME);
+ setLayout(savingsSheet);
+ populateSavingsSheet(savingsSheet);
+ savingsSheet.protectSheet("");
+ }
+
+ private void populateSavingsSheet(Sheet savingsSheet) {
+ int rowIndex=1;
+ for (SavingsAccountData savings: savingsAccountDataList) {
+ Row row=savingsSheet.createRow(rowIndex++);
+ writeLong(SAVINGS_ACCOUNT_ID_COL,row,savings.id());
+ writeString(SAVING_ACCOUNT_NO,row,savings.getAccountNo());
+ writeString(CURRENCY_COL,row,savings.currency().code());
+ writeString(CLIENT_NAME,row,savings.getClientName());
+ }
+ }
+
+
+ private void setLayout(Sheet savingsSheet) {
+ Row rowHeader = savingsSheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+
+ savingsSheet.setColumnWidth(SAVINGS_ACCOUNT_ID_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(SAVINGS_ACCOUNT_ID_COL,rowHeader,"Savings Account Id");
+
+ savingsSheet.setColumnWidth(SAVING_ACCOUNT_NO,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(SAVING_ACCOUNT_NO,rowHeader,"Savings Account No");
+
+ savingsSheet.setColumnWidth(CURRENCY_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CURRENCY_COL,rowHeader,"Currency Code");
+
+ savingsSheet.setColumnWidth(CLIENT_NAME,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CLIENT_NAME,rowHeader,"Client Name");
+
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SavingsProductSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SavingsProductSheetPopulator.java
new file mode 100644
index 000000000..2803a01a7
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SavingsProductSheetPopulator.java
@@ -0,0 +1,136 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.fineract.portfolio.savings.data.SavingsProductData;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.util.List;
+
+public class SavingsProductSheetPopulator extends AbstractWorkbookPopulator {
+ private List savingsProducts;
+
+ private static final int ID_COL = 0;
+ private static final int NAME_COL = 1;
+ private static final int NOMINAL_ANNUAL_INTEREST_RATE_COL = 2;
+ private static final int INTEREST_COMPOUNDING_PERIOD_COL = 3;
+ private static final int INTEREST_POSTING_PERIOD_COL = 4;
+ private static final int INTEREST_CALCULATION_COL = 5;
+ private static final int INTEREST_CALCULATION_DAYS_IN_YEAR_COL = 6;
+ private static final int MIN_OPENING_BALANCE_COL = 7;
+ private static final int LOCKIN_PERIOD_COL = 8;
+ private static final int LOCKIN_PERIOD_FREQUENCY_COL = 9;
+ private static final int CURRENCY_COL = 10;
+ private static final int DECIMAL_PLACES_COL = 11;
+ private static final int IN_MULTIPLES_OF_COL = 12;
+ private static final int WITHDRAWAL_FEE_COL = 13;
+ private static final int ALLOW_OVERDRAFT_COL = 14;
+ private static final int OVERDRAFT_LIMIT_COL = 15;
+
+ public SavingsProductSheetPopulator(List savingsProducts) {
+ this.savingsProducts=savingsProducts;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ int rowIndex = 1;
+ Sheet productSheet = workbook.createSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME);
+ setLayout(productSheet);
+ CellStyle dateCellStyle = workbook.createCellStyle();
+ short df = workbook.createDataFormat().getFormat(dateFormat);
+ dateCellStyle.setDataFormat(df);
+ for(SavingsProductData product : savingsProducts) {
+ Row row = productSheet.createRow(rowIndex++);
+ writeLong(ID_COL, row, product.getId());
+ writeString(NAME_COL, row, product.getName().trim().replaceAll("[ )(]", "_"));
+ writeBigDecimal(NOMINAL_ANNUAL_INTEREST_RATE_COL, row, product.getNominalAnnualInterestRate());
+ writeString(INTEREST_COMPOUNDING_PERIOD_COL, row, product.getInterestCompoundingPeriodType().getValue());
+ writeString(INTEREST_POSTING_PERIOD_COL, row, product.getInterestPostingPeriodType().getValue());
+ writeString(INTEREST_CALCULATION_COL, row, product.getInterestCalculationType().getValue());
+ writeString(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, row, product.getInterestCalculationDaysInYearType().getValue());
+ if(product.getMinRequiredOpeningBalance() != null)
+ writeBigDecimal(MIN_OPENING_BALANCE_COL, row, product.getMinRequiredOpeningBalance());
+ if(product.getLockinPeriodFrequency() != null)
+ writeInt(LOCKIN_PERIOD_COL, row, product.getLockinPeriodFrequency());
+ if(product.getLockinPeriodFrequencyType() != null)
+ writeString(LOCKIN_PERIOD_FREQUENCY_COL, row, product.getLockinPeriodFrequencyType().getValue());
+ CurrencyData currency = product.getCurrency();
+ writeString(CURRENCY_COL, row, currency.code());
+ writeInt(DECIMAL_PLACES_COL, row, currency.decimalPlaces());
+ if(currency.currencyInMultiplesOf() != null)
+ writeInt(IN_MULTIPLES_OF_COL, row, currency.currencyInMultiplesOf());
+ writeBoolean(WITHDRAWAL_FEE_COL, row, product.isWithdrawalFeeForTransfers());
+ writeBoolean(ALLOW_OVERDRAFT_COL, row,product.isAllowOverdraft());
+ if(product.getOverdraftLimit() != null)
+ writeBigDecimal(OVERDRAFT_LIMIT_COL, row, product.getOverdraftLimit());
+ }
+ productSheet.protectSheet("");
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(NOMINAL_ANNUAL_INTEREST_RATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_COMPOUNDING_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_POSTING_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_CALCULATION_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(MIN_OPENING_BALANCE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(LOCKIN_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(LOCKIN_PERIOD_FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CURRENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(DECIMAL_PLACES_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(IN_MULTIPLES_OF_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(WITHDRAWAL_FEE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ALLOW_OVERDRAFT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(OVERDRAFT_LIMIT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+
+ writeString(ID_COL, rowHeader, "ID");
+ writeString(NAME_COL, rowHeader, "Name");
+ writeString(NOMINAL_ANNUAL_INTEREST_RATE_COL, rowHeader, "Interest");
+ writeString(INTEREST_COMPOUNDING_PERIOD_COL, rowHeader, "Interest Compounding Period");
+ writeString(INTEREST_POSTING_PERIOD_COL, rowHeader, "Interest Posting Period");
+ writeString(INTEREST_CALCULATION_COL, rowHeader, "Interest Calculated Using");
+ writeString(INTEREST_CALCULATION_DAYS_IN_YEAR_COL, rowHeader, "# Days In Year");
+ writeString(MIN_OPENING_BALANCE_COL, rowHeader, "Min Opening Balance");
+ writeString(LOCKIN_PERIOD_COL, rowHeader, "Locked In For");
+ writeString(LOCKIN_PERIOD_FREQUENCY_COL, rowHeader, "Frequency");
+ writeString(CURRENCY_COL, rowHeader, "Currency");
+ writeString(DECIMAL_PLACES_COL, rowHeader, "Decimal Places");
+ writeString(IN_MULTIPLES_OF_COL, rowHeader, "In Multiples Of");
+ writeString(WITHDRAWAL_FEE_COL, rowHeader, "Withdrawal Fee for Transfers?");
+ writeString(ALLOW_OVERDRAFT_COL, rowHeader, "Apply Overdraft");
+ writeString(OVERDRAFT_LIMIT_COL, rowHeader, "Overdraft Limit");
+ }
+
+ public List getProducts() {
+ return savingsProducts;
+ }
+
+ public Integer getProductsSize() {
+ return savingsProducts.size();
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SharedProductsSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SharedProductsSheetPopulator.java
new file mode 100644
index 000000000..33fbd8fa1
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/SharedProductsSheetPopulator.java
@@ -0,0 +1,159 @@
+/**
+ * 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 org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.apache.fineract.portfolio.charge.data.ChargeData;
+import org.apache.fineract.portfolio.shareproducts.data.ShareProductData;
+import org.apache.fineract.portfolio.shareproducts.data.ShareProductMarketPriceData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+public class SharedProductsSheetPopulator extends AbstractWorkbookPopulator {
+ private List sharedProductDataList;
+ private List chargesForSharedProducts;
+ private MapproductToBeginEndIndexesofCharges;
+
+ private static final int PRODUCT_ID=0;
+ private static final int PRODUCT_NAME_COL = 1;
+ private static final int CURRENCY_COL = 2;
+ private static final int DECIMAL_PLACES_COL = 3;
+ private static final int TODAYS_PRICE_COL = 4;
+ private static final int CURRENCY_IN_MULTIPLES_COL = 5;
+ private static final int CHARGES_ID_1_COL = 7;
+ private static final int CHARGES_NAME_1_COL = 8;
+ private static final int CHARGES_ID_2_COL = 9;
+ private static final int CHARGES_NAME_2_COL = 10;
+ private static final int CHARGES_ID_3_COL = 11;
+ private static final int CHARGES_NAME_3_COL = 12;
+
+
+
+ public SharedProductsSheetPopulator(List shareProductDataList,List chargesForShares) {
+ this.sharedProductDataList=shareProductDataList;
+ this.chargesForSharedProducts=chargesForShares;
+
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet sharedProductsSheet=workbook.createSheet(TemplatePopulateImportConstants.SHARED_PRODUCTS_SHEET_NAME);
+ setLayout(sharedProductsSheet);
+ populateSheet(sharedProductsSheet);
+ sharedProductsSheet.protectSheet("");
+ }
+
+ private void populateSheet(Sheet sharedProductsSheet) {
+ int index = 0;
+ int startIndexCharges = 1;
+ int endIndexCharges = 0;
+ productToBeginEndIndexesofCharges = new HashMap<>();
+ for (ShareProductData productData : sharedProductDataList) {
+ Row row = sharedProductsSheet.createRow(++index);
+ writeLong(PRODUCT_ID, row, productData.getId());
+ writeString(PRODUCT_NAME_COL, row, productData.getName().replaceAll("[ ]", "_"));
+ writeString(CURRENCY_COL, row, productData.getCurrency().getName().replaceAll("[ ]", "_"));
+ writeInt(DECIMAL_PLACES_COL, row, productData.getCurrency().decimalPlaces());
+ writeBigDecimal(TODAYS_PRICE_COL, row, deriveMarketPrice(productData));
+ writeInt(CURRENCY_IN_MULTIPLES_COL,row,productData.getCurrency().currencyInMultiplesOf());
+ if (chargesForSharedProducts != null) {
+ int chargeRowIndex=0;
+ for (ChargeData chargeData:chargesForSharedProducts) {
+ if (chargeData.getCurrency().getName().equals(productData.getCurrency().getName())) {
+ writeString(CHARGES_NAME_1_COL+chargeRowIndex, row, chargeData.getName());
+ writeLong(CHARGES_ID_1_COL+chargeRowIndex, row, chargeData.getId());
+ chargeRowIndex+=2;
+ endIndexCharges++;
+ }
+ }
+ productToBeginEndIndexesofCharges.put(productData.getId(), new Integer[]{startIndexCharges, endIndexCharges});
+ startIndexCharges = endIndexCharges + 1;
+ }
+ }
+ }
+ private BigDecimal deriveMarketPrice(final ShareProductData shareProductData) {
+ BigDecimal marketValue = shareProductData.getUnitPrice();
+ Collection marketDataSet = shareProductData.getMarketPrice();
+ if (marketDataSet != null && !marketDataSet.isEmpty()) {
+ Date currentDate = DateUtils.getDateOfTenant();
+ for (ShareProductMarketPriceData data : marketDataSet) {
+ Date futureDate = data.getStartDate();
+ if (currentDate.after(futureDate)) {
+ marketValue = data.getShareValue();
+ }
+ }
+ }
+ return marketValue;
+ }
+
+ private void setLayout(Sheet workSheet) {
+ Row rowHeader=workSheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+
+ workSheet.setColumnWidth(PRODUCT_ID,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(PRODUCT_ID,rowHeader,"Product Id");
+
+ workSheet.setColumnWidth(PRODUCT_NAME_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(PRODUCT_NAME_COL,rowHeader,"Product Name");
+
+ workSheet.setColumnWidth(CURRENCY_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(CURRENCY_COL,rowHeader,"Currency");
+
+ workSheet.setColumnWidth(DECIMAL_PLACES_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(DECIMAL_PLACES_COL,rowHeader,"Decimal Places");
+
+ workSheet.setColumnWidth(TODAYS_PRICE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(TODAYS_PRICE_COL,rowHeader,"Today's Price");
+
+ workSheet.setColumnWidth(CURRENCY_IN_MULTIPLES_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CURRENCY_IN_MULTIPLES_COL,rowHeader,"Currency in multiples of");
+
+ workSheet.setColumnWidth(CHARGES_NAME_1_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CHARGES_NAME_1_COL,rowHeader,"Charges Name 1");
+
+ workSheet.setColumnWidth(CHARGES_ID_1_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CHARGES_ID_1_COL,rowHeader,"Charges Id 1");
+
+ workSheet.setColumnWidth(CHARGES_NAME_2_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CHARGES_NAME_2_COL,rowHeader,"Charges Name 2");
+
+ workSheet.setColumnWidth(CHARGES_ID_2_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CHARGES_ID_2_COL,rowHeader,"Charges Id 2");
+
+ workSheet.setColumnWidth(CHARGES_NAME_3_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CHARGES_NAME_3_COL,rowHeader,"Charges Name 3");
+
+ workSheet.setColumnWidth(CHARGES_ID_3_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(CHARGES_ID_3_COL,rowHeader,"Charges Id 3");
+
+ }
+
+ public List getSharedProductDataList() {
+ return sharedProductDataList;
+ }
+
+ public Map getProductToBeginEndIndexesofCharges() {
+ return productToBeginEndIndexesofCharges;
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/WorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/WorkbookPopulator.java
new file mode 100644
index 000000000..9ff2a1c17
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/WorkbookPopulator.java
@@ -0,0 +1,27 @@
+/**
+ * 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 org.apache.poi.ss.usermodel.Workbook;
+
+public interface WorkbookPopulator {
+
+ void populate(Workbook workbook,String dateFormat);
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/centers/CentersWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/centers/CentersWorkbookPopulator.java
new file mode 100644
index 000000000..27248c620
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/centers/CentersWorkbookPopulator.java
@@ -0,0 +1,235 @@
+/**
+ * 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.centers;
+
+import org.apache.fineract.infrastructure.bulkimport.constants.CenterConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.AbstractWorkbookPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.GroupSheetPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.OfficeSheetPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.PersonnelSheetPopulator;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.List;
+
+
+public class CentersWorkbookPopulator extends AbstractWorkbookPopulator {
+
+
+ private OfficeSheetPopulator officeSheetPopulator;
+ private PersonnelSheetPopulator personnelSheetPopulator;
+ private GroupSheetPopulator groupSheetPopulator;
+
+ public CentersWorkbookPopulator(OfficeSheetPopulator officeSheetPopulator,
+ PersonnelSheetPopulator personnelSheetPopulator,GroupSheetPopulator groupSheetPopulator) {
+ this.officeSheetPopulator = officeSheetPopulator;
+ this.personnelSheetPopulator = personnelSheetPopulator;
+ this.groupSheetPopulator=groupSheetPopulator;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet centerSheet = workbook.createSheet(TemplatePopulateImportConstants.CENTER_SHEET_NAME);
+ personnelSheetPopulator.populate(workbook,dateFormat);
+ officeSheetPopulator.populate(workbook,dateFormat);
+ groupSheetPopulator.populate(workbook,dateFormat);
+ setLayout(centerSheet);
+ setLookupTable(centerSheet,dateFormat);
+ setRules(centerSheet,dateFormat);
+ }
+
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(0);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(CenterConstants.CENTER_NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.STAFF_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.EXTERNAL_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.ACTIVE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.ACTIVATION_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.SUBMITTED_ON_DATE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.MEETING_START_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.IS_REPEATING_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.INTERVAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.REPEATS_ON_DAY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.CENTER_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.FAILURE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.GROUP_NAMES_STARTING_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.LOOKUP_OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.LOOKUP_OFFICE_OPENING_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.LOOKUP_REPEAT_NORMAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.LOOKUP_REPEAT_MONTHLY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(CenterConstants.LOOKUP_IF_REPEAT_WEEKLY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+
+ writeString(CenterConstants.CENTER_NAME_COL, rowHeader, "Center Name*");
+ writeString(CenterConstants.OFFICE_NAME_COL, rowHeader, "Office Name*");
+ writeString(CenterConstants.STAFF_NAME_COL, rowHeader, "Staff Name*");
+ writeString(CenterConstants.EXTERNAL_ID_COL, rowHeader, "External ID");
+ writeString(CenterConstants.ACTIVE_COL, rowHeader, "Active*");
+ writeString(CenterConstants.ACTIVATION_DATE_COL, rowHeader, "Activation Date*");
+ writeString(CenterConstants.SUBMITTED_ON_DATE_COL,rowHeader,"Submitted On Date");
+ writeString(CenterConstants.MEETING_START_DATE_COL, rowHeader, "Meeting Start Date* (On or After)");
+ writeString(CenterConstants.IS_REPEATING_COL, rowHeader, "Repeat*");
+ writeString(CenterConstants.FREQUENCY_COL, rowHeader, "Frequency*");
+ writeString(CenterConstants.INTERVAL_COL, rowHeader, "Interval*");
+ writeString(CenterConstants.REPEATS_ON_DAY_COL, rowHeader, "Repeats On*");
+ writeString(CenterConstants.GROUP_NAMES_STARTING_COL,rowHeader,"Group Names* (Enter in consecutive cells horizontally)");
+ writeString(CenterConstants.LOOKUP_OFFICE_NAME_COL, rowHeader, "Office Name");
+ writeString(CenterConstants.LOOKUP_OFFICE_OPENING_DATE_COL, rowHeader, "Opening Date");
+ writeString(CenterConstants.LOOKUP_REPEAT_NORMAL_COL, rowHeader, "Repeat Normal Range");
+ writeString(CenterConstants.LOOKUP_REPEAT_MONTHLY_COL, rowHeader, "Repeat Monthly Range");
+ writeString(CenterConstants.LOOKUP_IF_REPEAT_WEEKLY_COL, rowHeader, "If Repeat Weekly Range");
+ }
+ private void setLookupTable(Sheet centerSheet,String dateFormat) {
+ setOfficeDateLookupTable(centerSheet, officeSheetPopulator.getOffices(), CenterConstants.LOOKUP_OFFICE_NAME_COL,CenterConstants.LOOKUP_OFFICE_OPENING_DATE_COL,dateFormat);
+ int rowIndex;
+ for(rowIndex = 1; rowIndex <= 11; rowIndex++) {
+ Row row = centerSheet.getRow(rowIndex);
+ if(row == null)
+ row = centerSheet.createRow(rowIndex);
+ writeInt(CenterConstants.LOOKUP_REPEAT_MONTHLY_COL, row, rowIndex);
+ }
+ for(rowIndex = 1; rowIndex <= 3; rowIndex++)
+ writeInt(CenterConstants.LOOKUP_REPEAT_NORMAL_COL, centerSheet.getRow(rowIndex), rowIndex);
+
+ String[] days = new String[]{
+ TemplatePopulateImportConstants.MONDAY,
+ TemplatePopulateImportConstants.TUESDAY,
+ TemplatePopulateImportConstants.WEDNESDAY,
+ TemplatePopulateImportConstants.THURSDAY,
+ TemplatePopulateImportConstants.FRIDAY,
+ TemplatePopulateImportConstants.SATURDAY,
+ TemplatePopulateImportConstants.SUNDAY};
+
+ for(rowIndex = 1; rowIndex <= 7; rowIndex++)
+ writeString(CenterConstants.LOOKUP_IF_REPEAT_WEEKLY_COL, centerSheet.getRow(rowIndex), days[rowIndex-1]);
+
+ }
+ private void setRules(Sheet worksheet,String dateFormat) {
+ CellRangeAddressList officeNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(), CenterConstants.OFFICE_NAME_COL,CenterConstants. OFFICE_NAME_COL);
+ CellRangeAddressList staffNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(), CenterConstants.STAFF_NAME_COL,CenterConstants. STAFF_NAME_COL);
+ CellRangeAddressList activationDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),CenterConstants. ACTIVATION_DATE_COL,CenterConstants. ACTIVATION_DATE_COL);
+ CellRangeAddressList activeRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(), CenterConstants.ACTIVE_COL, CenterConstants.ACTIVE_COL);
+ CellRangeAddressList submittedDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),CenterConstants. SUBMITTED_ON_DATE_COL,CenterConstants.SUBMITTED_ON_DATE_COL);
+ CellRangeAddressList meetingStartDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(), CenterConstants.MEETING_START_DATE_COL,CenterConstants. MEETING_START_DATE_COL);
+ CellRangeAddressList isRepeatRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),CenterConstants. IS_REPEATING_COL,CenterConstants. IS_REPEATING_COL);
+ CellRangeAddressList repeatsRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(), CenterConstants.FREQUENCY_COL, CenterConstants.FREQUENCY_COL);
+ CellRangeAddressList repeatsEveryRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(), CenterConstants.INTERVAL_COL,CenterConstants. INTERVAL_COL);
+ CellRangeAddressList repeatsOnRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(), CenterConstants.REPEATS_ON_DAY_COL,CenterConstants. REPEATS_ON_DAY_COL);
+
+
+ DataValidationHelper validationHelper = new HSSFDataValidationHelper((HSSFSheet)worksheet);
+ List offices = officeSheetPopulator.getOffices();
+ setNames(worksheet, offices);
+
+
+ DataValidationConstraint officeNameConstraint = validationHelper.createFormulaListConstraint("Office");
+ DataValidationConstraint staffNameConstraint = validationHelper.
+ createFormulaListConstraint("INDIRECT(CONCATENATE(\"Staff_\",$B1))");
+ DataValidationConstraint activationDateConstraint = validationHelper.createDateConstraint
+ (DataValidationConstraint.OperatorType.BETWEEN, "=VLOOKUP($B1,$IR$2:$IS" + (offices.size() + 1)+",2,FALSE)",
+ "=TODAY()", dateFormat);
+ DataValidationConstraint booleanConstraint = validationHelper.createExplicitListConstraint(new String[]{"True", "False"});
+ DataValidationConstraint submittedOnDateConstraint =
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.LESS_OR_EQUAL,
+ "=$F1", null,dateFormat);
+ DataValidationConstraint meetingStartDateConstraint =
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN,
+ "=$F1", "=TODAY()", dateFormat);
+ DataValidationConstraint repeatsConstraint =
+ validationHelper.createExplicitListConstraint(new String[]{
+ TemplatePopulateImportConstants.FREQUENCY_DAILY,
+ TemplatePopulateImportConstants.FREQUENCY_WEEKLY,
+ TemplatePopulateImportConstants.FREQUENCY_MONTHLY,
+ TemplatePopulateImportConstants.FREQUENCY_YEARLY});
+ DataValidationConstraint repeatsEveryConstraint = validationHelper.createFormulaListConstraint("INDIRECT($J1)");
+ DataValidationConstraint repeatsOnConstraint = validationHelper.createFormulaListConstraint("INDIRECT(CONCATENATE($J1,\"_DAYS\"))");
+
+
+ DataValidation officeValidation = validationHelper.createValidation(officeNameConstraint, officeNameRange);
+ DataValidation staffValidation = validationHelper.createValidation(staffNameConstraint, staffNameRange);
+ DataValidation activationDateValidation = validationHelper.createValidation(activationDateConstraint, activationDateRange);
+ DataValidation activeValidation = validationHelper.createValidation(booleanConstraint, activeRange);
+ DataValidation submittedOnValidation=validationHelper.createValidation(submittedOnDateConstraint,submittedDateRange);
+ DataValidation meetingStartDateValidation = validationHelper.createValidation(meetingStartDateConstraint, meetingStartDateRange);
+ DataValidation isRepeatValidation = validationHelper.createValidation(booleanConstraint, isRepeatRange);
+ DataValidation repeatsValidation = validationHelper.createValidation(repeatsConstraint, repeatsRange);
+ DataValidation repeatsEveryValidation = validationHelper.createValidation(repeatsEveryConstraint, repeatsEveryRange);
+ DataValidation repeatsOnValidation = validationHelper.createValidation(repeatsOnConstraint, repeatsOnRange);
+
+
+ worksheet.addValidationData(activeValidation);
+ worksheet.addValidationData(officeValidation);
+ worksheet.addValidationData(staffValidation);
+ worksheet.addValidationData(activationDateValidation);
+ worksheet.addValidationData(submittedOnValidation);
+ worksheet.addValidationData(meetingStartDateValidation);
+ worksheet.addValidationData(isRepeatValidation);
+ worksheet.addValidationData(repeatsValidation);
+ worksheet.addValidationData(repeatsEveryValidation);
+ worksheet.addValidationData(repeatsOnValidation);
+ }
+
+ private void setNames(Sheet worksheet, List offices) {
+ Workbook centerWorkbook = worksheet.getWorkbook();
+ Name officeCenter = centerWorkbook.createName();
+ officeCenter.setNameName("Office");
+ officeCenter.setRefersToFormula(TemplatePopulateImportConstants.OFFICE_SHEET_NAME +"!$B$2:$B$" + (offices.size() + 1));
+
+
+ //Repeat constraint names
+ Name repeatsDaily = centerWorkbook.createName();
+ repeatsDaily.setNameName("Daily");
+ repeatsDaily.setRefersToFormula(TemplatePopulateImportConstants.CENTER_SHEET_NAME+"!$IT$2:$IT$4");
+ Name repeatsWeekly = centerWorkbook.createName();
+ repeatsWeekly.setNameName("Weekly");
+ repeatsWeekly.setRefersToFormula(TemplatePopulateImportConstants.CENTER_SHEET_NAME+"!$IT$2:$IT$4");
+ Name repeatYearly = centerWorkbook.createName();
+ repeatYearly.setNameName("Yearly");
+ repeatYearly.setRefersToFormula(TemplatePopulateImportConstants.CENTER_SHEET_NAME+"!$IT$2:$IT$4");
+ Name repeatsMonthly = centerWorkbook.createName();
+ repeatsMonthly.setNameName("Monthly");
+ repeatsMonthly.setRefersToFormula(TemplatePopulateImportConstants.CENTER_SHEET_NAME+"!$IU$2:$IU$12");
+ Name repeatsOnWeekly = centerWorkbook.createName();
+ repeatsOnWeekly.setNameName("Weekly_Days");
+ repeatsOnWeekly.setRefersToFormula(TemplatePopulateImportConstants.CENTER_SHEET_NAME+"!$IV$2:$IV$8");
+
+
+ //Staff Names for each office
+ for(Integer i = 0; i < offices.size(); i++) {
+ Integer[] officeNameToBeginEndIndexesOfStaff = personnelSheetPopulator.getOfficeNameToBeginEndIndexesOfStaff().get(i);
+ Name loanOfficerName = centerWorkbook.createName();
+ if(officeNameToBeginEndIndexesOfStaff != null) {
+ loanOfficerName.setNameName("Staff_" + offices.get(i).name().trim().replaceAll("[ )(]", "_"));
+ loanOfficerName.setRefersToFormula(TemplatePopulateImportConstants.STAFF_SHEET_NAME+"!$B$" + officeNameToBeginEndIndexesOfStaff[0] + ":$B$" + officeNameToBeginEndIndexesOfStaff[1]);
+ }
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/chartofaccounts/ChartOfAccountsWorkbook.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/chartofaccounts/ChartOfAccountsWorkbook.java
new file mode 100644
index 000000000..f65be136c
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/chartofaccounts/ChartOfAccountsWorkbook.java
@@ -0,0 +1,236 @@
+/**
+ * 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.chartofaccounts;
+
+import org.apache.fineract.accounting.glaccount.data.GLAccountData;
+import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
+import org.apache.fineract.accounting.glaccount.domain.GLAccountUsage;
+import org.apache.fineract.infrastructure.bulkimport.constants.ChartOfAcountsConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.AbstractWorkbookPopulator;
+import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ChartOfAccountsWorkbook extends AbstractWorkbookPopulator {
+ private List glAccounts;
+ private Map> accountTypeToAccountNameAndTag;
+ private MapaccountTypeToBeginEndIndexesofAccountNames;
+ private List accountTypesNoDuplicatesList;
+
+
+ public ChartOfAccountsWorkbook(List glAccounts) {
+ this.glAccounts = glAccounts;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet chartOfAccountsSheet=workbook.createSheet(TemplatePopulateImportConstants.CHART_OF_ACCOUNTS_SHEET_NAME);
+ setLayout(chartOfAccountsSheet);
+ setAccountTypeToAccountNameAndTag();
+ setLookupTable(chartOfAccountsSheet);
+ setRules(chartOfAccountsSheet);
+ setDefaults(chartOfAccountsSheet);
+ }
+
+ private void setAccountTypeToAccountNameAndTag() {
+ accountTypeToAccountNameAndTag=new HashMap<>();
+ for (GLAccountData glAccount: glAccounts) {
+ addToaccountTypeToAccountNameMap(glAccount.getType().getValue(),glAccount.getName()+
+ "-"+glAccount.getId()+"-"+glAccount.getTagId().getName()+"-"+glAccount.getTagId().getId());
+ }
+ }
+
+ private void addToaccountTypeToAccountNameMap(String key, String value) {
+ List values=accountTypeToAccountNameAndTag.get(key);
+ if (values==null){
+ values=new ArrayList();
+ }
+ if (!values.contains(value)){
+ values.add(value);
+ accountTypeToAccountNameAndTag.put(key,values);
+ }
+ }
+
+ private void setRules(Sheet chartOfAccountsSheet) {
+ CellRangeAddressList accountTypeRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ ChartOfAcountsConstants. ACCOUNT_TYPE_COL,ChartOfAcountsConstants.ACCOUNT_TYPE_COL);
+ CellRangeAddressList accountUsageRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ ChartOfAcountsConstants.ACCOUNT_USAGE_COL,ChartOfAcountsConstants.ACCOUNT_USAGE_COL);
+ CellRangeAddressList manualEntriesAllowedRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ ChartOfAcountsConstants.MANUAL_ENTRIES_ALLOWED_COL,ChartOfAcountsConstants.MANUAL_ENTRIES_ALLOWED_COL);
+ CellRangeAddressList parentRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ ChartOfAcountsConstants.PARENT_COL,ChartOfAcountsConstants.PARENT_COL);
+ CellRangeAddressList tagRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ ChartOfAcountsConstants.TAG_COL,ChartOfAcountsConstants.TAG_COL);
+
+ DataValidationHelper validationHelper=new HSSFDataValidationHelper((HSSFSheet) chartOfAccountsSheet);
+ setNames(chartOfAccountsSheet, accountTypesNoDuplicatesList);
+
+ DataValidationConstraint accountTypeConstraint=validationHelper.
+ createExplicitListConstraint(new String[]{
+ GLAccountType.ASSET.toString(),
+ GLAccountType.LIABILITY.toString(),
+ GLAccountType.EQUITY.toString(),
+ GLAccountType.INCOME.toString(),
+ GLAccountType.EXPENSE.toString()});
+ DataValidationConstraint accountUsageConstraint=validationHelper.
+ createExplicitListConstraint(new String[]{
+ GLAccountUsage.DETAIL.toString(),
+ GLAccountUsage.HEADER.toString()});
+ DataValidationConstraint booleanConstraint=validationHelper.
+ createExplicitListConstraint(new String[]{"True","False"});
+ DataValidationConstraint parentConstraint=validationHelper.
+ createFormulaListConstraint("INDIRECT(CONCATENATE(\"AccountName_\",$A1))");
+ DataValidationConstraint tagConstraint=validationHelper.
+ createFormulaListConstraint("INDIRECT(CONCATENATE(\"Tags_\",$A1))");
+
+ DataValidation accountTypeValidation=validationHelper.createValidation(accountTypeConstraint,accountTypeRange);
+ DataValidation accountUsageValidation=validationHelper.createValidation(accountUsageConstraint,accountUsageRange);
+ DataValidation manualEntriesValidation=validationHelper.createValidation(booleanConstraint,manualEntriesAllowedRange);
+ DataValidation parentValidation=validationHelper.createValidation(parentConstraint,parentRange);
+ DataValidation tagValidation=validationHelper.createValidation(tagConstraint,tagRange);
+
+ chartOfAccountsSheet.addValidationData(accountTypeValidation);
+ chartOfAccountsSheet.addValidationData(accountUsageValidation);
+ chartOfAccountsSheet.addValidationData(manualEntriesValidation);
+ chartOfAccountsSheet.addValidationData(parentValidation);
+ chartOfAccountsSheet.addValidationData(tagValidation);
+ }
+
+ private void setNames(Sheet chartOfAccountsSheet,List accountTypesNoDuplicatesList) {
+ Workbook chartOfAccountsWorkbook=chartOfAccountsSheet.getWorkbook();
+ for (Integer i=0;i();
+ for (int i = 0; i ();
+ for (String accountType: accountTypesNoDuplicatesList) {
+ startIndex=rowIndex+1;
+ Row row =chartOfAccountsSheet.createRow(rowIndex);
+ writeString(ChartOfAcountsConstants.LOOKUP_ACCOUNT_TYPE_COL,row,accountType);
+ List accountNamesandTags =accountTypeToAccountNameAndTag.get(accountType);
+ if (!accountNamesandTags.isEmpty()){
+ for (String accountNameandTag:accountNamesandTags) {
+ if (chartOfAccountsSheet.getRow(rowIndex)!=null){
+ String accountNameAndTagAr[]=accountNameandTag.split("-");
+ writeString(ChartOfAcountsConstants.LOOKUP_ACCOUNT_NAME_COL,row,accountNameAndTagAr[0]);
+ writeString(ChartOfAcountsConstants.LOOKUP_ACCOUNT_ID_COL,row,accountNameAndTagAr[1]);
+ writeString(ChartOfAcountsConstants.LOOKUP_TAG_COL,row,accountNameAndTagAr[2]);
+ writeString(ChartOfAcountsConstants.LOOKUP_TAG_ID_COL,row,accountNameAndTagAr[3]);
+ rowIndex++;
+ }else{
+ row =chartOfAccountsSheet.createRow(rowIndex);
+ String accountNameAndTagAr[]=accountNameandTag.split("-");
+ writeString(ChartOfAcountsConstants.LOOKUP_ACCOUNT_NAME_COL,row,accountNameAndTagAr[0]);
+ writeString(ChartOfAcountsConstants.LOOKUP_ACCOUNT_ID_COL,row,accountNameAndTagAr[1]);
+ writeString(ChartOfAcountsConstants.LOOKUP_TAG_COL,row,accountNameAndTagAr[2]);
+ writeString(ChartOfAcountsConstants.LOOKUP_TAG_ID_COL,row,accountNameAndTagAr[3]);
+ rowIndex++;
+ }
+ }
+ accountTypeToBeginEndIndexesofAccountNames.put(accountTypeIndex++,new Integer[]{startIndex,rowIndex});
+ }else {
+ accountTypeIndex++;
+ }
+ }
+ }
+
+ private void setLayout(Sheet chartOfAccountsSheet) {
+ Row rowHeader=chartOfAccountsSheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.ACCOUNT_TYPE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.ACCOUNT_NAME_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.ACCOUNT_USAGE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.MANUAL_ENTRIES_ALLOWED_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.PARENT_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.PARENT_ID_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.GL_CODE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.TAG_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.TAG_ID_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.DESCRIPTION_COL,TemplatePopulateImportConstants.EXTRALARGE_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.LOOKUP_ACCOUNT_TYPE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.LOOKUP_ACCOUNT_NAME_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.LOOKUP_ACCOUNT_ID_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.LOOKUP_TAG_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ chartOfAccountsSheet.setColumnWidth(ChartOfAcountsConstants.LOOKUP_TAG_ID_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+
+ writeString(ChartOfAcountsConstants.ACCOUNT_TYPE_COL,rowHeader,"Account Type*");
+ writeString(ChartOfAcountsConstants.GL_CODE_COL,rowHeader,"GL Code *");
+ writeString(ChartOfAcountsConstants.ACCOUNT_USAGE_COL,rowHeader,"Account Usage *");
+ writeString(ChartOfAcountsConstants.MANUAL_ENTRIES_ALLOWED_COL,rowHeader,"Manual entries allowed *");
+ writeString(ChartOfAcountsConstants.PARENT_COL,rowHeader,"Parent");
+ writeString(ChartOfAcountsConstants.PARENT_ID_COL,rowHeader,"Parent Id");
+ writeString(ChartOfAcountsConstants.ACCOUNT_NAME_COL,rowHeader,"Account Name");
+ writeString(ChartOfAcountsConstants.TAG_COL,rowHeader,"Tag *");
+ writeString(ChartOfAcountsConstants.TAG_ID_COL,rowHeader,"Tag Id");
+ writeString(ChartOfAcountsConstants.DESCRIPTION_COL,rowHeader,"Description *");
+ writeString(ChartOfAcountsConstants.LOOKUP_ACCOUNT_TYPE_COL,rowHeader,"Lookup Account type");
+ writeString(ChartOfAcountsConstants.LOOKUP_TAG_COL,rowHeader,"Lookup Tag");
+ writeString(ChartOfAcountsConstants.LOOKUP_TAG_ID_COL,rowHeader,"Lookup Tag Id");
+ writeString(ChartOfAcountsConstants.LOOKUP_ACCOUNT_NAME_COL,rowHeader,"Lookup Account name *");
+ writeString(ChartOfAcountsConstants.LOOKUP_ACCOUNT_ID_COL,rowHeader,"Lookup Account Id");
+
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/client/ClientEntityWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/client/ClientEntityWorkbookPopulator.java
new file mode 100644
index 000000000..9907985b3
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/client/ClientEntityWorkbookPopulator.java
@@ -0,0 +1,405 @@
+/**
+ * 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.client;
+
+import org.apache.fineract.infrastructure.bulkimport.constants.ClientEntityConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.AbstractWorkbookPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.OfficeSheetPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.PersonnelSheetPopulator;
+import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.List;
+
+public class ClientEntityWorkbookPopulator extends AbstractWorkbookPopulator {
+
+ private OfficeSheetPopulator officeSheetPopulator;
+ private PersonnelSheetPopulator personnelSheetPopulator;
+ private List clientTypeCodeValues;
+ private List constitutionCodeValues;
+ private List clientClassificationCodeValues;
+ private List addressTypesCodeValues;
+ private List stateProvinceCodeValues;
+ private List countryCodeValues;
+ private List mainBusinesslineCodeValues;
+
+
+ public ClientEntityWorkbookPopulator(OfficeSheetPopulator officeSheetPopulator,
+ PersonnelSheetPopulator personnelSheetPopulator,ListclientTypeCodeValues,
+ ListconstitutionCodeValues,ListmainBusinessline ,
+ ListclientClassification,ListaddressTypesCodeValues,
+ ListstateProvinceCodeValues,ListcountryCodeValues ) {
+ this.officeSheetPopulator = officeSheetPopulator;
+ this.personnelSheetPopulator = personnelSheetPopulator;
+ this.clientTypeCodeValues=clientTypeCodeValues;
+ this.constitutionCodeValues=constitutionCodeValues;
+ this.clientClassificationCodeValues=clientClassification;
+ this.addressTypesCodeValues=addressTypesCodeValues;
+ this.stateProvinceCodeValues=stateProvinceCodeValues;
+ this.countryCodeValues=countryCodeValues;
+ this.mainBusinesslineCodeValues=mainBusinessline;
+ }
+
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet clientSheet = workbook.createSheet(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME);
+ personnelSheetPopulator.populate(workbook,dateFormat);
+ officeSheetPopulator.populate(workbook,dateFormat);
+ setLayout(clientSheet);
+ setOfficeDateLookupTable(clientSheet, officeSheetPopulator.getOffices(),
+ ClientEntityConstants.RELATIONAL_OFFICE_NAME_COL, ClientEntityConstants.RELATIONAL_OFFICE_OPENING_DATE_COL,dateFormat);
+ setClientDataLookupTable(clientSheet);
+ setRules(clientSheet,dateFormat);
+ }
+
+ private void setClientDataLookupTable(Sheet clientSheet) {
+ int rowIndex=0;
+ for (CodeValueData clientTypeCodeValue:clientTypeCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientEntityConstants.LOOKUP_CLIENT_TYPES,row,clientTypeCodeValue.getName()+"-"+clientTypeCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData clientClassificationCodeValue:clientClassificationCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientEntityConstants.LOOKUP_CLIENT_CLASSIFICATION,row,
+ clientClassificationCodeValue.getName()+"-"+clientClassificationCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData constitutionCodeValue:constitutionCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientEntityConstants.LOOKUP_CONSTITUTION_COL,row,
+ constitutionCodeValue.getName()+"-"+constitutionCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData mainBusinessCodeValue:mainBusinesslineCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientEntityConstants.LOOKUP_MAIN_BUSINESS_LINE,row,
+ mainBusinessCodeValue.getName()+"-"+mainBusinessCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData addressTypeCodeValue:addressTypesCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientEntityConstants.LOOKUP_ADDRESS_TYPE,row,
+ addressTypeCodeValue.getName()+"-"+addressTypeCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData stateCodeValue:stateProvinceCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientEntityConstants.LOOKUP_STATE_PROVINCE,row,
+ stateCodeValue.getName()+"-"+stateCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData countryCodeValue: countryCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientEntityConstants.LOOKUP_COUNTRY,row,
+ countryCodeValue.getName()+"-"+countryCodeValue.getId());
+ }
+
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(ClientEntityConstants.NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(ClientEntityConstants.NAME_COL, rowHeader, "Name*");
+ worksheet.setColumnWidth(ClientEntityConstants.OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.STAFF_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.INCOPORATION_DATE_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.INCOPORATION_VALID_TILL_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.MOBILE_NO_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.CLIENT_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.CLIENT_CLASSIFICATION_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.INCOPORATION_NUMBER_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.MAIN_BUSINESS_LINE,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.CONSTITUTION_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.REMARKS_COL,TemplatePopulateImportConstants.LARGE_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.EXTERNAL_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.SUBMITTED_ON_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.ACTIVE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.ACTIVATION_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.ADDRESS_ENABLED,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.ADDRESS_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.STREET_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.ADDRESS_LINE_1_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.ADDRESS_LINE_2_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.ADDRESS_LINE_3_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.CITY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.STATE_PROVINCE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.COUNTRY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.POSTAL_CODE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.IS_ACTIVE_ADDRESS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.WARNING_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+
+ worksheet.setColumnWidth(ClientEntityConstants.RELATIONAL_OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.RELATIONAL_OFFICE_OPENING_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.LOOKUP_CONSTITUTION_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.LOOKUP_CLIENT_TYPES,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.LOOKUP_CLIENT_CLASSIFICATION,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.LOOKUP_ADDRESS_TYPE,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.LOOKUP_STATE_PROVINCE,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.LOOKUP_COUNTRY,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientEntityConstants.LOOKUP_MAIN_BUSINESS_LINE,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(ClientEntityConstants.NAME_COL,rowHeader,"Name");
+ writeString(ClientEntityConstants.OFFICE_NAME_COL, rowHeader, "Office Name*");
+ writeString(ClientEntityConstants.STAFF_NAME_COL, rowHeader, "Staff Name");
+ writeString(ClientEntityConstants.INCOPORATION_DATE_COL,rowHeader,"Incorporation Date");
+ writeString(ClientEntityConstants.INCOPORATION_VALID_TILL_COL,rowHeader,"Incorporation Validity Till Date");
+ writeString(ClientEntityConstants.MOBILE_NO_COL, rowHeader, "Mobile number");
+ writeString(ClientEntityConstants.CLIENT_TYPE_COL, rowHeader, "Client Type ");
+ writeString(ClientEntityConstants.CLIENT_CLASSIFICATION_COL, rowHeader, "Client Classification ");
+ writeString(ClientEntityConstants.INCOPORATION_NUMBER_COL,rowHeader,"Incorporation Number");
+ writeString(ClientEntityConstants.MAIN_BUSINESS_LINE,rowHeader,"Main Business Line");
+ writeString(ClientEntityConstants.CONSTITUTION_COL,rowHeader,"Constitution");
+ writeString(ClientEntityConstants.REMARKS_COL,rowHeader,"Remarks");
+ writeString(ClientEntityConstants.EXTERNAL_ID_COL, rowHeader, "External ID ");
+ writeString(ClientEntityConstants.SUBMITTED_ON_COL,rowHeader,"Submitted On Date");
+ writeString(ClientEntityConstants.ACTIVE_COL, rowHeader, "Active*");
+ writeString(ClientEntityConstants.ACTIVATION_DATE_COL, rowHeader, "Activation Date ");
+ writeString(ClientEntityConstants.ADDRESS_ENABLED,rowHeader,"Address Enabled ");
+ writeString(ClientEntityConstants.ADDRESS_TYPE_COL, rowHeader, "Address Type ");
+ writeString(ClientEntityConstants.STREET_COL, rowHeader, "Street ");
+ writeString(ClientEntityConstants.ADDRESS_LINE_1_COL, rowHeader, "Address Line 1");
+ writeString(ClientEntityConstants.ADDRESS_LINE_2_COL, rowHeader, "Address Line 2");
+ writeString(ClientEntityConstants.ADDRESS_LINE_3_COL, rowHeader, "Address Line 3");
+ writeString(ClientEntityConstants.CITY_COL, rowHeader, "City");
+ writeString(ClientEntityConstants.STATE_PROVINCE_COL, rowHeader, "State/ Province");
+ writeString(ClientEntityConstants.COUNTRY_COL, rowHeader, "Country");
+ writeString(ClientEntityConstants.POSTAL_CODE_COL, rowHeader, "Postal Code");
+ writeString(ClientEntityConstants.IS_ACTIVE_ADDRESS_COL, rowHeader, "Is active Address ? ");
+ writeString(ClientEntityConstants.WARNING_COL, rowHeader, "All * marked fields are compulsory.");
+
+ writeString(ClientEntityConstants.RELATIONAL_OFFICE_NAME_COL, rowHeader, "Lookup office Name ");
+ writeString(ClientEntityConstants.RELATIONAL_OFFICE_OPENING_DATE_COL, rowHeader, "Lookup Office Opened Date ");
+ writeString(ClientEntityConstants.LOOKUP_CONSTITUTION_COL, rowHeader, "Lookup Constitution ");
+ writeString(ClientEntityConstants.LOOKUP_CLIENT_TYPES, rowHeader, "Lookup Client Types ");
+ writeString(ClientEntityConstants.LOOKUP_CLIENT_CLASSIFICATION, rowHeader, "Lookup Client Classification ");
+ writeString(ClientEntityConstants.LOOKUP_ADDRESS_TYPE, rowHeader, "Lookup AddressType ");
+ writeString(ClientEntityConstants.LOOKUP_STATE_PROVINCE, rowHeader, "Lookup State/Province ");
+ writeString(ClientEntityConstants.LOOKUP_COUNTRY, rowHeader, "Lookup Country ");
+ writeString(ClientEntityConstants.LOOKUP_MAIN_BUSINESS_LINE,rowHeader,"Lookup Business Line");
+
+
+ }
+
+ private void setRules(Sheet worksheet,String dateFormat) {
+ CellRangeAddressList officeNameRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.OFFICE_NAME_COL,
+ ClientEntityConstants.OFFICE_NAME_COL);
+ CellRangeAddressList staffNameRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.STAFF_NAME_COL, ClientEntityConstants.STAFF_NAME_COL);
+ CellRangeAddressList submittedOnDateRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.SUBMITTED_ON_COL,ClientEntityConstants. SUBMITTED_ON_COL);
+ CellRangeAddressList dateRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientEntityConstants. ACTIVATION_DATE_COL,ClientEntityConstants. ACTIVATION_DATE_COL);
+ CellRangeAddressList activeRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientEntityConstants. ACTIVE_COL,ClientEntityConstants. ACTIVE_COL);
+ CellRangeAddressList clientTypeRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientEntityConstants. CLIENT_TYPE_COL,ClientEntityConstants. CLIENT_TYPE_COL);
+ CellRangeAddressList constitutionRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.CONSTITUTION_COL,ClientEntityConstants. CONSTITUTION_COL);
+ CellRangeAddressList mainBusinessLineRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientEntityConstants. MAIN_BUSINESS_LINE,ClientEntityConstants. MAIN_BUSINESS_LINE);
+ CellRangeAddressList clientClassificationRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.CLIENT_CLASSIFICATION_COL,
+ ClientEntityConstants.CLIENT_CLASSIFICATION_COL);
+ CellRangeAddressList enabledAddressRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.ADDRESS_ENABLED, ClientEntityConstants.ADDRESS_ENABLED);
+ CellRangeAddressList addressTypeRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.ADDRESS_TYPE_COL,ClientEntityConstants. ADDRESS_TYPE_COL);
+ CellRangeAddressList stateProvinceRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.STATE_PROVINCE_COL,ClientEntityConstants. STATE_PROVINCE_COL);
+ CellRangeAddressList countryRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientEntityConstants. COUNTRY_COL,ClientEntityConstants. COUNTRY_COL);
+ CellRangeAddressList activeAddressRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientEntityConstants. IS_ACTIVE_ADDRESS_COL,ClientEntityConstants. IS_ACTIVE_ADDRESS_COL);
+ CellRangeAddressList incorporateDateRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.INCOPORATION_DATE_COL,ClientEntityConstants.INCOPORATION_DATE_COL);
+ CellRangeAddressList incorporateDateTillRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientEntityConstants.INCOPORATION_VALID_TILL_COL,
+ ClientEntityConstants.INCOPORATION_VALID_TILL_COL);
+
+
+ DataValidationHelper validationHelper = new HSSFDataValidationHelper((HSSFSheet) worksheet);
+
+ List offices = officeSheetPopulator.getOffices();
+ setNames(worksheet, offices);
+
+ DataValidationConstraint officeNameConstraint =
+ validationHelper.createFormulaListConstraint("Office");
+ DataValidationConstraint staffNameConstraint =
+ validationHelper.createFormulaListConstraint("INDIRECT(CONCATENATE(\"Staff_\",$B1))");
+ DataValidationConstraint submittedOnDateConstraint =
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.LESS_OR_EQUAL,
+ "=$O1" ,null, dateFormat);
+ DataValidationConstraint activationDateConstraint =
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN,
+ "=VLOOKUP($B1,$AJ$2:$AK" + (offices.size() + 1) + ",2,FALSE)", "=TODAY()", dateFormat);
+ DataValidationConstraint activeConstraint =
+ validationHelper.createExplicitListConstraint(new String[] {"True", "False"});
+ DataValidationConstraint clientTypesConstraint =
+ validationHelper.createFormulaListConstraint("ClientTypes");
+ DataValidationConstraint constitutionConstraint =
+ validationHelper.createFormulaListConstraint("Constitution");
+ DataValidationConstraint mainBusinessLineConstraint =
+ validationHelper.createFormulaListConstraint("MainBusinessLine");
+ DataValidationConstraint clientClassificationConstraint =
+ validationHelper.createFormulaListConstraint("ClientClassification");
+ DataValidationConstraint enabledAddressConstraint =
+ validationHelper.createExplicitListConstraint(new String[] {"True", "False"});
+ DataValidationConstraint addressTypeConstraint =
+ validationHelper.createFormulaListConstraint("AddressType");
+ DataValidationConstraint stateProvinceConstraint =
+ validationHelper.createFormulaListConstraint("StateProvince");
+ DataValidationConstraint countryConstraint =
+ validationHelper.createFormulaListConstraint("Country");
+ DataValidationConstraint activeAddressConstraint =
+ validationHelper.createExplicitListConstraint(new String[] {"True", "False"});
+ DataValidationConstraint incorpDateConstraint=
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.LESS_OR_EQUAL,
+ "=TODAY()",null,dateFormat);
+ DataValidationConstraint incorpDateTillConstraint=
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL,
+ "=TODAY()",null,dateFormat);
+
+
+ DataValidation officeValidation =
+ validationHelper.createValidation(officeNameConstraint, officeNameRange);
+ DataValidation staffValidation =
+ validationHelper.createValidation(staffNameConstraint, staffNameRange);
+ DataValidation submittedOnDateValidation =
+ validationHelper.createValidation(submittedOnDateConstraint, submittedOnDateRange);
+ DataValidation activationDateValidation =
+ validationHelper.createValidation(activationDateConstraint, dateRange);
+ DataValidation activeValidation =
+ validationHelper.createValidation(activeConstraint, activeRange);
+ DataValidation clientTypeValidation =
+ validationHelper.createValidation(clientTypesConstraint, clientTypeRange);
+ DataValidation constitutionValidation =
+ validationHelper.createValidation(constitutionConstraint,constitutionRange);
+ DataValidation mainBusinessLineValidation =
+ validationHelper.createValidation(mainBusinessLineConstraint,mainBusinessLineRange);
+ DataValidation clientClassificationValidation =
+ validationHelper.createValidation(clientClassificationConstraint, clientClassificationRange);
+ DataValidation enabledAddressValidation=
+ validationHelper.createValidation(enabledAddressConstraint,enabledAddressRange);
+ DataValidation addressTypeValidation =
+ validationHelper.createValidation(addressTypeConstraint, addressTypeRange);
+ DataValidation stateProvinceValidation =
+ validationHelper.createValidation(stateProvinceConstraint, stateProvinceRange);
+ DataValidation countryValidation =
+ validationHelper.createValidation(countryConstraint, countryRange);
+ DataValidation activeAddressValidation =
+ validationHelper.createValidation(activeAddressConstraint,activeAddressRange);
+ DataValidation incorporateDateValidation=validationHelper.createValidation(incorpDateConstraint,incorporateDateRange);
+ DataValidation incorporateDateTillValidation=validationHelper.createValidation(incorpDateTillConstraint,incorporateDateTillRange);
+
+ worksheet.addValidationData(activeValidation);
+ worksheet.addValidationData(officeValidation);
+ worksheet.addValidationData(staffValidation);
+ worksheet.addValidationData(activationDateValidation);
+ worksheet.addValidationData(submittedOnDateValidation);
+ worksheet.addValidationData(clientTypeValidation);
+ worksheet.addValidationData(constitutionValidation);
+ worksheet.addValidationData(mainBusinessLineValidation);
+ worksheet.addValidationData(clientClassificationValidation);
+ worksheet.addValidationData(enabledAddressValidation);
+ worksheet.addValidationData(addressTypeValidation);
+ worksheet.addValidationData(stateProvinceValidation);
+ worksheet.addValidationData(countryValidation);
+ worksheet.addValidationData(activeAddressValidation);
+ worksheet.addValidationData(incorporateDateValidation);
+ worksheet.addValidationData(incorporateDateTillValidation);
+ }
+
+ private void setNames(Sheet worksheet, List offices) {
+ Workbook clientWorkbook = worksheet.getWorkbook();
+ Name officeGroup = clientWorkbook.createName();
+ officeGroup.setNameName("Office");
+ officeGroup.setRefersToFormula(TemplatePopulateImportConstants.OFFICE_SHEET_NAME+"!$B$2:$B$" + (offices.size() + 1));
+
+ Name clientTypeGroup = clientWorkbook.createName();
+ clientTypeGroup.setNameName("ClientTypes");
+ clientTypeGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME+"!$AN$2:$AN$" +
+ (clientTypeCodeValues.size() + 1));
+
+ Name constitutionGroup = clientWorkbook.createName();
+ constitutionGroup.setNameName("Constitution");
+ constitutionGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME+"!$AL$2:$AL$" +
+ (constitutionCodeValues.size() + 1));
+
+ Name mainBusinessLineGroup = clientWorkbook.createName();
+ mainBusinessLineGroup.setNameName("MainBusinessLine");
+ mainBusinessLineGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME+"!$AR$2:$AR$" +
+ (mainBusinesslineCodeValues.size() + 1));
+
+ Name clientClassficationGroup = clientWorkbook.createName();
+ clientClassficationGroup.setNameName("ClientClassification");
+ clientClassficationGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME+"!$AM$2:$AM$" +
+ (clientClassificationCodeValues.size() + 1));
+
+ Name addressTypeGroup = clientWorkbook.createName();
+ addressTypeGroup.setNameName("AddressType");
+ addressTypeGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME+
+ "!$AO$2:$AO$" + (addressTypesCodeValues.size() + 1));
+
+ Name stateProvinceGroup = clientWorkbook.createName();
+ stateProvinceGroup.setNameName("StateProvince");
+ stateProvinceGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME+
+ "!$AP$2:$AP$" + (stateProvinceCodeValues.size() + 1));
+
+ Name countryGroup = clientWorkbook.createName();
+ countryGroup.setNameName("Country");
+ countryGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME+"!$AQ$2:$AQ$" +
+ (countryCodeValues.size() + 1));
+
+ for (Integer i = 0; i < offices.size(); i++) {
+ Integer[] officeNameToBeginEndIndexesOfStaff =
+ personnelSheetPopulator.getOfficeNameToBeginEndIndexesOfStaff().get(i);
+ if (officeNameToBeginEndIndexesOfStaff != null) {
+ Name name = clientWorkbook.createName();
+ name.setNameName("Staff_" + offices.get(i).name().trim().replaceAll("[ )(]", "_"));
+ name.setRefersToFormula(TemplatePopulateImportConstants.STAFF_SHEET_NAME+"!$B$" +
+ officeNameToBeginEndIndexesOfStaff[0] + ":$B$"
+ + officeNameToBeginEndIndexesOfStaff[1]);
+ }
+ }
+ }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/client/ClientPersonWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/client/ClientPersonWorkbookPopulator.java
new file mode 100644
index 000000000..69d11192a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/client/ClientPersonWorkbookPopulator.java
@@ -0,0 +1,370 @@
+/**
+ * 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.client;
+
+import org.apache.fineract.infrastructure.bulkimport.constants.ClientPersonConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.AbstractWorkbookPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.OfficeSheetPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.PersonnelSheetPopulator;
+import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.List;
+
+public class ClientPersonWorkbookPopulator extends AbstractWorkbookPopulator {
+
+ private OfficeSheetPopulator officeSheetPopulator;
+ private PersonnelSheetPopulator personnelSheetPopulator;
+ private ListclientTypeCodeValues;
+ private ListgenderCodeValues;
+ private ListclientClassificationCodeValues;
+ private ListaddressTypesCodeValues;
+ private ListstateProvinceCodeValues;
+ private ListcountryCodeValues;
+
+
+ public ClientPersonWorkbookPopulator(OfficeSheetPopulator officeSheetPopulator,
+ PersonnelSheetPopulator personnelSheetPopulator,ListclientTypeCodeValues,
+ ListgenderCodeValues, ListclientClassification,ListaddressTypesCodeValues,
+ ListstateProvinceCodeValues,ListcountryCodeValues ) {
+ this.officeSheetPopulator = officeSheetPopulator;
+ this.personnelSheetPopulator = personnelSheetPopulator;
+ this.clientTypeCodeValues=clientTypeCodeValues;
+ this.genderCodeValues=genderCodeValues;
+ this.clientClassificationCodeValues=clientClassification;
+ this.addressTypesCodeValues=addressTypesCodeValues;
+ this.stateProvinceCodeValues=stateProvinceCodeValues;
+ this.countryCodeValues=countryCodeValues;
+ }
+
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet clientSheet = workbook.createSheet(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME);
+ personnelSheetPopulator.populate(workbook,dateFormat);
+ officeSheetPopulator.populate(workbook,dateFormat);
+ setLayout(clientSheet);
+ setOfficeDateLookupTable(clientSheet, officeSheetPopulator.getOffices(),
+ ClientPersonConstants.RELATIONAL_OFFICE_NAME_COL, ClientPersonConstants.RELATIONAL_OFFICE_OPENING_DATE_COL,dateFormat);
+ setClientDataLookupTable(clientSheet);
+ setRules(clientSheet,dateFormat);
+ }
+
+ private void setClientDataLookupTable(Sheet clientSheet) {
+ int rowIndex=0;
+ for (CodeValueData clientTypeCodeValue:clientTypeCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientPersonConstants.LOOKUP_CLIENT_TYPES_COL,row,clientTypeCodeValue.getName()+
+ "-"+clientTypeCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData clientClassificationCodeValue:clientClassificationCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientPersonConstants.LOOKUP_CLIENT_CLASSIFICATION_COL,row,
+ clientClassificationCodeValue.getName()+"-"+clientClassificationCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData genderCodeValue:genderCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientPersonConstants.LOOKUP_GENDER_COL,row,genderCodeValue.getName()+"-"+genderCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData addressTypeCodeValue:addressTypesCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientPersonConstants.LOOKUP_ADDRESS_TYPE_COL,row,
+ addressTypeCodeValue.getName()+"-"+addressTypeCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData stateCodeValue:stateProvinceCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientPersonConstants.LOOKUP_STATE_PROVINCE_COL,row,stateCodeValue.getName()+"-"+stateCodeValue.getId());
+ }
+ rowIndex=0;
+ for (CodeValueData countryCodeValue: countryCodeValues) {
+ Row row =clientSheet.getRow(++rowIndex);
+ if(row==null)
+ row=clientSheet.createRow(rowIndex);
+ writeString(ClientPersonConstants.LOOKUP_COUNTRY_COL,row,countryCodeValue.getName()+"-"+countryCodeValue.getId());
+ }
+
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(ClientPersonConstants.FIRST_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.LAST_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.MIDDLE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ writeString(ClientPersonConstants.FIRST_NAME_COL, rowHeader, "First Name*");
+ writeString(ClientPersonConstants.LAST_NAME_COL, rowHeader, "Last Name*");
+ writeString(ClientPersonConstants.MIDDLE_NAME_COL, rowHeader, "Middle Name");
+ worksheet.setColumnWidth(ClientPersonConstants.OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.STAFF_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.EXTERNAL_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.SUBMITTED_ON_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.ACTIVATION_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.ACTIVE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.MOBILE_NO_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.DOB_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.CLIENT_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.GENDER_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.CLIENT_CLASSIFICATION_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.IS_STAFF_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.ADDRESS_ENABLED_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.ADDRESS_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.STREET_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.ADDRESS_LINE_1_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.ADDRESS_LINE_2_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.ADDRESS_LINE_3_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.CITY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.STATE_PROVINCE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.COUNTRY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.POSTAL_CODE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.IS_ACTIVE_ADDRESS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.WARNING_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+
+ worksheet.setColumnWidth(ClientPersonConstants.RELATIONAL_OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.RELATIONAL_OFFICE_OPENING_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.LOOKUP_GENDER_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.LOOKUP_CLIENT_TYPES_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.LOOKUP_CLIENT_CLASSIFICATION_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.LOOKUP_ADDRESS_TYPE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.LOOKUP_STATE_PROVINCE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(ClientPersonConstants.LOOKUP_COUNTRY_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ writeString(ClientPersonConstants.OFFICE_NAME_COL, rowHeader, "Office Name*");
+ writeString(ClientPersonConstants.STAFF_NAME_COL, rowHeader, "Staff Name");
+ writeString(ClientPersonConstants.EXTERNAL_ID_COL, rowHeader, "External ID ");
+ writeString(ClientPersonConstants.SUBMITTED_ON_COL,rowHeader,"Submitted On Date");
+ writeString(ClientPersonConstants.ACTIVATION_DATE_COL, rowHeader, "Activation date");
+ writeString(ClientPersonConstants.ACTIVE_COL, rowHeader, "Active*");
+ writeString(ClientPersonConstants.MOBILE_NO_COL, rowHeader, "Mobile number");
+ writeString(ClientPersonConstants.DOB_COL, rowHeader, "Date of Birth ");
+ writeString(ClientPersonConstants.CLIENT_TYPE_COL, rowHeader, "Client Type ");
+ writeString(ClientPersonConstants.IS_STAFF_COL, rowHeader, "Is a staff memeber ");
+ writeString(ClientPersonConstants.GENDER_COL, rowHeader, "Gender ");
+ writeString(ClientPersonConstants.ADDRESS_ENABLED_COL,rowHeader,"Address Enabled *");
+ writeString(ClientPersonConstants.CLIENT_CLASSIFICATION_COL, rowHeader, "Client Classification ");
+ writeString(ClientPersonConstants.ADDRESS_TYPE_COL, rowHeader, "Address Type ");
+ writeString(ClientPersonConstants.STREET_COL, rowHeader, "Street ");
+ writeString(ClientPersonConstants.ADDRESS_LINE_1_COL, rowHeader, "Address Line 1");
+ writeString(ClientPersonConstants.ADDRESS_LINE_2_COL, rowHeader, "Address Line 2");
+ writeString(ClientPersonConstants.ADDRESS_LINE_3_COL, rowHeader, "Address Line 3 ");
+ writeString(ClientPersonConstants.CITY_COL, rowHeader, "City ");
+ writeString(ClientPersonConstants.STATE_PROVINCE_COL, rowHeader, "State/ Province ");
+ writeString(ClientPersonConstants.COUNTRY_COL, rowHeader, "Country ");
+ writeString(ClientPersonConstants.POSTAL_CODE_COL, rowHeader, "Postal Code ");
+ writeString(ClientPersonConstants.IS_ACTIVE_ADDRESS_COL, rowHeader, "Is active Address ? ");
+ writeString(ClientPersonConstants.WARNING_COL, rowHeader, "All * marked fields are compulsory.");
+
+ writeString(ClientPersonConstants.RELATIONAL_OFFICE_NAME_COL, rowHeader, "Lookup office Name ");
+ writeString(ClientPersonConstants.RELATIONAL_OFFICE_OPENING_DATE_COL, rowHeader, "Lookup Office Opened Date ");
+ writeString(ClientPersonConstants.LOOKUP_GENDER_COL, rowHeader, "Lookup Gender ");
+ writeString(ClientPersonConstants.LOOKUP_CLIENT_TYPES_COL, rowHeader, "Lookup Client Types ");
+ writeString(ClientPersonConstants.LOOKUP_CLIENT_CLASSIFICATION_COL, rowHeader, "Lookup Client Classification ");
+ writeString(ClientPersonConstants.LOOKUP_ADDRESS_TYPE_COL, rowHeader, "Lookup AddressType ");
+ writeString(ClientPersonConstants.LOOKUP_STATE_PROVINCE_COL, rowHeader, "Lookup State/Province ");
+ writeString(ClientPersonConstants.LOOKUP_COUNTRY_COL, rowHeader, "Lookup Country ");
+
+
+ }
+
+ private void setRules(Sheet worksheet,String dateformat) {
+ CellRangeAddressList officeNameRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientPersonConstants.OFFICE_NAME_COL, ClientPersonConstants.OFFICE_NAME_COL);
+ CellRangeAddressList staffNameRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientPersonConstants. STAFF_NAME_COL,ClientPersonConstants. STAFF_NAME_COL);
+ CellRangeAddressList submittedOnDateRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientPersonConstants. SUBMITTED_ON_COL, ClientPersonConstants.SUBMITTED_ON_COL);
+ CellRangeAddressList activationDateRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientPersonConstants.ACTIVATION_DATE_COL, ClientPersonConstants.ACTIVATION_DATE_COL);
+ CellRangeAddressList activeRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientPersonConstants.ACTIVE_COL,ClientPersonConstants. ACTIVE_COL);
+ CellRangeAddressList clientTypeRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientPersonConstants. CLIENT_TYPE_COL,ClientPersonConstants. CLIENT_TYPE_COL);
+ CellRangeAddressList dobRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientPersonConstants. DOB_COL,ClientPersonConstants. DOB_COL);
+ CellRangeAddressList isStaffRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientPersonConstants. IS_STAFF_COL,ClientPersonConstants. IS_STAFF_COL);
+ CellRangeAddressList genderRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientPersonConstants.GENDER_COL,ClientPersonConstants. GENDER_COL);
+ CellRangeAddressList clientClassificationRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientPersonConstants.CLIENT_CLASSIFICATION_COL, ClientPersonConstants.CLIENT_CLASSIFICATION_COL);
+ CellRangeAddressList enabledAddressRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientPersonConstants.ADDRESS_ENABLED_COL, ClientPersonConstants.ADDRESS_ENABLED_COL);
+ CellRangeAddressList addressTypeRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientPersonConstants. ADDRESS_TYPE_COL, ClientPersonConstants.ADDRESS_TYPE_COL);
+ CellRangeAddressList stateProvinceRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientPersonConstants. STATE_PROVINCE_COL, ClientPersonConstants.STATE_PROVINCE_COL);
+ CellRangeAddressList countryRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), ClientPersonConstants.COUNTRY_COL, ClientPersonConstants.COUNTRY_COL);
+ CellRangeAddressList activeAddressRange=new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(),ClientPersonConstants. IS_ACTIVE_ADDRESS_COL,ClientPersonConstants. IS_ACTIVE_ADDRESS_COL);
+
+
+ DataValidationHelper validationHelper = new HSSFDataValidationHelper((HSSFSheet) worksheet);
+
+ List offices = officeSheetPopulator.getOffices();
+ setNames(worksheet, offices);
+
+ DataValidationConstraint officeNameConstraint =
+ validationHelper.createFormulaListConstraint("Office");
+ DataValidationConstraint staffNameConstraint =
+ validationHelper.createFormulaListConstraint("INDIRECT(CONCATENATE(\"Staff_\",$D1))");
+ DataValidationConstraint submittedOnDateConstraint =
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.LESS_OR_EQUAL,
+ "=$I1" ,null,dateformat);
+ DataValidationConstraint activationDateConstraint =
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN,
+ "=VLOOKUP($D1,$AJ$2:$AK" + (offices.size() + 1) + ",2,FALSE)", "=TODAY()", dateformat);
+ DataValidationConstraint dobDateConstraint =
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.LESS_OR_EQUAL,
+ "=TODAY()",null, dateformat);
+ DataValidationConstraint activeConstraint =
+ validationHelper.createExplicitListConstraint(new String[] {"True", "False"});
+ DataValidationConstraint clientTypesConstraint =
+ validationHelper.createFormulaListConstraint("ClientTypes");
+ DataValidationConstraint isStaffConstraint =
+ validationHelper.createExplicitListConstraint(new String[] {"True", "False"});
+ DataValidationConstraint genderConstraint =
+ validationHelper.createFormulaListConstraint("Gender");
+ DataValidationConstraint clientClassificationConstraint =
+ validationHelper.createFormulaListConstraint("ClientClassification");
+ DataValidationConstraint enabledAddressConstraint =
+ validationHelper.createExplicitListConstraint(new String[] {"True", "False"});
+ DataValidationConstraint addressTypeConstraint =
+ validationHelper.createFormulaListConstraint("AddressType");
+ DataValidationConstraint stateProvinceConstraint =
+ validationHelper.createFormulaListConstraint("StateProvince");
+ DataValidationConstraint countryConstraint =
+ validationHelper.createFormulaListConstraint("Country");
+ DataValidationConstraint activeAddressConstraint =
+ validationHelper.createExplicitListConstraint(new String[] {"True", "False"});
+
+ DataValidation officeValidation =
+ validationHelper.createValidation(officeNameConstraint, officeNameRange);
+ DataValidation staffValidation =
+ validationHelper.createValidation(staffNameConstraint, staffNameRange);
+ DataValidation submittedOnDateValidation =
+ validationHelper.createValidation(submittedOnDateConstraint, submittedOnDateRange);
+ DataValidation activationDateValidation =
+ validationHelper.createValidation(activationDateConstraint, activationDateRange);
+ DataValidation dobDateValidation =
+ validationHelper.createValidation(dobDateConstraint, dobRange);
+ DataValidation activeValidation =
+ validationHelper.createValidation(activeConstraint, activeRange);
+ DataValidation clientTypeValidation =
+ validationHelper.createValidation(clientTypesConstraint, clientTypeRange);
+ DataValidation isStaffValidation =
+ validationHelper.createValidation(isStaffConstraint, isStaffRange);
+ DataValidation genderValidation =
+ validationHelper.createValidation(genderConstraint, genderRange);
+ DataValidation clientClassificationValidation =
+ validationHelper.createValidation(clientClassificationConstraint, clientClassificationRange);
+ DataValidation enabledAddressValidation=
+ validationHelper.createValidation(enabledAddressConstraint,enabledAddressRange);
+ DataValidation addressTypeValidation =
+ validationHelper.createValidation(addressTypeConstraint, addressTypeRange);
+ DataValidation stateProvinceValidation =
+ validationHelper.createValidation(stateProvinceConstraint, stateProvinceRange);
+ DataValidation countryValidation =
+ validationHelper.createValidation(countryConstraint, countryRange);
+ DataValidation activeAddressValidation =
+ validationHelper.createValidation(activeAddressConstraint,activeAddressRange);
+
+ worksheet.addValidationData(activeValidation);
+ worksheet.addValidationData(officeValidation);
+ worksheet.addValidationData(staffValidation);
+ worksheet.addValidationData(activationDateValidation);
+ worksheet.addValidationData(submittedOnDateValidation);
+ worksheet.addValidationData(dobDateValidation);
+ worksheet.addValidationData(clientTypeValidation);
+ worksheet.addValidationData(isStaffValidation);
+ worksheet.addValidationData(genderValidation);
+ worksheet.addValidationData(clientClassificationValidation);
+ worksheet.addValidationData(enabledAddressValidation);
+ worksheet.addValidationData(addressTypeValidation);
+ worksheet.addValidationData(stateProvinceValidation);
+ worksheet.addValidationData(countryValidation);
+ worksheet.addValidationData(activeAddressValidation);
+ }
+
+ private void setNames(Sheet worksheet, List offices) {
+ Workbook clientWorkbook = worksheet.getWorkbook();
+ Name officeGroup = clientWorkbook.createName();
+ officeGroup.setNameName("Office");
+ officeGroup.setRefersToFormula(TemplatePopulateImportConstants.OFFICE_SHEET_NAME+"!$B$2:$B$" + (offices.size() + 1));
+
+ Name clientTypeGroup = clientWorkbook.createName();
+ clientTypeGroup.setNameName("ClientTypes");
+ clientTypeGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME+"!$AN$2:$AN$" +
+ (clientTypeCodeValues.size() + 1));
+
+ Name genderGroup = clientWorkbook.createName();
+ genderGroup.setNameName("Gender");
+ genderGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME+"!$AL$2:$AL$" + (genderCodeValues.size() + 1));
+
+ Name clientClassficationGroup = clientWorkbook.createName();
+ clientClassficationGroup.setNameName("ClientClassification");
+ clientClassficationGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME+"!$AM$2:$AM$" +
+ (clientClassificationCodeValues.size() + 1));
+
+ Name addressTypeGroup = clientWorkbook.createName();
+ addressTypeGroup.setNameName("AddressType");
+ addressTypeGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME+"!$AO$2:$AO$" +
+ (addressTypesCodeValues.size() + 1));
+
+ Name stateProvinceGroup = clientWorkbook.createName();
+ stateProvinceGroup.setNameName("StateProvince");
+ stateProvinceGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME+"!$AP$2:$AP$" +
+ (stateProvinceCodeValues.size() + 1));
+
+ Name countryGroup = clientWorkbook.createName();
+ countryGroup.setNameName("Country");
+ countryGroup.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME+"!$AQ$2:$AQ$" +
+ (countryCodeValues.size() + 1));
+
+ for (Integer i = 0; i < offices.size(); i++) {
+ Integer[] officeNameToBeginEndIndexesOfStaff =
+ personnelSheetPopulator.getOfficeNameToBeginEndIndexesOfStaff().get(i);
+ if (officeNameToBeginEndIndexesOfStaff != null) {
+ Name name = clientWorkbook.createName();
+ name.setNameName("Staff_" + offices.get(i).name().trim().replaceAll("[ )(]", "_"));
+ name.setRefersToFormula(TemplatePopulateImportConstants.STAFF_SHEET_NAME+"!$B$" +
+ officeNameToBeginEndIndexesOfStaff[0] + ":$B$" + officeNameToBeginEndIndexesOfStaff[1]);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/comparator/LoanComparatorByStatusActive.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/comparator/LoanComparatorByStatusActive.java
new file mode 100644
index 000000000..9a8157469
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/comparator/LoanComparatorByStatusActive.java
@@ -0,0 +1,52 @@
+/**
+ * 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.comparator;
+
+import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
+
+import java.util.Comparator;
+
+/**
+ * Sorting the loan values based on loan status giving priority to active loans
+ * */
+
+public class LoanComparatorByStatusActive implements Comparator {
+
+ @Override
+ public int compare(LoanAccountData o1, LoanAccountData o2) {
+
+ boolean isData1StatusActive = o1.getStatusStringValue().equals("Active");
+ boolean isData2StatusActive = o2.getStatusStringValue().equals("Active");
+
+ // if both status active, these have the same rank
+ if (isData1StatusActive && isData2StatusActive){
+ return 0;
+ }
+
+ if (isData1StatusActive){
+ return -1;
+ }
+
+ if (isData2StatusActive){
+ return 1;
+ }
+ // if no status active, these have the same rank
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/fixeddeposits/FixedDepositTransactionWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/fixeddeposits/FixedDepositTransactionWorkbookPopulator.java
new file mode 100644
index 000000000..cd7dd9bd2
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/fixeddeposits/FixedDepositTransactionWorkbookPopulator.java
@@ -0,0 +1,235 @@
+/**
+ * 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.fixeddeposits;
+
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TransactionConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.*;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
+import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+public class FixedDepositTransactionWorkbookPopulator extends AbstractWorkbookPopulator {
+ private OfficeSheetPopulator officeSheetPopulator;
+ private ClientSheetPopulator clientSheetPopulator;
+ private ExtrasSheetPopulator extrasSheetPopulator;
+
+ private ListsavingsAccounts;
+
+ public FixedDepositTransactionWorkbookPopulator(OfficeSheetPopulator officeSheetPopulator,
+ ClientSheetPopulator clientSheetPopulator, ExtrasSheetPopulator extrasSheetPopulator,
+ List savingsAccounts) {
+ this.officeSheetPopulator = officeSheetPopulator;
+ this.clientSheetPopulator = clientSheetPopulator;
+ this.extrasSheetPopulator = extrasSheetPopulator;
+ this.savingsAccounts=savingsAccounts;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet savingsTransactionSheet = workbook.createSheet(TemplatePopulateImportConstants.FIXED_DEPOSIT_TRANSACTION_SHEET_NAME);
+ setLayout(savingsTransactionSheet);
+ officeSheetPopulator.populate(workbook,dateFormat);
+ clientSheetPopulator.populate(workbook,dateFormat);
+ extrasSheetPopulator.populate(workbook,dateFormat);
+ populateSavingsTable(savingsTransactionSheet,dateFormat);
+ setRules(savingsTransactionSheet,dateFormat);
+ setDefaults(savingsTransactionSheet);
+ }
+
+ private void setDefaults(Sheet worksheet) {
+ for(Integer rowNo = 1; rowNo < 3000; rowNo++)
+ {
+ Row row = worksheet.getRow(rowNo);
+ if(row == null)
+ row = worksheet.createRow(rowNo);
+ writeFormula(TransactionConstants.PRODUCT_COL, row, "IF(ISERROR(VLOOKUP($C"+ (rowNo+1) +",$Q$2:$S$" + (savingsAccounts.size() + 1) + ",2,FALSE)),\"\",VLOOKUP($C"+ (rowNo+1) +",$Q$2:$S$" + (savingsAccounts.size() + 1) + ",2,FALSE))");
+ writeFormula(TransactionConstants.OPENING_BALANCE_COL, row, "IF(ISERROR(VLOOKUP($C"+ (rowNo+1) +",$Q$2:$S$" + (savingsAccounts.size() + 1) + ",3,FALSE)),\"\",VLOOKUP($C"+ (rowNo+1) +",$Q$2:$S$" + (savingsAccounts.size() + 1) + ",3,FALSE))");
+ }
+ }
+
+
+ private void setRules(Sheet worksheet,String dateFormat) {
+ CellRangeAddressList officeNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ TransactionConstants.OFFICE_NAME_COL, TransactionConstants.OFFICE_NAME_COL);
+ CellRangeAddressList clientNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ TransactionConstants.CLIENT_NAME_COL, TransactionConstants.CLIENT_NAME_COL);
+ CellRangeAddressList accountNumberRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ TransactionConstants.SAVINGS_ACCOUNT_NO_COL, TransactionConstants.SAVINGS_ACCOUNT_NO_COL);
+ CellRangeAddressList transactionTypeRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ TransactionConstants.TRANSACTION_TYPE_COL, TransactionConstants.TRANSACTION_TYPE_COL);
+ CellRangeAddressList paymentTypeRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ TransactionConstants.PAYMENT_TYPE_COL, TransactionConstants.PAYMENT_TYPE_COL);
+ CellRangeAddressList transactionDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ TransactionConstants.TRANSACTION_DATE_COL, TransactionConstants.TRANSACTION_DATE_COL);
+
+ DataValidationHelper validationHelper = new HSSFDataValidationHelper((HSSFSheet)worksheet);
+
+ setNames(worksheet);
+
+ DataValidationConstraint officeNameConstraint = validationHelper.createFormulaListConstraint("Office");
+ DataValidationConstraint clientNameConstraint = validationHelper.createFormulaListConstraint("INDIRECT(CONCATENATE(\"Client_\",$A1))");
+ DataValidationConstraint accountNumberConstraint = validationHelper.createFormulaListConstraint("INDIRECT(CONCATENATE(\"Account_\",SUBSTITUTE(SUBSTITUTE(SUBSTITUTE($B1,\" \",\"_\"),\"(\",\"_\"),\")\",\"_\")))");
+ DataValidationConstraint transactionTypeConstraint = validationHelper.createExplicitListConstraint(new String[] {"Withdrawal","Deposit"});
+ DataValidationConstraint paymentTypeConstraint = validationHelper.createFormulaListConstraint("PaymentTypes");
+ DataValidationConstraint transactionDateConstraint = validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN, "=VLOOKUP($C1,$Q$2:$T$" + (savingsAccounts.size() + 1) + ",4,FALSE)", "=TODAY()", dateFormat);
+
+ DataValidation officeValidation = validationHelper.createValidation(officeNameConstraint, officeNameRange);
+ DataValidation clientValidation = validationHelper.createValidation(clientNameConstraint, clientNameRange);
+ DataValidation accountNumberValidation = validationHelper.createValidation(accountNumberConstraint, accountNumberRange);
+ DataValidation transactionTypeValidation = validationHelper.createValidation(transactionTypeConstraint, transactionTypeRange);
+ DataValidation paymentTypeValidation = validationHelper.createValidation(paymentTypeConstraint, paymentTypeRange);
+ DataValidation transactionDateValidation = validationHelper.createValidation(transactionDateConstraint, transactionDateRange);
+
+ worksheet.addValidationData(officeValidation);
+ worksheet.addValidationData(clientValidation);
+ worksheet.addValidationData(accountNumberValidation);
+ worksheet.addValidationData(transactionTypeValidation);
+ worksheet.addValidationData(paymentTypeValidation);
+ worksheet.addValidationData(transactionDateValidation);
+ }
+
+ private void setNames(Sheet worksheet) {
+ Workbook savingsTransactionWorkbook = worksheet.getWorkbook();
+ List officeNames = officeSheetPopulator.getOfficeNames();
+
+ //Office Names
+ Name officeGroup = savingsTransactionWorkbook.createName();
+ officeGroup.setNameName("Office");
+ officeGroup.setRefersToFormula(TemplatePopulateImportConstants.OFFICE_SHEET_NAME+"!$B$2:$B$" + (officeNames.size() + 1));
+
+ //Clients Named after Offices
+ for(Integer i = 0; i < officeNames.size(); i++) {
+ Integer[] officeNameToBeginEndIndexesOfClients = clientSheetPopulator.getOfficeNameToBeginEndIndexesOfClients().get(i);
+ Name name = savingsTransactionWorkbook.createName();
+ if(officeNameToBeginEndIndexesOfClients != null) {
+ name.setNameName("Client_" + officeNames.get(i).trim().replaceAll("[ )(]", "_"));
+ name.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_SHEET_NAME+"!$B$" + officeNameToBeginEndIndexesOfClients[0] + ":$B$" + officeNameToBeginEndIndexesOfClients[1]);
+ }
+ }
+
+ //Counting clients with active savings and starting and end addresses of cells for naming
+ HashMap clientNameToBeginEndIndexes = new HashMap<>();
+ ArrayList clientsWithActiveSavings = new ArrayList<>();
+ ArrayList clientIdsWithActiveSavings = new ArrayList<>();
+ int startIndex = 1, endIndex = 1;
+ String clientName = "";
+ Long clientId = null;
+ for(int i = 0; i < savingsAccounts.size(); i++){
+ if(!clientName.equals(savingsAccounts.get(i).getClientName())) {
+ endIndex = i + 1;
+ clientNameToBeginEndIndexes.put(clientName, new Integer[]{startIndex, endIndex});
+ startIndex = i + 2;
+ clientName = savingsAccounts.get(i).getClientName();
+ clientId = savingsAccounts.get(i).getClientId();
+ clientsWithActiveSavings.add(clientName);
+ clientIdsWithActiveSavings.add(clientId);
+ }
+ if(i == savingsAccounts.size()-1) {
+ endIndex = i + 2;
+ clientNameToBeginEndIndexes.put(clientName, new Integer[]{startIndex, endIndex});
+ }
+ }
+
+ //Account Number Named after Clients
+ for(int j = 0; j < clientsWithActiveSavings.size(); j++) {
+ Name name = savingsTransactionWorkbook.createName();
+ name.setNameName("Account_" + clientsWithActiveSavings.get(j).replaceAll(" ", "_") + "_" + clientIdsWithActiveSavings.get(j) + "_");
+ name.setRefersToFormula(TemplatePopulateImportConstants.FIXED_DEPOSIT_TRANSACTION_SHEET_NAME+"!$Q$" + clientNameToBeginEndIndexes.get(clientsWithActiveSavings.get(j))[0] + ":$Q$" + clientNameToBeginEndIndexes.get(clientsWithActiveSavings.get(j))[1]);
+ }
+
+ //Payment Type Name
+ Name paymentTypeGroup = savingsTransactionWorkbook.createName();
+ paymentTypeGroup.setNameName("PaymentTypes");
+ paymentTypeGroup.setRefersToFormula(TemplatePopulateImportConstants.EXTRAS_SHEET_NAME+"!$D$2:$D$" + (extrasSheetPopulator.getPaymentTypesSize() + 1));
+ }
+
+ private void populateSavingsTable(Sheet savingsTransactionSheet,String dateFormat) {
+ Workbook workbook = savingsTransactionSheet.getWorkbook();
+ CellStyle dateCellStyle = workbook.createCellStyle();
+ short df = workbook.createDataFormat().getFormat(dateFormat);
+ dateCellStyle.setDataFormat(df);
+ int rowIndex = 1;
+ Row row;
+ Collections.sort(savingsAccounts, SavingsAccountData.ClientNameComparator);
+ for(SavingsAccountData savingsAccount : savingsAccounts) {
+ row = savingsTransactionSheet.createRow(rowIndex++);
+ writeString(TransactionConstants.LOOKUP_CLIENT_NAME_COL, row, savingsAccount.getClientName() + "(" + savingsAccount.getClientId() + ")");
+ writeLong(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, row, Long.parseLong(savingsAccount.getAccountNo()));
+ writeString(TransactionConstants.LOOKUP_PRODUCT_COL, row, savingsAccount.getSavingsProductName());
+ if(savingsAccount.getMinRequiredOpeningBalance() != null)
+ writeBigDecimal(TransactionConstants.LOOKUP_OPENING_BALANCE_COL, row, savingsAccount.getMinRequiredOpeningBalance());
+ writeDate(TransactionConstants.LOOKUP_SAVINGS_ACTIVATION_DATE_COL, row,"" +
+ savingsAccount.getTimeline().getActivatedOnDate().getDayOfMonth() + "/"
+ + savingsAccount.getTimeline().getActivatedOnDate().getMonthOfYear() + "/"
+ + savingsAccount.getTimeline().getActivatedOnDate().getYear() , dateCellStyle,dateFormat);
+ }
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(TransactionConstants.OFFICE_NAME_COL, 4000);
+ worksheet.setColumnWidth(TransactionConstants.CLIENT_NAME_COL, 5000);
+ worksheet.setColumnWidth(TransactionConstants.SAVINGS_ACCOUNT_NO_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.PRODUCT_COL, 4000);
+ worksheet.setColumnWidth(TransactionConstants.OPENING_BALANCE_COL, 4000);
+ worksheet.setColumnWidth(TransactionConstants.TRANSACTION_TYPE_COL, 3300);
+ worksheet.setColumnWidth(TransactionConstants.AMOUNT_COL, 4000);
+ worksheet.setColumnWidth(TransactionConstants.TRANSACTION_DATE_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.PAYMENT_TYPE_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.ACCOUNT_NO_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.CHECK_NO_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.RECEIPT_NO_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.ROUTING_CODE_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.BANK_NO_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.LOOKUP_CLIENT_NAME_COL, 5000);
+ worksheet.setColumnWidth(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.LOOKUP_PRODUCT_COL, 3000);
+ worksheet.setColumnWidth(TransactionConstants.LOOKUP_OPENING_BALANCE_COL, 3700);
+ worksheet.setColumnWidth(TransactionConstants.LOOKUP_SAVINGS_ACTIVATION_DATE_COL, 3500);
+ writeString(TransactionConstants.OFFICE_NAME_COL, rowHeader, "Office Name*");
+ writeString(TransactionConstants.CLIENT_NAME_COL, rowHeader, "Client Name*");
+ writeString(TransactionConstants.SAVINGS_ACCOUNT_NO_COL, rowHeader, "Account No.*");
+ writeString(TransactionConstants.PRODUCT_COL, rowHeader, "Product Name");
+ writeString(TransactionConstants.OPENING_BALANCE_COL, rowHeader, "Opening Balance");
+ writeString(TransactionConstants.TRANSACTION_TYPE_COL, rowHeader, "Transaction Type*");
+ writeString(TransactionConstants.AMOUNT_COL, rowHeader, "Amount*");
+ writeString(TransactionConstants.TRANSACTION_DATE_COL, rowHeader, "Date*");
+ writeString(TransactionConstants.PAYMENT_TYPE_COL, rowHeader, "Type*");
+ writeString(TransactionConstants.ACCOUNT_NO_COL, rowHeader, "Account No");
+ writeString(TransactionConstants.CHECK_NO_COL, rowHeader, "Check No");
+ writeString(TransactionConstants.RECEIPT_NO_COL, rowHeader, "Receipt No");
+ writeString(TransactionConstants.ROUTING_CODE_COL, rowHeader, "Routing Code");
+ writeString(TransactionConstants.BANK_NO_COL, rowHeader, "Bank No");
+ writeString(TransactionConstants.LOOKUP_CLIENT_NAME_COL, rowHeader, "Lookup Client");
+ writeString(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, rowHeader, "Lookup Account");
+ writeString(TransactionConstants.LOOKUP_PRODUCT_COL, rowHeader, "Lookup Product");
+ writeString(TransactionConstants.LOOKUP_OPENING_BALANCE_COL, rowHeader, "Lookup Opening Balance");
+ writeString(TransactionConstants.LOOKUP_SAVINGS_ACTIVATION_DATE_COL, rowHeader, "Lookup Savings Activation Date");
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/fixeddeposits/FixedDepositWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/fixeddeposits/FixedDepositWorkbookPopulator.java
new file mode 100644
index 000000000..9afe7dc44
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/fixeddeposits/FixedDepositWorkbookPopulator.java
@@ -0,0 +1,349 @@
+/**
+ * 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.fixeddeposits;
+
+import org.apache.fineract.infrastructure.bulkimport.constants.FixedDepositConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.*;
+import org.apache.fineract.portfolio.savings.data.FixedDepositProductData;
+import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.List;
+
+public class FixedDepositWorkbookPopulator extends AbstractWorkbookPopulator {
+
+ private OfficeSheetPopulator officeSheetPopulator;
+ private ClientSheetPopulator clientSheetPopulator;
+ private PersonnelSheetPopulator personnelSheetPopulator;
+ private FixedDepositProductSheetPopulator productSheetPopulator;
+
+
+
+ public FixedDepositWorkbookPopulator(OfficeSheetPopulator officeSheetPopulator,
+ ClientSheetPopulator clientSheetPopulator, PersonnelSheetPopulator personnelSheetPopulator,
+ FixedDepositProductSheetPopulator fixedDepositProductSheetPopulator) {
+ this.officeSheetPopulator = officeSheetPopulator;
+ this.clientSheetPopulator = clientSheetPopulator;
+ this.personnelSheetPopulator = personnelSheetPopulator;
+ this.productSheetPopulator = fixedDepositProductSheetPopulator;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet fixedDepositSheet = workbook.createSheet(TemplatePopulateImportConstants.FIXED_DEPOSIT_SHEET_NAME);
+ officeSheetPopulator.populate(workbook,dateFormat);
+ clientSheetPopulator.populate(workbook,dateFormat);
+ personnelSheetPopulator.populate(workbook,dateFormat);
+ productSheetPopulator.populate(workbook,dateFormat);
+ setRules(fixedDepositSheet,dateFormat);
+ setDefaults(fixedDepositSheet,dateFormat);
+ setClientAndGroupDateLookupTable(fixedDepositSheet, clientSheetPopulator.getClients(), null,
+ FixedDepositConstants.LOOKUP_CLIENT_NAME_COL,FixedDepositConstants.LOOKUP_ACTIVATION_DATE_COL,!TemplatePopulateImportConstants.CONTAINS_CLIENT_EXTERNAL_ID,dateFormat);
+ setLayout(fixedDepositSheet);
+ }
+
+ private void setRules(Sheet worksheet,String dateFormat) {
+ CellRangeAddressList officeNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.OFFICE_NAME_COL,FixedDepositConstants.OFFICE_NAME_COL);
+ CellRangeAddressList clientNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.CLIENT_NAME_COL,FixedDepositConstants.CLIENT_NAME_COL);
+ CellRangeAddressList productNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.PRODUCT_COL, FixedDepositConstants.PRODUCT_COL);
+ CellRangeAddressList fieldOfficerRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.FIELD_OFFICER_NAME_COL, FixedDepositConstants.FIELD_OFFICER_NAME_COL);
+ CellRangeAddressList submittedDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.SUBMITTED_ON_DATE_COL, FixedDepositConstants.SUBMITTED_ON_DATE_COL);
+ CellRangeAddressList approvedDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.APPROVED_DATE_COL, FixedDepositConstants.APPROVED_DATE_COL);
+ CellRangeAddressList activationDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.ACTIVATION_DATE_COL, FixedDepositConstants.ACTIVATION_DATE_COL);
+ CellRangeAddressList interestCompudingPeriodRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.INTEREST_COMPOUNDING_PERIOD_COL, FixedDepositConstants.INTEREST_COMPOUNDING_PERIOD_COL);
+ CellRangeAddressList interestPostingPeriodRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.INTEREST_POSTING_PERIOD_COL, FixedDepositConstants.INTEREST_POSTING_PERIOD_COL);
+ CellRangeAddressList interestCalculationRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.INTEREST_CALCULATION_COL, FixedDepositConstants.INTEREST_CALCULATION_COL);
+ CellRangeAddressList interestCalculationDaysInYearRange = new CellRangeAddressList(1,
+ SpreadsheetVersion.EXCEL97.getLastRowIndex(), FixedDepositConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL,
+ FixedDepositConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL);
+ CellRangeAddressList lockinPeriodFrequencyRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.LOCKIN_PERIOD_FREQUENCY_COL, FixedDepositConstants.LOCKIN_PERIOD_FREQUENCY_COL);
+ CellRangeAddressList depositAmountRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.DEPOSIT_AMOUNT_COL, FixedDepositConstants.DEPOSIT_AMOUNT_COL);
+ CellRangeAddressList depositPeriodTypeRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ FixedDepositConstants.DEPOSIT_PERIOD_FREQUENCY_COL, FixedDepositConstants.DEPOSIT_PERIOD_FREQUENCY_COL);
+
+ DataValidationHelper validationHelper = new HSSFDataValidationHelper((HSSFSheet) worksheet);
+
+ setNames(worksheet);
+
+ DataValidationConstraint officeNameConstraint = validationHelper.createFormulaListConstraint("Office");
+ DataValidationConstraint clientNameConstraint = validationHelper
+ .createFormulaListConstraint("INDIRECT(CONCATENATE(\"Client_\",$A1))");
+ DataValidationConstraint productNameConstraint = validationHelper.createFormulaListConstraint("Products");
+ DataValidationConstraint fieldOfficerNameConstraint = validationHelper
+ .createFormulaListConstraint("INDIRECT(CONCATENATE(\"Staff_\",$A1))");
+ DataValidationConstraint submittedDateConstraint = validationHelper.createDateConstraint(
+ DataValidationConstraint.OperatorType.BETWEEN, "=VLOOKUP($B1,$AF$2:$AG$"
+ + (clientSheetPopulator.getClientsSize() + 1) + ",2,FALSE)", "=TODAY()",
+ dateFormat);
+ DataValidationConstraint approvalDateConstraint = validationHelper.createDateConstraint(
+ DataValidationConstraint.OperatorType.BETWEEN, "=$E1", "=TODAY()", dateFormat);
+ DataValidationConstraint activationDateConstraint = validationHelper.createDateConstraint(
+ DataValidationConstraint.OperatorType.BETWEEN, "=$F1", "=TODAY()", dateFormat);
+ DataValidationConstraint interestCompudingPeriodConstraint = validationHelper.
+ createExplicitListConstraint(new String[] {
+ TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_DAILY,
+ TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_MONTHLY,
+ TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_QUARTERLY,
+ TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_SEMI_ANNUALLY,
+ TemplatePopulateImportConstants.INTEREST_COMPOUNDING_PERIOD_ANNUALLY });
+ DataValidationConstraint interestPostingPeriodConstraint = validationHelper.createExplicitListConstraint(new String[] {
+ TemplatePopulateImportConstants.INTEREST_POSTING_PERIOD_MONTHLY,
+ TemplatePopulateImportConstants.INTEREST_POSTING_PERIOD_QUARTERLY,
+ TemplatePopulateImportConstants.INTEREST_POSTING_PERIOD_BIANUALLY,
+ TemplatePopulateImportConstants.INTEREST_POSTING_PERIOD_ANNUALLY });
+ DataValidationConstraint interestCalculationConstraint = validationHelper.createExplicitListConstraint(new String[] {
+ TemplatePopulateImportConstants.INTEREST_CAL_DAILY_BALANCE,
+ TemplatePopulateImportConstants.INTEREST_CAL_AVG_BALANCE });
+ DataValidationConstraint interestCalculationDaysInYearConstraint = validationHelper.createExplicitListConstraint(new String[] {
+ TemplatePopulateImportConstants.INTEREST_CAL_DAYS_IN_YEAR_360,
+ TemplatePopulateImportConstants.INTEREST_CAL_DAYS_IN_YEAR_365 });
+ DataValidationConstraint frequency = validationHelper.createExplicitListConstraint(new String[] {
+ TemplatePopulateImportConstants.FREQUENCY_DAYS,
+ TemplatePopulateImportConstants.FREQUENCY_WEEKS,
+ TemplatePopulateImportConstants.FREQUENCY_MONTHS,
+ TemplatePopulateImportConstants.FREQUENCY_YEARS });
+ DataValidationConstraint depositConstraint = validationHelper.createDecimalConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL, "=INDIRECT(CONCATENATE(\"Min_Deposit_\",$C1))", null);
+
+ DataValidation officeValidation = validationHelper.createValidation(officeNameConstraint, officeNameRange);
+ DataValidation clientValidation = validationHelper.createValidation(clientNameConstraint, clientNameRange);
+ DataValidation productNameValidation = validationHelper.createValidation(productNameConstraint, productNameRange);
+ DataValidation fieldOfficerValidation = validationHelper.createValidation(fieldOfficerNameConstraint, fieldOfficerRange);
+ DataValidation interestCompudingPeriodValidation = validationHelper.createValidation(interestCompudingPeriodConstraint,
+ interestCompudingPeriodRange);
+ DataValidation interestPostingPeriodValidation = validationHelper.createValidation(interestPostingPeriodConstraint,
+ interestPostingPeriodRange);
+ DataValidation interestCalculationValidation = validationHelper.createValidation(interestCalculationConstraint,
+ interestCalculationRange);
+ DataValidation interestCalculationDaysInYearValidation = validationHelper.createValidation(
+ interestCalculationDaysInYearConstraint, interestCalculationDaysInYearRange);
+ DataValidation lockinPeriodFrequencyValidation = validationHelper.createValidation(frequency,
+ lockinPeriodFrequencyRange);
+ DataValidation depositPeriodTypeValidation = validationHelper.createValidation(frequency,
+ depositPeriodTypeRange);
+ DataValidation submittedDateValidation = validationHelper.createValidation(submittedDateConstraint, submittedDateRange);
+ DataValidation approvalDateValidation = validationHelper.createValidation(approvalDateConstraint, approvedDateRange);
+ DataValidation activationDateValidation = validationHelper.createValidation(activationDateConstraint, activationDateRange);
+ DataValidation depositAmountValidation = validationHelper.createValidation(depositConstraint, depositAmountRange);
+
+
+ worksheet.addValidationData(officeValidation);
+ worksheet.addValidationData(clientValidation);
+ worksheet.addValidationData(productNameValidation);
+ worksheet.addValidationData(fieldOfficerValidation);
+ worksheet.addValidationData(submittedDateValidation);
+ worksheet.addValidationData(approvalDateValidation);
+ worksheet.addValidationData(activationDateValidation);
+ worksheet.addValidationData(interestCompudingPeriodValidation);
+ worksheet.addValidationData(interestPostingPeriodValidation);
+ worksheet.addValidationData(interestCalculationValidation);
+ worksheet.addValidationData(interestCalculationDaysInYearValidation);
+ worksheet.addValidationData(lockinPeriodFrequencyValidation);
+ worksheet.addValidationData(depositPeriodTypeValidation);
+ worksheet.addValidationData(depositAmountValidation);
+
+ }
+
+ private void setNames(Sheet worksheet) {
+ Workbook savingsWorkbook = worksheet.getWorkbook();
+ List officeNames = officeSheetPopulator.getOfficeNames();
+ List products = productSheetPopulator.getProducts();
+
+ // Office Names
+ Name officeGroup = savingsWorkbook.createName();
+ officeGroup.setNameName("Office");
+ officeGroup.setRefersToFormula(TemplatePopulateImportConstants.OFFICE_SHEET_NAME+"!$B$2:$B$" + (officeNames.size() + 1));
+
+ // Client and Loan Officer Names for each office
+ for (Integer i = 0; i < officeNames.size(); i++) {
+ Integer[] officeNameToBeginEndIndexesOfClients = clientSheetPopulator.getOfficeNameToBeginEndIndexesOfClients().get(i);
+ Integer[] officeNameToBeginEndIndexesOfStaff = personnelSheetPopulator.getOfficeNameToBeginEndIndexesOfStaff().get(i);
+ Name clientName = savingsWorkbook.createName();
+ Name fieldOfficerName = savingsWorkbook.createName();
+ if (officeNameToBeginEndIndexesOfStaff != null) {
+ fieldOfficerName.setNameName("Staff_" + officeNames.get(i).trim().replaceAll("[ )(]", "_"));
+ fieldOfficerName.setRefersToFormula(TemplatePopulateImportConstants.STAFF_SHEET_NAME+"!$B$" + officeNameToBeginEndIndexesOfStaff[0] + ":$B$"
+ + officeNameToBeginEndIndexesOfStaff[1]);
+ }
+ if (officeNameToBeginEndIndexesOfClients != null) {
+ clientName.setNameName("Client_" + officeNames.get(i).trim().replaceAll("[ )(]", "_"));
+ clientName.setRefersToFormula(TemplatePopulateImportConstants.CLIENT_SHEET_NAME+"!$B$" + officeNameToBeginEndIndexesOfClients[0] + ":$B$"
+ + officeNameToBeginEndIndexesOfClients[1]);
+ }
+ }
+
+ // Product Name
+ Name productGroup = savingsWorkbook.createName();
+ productGroup.setNameName("Products");
+ productGroup.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$B$2:$B$" + (productSheetPopulator.getProductsSize() + 1));
+
+ // Default Interest Rate, Interest Compounding Period, Interest Posting
+ // Period, Interest Calculation, Interest Calculation Days In Year,
+ // Minimum Deposit, Lockin Period, Lockin Period Frequency
+ // Names for each product
+ for (Integer i = 0; i < products.size(); i++) {
+ Name interestCompoundingPeriodName = savingsWorkbook.createName();
+ Name interestPostingPeriodName = savingsWorkbook.createName();
+ Name interestCalculationName = savingsWorkbook.createName();
+ Name daysInYearName = savingsWorkbook.createName();
+ Name lockinPeriodName = savingsWorkbook.createName();
+ Name lockinPeriodFrequencyName = savingsWorkbook.createName();
+ Name depositName = savingsWorkbook.createName();
+ Name minDepositName = savingsWorkbook.createName();
+ Name maxDepositName = savingsWorkbook.createName();
+ Name minDepositTermTypeName = savingsWorkbook.createName();
+
+ FixedDepositProductData product = products.get(i);
+ String productName = product.getName().replaceAll("[ ]", "_");
+
+ interestCompoundingPeriodName.setNameName("Interest_Compouding_" + productName);
+ interestPostingPeriodName.setNameName("Interest_Posting_" + productName);
+ interestCalculationName.setNameName("Interest_Calculation_" + productName);
+ daysInYearName.setNameName("Days_In_Year_" + productName);
+ minDepositName.setNameName("Min_Deposit_" + productName);
+ maxDepositName.setNameName("Max_Deposit_" + productName);
+ depositName.setNameName("Deposit_" + productName);
+ interestCompoundingPeriodName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$E$" + (i + 2));
+ interestPostingPeriodName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$F$" + (i + 2));
+ interestCalculationName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$G$" + (i + 2));
+ daysInYearName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$H$" + (i + 2));
+ depositName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$N$" + (i + 2));
+ minDepositName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$L$" + (i + 2));
+ maxDepositName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$M$" + (i + 2));
+
+ if(product.getMinDepositTermType() != null) {
+ minDepositTermTypeName.setNameName("Term_Type_" + productName);
+ minDepositTermTypeName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$P$" + (i + 2));
+ }
+ if (product.getLockinPeriodFrequency() != null) {
+ lockinPeriodName.setNameName("Lockin_Period_" + productName);
+ lockinPeriodName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$I$" + (i + 2));
+ }
+ if (product.getLockinPeriodFrequencyType() != null) {
+ lockinPeriodFrequencyName.setNameName("Lockin_Frequency_" + productName);
+ lockinPeriodFrequencyName.setRefersToFormula(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME+"!$J$" + (i + 2));
+ }
+ }
+ }
+
+ private void setDefaults(Sheet worksheet,String dateFormat) {
+ Workbook workbook = worksheet.getWorkbook();
+ CellStyle dateCellStyle = workbook.createCellStyle();
+ short df = workbook.createDataFormat().getFormat(dateFormat);
+ dateCellStyle.setDataFormat(df);
+ try {
+ for (Integer rowNo = 1; rowNo < 1000; rowNo++) {
+ Row row = worksheet.createRow(rowNo);
+ writeFormula(FixedDepositConstants.INTEREST_COMPOUNDING_PERIOD_COL, row, "IF(ISERROR(INDIRECT(CONCATENATE(\"Interest_Compouding_\",$C"
+ + (rowNo + 1) + "))),\"\",INDIRECT(CONCATENATE(\"Interest_Compouding_\",$C" + (rowNo + 1) + ")))");
+ writeFormula(FixedDepositConstants.INTEREST_POSTING_PERIOD_COL, row, "IF(ISERROR(INDIRECT(CONCATENATE(\"Interest_Posting_\",$C" + (rowNo + 1)
+ + "))),\"\",INDIRECT(CONCATENATE(\"Interest_Posting_\",$C" + (rowNo + 1) + ")))");
+ writeFormula(FixedDepositConstants.INTEREST_CALCULATION_COL, row, "IF(ISERROR(INDIRECT(CONCATENATE(\"Interest_Calculation_\",$C" + (rowNo + 1)
+ + "))),\"\",INDIRECT(CONCATENATE(\"Interest_Calculation_\",$C" + (rowNo + 1) + ")))");
+ writeFormula(FixedDepositConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL, row, "IF(ISERROR(INDIRECT(CONCATENATE(\"Days_In_Year_\",$C"
+ + (rowNo + 1) + "))),\"\",INDIRECT(CONCATENATE(\"Days_In_Year_\",$C" + (rowNo + 1) + ")))");
+ writeFormula(FixedDepositConstants.LOCKIN_PERIOD_COL, row, "IF(ISERROR(INDIRECT(CONCATENATE(\"Lockin_Period_\",$C" + (rowNo + 1)
+ + "))),\"\",INDIRECT(CONCATENATE(\"Lockin_Period_\",$C" + (rowNo + 1) + ")))");
+ writeFormula(FixedDepositConstants.LOCKIN_PERIOD_FREQUENCY_COL, row, "IF(ISERROR(INDIRECT(CONCATENATE(\"Lockin_Frequency_\",$C" + (rowNo + 1)
+ + "))),\"\",INDIRECT(CONCATENATE(\"Lockin_Frequency_\",$C" + (rowNo + 1) + ")))");
+ writeFormula(FixedDepositConstants.DEPOSIT_AMOUNT_COL, row, "IF(ISERROR(INDIRECT(CONCATENATE(\"Deposit_\",$C" + (rowNo + 1)
+ + "))),\"\",INDIRECT(CONCATENATE(\"Deposit_\",$C" + (rowNo + 1) + ")))");
+ writeFormula(FixedDepositConstants.DEPOSIT_PERIOD_FREQUENCY_COL, row, "IF(ISERROR(INDIRECT(CONCATENATE(\"Term_Type_\",$C" + (rowNo + 1)
+ + "))),\"\",INDIRECT(CONCATENATE(\"Term_Type_\",$C" + (rowNo + 1) + ")))");
+ }
+ } catch (RuntimeException re) {
+ re.printStackTrace();
+ }
+ }
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(FixedDepositConstants.OFFICE_NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.CLIENT_NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.PRODUCT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.FIELD_OFFICER_NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.SUBMITTED_ON_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.APPROVED_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.ACTIVATION_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.INTEREST_COMPOUNDING_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.INTEREST_POSTING_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.INTEREST_CALCULATION_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.LOCKIN_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.LOCKIN_PERIOD_FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.DEPOSIT_AMOUNT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.DEPOSIT_PERIOD_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.DEPOSIT_PERIOD_FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.EXTERNAL_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+
+ worksheet.setColumnWidth(FixedDepositConstants.CHARGE_ID_1, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.CHARGE_AMOUNT_1, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.CHARGE_DUE_DATE_1, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.CHARGE_ID_2, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.CHARGE_AMOUNT_2, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.CHARGE_DUE_DATE_2, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+
+ worksheet.setColumnWidth(FixedDepositConstants.LOOKUP_CLIENT_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(FixedDepositConstants.LOOKUP_ACTIVATION_DATE_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+
+ writeString(FixedDepositConstants.OFFICE_NAME_COL, rowHeader, "Office Name*");
+ writeString(FixedDepositConstants.CLIENT_NAME_COL, rowHeader, "Client Name*");
+ writeString(FixedDepositConstants.PRODUCT_COL, rowHeader, "Product*");
+ writeString(FixedDepositConstants.FIELD_OFFICER_NAME_COL, rowHeader, "Field Officer*");
+ writeString(FixedDepositConstants.SUBMITTED_ON_DATE_COL, rowHeader, "Submitted On*");
+ writeString(FixedDepositConstants.APPROVED_DATE_COL, rowHeader, "Approved On*");
+ writeString(FixedDepositConstants.ACTIVATION_DATE_COL, rowHeader, "Activation Date*");
+ writeString(FixedDepositConstants.INTEREST_COMPOUNDING_PERIOD_COL, rowHeader, "Interest Compounding Period*");
+ writeString(FixedDepositConstants.INTEREST_POSTING_PERIOD_COL, rowHeader, "Interest Posting Period*");
+ writeString(FixedDepositConstants.INTEREST_CALCULATION_COL, rowHeader, "Interest Calculated*");
+ writeString(FixedDepositConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL, rowHeader, "# Days in Year*");
+ writeString(FixedDepositConstants.LOCKIN_PERIOD_COL, rowHeader, "Locked In For");
+ writeString(FixedDepositConstants.DEPOSIT_AMOUNT_COL, rowHeader, "Deposit Amount");
+ writeString(FixedDepositConstants.DEPOSIT_PERIOD_COL, rowHeader, "Deposit Period");
+ writeString(FixedDepositConstants.EXTERNAL_ID_COL, rowHeader, "External Id");
+
+ writeString(FixedDepositConstants.CHARGE_ID_1,rowHeader,"Charge Id");
+ writeString(FixedDepositConstants.CHARGE_AMOUNT_1, rowHeader, "Charged Amount");
+ writeString(FixedDepositConstants.CHARGE_DUE_DATE_1, rowHeader, "Charged On Date");
+ writeString(FixedDepositConstants.CHARGE_ID_2,rowHeader,"Charge Id");
+ writeString(FixedDepositConstants.CHARGE_AMOUNT_2, rowHeader, "Charged Amount");
+ writeString(FixedDepositConstants.CHARGE_DUE_DATE_2, rowHeader, "Charged On Date");
+ writeString(FixedDepositConstants.CLOSED_ON_DATE, rowHeader, "Close on Date");
+ writeString(FixedDepositConstants.ON_ACCOUNT_CLOSURE_ID,rowHeader,"Action(Account Transfer(200) or cash(100) ");
+ writeString(FixedDepositConstants.TO_SAVINGS_ACCOUNT_ID,rowHeader, "Transfered Account No.");
+ writeString(FixedDepositConstants.LOOKUP_CLIENT_NAME_COL, rowHeader, "Client Name");
+ writeString(FixedDepositConstants.LOOKUP_ACTIVATION_DATE_COL, rowHeader, "Client Activation Date");
+ }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/group/GroupsWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/group/GroupsWorkbookPopulator.java
new file mode 100644
index 000000000..038e10872
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/group/GroupsWorkbookPopulator.java
@@ -0,0 +1,254 @@
+/**
+ * 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.group;
+
+import org.apache.fineract.infrastructure.bulkimport.constants.GroupConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.*;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.List;
+
+public class GroupsWorkbookPopulator extends AbstractWorkbookPopulator {
+
+ private OfficeSheetPopulator officeSheetPopulator;
+ private PersonnelSheetPopulator personnelSheetPopulator;
+ private CenterSheetPopulator centerSheetPopulator;
+ private ClientSheetPopulator clientSheetPopulator;
+
+ public GroupsWorkbookPopulator(OfficeSheetPopulator officeSheetPopulator,
+ PersonnelSheetPopulator personnelSheetPopulator, CenterSheetPopulator centerSheetPopulator,
+ ClientSheetPopulator clientSheetPopulator) {
+ this.officeSheetPopulator = officeSheetPopulator;
+ this.personnelSheetPopulator = personnelSheetPopulator;
+ this.centerSheetPopulator = centerSheetPopulator;
+ this.clientSheetPopulator = clientSheetPopulator;
+ }
+
+ @Override
+ public void populate(Workbook workbook,String dateFormat) {
+ Sheet groupSheet = workbook.createSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME);
+ personnelSheetPopulator.populate(workbook,dateFormat);
+ officeSheetPopulator.populate(workbook,dateFormat);
+ centerSheetPopulator.populate(workbook,dateFormat);
+ clientSheetPopulator.populate(workbook,dateFormat);
+ setLayout(groupSheet);
+ setLookupTable(groupSheet,dateFormat);
+ setRules(groupSheet,dateFormat);
+
+ }
+
+ private void setLayout(Sheet worksheet) {
+ Row rowHeader = worksheet.createRow(TemplatePopulateImportConstants.ROWHEADER_INDEX);
+ rowHeader.setHeight(TemplatePopulateImportConstants.ROW_HEADER_HEIGHT);
+ worksheet.setColumnWidth(GroupConstants.NAME_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.STAFF_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.CENTER_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.EXTERNAL_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.ACTIVE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.ACTIVATION_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.SUBMITTED_ON_DATE_COL,TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.MEETING_START_DATE_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.IS_REPEATING_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.FREQUENCY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.INTERVAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.REPEATS_ON_DAY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.STATUS_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.GROUP_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.FAILURE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.CLIENT_NAMES_STARTING_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.LOOKUP_OFFICE_NAME_COL, TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.LOOKUP_OFFICE_OPENING_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.LOOKUP_REPEAT_NORMAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.LOOKUP_REPEAT_MONTHLY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+ worksheet.setColumnWidth(GroupConstants.LOOKUP_IF_REPEAT_WEEKLY_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
+
+ writeString(GroupConstants.NAME_COL, rowHeader, "Group Name*");
+ writeString(GroupConstants.OFFICE_NAME_COL, rowHeader, "Office Name*");
+ writeString(GroupConstants.STAFF_NAME_COL, rowHeader, "Staff Name*");
+ writeString(GroupConstants.CENTER_NAME_COL, rowHeader, "Center Name");
+ writeString(GroupConstants.EXTERNAL_ID_COL, rowHeader, "External ID");
+ writeString(GroupConstants.ACTIVE_COL, rowHeader, "Active*");
+ writeString(GroupConstants.ACTIVATION_DATE_COL, rowHeader, "Activation Date*");
+ writeString(GroupConstants.SUBMITTED_ON_DATE_COL,rowHeader,"Submitted On Date *");
+ writeString(GroupConstants.MEETING_START_DATE_COL, rowHeader, "Meeting Start Date* (On or After)");
+ writeString(GroupConstants.IS_REPEATING_COL, rowHeader, "Repeat*");
+ writeString(GroupConstants.FREQUENCY_COL, rowHeader, "Frequency*");
+ writeString(GroupConstants.INTERVAL_COL, rowHeader, "Interval*");
+ writeString(GroupConstants.REPEATS_ON_DAY_COL, rowHeader, "Repeats On*");
+ writeString(GroupConstants.CLIENT_NAMES_STARTING_COL, rowHeader, "Client Names* (Enter in consecutive cells horizontally)");
+ writeString(GroupConstants.LOOKUP_OFFICE_NAME_COL, rowHeader, "Office Name");
+ writeString(GroupConstants.LOOKUP_OFFICE_OPENING_DATE_COL, rowHeader, "Opening Date");
+ writeString(GroupConstants.LOOKUP_REPEAT_NORMAL_COL, rowHeader, "Repeat Normal Range");
+ writeString(GroupConstants.LOOKUP_REPEAT_MONTHLY_COL, rowHeader, "Repeat Monthly Range");
+ writeString(GroupConstants.LOOKUP_IF_REPEAT_WEEKLY_COL, rowHeader, "If Repeat Weekly Range");
+
+ }
+ private void setLookupTable(Sheet groupSheet,String dateFormat) {
+ setOfficeDateLookupTable(groupSheet, officeSheetPopulator.getOffices(),GroupConstants.LOOKUP_OFFICE_NAME_COL,
+ GroupConstants. LOOKUP_OFFICE_OPENING_DATE_COL,dateFormat);
+ int rowIndex;
+ for(rowIndex = 1; rowIndex <= 11; rowIndex++) {
+ Row row = groupSheet.getRow(rowIndex);
+ if(row == null)
+ row = groupSheet.createRow(rowIndex);
+ writeInt(GroupConstants.LOOKUP_REPEAT_MONTHLY_COL, row, rowIndex);
+ }
+ for(rowIndex = 1; rowIndex <= 3; rowIndex++)
+ writeInt(GroupConstants.LOOKUP_REPEAT_NORMAL_COL, groupSheet.getRow(rowIndex), rowIndex);
+ String[] days = new String[]{
+ TemplatePopulateImportConstants.MONDAY,
+ TemplatePopulateImportConstants.TUESDAY,
+ TemplatePopulateImportConstants.WEDNESDAY,
+ TemplatePopulateImportConstants.THURSDAY,
+ TemplatePopulateImportConstants.FRIDAY,
+ TemplatePopulateImportConstants.SATURDAY,
+ TemplatePopulateImportConstants.SUNDAY};
+ for(rowIndex = 1; rowIndex <= 7; rowIndex++)
+ writeString(GroupConstants.LOOKUP_IF_REPEAT_WEEKLY_COL, groupSheet.getRow(rowIndex), days[rowIndex-1]);
+ }
+
+ private void setRules(Sheet worksheet,String dateFormat){
+ CellRangeAddressList officeNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.OFFICE_NAME_COL, GroupConstants.OFFICE_NAME_COL);
+ CellRangeAddressList staffNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.STAFF_NAME_COL, GroupConstants.STAFF_NAME_COL);
+ CellRangeAddressList centerNameRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.CENTER_NAME_COL, GroupConstants.CENTER_NAME_COL);
+ CellRangeAddressList activeRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.ACTIVE_COL, GroupConstants.ACTIVE_COL);
+ CellRangeAddressList activationDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.ACTIVATION_DATE_COL,GroupConstants.ACTIVATION_DATE_COL);
+ CellRangeAddressList submittedOnDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.SUBMITTED_ON_DATE_COL,GroupConstants.SUBMITTED_ON_DATE_COL);
+ CellRangeAddressList meetingStartDateRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.MEETING_START_DATE_COL,GroupConstants.MEETING_START_DATE_COL);
+ CellRangeAddressList isRepeatRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.IS_REPEATING_COL, GroupConstants.IS_REPEATING_COL);
+ CellRangeAddressList repeatsRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants. FREQUENCY_COL, GroupConstants.FREQUENCY_COL);
+ CellRangeAddressList repeatsEveryRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.INTERVAL_COL,GroupConstants. INTERVAL_COL);
+ CellRangeAddressList repeatsOnRange = new CellRangeAddressList(1, SpreadsheetVersion.EXCEL97.getLastRowIndex(),
+ GroupConstants.REPEATS_ON_DAY_COL, GroupConstants.REPEATS_ON_DAY_COL);
+
+ DataValidationHelper validationHelper = new HSSFDataValidationHelper((HSSFSheet)worksheet);
+ List offices = officeSheetPopulator.getOffices();
+ setNames(worksheet, offices);
+
+ DataValidationConstraint centerNameConstraint = validationHelper.createFormulaListConstraint("INDIRECT(CONCATENATE(\"Center_\",$B1))");
+ DataValidationConstraint officeNameConstraint = validationHelper.createFormulaListConstraint("Office");
+ DataValidationConstraint staffNameConstraint = validationHelper.createFormulaListConstraint("INDIRECT(CONCATENATE(\"Staff_\",$B1))");
+ DataValidationConstraint booleanConstraint = validationHelper.createExplicitListConstraint(new String[]{"True", "False"});
+ DataValidationConstraint activationDateConstraint = validationHelper.createDateConstraint
+ (DataValidationConstraint.OperatorType.BETWEEN,
+ "=VLOOKUP($B1,$IR$2:$IS" + (offices.size() + 1)+",2,FALSE)", "=TODAY()", dateFormat);
+ DataValidationConstraint submittedOnDateConstraint =
+ validationHelper.createDateConstraint(DataValidationConstraint.OperatorType.LESS_OR_EQUAL,
+ "=$G1" ,null,dateFormat);
+ DataValidationConstraint meetingStartDateConstraint = validationHelper.
+ createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN,
+ "=$G1", "=TODAY()", dateFormat);
+ DataValidationConstraint repeatsConstraint = validationHelper.createExplicitListConstraint(new String[]{
+ TemplatePopulateImportConstants.FREQUENCY_DAILY,
+ TemplatePopulateImportConstants.FREQUENCY_WEEKLY,
+ TemplatePopulateImportConstants.FREQUENCY_MONTHLY,
+ TemplatePopulateImportConstants.FREQUENCY_YEARLY});
+ DataValidationConstraint repeatsEveryConstraint = validationHelper.createFormulaListConstraint("INDIRECT($K1)");
+ DataValidationConstraint repeatsOnConstraint = validationHelper.createFormulaListConstraint("INDIRECT(CONCATENATE($K1,\"_DAYS\"))");
+
+ DataValidation centerValidation=validationHelper.createValidation(centerNameConstraint, centerNameRange);
+ DataValidation officeValidation = validationHelper.createValidation(officeNameConstraint, officeNameRange);
+ DataValidation staffValidation = validationHelper.createValidation(staffNameConstraint, staffNameRange);
+ DataValidation activationDateValidation = validationHelper.createValidation(activationDateConstraint, activationDateRange);
+ DataValidation activeValidation = validationHelper.createValidation(booleanConstraint, activeRange);
+ DataValidation submittedOnDateValidation=validationHelper.createValidation(submittedOnDateConstraint,submittedOnDateRange);
+ DataValidation meetingStartDateValidation = validationHelper.createValidation(meetingStartDateConstraint, meetingStartDateRange);
+ DataValidation isRepeatValidation = validationHelper.createValidation(booleanConstraint, isRepeatRange);
+ DataValidation repeatsValidation = validationHelper.createValidation(repeatsConstraint, repeatsRange);
+ DataValidation repeatsEveryValidation = validationHelper.createValidation(repeatsEveryConstraint, repeatsEveryRange);
+ DataValidation repeatsOnValidation = validationHelper.createValidation(repeatsOnConstraint, repeatsOnRange);
+
+ worksheet.addValidationData(centerValidation);
+ worksheet.addValidationData(activeValidation);
+ worksheet.addValidationData(officeValidation);
+ worksheet.addValidationData(staffValidation);
+ worksheet.addValidationData(activationDateValidation);
+ worksheet.addValidationData(submittedOnDateValidation);
+ worksheet.addValidationData(meetingStartDateValidation);
+ worksheet.addValidationData(isRepeatValidation);
+ worksheet.addValidationData(repeatsValidation);
+ worksheet.addValidationData(repeatsEveryValidation);
+ worksheet.addValidationData(repeatsOnValidation);
+ }
+
+ private void setNames(Sheet worksheet, List offices) {
+ Workbook centerWorkbook = worksheet.getWorkbook();
+ Name officeCenter = centerWorkbook.createName();
+ officeCenter.setNameName("Office");
+ officeCenter.setRefersToFormula(TemplatePopulateImportConstants.OFFICE_SHEET_NAME+"!$B$2:$B$" + (offices.size() + 1));
+
+
+ //Repeat constraint names
+ Name repeatsDaily = centerWorkbook.createName();
+ repeatsDaily.setNameName("Daily");
+ repeatsDaily.setRefersToFormula(TemplatePopulateImportConstants.GROUP_SHEET_NAME+"!$IT$2:$IT$4");
+ Name repeatsWeekly = centerWorkbook.createName();
+ repeatsWeekly.setNameName("Weekly");
+ repeatsWeekly.setRefersToFormula(TemplatePopulateImportConstants.GROUP_SHEET_NAME+"!$IT$2:$IT$4");
+ Name repeatYearly = centerWorkbook.createName();
+ repeatYearly.setNameName("Yearly");
+ repeatYearly.setRefersToFormula(TemplatePopulateImportConstants.GROUP_SHEET_NAME+"!$IT$2:$IT$4");
+ Name repeatsMonthly = centerWorkbook.createName();
+ repeatsMonthly.setNameName("Monthly");
+ repeatsMonthly.setRefersToFormula(TemplatePopulateImportConstants.GROUP_SHEET_NAME+"!$IU$2:$IU$12");
+ Name repeatsOnWeekly = centerWorkbook.createName();
+ repeatsOnWeekly.setNameName("Weekly_Days");
+ repeatsOnWeekly.setRefersToFormula(TemplatePopulateImportConstants.GROUP_SHEET_NAME+"!$IV$2:$IV$8");
+
+
+ //Staff Names for each office & center Names for each office
+ for(Integer i = 0; i < offices.size(); i++) {
+ Integer[] officeNameToBeginEndIndexesOfCenters =centerSheetPopulator.getOfficeNameToBeginEndIndexesOfCenters().get(i);
+ Integer[] officeNameToBeginEndIndexesOfStaff = personnelSheetPopulator.getOfficeNameToBeginEndIndexesOfStaff().get(i);
+
+ Name loanOfficerName = centerWorkbook.createName();
+ Name centerName=centerWorkbook.createName();
+
+ if(officeNameToBeginEndIndexesOfStaff != null) {
+ loanOfficerName.setNameName("Staff_" + offices.get(i).name().trim().replaceAll("[ )(]", "_"));
+ loanOfficerName.setRefersToFormula(TemplatePopulateImportConstants.STAFF_SHEET_NAME+
+ "!$B$" + officeNameToBeginEndIndexesOfStaff[0] + ":$B$" + officeNameToBeginEndIndexesOfStaff[1]);
+ }
+ if (officeNameToBeginEndIndexesOfCenters!=null) {
+ centerName.setNameName("Center_" + offices.get(i).name().trim().replaceAll("[ )(]", "_"));
+ centerName.setRefersToFormula(TemplatePopulateImportConstants.CENTER_SHEET_NAME+
+ "!$B$" + officeNameToBeginEndIndexesOfCenters[0] + ":$B$" + officeNameToBeginEndIndexesOfCenters[1]);
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/guarantor/GuarantorWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/guarantor/GuarantorWorkbookPopulator.java
new file mode 100644
index 000000000..912eb2b1a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/guarantor/GuarantorWorkbookPopulator.java
@@ -0,0 +1,314 @@
+/**
+ * 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.guarantor;
+
+import org.apache.fineract.infrastructure.bulkimport.constants.GuarantorConstants;
+import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
+import org.apache.fineract.infrastructure.bulkimport.populator.AbstractWorkbookPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.ClientSheetPopulator;
+import org.apache.fineract.infrastructure.bulkimport.populator.OfficeSheetPopulator;
+import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
+import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+public class GuarantorWorkbookPopulator extends AbstractWorkbookPopulator {
+ private OfficeSheetPopulator officeSheetPopulator;
+ private ClientSheetPopulator clientSheetPopulator;
+ private List loans;
+ private List savings;
+ private ListguarantorRelationshipTypes;
+
+ public GuarantorWorkbookPopulator(OfficeSheetPopulator officeSheetPopulator,
+ ClientSheetPopulator clientSheetPopulator,
+ List loans, List