You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by aw...@apache.org on 2019/09/02 20:43:45 UTC

[fineract-cn-reporting] branch develop updated (59aade7 -> 4792359)

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

awasum pushed a change to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git.


    from 59aade7  Merge pull request #9 from Anh3h/develop
     new 13ecc2a  FINCN-170 create multi-stage Docker build
     new 65c2237  FINCN-170 fix jar path
     new 4792359  Merge pull request #10 from aasaru/multi-stage-docker-build

The 47 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .dockerignore | 10 ----------
 Dockerfile    | 13 ++++++++++---
 2 files changed, 10 insertions(+), 13 deletions(-)


[fineract-cn-reporting] 23/47: Merge pull request #3 from skylabaseInc/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 129db80f538bcb48c9133fb465c731481d0791ef
Merge: a3dee1e c35f4b9
Author: Markus Geiß <ma...@apache.org>
AuthorDate: Wed Oct 4 08:36:21 2017 +0200

    Merge pull request #3 from skylabaseInc/develop
    
    Updates to fix Internal server errors

 .../io/mifos/reporting/api/v1/domain/Sample.java   |  15 +
 .../TestBalanceSheetReportSpecification.java       |  37 +++
 .../TestDepositListReportSpecification.java        |  36 ++
 .../TestIncomeStatementReportSpecification.java    |  36 ++
 .../reporting/TestLoanListReportSpecification.java |  36 ++
 .../TestSavingListReportSpecification.java         |  21 --
 .../TestTellerListReportSpecification.java         |  36 ++
 .../TestTellerTransactionReportSpecification.java  |  36 ++
 gradle/wrapper/gradle-wrapper.properties           |   4 +-
 gradlew                                            |   0
 .../service/internal/repository/DummyEntity.java   |   2 +-
 .../internal/repository/DummyRepository.java       |   2 +-
 .../BalanceSheetReportSpecification.java           | 364 ++++++++++++++++++++
 .../DepositListReportSpecification.java            | 294 ++++++++--------
 .../IncomeStatementReportSpecification.java        | 165 ++++++---
 .../specification/LoanListReportSpecification.java | 155 ++++++---
 .../OfficeListReportSpecification.java             | 278 ++++++++++++++++
 ...llerCashierDailyBalanceReportSpecification.java |  72 ----
 .../TellerListReportSpecification.java             |  19 +-
 .../TellerTransactionReportSpecification.java      | 370 +++++++++++++++++++++
 service/src/main/resources/ESAPI.properties        |  62 +---
 service/src/main/resources/validation.properties   |  18 +-
 22 files changed, 1676 insertions(+), 382 deletions(-)


[fineract-cn-reporting] 12/47: Teller, Loan skeleton, Tellerlisting query update

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit da105ea97c8a43e78be918ce8d889fe1e602ee3f
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Fri Aug 25 17:17:19 2017 +0100

    Teller, Loan skeleton, Tellerlisting query update
---
 ...InactiveCustomerAccountReportSpecification.java |  24 ---
 .../LoanListingReportSpecification.java            |  51 ++++++
 .../SavingListReportSpecification.java             |   2 +-
 ...llerCashierDailyBalanceReportSpecification.java |  72 +++++++++
 .../TellerListingReportSpecification.java          | 172 +++++++++++++++++++++
 5 files changed, 296 insertions(+), 25 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/InactiveCustomerAccountReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/InactiveCustomerAccountReportSpecification.java
deleted file mode 100644
index 148743b..0000000
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/InactiveCustomerAccountReportSpecification.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
-@Report(category = "Customer", identifier = "Inactive")
-public class InactiveCustomerAccountReportSpecification implements ReportSpecification {
-    @Override
-    public ReportDefinition getReportDefinition() {
-        return null;
-    }
-
-    @Override
-    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
-        return null;
-    }
-
-    @Override
-    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
-
-    }
-}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListingReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListingReportSpecification.java
new file mode 100644
index 0000000..d90dd75
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListingReportSpecification.java
@@ -0,0 +1,51 @@
+package io.mifos.reporting.service.internal.specification;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import javax.persistence.EntityManager;
+
+@Report(category = "Loan", identifier = "Listing")
+public class LoanListingReportSpecification implements ReportSpecification {
+
+    private static final String TOTAL_CASH_ON_HAND = "Cash on hand";
+
+
+    private final Logger logger;
+
+    private final EntityManager entityManager;
+
+    @Autowired
+    public LoanListingReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                                        final EntityManager entityManager) {
+        super();
+        this.logger = logger;
+        this.entityManager = entityManager;
+        this.initializeMapping();
+    }
+
+    private void initializeMapping() {
+    }
+
+    @Override
+    public ReportDefinition getReportDefinition() {
+        return null;
+    }
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        return null;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+
+    }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
index 1e8ccbe..a7f8e08 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
@@ -246,7 +246,7 @@ public class SavingListReportSpecification implements ReportSpecification {
             final Value lastActivityValue = new Value();
             lastActivityValue.setValues(val.toArray(new String[values.size()]));
             row.getValues().add(lastActivityValue);
-            
+
             rows.add(row);
         });
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerCashierDailyBalanceReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerCashierDailyBalanceReportSpecification.java
new file mode 100644
index 0000000..591351e
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerCashierDailyBalanceReportSpecification.java
@@ -0,0 +1,72 @@
+package io.mifos.reporting.service.internal.specification;
+
+import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+@Report(category = "Teller" , identifier = "Transaction")
+public class TellerCashierDailyBalanceReportSpecification implements ReportSpecification {
+
+    private static final String TOTAL_CASH_ON_HAND = "Cash on hand";
+    private static final String TOTAL_CASH_RECEIVED = "Cash received";
+    private static final String TOTAL_CASH_DISBURSED = "Cash Disbursed";
+    private static final String TOTAL_NEGOTIABLE_INSTRUMENT_RECEIVED = "Negotiable instrument received";
+    private static final String TOTAL_CHEQUES_RECEIVED = "Total cheques received";
+    private static final String TELLER = "Teller";
+    private static final String EMPLOYEE = "Employee";
+    private static final String OFFICE = "Office";
+    private static final String CASHDRAW_LIMIT = "Cashdraw limit";
+
+    private final Logger logger;
+
+    private final EntityManager entityManager;
+
+    @Autowired
+    public TellerCashierDailyBalanceReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                           final EntityManager entityManager) {
+        super();
+        this.logger = logger;
+        this.entityManager = entityManager;
+        this.initializeMapping();
+    }
+
+    private void initializeMapping() {
+    }
+
+    @Override
+    public ReportDefinition getReportDefinition() {
+        final ReportDefinition reportDefinition = new ReportDefinition();
+        reportDefinition.setIdentifier("Transactions");
+        reportDefinition.setName("Teller transactions");
+        reportDefinition.setDescription("List total teller/cashier transactions.");
+        reportDefinition.setQueryParameters(this.buildQueryParameters());
+        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+        return reportDefinition;
+    }
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return null;
+    }
+
+    private List<QueryParameter> buildQueryParameters() {
+
+        return null;
+    }
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        return null;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+
+    }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListingReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListingReportSpecification.java
new file mode 100644
index 0000000..34af570
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListingReportSpecification.java
@@ -0,0 +1,172 @@
+package io.mifos.reporting.service.internal.specification;
+
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.DateConverter;
+import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.CriteriaBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.time.Clock;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Report(category = "Teller" , identifier = "Listing")
+public class TellerListingReportSpecification implements ReportSpecification {
+
+   // private static final String TOTAL_CASH_ON_HAND = "Cash on hand";
+   // private static final String TOTAL_CASH_RECEIVED = "Cash received";
+   // private static final String TOTAL_CASH_DISBURSED = "Cash Disbursed";
+   // private static final String TOTAL_NEGOTIABLE_INSTRUMENT_RECEIVED = "Negotiable instrument received";
+   // private static final String TOTAL_CHEQUES_RECEIVED = "Total cheques received";
+    private static final String TELLER = "Teller";
+    private static final String EMPLOYEE = "Employee";
+    private static final String OFFICE = "Office";
+    private static final String CASHDRAW_LIMIT = "Cashdraw limit";
+    private static final String STATE = "State";
+
+    private final Logger logger;
+
+    private final EntityManager entityManager;
+
+    private final HashMap<String, String> tellerColumnMapping = new HashMap<>();
+    private final HashMap<String, String> allColumnMapping = new HashMap<>();
+
+
+    @Autowired
+    public TellerListingReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                                        final EntityManager entityManager) {
+        super();
+        this.logger = logger;
+        this.entityManager = entityManager;
+        this.initializeMapping();
+    }
+
+    private void initializeMapping() {
+        this.tellerColumnMapping.put(TELLER, "tl.identifier");
+        this.tellerColumnMapping.put(OFFICE, "tl.office_identifier");
+        this.tellerColumnMapping.put(CASHDRAW_LIMIT, "tl.cashdraw_limit");
+        this.tellerColumnMapping.put(EMPLOYEE, "tl.assigned_employee_identifier");
+        this.tellerColumnMapping.put(STATE, "tl.a_state");
+
+        this.allColumnMapping.putAll(tellerColumnMapping);
+    }
+
+    @Override
+    public ReportDefinition getReportDefinition() {
+        final ReportDefinition reportDefinition = new ReportDefinition();
+        reportDefinition.setIdentifier("Listing");
+        reportDefinition.setName("Teller Listing");
+        reportDefinition.setDescription("List of all Tellers.");
+        reportDefinition.setQueryParameters(this.buildQueryParameters());
+        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+        return reportDefinition;
+    }
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return null;
+    }
+
+    private List<QueryParameter> buildQueryParameters() {
+        return null;
+    }
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        final ReportDefinition reportDefinition = this.getReportDefinition();
+        this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
+
+        final ReportPage reportPage = new ReportPage();
+        reportPage.setName(reportDefinition.getName());
+        reportPage.setDescription(reportDefinition.getDescription());
+        reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
+
+        final Query tellerQuery = this.entityManager.createNativeQuery(this.buildTellerQuery(reportRequest, pageIndex, size));
+        final List<?> tellerResultList =  tellerQuery.getResultList();
+        reportPage.setRows(this.buildRows(reportRequest, tellerResultList));
+
+        reportPage.setHasMore(
+                !this.entityManager.createNativeQuery(this.buildTellerQuery(reportRequest, pageIndex + 1, size))
+                        .getResultList().isEmpty()
+        );
+
+        reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
+        reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+        return reportPage;
+    }
+
+    private String buildTellerQuery(ReportRequest reportRequest, int pageIndex, int size) {
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.tellerColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("tajet_teller tl ");
+
+        final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
+        if (!queryParameters.isEmpty()) {
+            final ArrayList<String> criteria = new ArrayList<>();
+            queryParameters.forEach(queryParameter -> {
+                if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
+                    criteria.add(
+                            CriteriaBuilder.buildCriteria(this.tellerColumnMapping.get(queryParameter.getName()), queryParameter)
+                    );
+                }
+            });
+
+            if (!criteria.isEmpty()) {
+                query.append(" WHERE ");
+                query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+            }
+
+        }
+        query.append(" ORDER BY tl.identifier");
+
+        query.append(" LIMIT ");
+        query.append(size);
+        if (pageIndex > 0) {
+            query.append(" OFFSET ");
+            query.append(size * pageIndex);
+        }
+
+        return query.toString();
+    }
+
+    private List<Row> buildRows(ReportRequest reportRequest, List<?> tellerResultList) {
+    return null;
+    }
+
+    private Header createHeader(List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+
+    }
+    
+}


[fineract-cn-reporting] 10/47: Deposit Listing data rows built, Inactive Account Skeleton: Hopefully completes deposit account listing

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit e75d262a7df98cd866d9bd3e72898b4e7bcbdc89
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Mon Aug 21 16:17:18 2017 +0100

    Deposit Listing data rows built, Inactive Account Skeleton: Hopefully completes deposit account listing
---
 ...InactiveCustomerAccountReportSpecification.java |  24 +++++
 .../SavingListReportSpecification.java             | 100 +++++++++++++++++----
 2 files changed, 107 insertions(+), 17 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/InactiveCustomerAccountReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/InactiveCustomerAccountReportSpecification.java
new file mode 100644
index 0000000..148743b
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/InactiveCustomerAccountReportSpecification.java
@@ -0,0 +1,24 @@
+package io.mifos.reporting.service.internal.specification;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
+@Report(category = "Customer", identifier = "Inactive")
+public class InactiveCustomerAccountReportSpecification implements ReportSpecification {
+    @Override
+    public ReportDefinition getReportDefinition() {
+        return null;
+    }
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        return null;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+
+    }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
index 8496a04..a5cf74b 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
@@ -1,5 +1,7 @@
 package io.mifos.reporting.service.internal.specification;
 
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.DateConverter;
 import io.mifos.reporting.api.v1.domain.*;
 import io.mifos.reporting.service.ServiceConstants;
 import io.mifos.reporting.service.spi.*;
@@ -9,6 +11,8 @@ import org.springframework.beans.factory.annotation.Qualifier;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
+import java.time.Clock;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -75,11 +79,15 @@ public class SavingListReportSpecification implements ReportSpecification {
         final List<?> depositAccountResultList = depositAccountQuery.getResultList();
         reportPage.setRows(this.buildRows(reportRequest, depositAccountResultList));
 
-        return null;
-    }
 
-    private List<Row> buildRows(ReportRequest reportRequest, List<?> customerResultList) {
-        return null;
+        reportPage.setHasMore(
+                !this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, pageIndex + 1, size))
+                        .getResultList().isEmpty()
+        );
+
+        reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
+        reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+        return reportPage;
     }
 
     private List<QueryParameter> buildQueryParameters() {
@@ -132,6 +140,77 @@ public class SavingListReportSpecification implements ReportSpecification {
         this.allColumnMapping.putAll(employeeColumnMapping);
         this.allColumnMapping.putAll(accountColumnMapping);
     }
+    private Header createHeader(final List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+
+    private List<Row> buildRows(final ReportRequest reportRequest, final List<?> depositAccountResultList) {
+        final ArrayList<Row> rows =new ArrayList<>();
+        depositAccountResultList.forEach(result -> {
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            final String customerIdentifier;
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues = (Object[]) result;
+
+                customerIdentifier = resultValues[0].toString();
+
+                for (final Object resultValue : resultValues) {
+                    final Value value = new Value();
+                    if (resultValue != null) {
+                        value.setValues(new String[]{resultValue.toString()});
+                    } else {
+                        value.setValues(new String[]{});
+                    }
+
+                    row.getValues().add(value);
+                }
+            } else {
+
+                customerIdentifier = result.toString();
+                final Value value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
+            final Query customerQuery = this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, customerIdentifier));
+            final List<?> accountResultList = customerQuery.getResultList();
+            final ArrayList<String> values = new ArrayList<>();
+            accountResultList.forEach(customerResult -> {
+                if (customerResult instanceof Object[]) {
+                    final Object[] customerResultValues = (Object[]) customerResult;
+                    final String customerValue = customerResultValues[0].toString();
+                    values.add(customerValue);
+                }
+            });
+            final Value customerValue = new Value();
+            customerValue.setValues(values.toArray(new String[values.size()]));
+            row.getValues().add(customerValue);
+
+            final String officeQueryString = this.buildOfficeQuery(reportRequest, customerIdentifier);
+            if (officeQueryString != null) {
+                final Query officeQuery = this.entityManager.createNativeQuery(officeQueryString);
+                final List<?> resultList = officeQuery.getResultList();
+                final Value officeValue = new Value();
+                officeValue.setValues(new String[]{resultList.get(0).toString()});
+                row.getValues().add(officeValue);
+            }
+
+            rows.add(row);
+        });
+
+        return rows;
+    }
 
     private String buildAccountQuery(final ReportRequest reportRequest, int pageIndex, int size) {
         final StringBuilder query = new StringBuilder("SELECT ");
@@ -216,19 +295,6 @@ public class SavingListReportSpecification implements ReportSpecification {
                 "ORDER BY cst.identifier";
     }
 
-
-    private Header createHeader(final List<DisplayableField> displayableFields) {
-        final Header header = new Header();
-        header.setColumnNames(
-                displayableFields
-                        .stream()
-                        .map(DisplayableField::getName)
-                        .collect(Collectors.toList())
-        );
-        return header;
-    }
-
-
     private List<DisplayableField> buildDisplayableFields() {
 
         return Arrays.asList(


[fineract-cn-reporting] 09/47: Add displayable fields, customer query, office query and deposit account query for savings accounts

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 8eba0c024926f7294f2336659338f6922f4f090d
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Mon Aug 21 08:47:19 2017 +0100

    Add displayable fields, customer query, office query and deposit account query for savings accounts
---
 .../TestSavingListReportSpecification.java         |  21 +++
 .../SavingListReportSpecification.java             | 195 ++++++++++++++++++---
 2 files changed, 188 insertions(+), 28 deletions(-)

diff --git a/component-test/src/main/java/io/mifos/reporting/TestSavingListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestSavingListReportSpecification.java
new file mode 100644
index 0000000..4627617
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/reporting/TestSavingListReportSpecification.java
@@ -0,0 +1,21 @@
+package io.mifos.reporting;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestSavingListReportSpecification extends AbstractReportingSpecificationTest {
+    public TestSavingListReportSpecification() {
+        super();
+    }
+
+    @Test
+    public void shouldReturnReportDefinition() {
+        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Deposit");
+        Assert.assertTrue(
+                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+        );
+    }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
index 1c6fdf0..8496a04 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
@@ -2,40 +2,49 @@ package io.mifos.reporting.service.internal.specification;
 
 import io.mifos.reporting.api.v1.domain.*;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+import io.mifos.reporting.service.spi.*;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 
 import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
 
-@Report(category = "Saving", identifier = "Listing")
-public class SavingListReportSpecification implements ReportSpecification{
-    private static final String SAVING_ACCOUNT = "Saving account";
+@Report(category = "Deposit", identifier = "Listing")
+public class SavingListReportSpecification implements ReportSpecification {
+
     private static final String CUSTOMER = "Customer";
+    private static final String FIRST_NAME = "First name";
+    private static final String MIDDLE_NAME = "Middle name";
+    private static final String LAST_NAME = "Last name";
     private static final String EMPLOYEE = "Employee";
-    //private static final String OFFICE = "Office";
-    private static final String DATE_RANGE = "Date range";
+    private static final String ACCOUNT_NUMBER = "Account number";
+    private static final String ACCOUNT_TYPE = "Account type";
+    private static final String STATE = "State";
+    private static final String OFFICE = "Office";
+    private static final String DATE_RANGE = "Date created";
 
     private final EntityManager entityManager;
 
     private final Logger logger;
 
     private final HashMap<String, String> customerColumnMapping = new HashMap<>();
-    private final HashMap<String, String> savingAccountColumnMapping = new HashMap<>();
-    // private final HashMap<String, String> officeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> accountColumnMapping = new HashMap<>();
+    private final HashMap<String, String> officeColumnMapping = new HashMap<>();
     private final HashMap<String, String> employeeColumnMapping = new HashMap<>();
     private final HashMap<String, String> allColumnMapping = new HashMap<>();
 
 
     @Autowired
-    public SavingListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, final EntityManager entityManager){
+    public SavingListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, final EntityManager entityManager) {
         this.entityManager = entityManager;
         this.logger = logger;
+        this.initializeMapping();
     }
 
 
@@ -53,37 +62,161 @@ public class SavingListReportSpecification implements ReportSpecification{
 
     @Override
     public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        final ReportDefinition reportDefinition = this.getReportDefinition();
+        this.logger.info("Generating report {0} ", reportDefinition.getIdentifier());
+
+        final ReportPage reportPage = new ReportPage();
+        reportPage.setName(reportDefinition.getName());
+        reportPage.setDescription(reportDefinition.getDescription());
+        reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
+
+        final Query depositAccountQuery = this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, pageIndex, size));
+
+        final List<?> depositAccountResultList = depositAccountQuery.getResultList();
+        reportPage.setRows(this.buildRows(reportRequest, depositAccountResultList));
+
+        return null;
+    }
+
+    private List<Row> buildRows(ReportRequest reportRequest, List<?> customerResultList) {
         return null;
     }
 
+    private List<QueryParameter> buildQueryParameters() {
+        return Arrays.asList(
+                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+        );
+    }
+
     @Override
     public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+        final ArrayList<String> unknownFields = new ArrayList<>();
+        reportRequest.getQueryParameters().forEach(queryParameter -> {
+            if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
+                unknownFields.add(queryParameter.getName());
+            }
+        });
+
+        reportRequest.getDisplayableFields().forEach(displayableField -> {
+            if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
+                unknownFields.add(displayableField.getName());
+            }
+        });
+
+        if (!unknownFields.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
+            );
+        }
 
     }
 
-    public String buildSavingAccountQuery(){
+    private void initializeMapping() {
+        this.customerColumnMapping.put(CUSTOMER, "cst.identifier");
+        this.customerColumnMapping.put(FIRST_NAME, "cst.given_name");
+        this.customerColumnMapping.put(MIDDLE_NAME, "cst.middle_name");
+        this.customerColumnMapping.put(LAST_NAME, "cst.surname");
+
+        this.officeColumnMapping.put(OFFICE, "cst.assigned_office");
+
+        this.employeeColumnMapping.put(EMPLOYEE, "pi.created_by");
 
-        return "SELECT ... FROM shed_product_instances pi";
+        this.accountColumnMapping.put(ACCOUNT_NUMBER, "pi.customer_identifier, pi.account_identifier");
+        this.accountColumnMapping.put(STATE, " pi.a_state");
+        this.accountColumnMapping.put(ACCOUNT_TYPE, "pi.product_definition_id");
+        this.accountColumnMapping.put(DATE_RANGE, "pi.created_on");
 
+        this.allColumnMapping.putAll(customerColumnMapping);
+        this.allColumnMapping.putAll(officeColumnMapping);
+        this.allColumnMapping.putAll(employeeColumnMapping);
+        this.allColumnMapping.putAll(accountColumnMapping);
     }
 
-    public String buildCustomerQuery(){
+    private String buildAccountQuery(final ReportRequest reportRequest, int pageIndex, int size) {
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.accountColumnMapping.get(displayableField.getName())
+                    + this.employeeColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("shed_product_instances pi ");
+        final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
+        if (!queryParameters.isEmpty()) {
+            final ArrayList<String> criteria = new ArrayList<>();
+            queryParameters.forEach(queryParameter -> {
+                if (queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
+                    criteria.add(
+                            CriteriaBuilder.buildCriteria(this.accountColumnMapping.get(queryParameter.getName()), queryParameter)
+                    );
+                    criteria.add(
+                            CriteriaBuilder.buildCriteria(this.employeeColumnMapping.get(queryParameter.getName()), queryParameter)
+                    );
+                }
+            });
+
+            if (!criteria.isEmpty()) {
+                query.append(" WHERE ");
+                query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+            }
+
+        }
+        query.append(" ORDER BY pi.customer_identifier");
+
+        query.append(" LIMIT ");
+        query.append(size);
+        if (pageIndex > 0) {
+            query.append(" OFFSET ");
+            query.append(size * pageIndex);
+        }
+
+        return query.toString();
+
+        // return "SELECT ... FROM shed_product_instances pi";
 
-        return null;
     }
 
-    private void initializeMapping(){
-        this.customerColumnMapping.put(CUSTOMER, "cst.identifier, cst.given_name, cst.middle_name, " +
-                "cst.surname, cst.assigned_office");
-        this.employeeColumnMapping.put(EMPLOYEE, "pi.created_by");
-        this.savingAccountColumnMapping.put(SAVING_ACCOUNT, "pi.customer_identifier, pi.product_definition_id, pi.account_identifier, pi.a_state");
-        this.savingAccountColumnMapping.put(DATE_RANGE, "pi.created_on");
+    private String buildCustomerQuery(final ReportRequest reportRequest, final String customerIdentifier) {
+            final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+            final ArrayList<String> columns = new ArrayList<>();
+            displayableFields.forEach(displayableField -> {
+                final String column = this.customerColumnMapping.get(displayableField.getName());
+                if (column != null) {
+                    columns.add(column);
+                }
+            });
+        return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
+                "FROM maat_customers cst " +
+                "LEFT JOIN shed_product_instances pi on cst.identifier = pi.customer_identifier " +
+                "WHERE pi.customer_identifier ='" + customerIdentifier + "' " +
+                "ORDER BY cst.identifier";
+    }
 
-        this.allColumnMapping.putAll(customerColumnMapping);
-        this.allColumnMapping.putAll(employeeColumnMapping);
-        this.allColumnMapping.putAll(savingAccountColumnMapping);
+    private String buildOfficeQuery(final ReportRequest reportRequest, final String customerIdentifier) {
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.officeColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
+                "FROM maat_customers cst " +
+                "WHERE cst.identifier ='" + customerIdentifier + "' " +
+                "ORDER BY cst.identifier";
     }
 
+
     private Header createHeader(final List<DisplayableField> displayableFields) {
         final Header header = new Header();
         header.setColumnNames(
@@ -98,12 +231,18 @@ public class SavingListReportSpecification implements ReportSpecification{
 
     private List<DisplayableField> buildDisplayableFields() {
 
-        return null;
-    }
-
-    private List<QueryParameter> buildQueryParameters(){
+        return Arrays.asList(
+                DisplayableFieldBuilder.create(CUSTOMER, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(ACCOUNT_NUMBER, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(DATE_RANGE, Type.TEXT).build()
+        );
 
-        return null;
     }
 
+
 }


[fineract-cn-reporting] 13/47: Refactor, loan skeleton builders

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 3b8eb87fb34a4e6f511d01147457a23bcac69c1d
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Mon Aug 28 10:10:04 2017 +0100

    Refactor, loan skeleton builders
---
 .../specification/LoanListReportSpecification.java | 91 ++++++++++++++++++++++
 .../LoanListingReportSpecification.java            | 51 ------------
 ...ion.java => TellerListReportSpecification.java} |  6 +-
 3 files changed, 94 insertions(+), 54 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
new file mode 100644
index 0000000..429f42d
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
@@ -0,0 +1,91 @@
+package io.mifos.reporting.service.internal.specification;
+
+import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import javax.persistence.EntityManager;
+import java.util.HashMap;
+import java.util.List;
+
+@Report(category = "Loan", identifier = "Listing")
+public class LoanListReportSpecification implements ReportSpecification {
+
+    private static final String CUSTOMER = "Customer";
+    private static final String FIRST_NAME = "First name";
+    private static final String MIDDLE_NAME = "Middle name";
+    private static final String LAST_NAME = "Last name";
+    private static final String EMPLOYEE = "Employee";
+    private static final String ACCOUNT_NUMBER = "Account number";
+    private static final String ACCOUNT_TYPE = "Account type";
+    private static final String STATE = "State";
+    private static final String OFFICE = "Office";
+    private static final String DATE_RANGE = "Date created";
+
+    private final Logger logger;
+
+    private final EntityManager entityManager;
+
+    private final HashMap<String, String> customerColumnMapping = new HashMap<>();
+    private final HashMap<String, String> loanColumnMapping = new HashMap<>();
+    private final HashMap<String, String> officeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> employeeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> allColumnMapping = new HashMap<>();
+
+    @Autowired
+    public LoanListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                       final EntityManager entityManager) {
+        super();
+        this.logger = logger;
+        this.entityManager = entityManager;
+        this.initializeMapping();
+    }
+
+    private void initializeMapping() {
+    }
+
+    @Override
+    public ReportDefinition getReportDefinition() {
+        final ReportDefinition reportDefinition = new ReportDefinition();
+        reportDefinition.setIdentifier("Listing");
+        reportDefinition.setName("Loan Account Listing");
+        reportDefinition.setDescription("List of all loan accounts.");
+        reportDefinition.setQueryParameters(this.buildQueryParameters());
+        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+        return reportDefinition;
+    }
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return null;
+    }
+
+    private List<QueryParameter> buildQueryParameters() {
+        return null;
+    }
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        return null;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+
+    }
+
+    private String buildCustomerQuery(final ReportRequest reportRequest, int pageIndex, int size){
+        return null;
+    }
+
+    private String buildLoanAccountQuery(final ReportRequest reportRequest, final String customerIdentifier){
+        return null;
+    }
+
+    private String buildOfficeQuery(final ReportRequest reportRequest, final String customerIdentifier){
+        return null;
+    }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListingReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListingReportSpecification.java
deleted file mode 100644
index d90dd75..0000000
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListingReportSpecification.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-
-@Report(category = "Loan", identifier = "Listing")
-public class LoanListingReportSpecification implements ReportSpecification {
-
-    private static final String TOTAL_CASH_ON_HAND = "Cash on hand";
-
-
-    private final Logger logger;
-
-    private final EntityManager entityManager;
-
-    @Autowired
-    public LoanListingReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
-                                                        final EntityManager entityManager) {
-        super();
-        this.logger = logger;
-        this.entityManager = entityManager;
-        this.initializeMapping();
-    }
-
-    private void initializeMapping() {
-    }
-
-    @Override
-    public ReportDefinition getReportDefinition() {
-        return null;
-    }
-
-    @Override
-    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
-        return null;
-    }
-
-    @Override
-    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
-
-    }
-}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListingReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
similarity index 95%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListingReportSpecification.java
rename to service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
index 34af570..3c51c85 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListingReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
@@ -21,7 +21,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 @Report(category = "Teller" , identifier = "Listing")
-public class TellerListingReportSpecification implements ReportSpecification {
+public class TellerListReportSpecification implements ReportSpecification {
 
    // private static final String TOTAL_CASH_ON_HAND = "Cash on hand";
    // private static final String TOTAL_CASH_RECEIVED = "Cash received";
@@ -43,8 +43,8 @@ public class TellerListingReportSpecification implements ReportSpecification {
 
 
     @Autowired
-    public TellerListingReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
-                                                        final EntityManager entityManager) {
+    public TellerListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                         final EntityManager entityManager) {
         super();
         this.logger = logger;
         this.entityManager = entityManager;


[fineract-cn-reporting] 30/47: Adding rat checks.

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit d4f065c78ccec1ddf415217e66fb14f761c51284
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Apr 9 20:46:48 2018 +0200

    Adding rat checks.
---
 api/build.gradle               | 18 ++++++++++++++++++
 api/settings.gradle            | 17 +++++++++++++++++
 build.gradle                   | 24 ++++++++++++++++++++++++
 component-test/build.gradle    | 18 ++++++++++++++++++
 component-test/settings.gradle | 17 +++++++++++++++++
 service/build.gradle           | 18 ++++++++++++++++++
 service/settings.gradle        | 17 +++++++++++++++++
 settings.gradle                | 17 +++++++++++++++++
 shared.gradle                  | 30 ++++++++++++++++++++++++++++++
 9 files changed, 176 insertions(+)

diff --git a/api/build.gradle b/api/build.gradle
index 1ed9d2b..5b9924a 100644
--- a/api/build.gradle
+++ b/api/build.gradle
@@ -1,3 +1,20 @@
+/*
+ * 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.
+ */
+
 buildscript {
     repositories {
         jcenter()
@@ -10,6 +27,7 @@ buildscript {
 
 plugins {
     id "com.github.hierynomus.license" version "0.13.1"
+    id("org.nosphere.apache.rat") version "0.3.1"
 }
 
 apply from: '../shared.gradle'
diff --git a/api/settings.gradle b/api/settings.gradle
index 7c8e3dc..491f745 100644
--- a/api/settings.gradle
+++ b/api/settings.gradle
@@ -1 +1,18 @@
+/*
+ * 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.
+ */
+
 rootProject.name = 'api'
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index b82a3b2..848847a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,3 +1,20 @@
+/*
+ * 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.
+ */
+
 group 'org.apache.fineract.cn'
 
 task publishApiToMavenLocal {
@@ -34,3 +51,10 @@ task licenseFormat {
     dependsOn gradle.includedBuild('service').task(':licenseFormat')
     dependsOn gradle.includedBuild('component-test').task(':licenseFormat')
 }
+
+task rat {
+    group 'all'
+    dependsOn gradle.includedBuild('api').task(':rat')
+    dependsOn gradle.includedBuild('service').task(':rat')
+    dependsOn gradle.includedBuild('component-test').task(':rat')
+}
diff --git a/component-test/build.gradle b/component-test/build.gradle
index 04f63bb..fb630c5 100644
--- a/component-test/build.gradle
+++ b/component-test/build.gradle
@@ -1,3 +1,20 @@
+/*
+ * 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.
+ */
+
 buildscript {
     ext {
         springBootVersion = '1.4.1.RELEASE'
@@ -14,6 +31,7 @@ buildscript {
 
 plugins {
     id "com.github.hierynomus.license" version "0.13.1"
+    id("org.nosphere.apache.rat") version "0.3.1"
 }
 apply from: '../shared.gradle'
 
diff --git a/component-test/settings.gradle b/component-test/settings.gradle
index 07867cb..a07a3bc 100644
--- a/component-test/settings.gradle
+++ b/component-test/settings.gradle
@@ -1 +1,18 @@
+/*
+ * 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.
+ */
+
 rootProject.name = 'component-test'
\ No newline at end of file
diff --git a/service/build.gradle b/service/build.gradle
index a5d5eea..226d55e 100644
--- a/service/build.gradle
+++ b/service/build.gradle
@@ -1,3 +1,20 @@
+/*
+ * 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.
+ */
+
 buildscript {
     ext {
         springBootVersion = '1.4.1.RELEASE'
@@ -14,6 +31,7 @@ buildscript {
 
 plugins {
     id "com.github.hierynomus.license" version "0.13.1"
+    id("org.nosphere.apache.rat") version "0.3.1"
 }
 
 apply from: '../shared.gradle'
diff --git a/service/settings.gradle b/service/settings.gradle
index 081feb4..1a4c2fd 100644
--- a/service/settings.gradle
+++ b/service/settings.gradle
@@ -1 +1,18 @@
+/*
+ * 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.
+ */
+
 rootProject.name = 'service'
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 7c66673..497fb1d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,20 @@
+/*
+ * 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.
+ */
+
 rootProject.name = 'reporting'
 
 includeBuild 'api'
diff --git a/shared.gradle b/shared.gradle
index 3b93291..fd71003 100644
--- a/shared.gradle
+++ b/shared.gradle
@@ -1,3 +1,20 @@
+/*
+ * 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.
+ */
+
 group 'org.apache.fineract.cn.reporting'
 version '0.1.0-BUILD-SNAPSHOT'
 
@@ -65,3 +82,16 @@ license {
         yaml = 'SCRIPT_STYLE'
     }
 }
+
+rat {
+    // List of exclude directives, defaults to ['**/.gradle/**']
+    excludes = [
+            "**/.idea/**",
+            "**/.gradle/**",
+            "**/gradle/**",
+            "**/build/**",
+            "gradlew",
+            "gradlew.bat",
+            "README.md"
+    ]
+}


[fineract-cn-reporting] 08/47: saving list skeleton

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit c843bc0b94ab588290809ec72b1ac8ed3539294c
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Fri Aug 18 05:38:13 2017 +0100

    saving list skeleton
---
 .../SavingListReportSpecification.java             | 109 +++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
new file mode 100644
index 0000000..1c6fdf0
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
@@ -0,0 +1,109 @@
+package io.mifos.reporting.service.internal.specification;
+
+import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import javax.persistence.EntityManager;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Report(category = "Saving", identifier = "Listing")
+public class SavingListReportSpecification implements ReportSpecification{
+    private static final String SAVING_ACCOUNT = "Saving account";
+    private static final String CUSTOMER = "Customer";
+    private static final String EMPLOYEE = "Employee";
+    //private static final String OFFICE = "Office";
+    private static final String DATE_RANGE = "Date range";
+
+    private final EntityManager entityManager;
+
+    private final Logger logger;
+
+    private final HashMap<String, String> customerColumnMapping = new HashMap<>();
+    private final HashMap<String, String> savingAccountColumnMapping = new HashMap<>();
+    // private final HashMap<String, String> officeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> employeeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> allColumnMapping = new HashMap<>();
+
+
+    @Autowired
+    public SavingListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, final EntityManager entityManager){
+        this.entityManager = entityManager;
+        this.logger = logger;
+    }
+
+
+    @Override
+    public ReportDefinition getReportDefinition() {
+
+        final ReportDefinition reportDefinition = new ReportDefinition();
+        reportDefinition.setIdentifier("Listing");
+        reportDefinition.setName("Saving Listing");
+        reportDefinition.setDescription("List of all savings.");
+        reportDefinition.setQueryParameters(this.buildQueryParameters());
+        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+        return reportDefinition;
+    }
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        return null;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+
+    }
+
+    public String buildSavingAccountQuery(){
+
+        return "SELECT ... FROM shed_product_instances pi";
+
+    }
+
+    public String buildCustomerQuery(){
+
+        return null;
+    }
+
+    private void initializeMapping(){
+        this.customerColumnMapping.put(CUSTOMER, "cst.identifier, cst.given_name, cst.middle_name, " +
+                "cst.surname, cst.assigned_office");
+        this.employeeColumnMapping.put(EMPLOYEE, "pi.created_by");
+        this.savingAccountColumnMapping.put(SAVING_ACCOUNT, "pi.customer_identifier, pi.product_definition_id, pi.account_identifier, pi.a_state");
+        this.savingAccountColumnMapping.put(DATE_RANGE, "pi.created_on");
+
+        this.allColumnMapping.putAll(customerColumnMapping);
+        this.allColumnMapping.putAll(employeeColumnMapping);
+        this.allColumnMapping.putAll(savingAccountColumnMapping);
+    }
+
+    private Header createHeader(final List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+
+    private List<DisplayableField> buildDisplayableFields() {
+
+        return null;
+    }
+
+    private List<QueryParameter> buildQueryParameters(){
+
+        return null;
+    }
+
+}


[fineract-cn-reporting] 15/47: Update Loan Report, Income stat skeleton

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 2ec5602a252421f3803f9e35ce69233e747e9ff6
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Wed Aug 30 19:46:47 2017 +0100

    Update Loan Report, Income stat skeleton
---
 .../IncomeStatementReportSpecification.java        |  27 +++
 .../specification/LoanListReportSpecification.java | 246 +++++++++++++++++++--
 .../SavingListReportSpecification.java             |  17 +-
 3 files changed, 262 insertions(+), 28 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
new file mode 100644
index 0000000..936e573
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -0,0 +1,27 @@
+package io.mifos.reporting.service.internal.specification;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.service.spi.ReportSpecification;
+
+public class IncomeStatementReportSpecification implements ReportSpecification {
+
+    public IncomeStatementReportSpecification(){
+
+    }
+    @Override
+    public ReportDefinition getReportDefinition() {
+        return null;
+    }
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        return null;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+
+    }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
index 429f42d..0b6509b 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
@@ -1,30 +1,40 @@
 package io.mifos.reporting.service.internal.specification;
 
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.DateConverter;
 import io.mifos.reporting.api.v1.domain.*;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+import io.mifos.reporting.service.spi.*;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 
 import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.text.DecimalFormat;
+import java.time.Clock;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Report(category = "Loan", identifier = "Listing")
 public class LoanListReportSpecification implements ReportSpecification {
 
+    private static final String DATE_RANGE = "Date created";
     private static final String CUSTOMER = "Customer";
     private static final String FIRST_NAME = "First name";
     private static final String MIDDLE_NAME = "Middle name";
     private static final String LAST_NAME = "Last name";
     private static final String EMPLOYEE = "Employee";
-    private static final String ACCOUNT_NUMBER = "Account number";
-    private static final String ACCOUNT_TYPE = "Account type";
-    private static final String STATE = "State";
+    private static final String LOAN_STATE = "State";
+    private static final String LOAN_ACCOUNT_NUMBER = "Account number";
+    private static final String LOAN_TYPE = "Account type";
+    private static final String LOAN_TERM = "Loan term";
     private static final String OFFICE = "Office";
-    private static final String DATE_RANGE = "Date created";
+
 
     private final Logger logger;
 
@@ -45,9 +55,6 @@ public class LoanListReportSpecification implements ReportSpecification {
         this.initializeMapping();
     }
 
-    private void initializeMapping() {
-    }
-
     @Override
     public ReportDefinition getReportDefinition() {
         final ReportDefinition reportDefinition = new ReportDefinition();
@@ -59,33 +66,230 @@ public class LoanListReportSpecification implements ReportSpecification {
         return reportDefinition;
     }
 
-    private List<DisplayableField> buildDisplayableFields() {
-        return null;
-    }
-
-    private List<QueryParameter> buildQueryParameters() {
-        return null;
-    }
-
     @Override
     public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
-        return null;
+        final ReportDefinition reportDefinition = this.getReportDefinition();
+        this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
+
+        final ReportPage reportPage = new ReportPage();
+        reportPage.setName(reportDefinition.getName());
+        reportPage.setDescription(reportDefinition.getDescription());
+        reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
+
+        final Query customerQuery;
+        customerQuery = this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, pageIndex, size));
+        final List<?> customerResultList =  customerQuery.getResultList();
+        reportPage.setRows(this.buildRows(reportRequest, customerResultList));
+
+        reportPage.setHasMore(
+                !this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, pageIndex + 1, size))
+                        .getResultList().isEmpty()
+        );
+
+        reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
+        reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+        return reportPage;
     }
 
     @Override
     public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+        final ArrayList<String> unknownFields =  new ArrayList<>();
+        reportRequest.getQueryParameters().forEach(queryParameter -> {
+            if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
+                unknownFields.add(queryParameter.getName());
+            }
+        });
+
+        reportRequest.getDisplayableFields().forEach(displayableField -> {
+            if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
+                unknownFields.add(displayableField.getName());
+            }
+        });
+
+        if (!unknownFields.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
+            );
+        }
+    }
+
+    private void initializeMapping() {
+        this.customerColumnMapping.put(CUSTOMER, "cst.identifier");
+        this.customerColumnMapping.put(FIRST_NAME, "cst.given_name");
+        this.customerColumnMapping.put(MIDDLE_NAME, "cst.middle_name");
+        this.customerColumnMapping.put(LAST_NAME, "cst.surname");
+        this.customerColumnMapping.put(OFFICE, "cst.assigned_office");
+
+        this.loanColumnMapping.put(DATE_RANGE, "cases.created_on");
+        this.loanColumnMapping.put(LOAN_STATE, "cases.current_state");
+        this.loanColumnMapping.put(LOAN_TYPE, "cases.product_identifier");
+        this.loanColumnMapping.put(EMPLOYEE, "cases.created_by");
+        this.loanColumnMapping.put(LOAN_TERM,
+                "il_cases.term_range_temporal_unit, " +
+                "il_cases.term_range_minimum, " +
+                "il_cases.term_range_maximum, " +
+                "il_cases.balance_range_maximum");
+
+        this.loanColumnMapping.put(LOAN_ACCOUNT_NUMBER, "il_cases.case_id");
+
+        this.allColumnMapping.putAll(customerColumnMapping);
+        this.allColumnMapping.putAll(loanColumnMapping);
+    }
 
+    private Header createHeader(List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+    private List<Row> buildRows(ReportRequest reportRequest, List<?> customerResultList) {
+        final ArrayList<Row> rows = new ArrayList<>();
+
+        customerResultList.forEach(result -> {
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            final String customerIdentifier;
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues;
+                resultValues = (Object[]) result;
+
+                customerIdentifier = resultValues[0].toString();
+
+                for (final Object resultValue : resultValues) {
+                    final Value value = new Value();
+                    if (resultValue != null) {
+                        value.setValues(new String[]{resultValue.toString()});
+                    } else {
+                        value.setValues(new String[]{});
+                    }
+
+                    row.getValues().add(value);
+                }
+            } else {
+                customerIdentifier = result.toString();
+
+                final Value value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
+            final DecimalFormat decimalFormat = new DecimalFormat("0.00");
+            final Query accountQuery = this.entityManager.createNativeQuery(this.buildLoanAccountQuery(reportRequest, customerIdentifier));
+            final List<?> accountResultList = accountQuery.getResultList();
+            final ArrayList<String> values = new ArrayList<>();
+            accountResultList.forEach(accountResult -> {
+                if (accountResult instanceof Object[]) {
+                    final Object[] accountResultValues;
+                    accountResultValues = (Object[]) accountResult;
+                    final String accountValue = accountResultValues[0].toString() + " (" +
+                            decimalFormat.format(Double.valueOf(accountResultValues[1].toString())) + ")";
+                    values.add(accountValue);
+                }
+            });
+            final Value accountValue = new Value();
+            accountValue.setValues(values.toArray(new String[values.size()]));
+            row.getValues().add(accountValue);
+
+            rows.add(row);
+        });
+
+        return rows;
+    }
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return Arrays.asList(
+                DisplayableFieldBuilder.create(CUSTOMER, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LOAN_TYPE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LOAN_ACCOUNT_NUMBER, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LOAN_STATE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LOAN_TERM, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).build()
+        );
+    }
+
+    private List<QueryParameter> buildQueryParameters() {
+        return Arrays.asList(
+                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                QueryParameterBuilder.create(LOAN_STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+        );
     }
 
     private String buildCustomerQuery(final ReportRequest reportRequest, int pageIndex, int size){
-        return null;
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column;
+            column = this.customerColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("maat_customers cst ");
+
+        final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
+        if (!queryParameters.isEmpty()) {
+            final ArrayList<String> criteria = new ArrayList<>();
+            queryParameters.forEach(queryParameter -> {
+                if((queryParameter.getValue() != null) && !queryParameter.getValue().isEmpty()) {
+                    criteria.add(
+                            CriteriaBuilder.buildCriteria(this.customerColumnMapping.get(queryParameter.getName()), queryParameter)
+                    );
+                }
+            });
+
+            if (!criteria.isEmpty()) {
+                query.append(" WHERE ");
+                query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+            }
+
+        }
+        query.append(" ORDER BY cst.identifier");
+
+        query.append(" LIMIT ");
+        query.append(size);
+        if (pageIndex > 0) {
+            query.append(" OFFSET ");
+            query.append(size * pageIndex);
+        }
+
+        return query.toString();
     }
 
     private String buildLoanAccountQuery(final ReportRequest reportRequest, final String customerIdentifier){
-        return null;
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.loanColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
+                "FROM bastet_il_cases il_cases " +
+                "LEFT JOIN maat_customers cst on il_cases.customer_identifier = cst.identifier " +
+                "WHERE cst.identifier ='" + customerIdentifier + "' " +
+                "ORDER BY il_cases.cases_id";
     }
 
-    private String buildOfficeQuery(final ReportRequest reportRequest, final String customerIdentifier){
+    //Need this for getting details from cases table
+    private String buildLoanCaseQuery(final ReportRequest reportRequest, final String customerIdentifier){
         return null;
     }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
index a7f8e08..1820df5 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
@@ -169,9 +169,9 @@ public class SavingListReportSpecification implements ReportSpecification {
 
                 for (final Object resultValue : resultValues) {
                     final Value value = new Value();
-                    if (resultValue != null) {
+                    if (resultValue != null)
                         value.setValues(new String[]{resultValue.toString()});
-                    } else {
+                    else {
                         value.setValues(new String[]{});
                     }
 
@@ -180,7 +180,8 @@ public class SavingListReportSpecification implements ReportSpecification {
             } else {
 
                 customerIdentifier = result.toString();
-                final Value value = new Value();
+                final Value value;
+                value = new Value();
                 value.setValues(new String[]{result.toString()});
                 row.getValues().add(value);
             }
@@ -193,10 +194,11 @@ public class SavingListReportSpecification implements ReportSpecification {
                 accountIdentifier = resultValues[2].toString();
 
                 for (final Object resultValue : resultValues) {
-                    final Value value = new Value();
-                    if (resultValue != null) {
+                    final Value value;
+                    value = new Value();
+                    if (resultValue != null)
                         value.setValues(new String[]{resultValue.toString()});
-                    } else {
+                    else {
                         value.setValues(new String[]{});
                     }
 
@@ -226,7 +228,8 @@ public class SavingListReportSpecification implements ReportSpecification {
 
             final String officeQueryString = this.buildOfficeQuery(reportRequest, customerIdentifier);
             if (officeQueryString != null) {
-                final Query officeQuery = this.entityManager.createNativeQuery(officeQueryString);
+                final Query officeQuery;
+                officeQuery = this.entityManager.createNativeQuery(officeQueryString);
                 final List<?> resultList = officeQuery.getResultList();
                 final Value officeValue = new Value();
                 officeValue.setValues(new String[]{resultList.get(0).toString()});


[fineract-cn-reporting] 41/47: FINCN-148 build with travis-ci.com and upload artifacts to Artifactory

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit c608895e064dc56f48f81776fb785f97a6001a05
Author: Juhan Aasaru <Ju...@nortal.com>
AuthorDate: Thu Apr 25 14:12:59 2019 +0300

    FINCN-148 build with travis-ci.com and upload artifacts to Artifactory
---
 .travis.yml                 | 30 +++++++++++++++++++
 README.md                   |  2 +-
 api/build.gradle            |  3 +-
 build.gradle                |  8 +++++
 component-test/build.gradle |  4 ++-
 service/build.gradle        |  5 ++--
 shared.gradle               | 17 +++++++++++
 travis.sh                   | 71 +++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 135 insertions(+), 5 deletions(-)

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b9f156f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+language: java
+sudo: false
+jdk:
+- openjdk8
+install: true
+script: "./travis.sh"
+env:
+  global:
+    - BUILD_SNAPSHOTS_BRANCH=develop
+    - ARTIFACTORY_URL=https://mifos.jfrog.io/mifos
+    - ARTIFACTORY_USER=travis-ci
+    - secure: "OrSywo5h2lcZyzJYuxcUuRca4c9M5ikrDoyarK22wRwzpDzSGlfxraYk63XfZ54k+P2xcnWHx+OZCE4oJWCAqlrko7yRa3EW0MVRWPxVHnATIXqUXZU9xAFNAttmWO21zcsN6Z2pQdaqdJbOKgacpy8sgQSPYggkEqa9uKuIeUhRoAdI7895yq3tADCYvlGOzKSc4g9i32THbctk3KyRA6lfgSJ0jfMf/m0AkXIrvTgn4Id6OK2813omkKdXpvD6d7Xc+6FuXJf/WNjwANkFe+vjg1qbBWcTgq7D5yNVqKujLp60VYjr5unz+Xb12OnUWK++oc6rx2ug/c92dryDnC/mmP064pM1xdi8V5zcyb/hALyr2qvH7n2a7Njyb6mCf5NjMb7BFaxgYMeBQ0lzd5pPp5ZZ7pP2AQl+9D+b87waaY2FXjEqeqxsJMj+MShFo0ozGy1rJXsJBHIvrMxPFH3uTbnQR [...]
diff --git a/README.md b/README.md
index 62f18d4..7e89825 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Apache Fineract CN Reporting
+# Apache Fineract CN Reporting [![Build Status](https://api.travis-ci.com/apache/fineract-cn-reporting.svg?branch=develop)](https://travis-ci.com/apache/fineract-cn-reporting)
 
 This project provides simple reporting capabilities.
 
diff --git a/api/build.gradle b/api/build.gradle
index 5b9924a..a11f487 100644
--- a/api/build.gradle
+++ b/api/build.gradle
@@ -28,6 +28,7 @@ buildscript {
 plugins {
     id "com.github.hierynomus.license" version "0.13.1"
     id("org.nosphere.apache.rat") version "0.3.1"
+    id "com.jfrog.artifactory" version "4.9.5"
 }
 
 apply from: '../shared.gradle'
@@ -51,7 +52,7 @@ publishing {
             from components.java
             groupId project.group
             artifactId project.name
-            version project.version
+            version project.findProperty('externalVersion') ?: project.version
         }
     }
 }
diff --git a/build.gradle b/build.gradle
index 848847a..eeb68fb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -39,6 +39,14 @@ task publishToMavenLocal {
     dependsOn publishComponentTestToMavenLocal
 }
 
+task artifactoryPublish {
+    group 'all'
+    dependsOn publishToMavenLocal
+    dependsOn gradle.includedBuild('api').task(':artifactoryPublish')
+    dependsOn gradle.includedBuild('service').task(':artifactoryPublish')
+    dependsOn gradle.includedBuild('component-test').task(':artifactoryPublish')
+}
+
 task prepareForTest {
     group 'all'
     dependsOn publishToMavenLocal
diff --git a/component-test/build.gradle b/component-test/build.gradle
index fb630c5..8801703 100644
--- a/component-test/build.gradle
+++ b/component-test/build.gradle
@@ -32,6 +32,7 @@ buildscript {
 plugins {
     id "com.github.hierynomus.license" version "0.13.1"
     id("org.nosphere.apache.rat") version "0.3.1"
+    id "com.jfrog.artifactory" version "4.9.5"
 }
 apply from: '../shared.gradle'
 
@@ -49,8 +50,9 @@ dependencies {
 
 publishing {
     publications {
-        mavenJava(MavenPublication) {
+        componentTest(MavenPublication) {
             from components.java
+            version project.findProperty('externalVersion') ?: project.version
         }
     }
 }
diff --git a/service/build.gradle b/service/build.gradle
index 226d55e..2a866bd 100644
--- a/service/build.gradle
+++ b/service/build.gradle
@@ -32,6 +32,7 @@ buildscript {
 plugins {
     id "com.github.hierynomus.license" version "0.13.1"
     id("org.nosphere.apache.rat") version "0.3.1"
+    id "com.jfrog.artifactory" version "4.9.5"
 }
 
 apply from: '../shared.gradle'
@@ -69,14 +70,14 @@ publishing {
             from components.java
             groupId project.group
             artifactId project.name
-            version project.version
+            version project.findProperty('externalVersion') ?: project.version
         }
         bootService(MavenPublication) {
             // "boot" jar
             artifact ("$buildDir/libs/$project.name-$version-boot.jar")
             groupId project.group
             artifactId ("$project.name-boot")
-            version project.version
+            version project.findProperty('externalVersion') ?: project.version
         }
     }
 }
diff --git a/shared.gradle b/shared.gradle
index fd71003..98f7948 100644
--- a/shared.gradle
+++ b/shared.gradle
@@ -43,6 +43,7 @@ tasks.withType(JavaCompile) {
 repositories {
     jcenter()
     mavenLocal()
+    maven { url 'https://mifos.jfrog.io/mifos/libs-snapshot/' }
 }
 
 dependencyManagement {
@@ -72,6 +73,22 @@ jar {
     from sourceSets.main.allSource
 }
 
+artifactory {
+    contextUrl = System.getenv("ARTIFACTORY_URL")
+    publish {
+        repository {
+            repoKey = project.findProperty('artifactoryRepoKey')
+            username = System.getenv("ARTIFACTORY_USER")
+            password = System.getenv("ARTIFACTORY_PASSWORD")
+        }
+
+        defaults {
+            publications ('api', 'componentTest', 'service', 'bootService')
+        }
+    }
+}
+artifactoryPublish.dependsOn('clean','publishToMavenLocal')
+
 license {
     header rootProject.file('../HEADER')
     strictCheck true
diff --git a/travis.sh b/travis.sh
new file mode 100755
index 0000000..03a75ee
--- /dev/null
+++ b/travis.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+# Documentation: https://cwiki.apache.org/confluence/display/FINERACT/Fineract-CN+Artifactory
+
+#Exit immediately if a command exits with a non-zero status.
+set -e
+EXIT_STATUS=0
+
+# Builds and Publishes a SNAPSHOT
+function build_snapshot() {
+  echo -e "Building and publishing a snapshot out of branch [$TRAVIS_BRANCH]"
+  ./gradlew -PartifactoryRepoKey=libs-snapshot-local -DbuildInfo.build.number=${TRAVIS_COMMIT::7} artifactoryPublish --stacktrace || EXIT_STATUS=$?
+}
+
+# Builds a Pull Request
+function build_pullrequest() {
+  echo -e "Building pull request #$TRAVIS_PULL_REQUEST of branch [$TRAVIS_BRANCH]. Won't publish anything to Artifactory."
+  ./gradlew publishToMavenLocal rat || EXIT_STATUS=$?
+}
+
+# For other branches we need to add branch name as prefix
+function build_otherbranch() {
+  echo -e "Building a snapshot out of branch [$TRAVIS_BRANCH] and publishing it with prefix '${TRAVIS_BRANCH}-SNAPSHOT'"
+  ./gradlew -PartifactoryRepoKey=libs-snapshot-local -DbuildInfo.build.number=${TRAVIS_COMMIT::7} -PexternalVersion=${TRAVIS_BRANCH}-SNAPSHOT artifactoryPublish --stacktrace || EXIT_STATUS=$?
+}
+
+# Builds and Publishes a Tag
+function build_tag() {
+  echo -e "Building tag [$TRAVIS_TAG] and publishing it as a release"
+  ./gradlew -PartifactoryRepoKey=libs-release-local -PexternalVersion=$TRAVIS_TAG artifactoryPublish --stacktrace || EXIT_STATUS=$?
+
+}
+
+echo -e "TRAVIS_BRANCH=$TRAVIS_BRANCH"
+echo -e "TRAVIS_TAG=$TRAVIS_TAG"
+echo -e "TRAVIS_COMMIT=${TRAVIS_COMMIT::7}"
+echo -e "TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST"
+
+# Build Logic
+if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
+  build_pullrequest
+elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" != "$BUILD_SNAPSHOTS_BRANCH" ] && [ "$TRAVIS_TAG" == "" ]  ; then
+  build_otherbranch
+elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "$BUILD_SNAPSHOTS_BRANCH" ] && [ "$TRAVIS_TAG" == "" ] ; then
+  build_snapshot
+elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" != "" ]; then
+  build_tag
+else
+  echo -e "WARN: Unexpected env variable values => Branch [$TRAVIS_BRANCH], Tag [$TRAVIS_TAG], Pull Request [#$TRAVIS_PULL_REQUEST]"
+  ./gradlew clean build
+fi
+
+exit ${EXIT_STATUS}


[fineract-cn-reporting] 36/47: Merge pull request #4 from myrle-krantz/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit a59b90418082d0dc53e692c066495eb4ba252762
Merge: 1efffc4 cf41f64
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Apr 16 21:17:32 2018 +0200

    Merge pull request #4 from myrle-krantz/develop
    
    Updating package names.

 README.md                                          |  2 -
 .../cn}/reporting/api/v1/EventConstants.java       |  2 +-
 .../cn}/reporting/api/v1/PermittableGroupIds.java  |  2 +-
 .../cn}/reporting/api/v1/client/ReportManager.java | 20 +++-----
 .../api/v1/client/ReportNotFoundException.java     |  2 +-
 .../client/ReportParameterValidationException.java |  2 +-
 .../api/v1/domain/AutoCompleteResource.java        |  2 +-
 .../reporting/api/v1/domain/DisplayableField.java  |  2 +-
 .../cn}/reporting/api/v1/domain/Footer.java        |  2 +-
 .../cn}/reporting/api/v1/domain/Header.java        |  2 +-
 .../reporting/api/v1/domain/QueryParameter.java    |  2 +-
 .../reporting/api/v1/domain/ReportDefinition.java  |  2 +-
 .../cn}/reporting/api/v1/domain/ReportPage.java    |  2 +-
 .../cn}/reporting/api/v1/domain/ReportRequest.java |  2 +-
 .../fineract/cn}/reporting/api/v1/domain/Row.java  |  2 +-
 .../fineract/cn}/reporting/api/v1/domain/Type.java |  2 +-
 .../cn}/reporting/api/v1/domain/Value.java         |  2 +-
 .../io/mifos/reporting/api/v1/domain/Sample.java   | 38 --------------
 .../mifos/reporting/api/v1/domain/SampleTest.java  | 58 ----------------------
 .../AbstractReportingSpecificationTest.java        | 25 +++++-----
 .../TestBalanceSheetReportSpecification.java       |  4 +-
 .../TestCustomerListReportSpecification.java       |  4 +-
 .../TestDepositListReportSpecification.java        |  4 +-
 .../TestIncomeStatementReportSpecification.java    |  4 +-
 .../reporting/TestLoanListReportSpecification.java |  4 +-
 .../TestTellerListReportSpecification.java         |  4 +-
 .../TestTellerTransactionReportSpecification.java  |  4 +-
 .../reporting/service/ReportingApplication.java    |  2 +-
 .../reporting/service/ReportingConfiguration.java  | 23 +++++----
 .../cn}/reporting/service/ServiceConstants.java    |  2 +-
 .../provider/ReportSpecificationProvider.java      | 10 ++--
 .../service/internal/repository/DummyEntity.java   |  2 +-
 .../internal/repository/DummyRepository.java       |  2 +-
 .../BalanceSheetReportSpecification.java           | 33 +++++++-----
 .../CustomerListReportSpecification.java           | 49 +++++++++---------
 .../DepositListReportSpecification.java            | 37 +++++++++-----
 .../IncomeStatementReportSpecification.java        | 33 +++++++-----
 .../specification/LoanListReportSpecification.java | 36 +++++++++-----
 .../OfficeListReportSpecification.java             | 36 +++++++++-----
 .../TellerListReportSpecification.java             | 37 +++++++++-----
 .../TellerTransactionReportSpecification.java      | 37 +++++++++-----
 .../service/rest/ReportingRestController.java      | 35 +++++++------
 .../cn}/reporting/service/spi/CriteriaBuilder.java |  4 +-
 .../service/spi/DisplayableFieldBuilder.java       |  6 +--
 .../service/spi/QueryParameterBuilder.java         |  8 +--
 .../fineract/cn}/reporting/service/spi/Report.java |  2 +-
 .../reporting/service/spi/ReportSpecification.java |  8 +--
 47 files changed, 285 insertions(+), 318 deletions(-)


[fineract-cn-reporting] 28/47: Removed unused year and name variables

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 35817cdb5f93cebb74562f6c28fddcb5dc849972
Author: Isaac Kamga <u2...@gmail.com>
AuthorDate: Mon Mar 5 21:21:29 2018 +0100

    Removed unused year and name variables
---
 shared.gradle | 2 --
 1 file changed, 2 deletions(-)

diff --git a/shared.gradle b/shared.gradle
index d189c84..3b93291 100644
--- a/shared.gradle
+++ b/shared.gradle
@@ -64,6 +64,4 @@ license {
         yml = 'SCRIPT_STYLE'
         yaml = 'SCRIPT_STYLE'
     }
-    ext.year = Calendar.getInstance().get(Calendar.YEAR)
-    ext.name = 'The Apache Software Foundation'
 }


[fineract-cn-reporting] 16/47: Listing concrete GL (thoths_accounts) and balances

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit b4b0629946113a2204eeac71629ec1c1f035f62f
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Thu Aug 31 09:57:44 2017 +0100

    Listing concrete GL (thoths_accounts) and balances
---
 .../IncomeStatementReportSpecification.java        | 181 ++++++++++++++++++++-
 1 file changed, 174 insertions(+), 7 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
index 936e573..da4c9df 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -1,27 +1,194 @@
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.service.spi.ReportSpecification;
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.DateConverter;
+import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.*;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Qualifier;
 
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.time.Clock;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Report(category = "Accounting", identifier = "Incomestatement")
 public class IncomeStatementReportSpecification implements ReportSpecification {
 
-    public IncomeStatementReportSpecification(){
+    private static final String DATE_RANGE = "Date range";
+    private static final String TYPE = "Type";
+    private static final String IDENTIFIER = "Identifier";
+    private static final String NAME = "Name";
+    private static final String HOLDER = "Holder";
+    private static final String BALANCE = "Balance";
+    private static final String STATE = "State";
+
+    private final Logger logger;
+
+    private final EntityManager entityManager;
+
+    private final HashMap<String, String> accountColumnMapping = new HashMap<>();
+    private final HashMap<String, String> allColumnMapping = new HashMap<>();
+
 
+    public IncomeStatementReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                              final EntityManager entityManager){
+        super();
+        this.logger = logger;
+        this.entityManager = entityManager;
+        this.initializeMapping();
     }
+
     @Override
     public ReportDefinition getReportDefinition() {
-        return null;
+        final ReportDefinition reportDefinition = new ReportDefinition();
+        reportDefinition.setIdentifier("Incomestatement");
+        reportDefinition.setName("Income Statement");
+        reportDefinition.setDescription("Income statement listing.");
+        reportDefinition.setQueryParameters(this.buildQueryParameters());
+        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+        return reportDefinition;
     }
 
     @Override
     public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
-        return null;
+        final ReportDefinition reportDefinition = this.getReportDefinition();
+        this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
+
+        final ReportPage reportPage = new ReportPage();
+        reportPage.setName(reportDefinition.getName());
+        reportPage.setDescription(reportDefinition.getDescription());
+        reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
+
+        final Query accountQuery = this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, pageIndex, size));
+        final List<?> accountResultList =  accountQuery.getResultList();
+        reportPage.setRows(this.buildRows(reportRequest, accountResultList));
+
+        reportPage.setHasMore(
+                !this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, pageIndex + 1, size))
+                        .getResultList().isEmpty()
+        );
+
+        reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
+        reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+        return reportPage;
     }
 
     @Override
     public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+        final ArrayList<String> unknownFields =  new ArrayList<>();
+        reportRequest.getQueryParameters().forEach(queryParameter -> {
+            if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
+                unknownFields.add(queryParameter.getName());
+            }
+        });
+
+        reportRequest.getDisplayableFields().forEach(displayableField -> {
+            if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
+                unknownFields.add(displayableField.getName());
+            }
+        });
+
+        if (!unknownFields.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
+            );
+        }
+    }
+
+    private void initializeMapping() {
+        this.accountColumnMapping.put(DATE_RANGE, "acc.created_on");
+        this.accountColumnMapping.put(TYPE, "acc.a_type");
+        this.accountColumnMapping.put(IDENTIFIER, "acc.identifier");
+        this.accountColumnMapping.put(NAME, "acc.a_name");
+        this.accountColumnMapping.put(HOLDER, "acc.holders");
+        this.accountColumnMapping.put(BALANCE, "acc.balance");
+        this.accountColumnMapping.put(STATE, "acc.a_state");
+
+        this.allColumnMapping.putAll(accountColumnMapping);
+    }
+
+    private Header createHeader(List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+    private List<Row> buildRows(ReportRequest reportRequest, List<?> customerResultList) {
+        return null;
+    }
+
+    private String buildAccountQuery(ReportRequest reportRequest, int pageIndex, int size) {
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.accountColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("thoth_accounts acc ");
+
+        final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
+        if (!queryParameters.isEmpty()) {
+            final ArrayList<String> criteria = new ArrayList<>();
+            queryParameters.forEach(queryParameter -> {
+                if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
+                    criteria.add(
+                            CriteriaBuilder.buildCriteria(this.accountColumnMapping.get(queryParameter.getName()), queryParameter)
+                    );
+                }
+            });
+
+            if (!criteria.isEmpty()) {
+                query.append(" WHERE ");
+                query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+            }
+
+        }
+        query.append(" ORDER BY acc.identifier");
+
+        query.append(" LIMIT ");
+        query.append(size);
+        if (pageIndex > 0) {
+            query.append(" OFFSET ");
+            query.append(size * pageIndex);
+        }
+
+        return query.toString();
+    }
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return Arrays.asList(
+                DisplayableFieldBuilder.create(TYPE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(IDENTIFIER, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(HOLDER, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(BALANCE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(STATE, Type.TEXT).build()
+        );
+    }
 
+    private List<QueryParameter> buildQueryParameters() {
+        return Arrays.asList(
+                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+        );
     }
 }


[fineract-cn-reporting] 02/47: added first report defition

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit bf26ed8722e81f105fee93d24d9b80f16460d8f6
Author: mgeiss <mg...@mifos.org>
AuthorDate: Fri Jun 30 22:51:43 2017 +0200

    added first report defition
---
 .../AbstractReportingSpecificationTest.java        | 117 ++++++++++++++++++++
 .../TestCustomerListReportSpecification.java       |  27 ++---
 component-test/src/main/resources/logback-test.xml |  37 +------
 .../reporting/service/ReportingConfiguration.java  |   5 +-
 .../provider/ReportSpecificationProvider.java      |  95 ++++++++++++++++
 .../CustomerListReportSpecification.java           | 120 +++++++++++++++++++++
 .../service/rest/ReportingRestController.java      |  92 ++++++++++++++--
 .../service/spi/DisplayableFieldBuilder.java       |  49 +++++++++
 .../service/spi/QueryParameterBuilder.java         |  71 ++++++++++++
 .../ReportingService.java => spi/Report.java}      |  29 +++--
 .../ReportSpecification.java}                      |  23 ++--
 11 files changed, 580 insertions(+), 85 deletions(-)

diff --git a/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java b/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
new file mode 100644
index 0000000..47fc8a7
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting;
+
+import io.mifos.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
+import io.mifos.core.api.context.AutoUserContext;
+import io.mifos.core.lang.ApplicationName;
+import io.mifos.core.test.env.TestEnvironment;
+import io.mifos.core.test.fixture.TenantDataStoreContextTestRule;
+import io.mifos.core.test.fixture.cassandra.CassandraInitializer;
+import io.mifos.core.test.fixture.mariadb.MariaDBInitializer;
+import io.mifos.reporting.api.v1.client.ReportManager;
+import io.mifos.reporting.service.ReportingConfiguration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+import org.springframework.cloud.netflix.ribbon.RibbonClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.security.interfaces.RSAPrivateKey;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+    webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
+    classes = {AbstractReportingSpecificationTest.TestConfiguration.class}
+)
+public class AbstractReportingSpecificationTest {
+  private static final String APP_NAME = "reporting-v1";
+  public static final String LOGGER_NAME = "test-logger";
+
+  @Configuration
+  @EnableFeignClients(basePackages = {"io.mifos.reporting.api.v1.client"})
+  @RibbonClient(name = APP_NAME)
+  @Import({ReportingConfiguration.class})
+  public static class TestConfiguration {
+    public TestConfiguration() {
+      super();
+    }
+
+    @Bean(name = LOGGER_NAME)
+    public Logger logger() {
+      return LoggerFactory.getLogger(LOGGER_NAME);
+    }
+  }
+
+  static final String TEST_USER = "homer";
+
+  private final static TestEnvironment testEnvironment = new TestEnvironment(APP_NAME);
+  private final static CassandraInitializer cassandraInitializer = new CassandraInitializer();
+  private final static MariaDBInitializer mariaDBInitializer = new MariaDBInitializer();
+  final static TenantDataStoreContextTestRule tenantDataStoreContext = TenantDataStoreContextTestRule.forRandomTenantName(cassandraInitializer, mariaDBInitializer);
+
+  @ClassRule
+  public static TestRule orderClassRules = RuleChain
+      .outerRule(testEnvironment)
+      .around(cassandraInitializer)
+      .around(mariaDBInitializer)
+      .around(tenantDataStoreContext);
+
+  @Rule
+  public final TenantApplicationSecurityEnvironmentTestRule tenantApplicationSecurityEnvironment
+      = new TenantApplicationSecurityEnvironmentTestRule(testEnvironment, this::waitForInitialize);
+
+  private AutoUserContext userContext;
+
+  @Autowired
+  ReportManager testSubject;
+
+  @Autowired
+  private ApplicationName applicationName;
+
+  @Autowired
+  @Qualifier(LOGGER_NAME)
+  Logger logger;
+
+  @Before
+  public void prepTest() {
+    userContext = tenantApplicationSecurityEnvironment.createAutoUserContext(TEST_USER);
+    final RSAPrivateKey tenantPrivateKey = tenantApplicationSecurityEnvironment.getSystemSecurityEnvironment().tenantPrivateKey();
+    logger.info("tenantPrivateKey = {}", tenantPrivateKey);
+  }
+
+  @After
+  public void cleanTest() {
+    userContext.close();
+  }
+
+  boolean waitForInitialize() {
+    return true;
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java b/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java
similarity index 50%
copy from service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java
copy to component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java
index 620dff3..dfabeaf 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java
+++ b/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java
@@ -13,22 +13,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.reporting.service.internal.service;
+package io.mifos.reporting;
 
-import io.mifos.reporting.service.ServiceConstants;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Service;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
 
-@Service
-public class ReportingService {
+import java.util.List;
 
-  private final Logger logger;
+public class TestCustomerListReportSpecification extends AbstractReportingSpecificationTest {
 
-  @Autowired
-  public ReportingService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+  public TestCustomerListReportSpecification() {
     super();
-    this.logger = logger;
+  }
+
+  @Test
+  public void shouldReturnReportDefinition() {
+    final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Customer");
+    Assert.assertTrue(
+        reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+    );
   }
 }
diff --git a/component-test/src/main/resources/logback-test.xml b/component-test/src/main/resources/logback-test.xml
index 2473b99..735b8e5 100644
--- a/component-test/src/main/resources/logback-test.xml
+++ b/component-test/src/main/resources/logback-test.xml
@@ -16,44 +16,17 @@
 
 -->
 <configuration>
-    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <file>logs/reporting.log</file>
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <fileNamePattern>logs/archive/reporting.%d{yyyy-MM-dd}.log</fileNamePattern>
-            <maxHistory>7</maxHistory>
-            <totalSizeCap>2GB</totalSizeCap>
-        </rollingPolicy>
-        <encoder>
-            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
-        </encoder>
-    </appender>
     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
         <encoder>
             <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
         </encoder>
     </appender>
 
-    <logger name="com" level="INFO">
-        <appender-ref ref="STDOUT" />
-    </logger>
-
-    <logger name="ch" level="INFO">
-        <appender-ref ref="STDOUT" />
-    </logger>
-
-    <logger name="org" level="INFO">
-        <appender-ref ref="STDOUT" />
-    </logger>
-
-    <logger name="io" level="DEBUG">
-        <appender-ref ref="STDOUT" />
-    </logger>
-
-    <logger name="net" level="INFO">
-        <appender-ref ref="STDOUT" />
-    </logger>
+    <logger name="org" level="ERROR"/>
+    <logger name="com" level="OFF"/>
+    <logger name="ch" level="OFF"/>
 
-    <root level="WARN">
-        <appender-ref ref="FILE"/>
+    <root level="DEBUG">
+        <appender-ref ref="STDOUT"/>
     </root>
 </configuration>
\ No newline at end of file
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
index 58dd263..f0ab979 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
@@ -42,9 +42,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
 @EnableServiceException
 @ComponentScan({
     "io.mifos.reporting.service.rest",
-    "io.mifos.reporting.service.internal.service",
-    "io.mifos.reporting.service.repository",
-    "io.mifos.reporting.service.internal.provider"
+    "io.mifos.reporting.service.internal",
+    "io.mifos.reporting.service.repository"
 })
 @EnableJpaRepositories({
     "io.mifos.reporting.service.repository"
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java b/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
new file mode 100644
index 0000000..7ef4871
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.provider;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
+import org.slf4j.Logger;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class ReportSpecificationProvider implements ApplicationContextAware {
+
+  private final Logger logger;
+  private final HashMap<String, ReportSpecification> reportSpecificationCache = new HashMap<>();
+  private final HashMap<String, List<ReportDefinition>> reportCategoryCache = new HashMap<>();
+
+  private ApplicationContext applicationContext;
+
+  @Autowired
+  public ReportSpecificationProvider(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+    super();
+    this.logger = logger;
+  }
+
+  @Override
+  public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
+    this.applicationContext = applicationContext;
+    this.initialize();
+  }
+
+  public List<String> getAvailableCategories() {
+    return new ArrayList<>(this.reportCategoryCache.keySet());
+  }
+
+  public List<ReportDefinition> getAvailableReports(final String category) {
+    this.logger.debug("Looking up report definitions for category {}.", category);
+    return this.reportCategoryCache.getOrDefault(category, Collections.emptyList());
+  }
+
+  public Optional<ReportSpecification> getReportSpecification(final String category, final String identifier) {
+    final String keyForReportSpecificationCache = this.buildKeyForSpecificationCache(category, identifier);
+    this.logger.debug("Looking up report specification for {}.", keyForReportSpecificationCache);
+    return Optional.ofNullable(this.reportSpecificationCache.get(keyForReportSpecificationCache));
+  }
+
+  private void initialize() {
+    final Map<String, Object> beansWithAnnotation = this.applicationContext.getBeansWithAnnotation(Report.class);
+
+    beansWithAnnotation.values().forEach(bean -> {
+      final ReportSpecification reportSpecification = ReportSpecification.class.cast(bean);
+      final Report report = reportSpecification.getClass().getAnnotation(Report.class);
+      final String keyForReportSpecificationCache =
+          this.buildKeyForSpecificationCache(report.category(), report.identifier());
+      this.logger.debug("Adding report specification for {}", keyForReportSpecificationCache);
+
+      this.reportCategoryCache.computeIfAbsent(report.category(), (key) -> new ArrayList<>());
+      this.reportCategoryCache.get(report.category()).add(reportSpecification.getReportDefinition());
+      this.reportSpecificationCache.put(keyForReportSpecificationCache, reportSpecification);
+    });
+  }
+
+  private String buildKeyForSpecificationCache(final String category, final String identifier) {
+    return category + "~" + identifier;
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
new file mode 100644
index 0000000..b166b53
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
+
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
+import io.mifos.reporting.service.spi.QueryParameterBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Report(category = "Customer", identifier = "Listing")
+public class CustomerListReportSpecification implements ReportSpecification {
+
+  private final Logger logger;
+  private final HashMap<String, String> columnMapping = new HashMap<>();
+
+  @Autowired
+  public CustomerListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+    super();
+    this.logger = logger;
+    this.initializeMapping();
+  }
+
+  @Override
+  public ReportDefinition getReportDefinition() {
+    final ReportDefinition reportDefinition = new ReportDefinition();
+    reportDefinition.setIdentifier("Listing");
+    reportDefinition.setName("Customer Listing");
+    reportDefinition.setDescription("List of all customers.");
+    reportDefinition.setQueryParameters(this.buildQueryParameters());
+    reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+    return reportDefinition;
+  }
+
+  @Override
+  public ReportPage generateReport(final ReportRequest reportRequest) {
+    return null;
+  }
+
+  @Override
+  public void validate(final ReportRequest reportRequest) throws IllegalArgumentException {
+    final ArrayList<String> unknownFields =  new ArrayList<>();
+    reportRequest.getQueryParameters().forEach(queryParameter -> {
+      if (!this.columnMapping.keySet().contains(queryParameter.getName())) {
+        unknownFields.add(queryParameter.getName());
+      }
+    });
+
+    reportRequest.getDisplayableFields().forEach(displayableField -> {
+      if (!this.columnMapping.keySet().contains(displayableField.getName())) {
+        unknownFields.add(displayableField.getName());
+      }
+    });
+
+    if (!unknownFields.isEmpty()) {
+      throw new IllegalArgumentException(
+          "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
+      );
+    }
+  }
+
+  private void initializeMapping() {
+    this.columnMapping.put("Date Range", "createdBy");
+    this.columnMapping.put("State", "currentState");
+    this.columnMapping.put("Customer", "identifier");
+    this.columnMapping.put("Account number", "identifier");
+    this.columnMapping.put("First name", "givenName");
+    this.columnMapping.put("Middle Name", "middleName");
+    this.columnMapping.put("Last Name", "surname");
+    this.columnMapping.put("Balance", "balance");
+    this.columnMapping.put("Address", "address");
+  }
+
+  private List<QueryParameter> buildQueryParameters() {
+    return Arrays.asList(
+        QueryParameterBuilder.create("Date range", Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+        QueryParameterBuilder.create("State", Type.TEXT).operator(QueryParameter.Operator.IN).build()
+    );
+  }
+
+  private List<DisplayableField> buildDisplayableFields() {
+    return Arrays.asList(
+        DisplayableFieldBuilder.create("Customer", Type.TEXT).mandatory().build(),
+        DisplayableFieldBuilder.create("First name", Type.TEXT).build(),
+        DisplayableFieldBuilder.create("Middle name", Type.TEXT).build(),
+        DisplayableFieldBuilder.create("Last name", Type.TEXT).build(),
+        DisplayableFieldBuilder.create("Account number", Type.TEXT).mandatory().build(),
+        DisplayableFieldBuilder.create("Balance", Type.NUMBER).build(),
+        DisplayableFieldBuilder.create("Address", Type.TEXT).build()
+    );
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
index d639ae7..16307c5 100644
--- a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
+++ b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
@@ -17,15 +17,28 @@ package io.mifos.reporting.service.rest;
 
 import io.mifos.anubis.annotation.AcceptedTokenType;
 import io.mifos.anubis.annotation.Permittable;
-import io.mifos.core.command.gateway.CommandGateway;
+import io.mifos.core.lang.ServiceException;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.internal.service.ReportingService;
+import io.mifos.reporting.service.internal.provider.ReportSpecificationProvider;
+import io.mifos.reporting.service.spi.ReportSpecification;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Optional;
 
 @SuppressWarnings("unused")
 @RestController
@@ -33,16 +46,77 @@ import org.springframework.web.bind.annotation.*;
 public class ReportingRestController {
 
   private final Logger logger;
-  private final CommandGateway commandGateway;
-  private final ReportingService reportingService;
+  private final ReportSpecificationProvider reportSpecificationProvider;
 
   @Autowired
   public ReportingRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
-                                 final CommandGateway commandGateway,
-                                 final ReportingService reportingService) {
+                                 final ReportSpecificationProvider reportSpecificationProvider) {
     super();
     this.logger = logger;
-    this.commandGateway = commandGateway;
-    this.reportingService = reportingService;
+    this.reportSpecificationProvider = reportSpecificationProvider;
+  }
+
+  @Permittable(value = AcceptedTokenType.SYSTEM)
+  @RequestMapping(
+      value = "/initialize",
+      method = RequestMethod.POST,
+      consumes = MediaType.ALL_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  public
+  @ResponseBody
+  ResponseEntity<Void> initialize() {
+    return ResponseEntity.accepted().build();
+  }
+
+  @RequestMapping(
+      value = "/categories",
+      method = RequestMethod.GET,
+      produces = MediaType.APPLICATION_JSON_VALUE,
+      consumes = MediaType.ALL_VALUE
+  )
+  public
+  ResponseEntity<List<String>> fetchCategories() {
+    return ResponseEntity.ok(this.reportSpecificationProvider.getAvailableCategories());
+  }
+
+  @RequestMapping(
+      value = "categories/{category}",
+      method = RequestMethod.GET,
+      produces = MediaType.APPLICATION_JSON_VALUE,
+      consumes = MediaType.ALL_VALUE)
+  public
+  ResponseEntity<List<ReportDefinition>> fetchReportDefinitions(@PathVariable("category") final String category) {
+    return ResponseEntity.ok(this.reportSpecificationProvider.getAvailableReports(category));
+  }
+
+  @RequestMapping(
+      value = "/categories/{category}/reports/{identifier}",
+      method = RequestMethod.POST,
+      produces = MediaType.APPLICATION_JSON_VALUE,
+      consumes = MediaType.APPLICATION_JSON_VALUE
+  )
+  public
+  ResponseEntity<ReportPage> generateReport(@PathVariable("category") final String category,
+                                           @PathVariable("identifier") final String identifier,
+                                           @RequestBody final ReportRequest reportRequest,
+                                           @RequestParam(value = "pageIndex", required = false) final Integer pageIndex,
+                                           @RequestParam(value = "size", required = false) final Integer size) {
+
+    final Optional<ReportSpecification> optionalReportSpecification =
+        this.reportSpecificationProvider.getReportSpecification(category, identifier);
+    if (optionalReportSpecification.isPresent()) {
+      final ReportSpecification reportSpecification = optionalReportSpecification.get();
+
+      try {
+        reportSpecification.validate(reportRequest);
+      } catch (final IllegalArgumentException iaex) {
+        throw ServiceException.badRequest(iaex.getMessage());
+      }
+
+      return ResponseEntity.ok(reportSpecification.generateReport(reportRequest));
+    } else {
+      throw ServiceException.notFound("Report {0} not found.", identifier);
+    }
   }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java
new file mode 100644
index 0000000..987ad9b
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.spi;
+
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Type;
+
+public class DisplayableFieldBuilder {
+
+  private String name;
+  private Type type;
+  private Boolean mandatory;
+
+  private DisplayableFieldBuilder(final String name, final Type type) {
+    super();
+    this.name = name;
+    this.type = type;
+  }
+
+  public static DisplayableFieldBuilder create(final String name, final Type type) {
+    return new DisplayableFieldBuilder(name, type);
+  }
+
+  public DisplayableFieldBuilder mandatory() {
+    this.mandatory = Boolean.TRUE;
+    return this;
+  }
+
+  public DisplayableField build() {
+    final DisplayableField displayableField = new DisplayableField();
+    displayableField.setName(this.name);
+    displayableField.setType(this.type);
+    displayableField.setMandatory(this.mandatory != null ? this.mandatory : Boolean.FALSE);
+    return displayableField;
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java
new file mode 100644
index 0000000..00251f3
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.spi;
+
+import io.mifos.reporting.api.v1.domain.AutoCompleteResource;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.Type;
+
+import java.util.Arrays;
+
+public class QueryParameterBuilder {
+
+  private String name;
+  private Type type;
+  private QueryParameter.Operator operator;
+  private Boolean mandatory;
+  private AutoCompleteResource autoCompleteResource;
+
+  private QueryParameter queryParameter;
+
+  private QueryParameterBuilder(final String name, final Type type) {
+    super();
+    this.name = name;
+    this.type = type;
+  }
+
+  public static QueryParameterBuilder create(final String name, final Type type) {
+    return new QueryParameterBuilder(name, type);
+  }
+
+  public QueryParameterBuilder operator(final QueryParameter.Operator operator) {
+    this.operator = operator;
+    return this;
+  }
+
+  public QueryParameterBuilder mandatory() {
+    this.mandatory = Boolean.TRUE;
+    return this;
+  }
+
+  public QueryParameterBuilder autoComplete(final String path, final String... terms) {
+    final AutoCompleteResource autoCompleteResource = new AutoCompleteResource();
+    autoCompleteResource.setPath(path);
+    autoCompleteResource.setTerms(Arrays.asList(terms));
+    this.autoCompleteResource = autoCompleteResource;
+    return this;
+  }
+
+  public QueryParameter build() {
+    final QueryParameter queryParameter = new QueryParameter();
+    queryParameter.setName(this.name);
+    queryParameter.setType(this.type);
+    queryParameter.setOperator(this.operator != null ? this.operator : QueryParameter.Operator.EQUALS);
+    queryParameter.setMandatory(this.mandatory != null ? this.mandatory : Boolean.FALSE);
+    queryParameter.setAutoCompleteResource(this.autoCompleteResource);
+    return queryParameter;
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java b/service/src/main/java/io/mifos/reporting/service/spi/Report.java
similarity index 53%
copy from service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java
copy to service/src/main/java/io/mifos/reporting/service/spi/Report.java
index 620dff3..ec40ec8 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/Report.java
@@ -13,22 +13,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.reporting.service.internal.service;
+package io.mifos.reporting.service.spi;
 
-import io.mifos.reporting.service.ServiceConstants;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Service;
+import org.springframework.stereotype.Component;
 
-@Service
-public class ReportingService {
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
-  private final Logger logger;
-
-  @Autowired
-  public ReportingService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
-    super();
-    this.logger = logger;
-  }
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Documented
+@Component
+public @interface Report {
+  String category();
+  String identifier();
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java b/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
similarity index 53%
rename from service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java
rename to service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
index 620dff3..3502b94 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
@@ -13,22 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.reporting.service.internal.service;
+package io.mifos.reporting.service.spi;
 
-import io.mifos.reporting.service.ServiceConstants;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Service;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
 
-@Service
-public class ReportingService {
+public interface ReportSpecification {
 
-  private final Logger logger;
+  ReportDefinition getReportDefinition();
 
-  @Autowired
-  public ReportingService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
-    super();
-    this.logger = logger;
-  }
+  ReportPage generateReport(final ReportRequest reportRequest);
+
+  void validate(final ReportRequest reportRequest) throws IllegalArgumentException;
 }


[fineract-cn-reporting] 38/47: Merge pull request #5 from Izakey/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 2c300e96742db46bef6a191e9752cfda02dcc989
Merge: a59b904 1d0699a
Author: Isaac Kamga <u2...@gmail.com>
AuthorDate: Sun Oct 14 15:10:44 2018 +0100

    Merge pull request #5 from Izakey/develop
    
    Put unit tests together in single test class and use unique Egyptian god "shu" for reporting service test user

 .../AbstractReportingSpecificationTest.java        |  2 +-
 .../cn/reporting/SuiteTestEnvironment.java         | 40 +++++++++++
 .../TestBalanceSheetReportSpecification.java       | 40 -----------
 .../TestCustomerListReportSpecification.java       | 40 -----------
 .../TestDepositListReportSpecification.java        | 39 ----------
 .../TestIncomeStatementReportSpecification.java    | 39 ----------
 .../reporting/TestLoanListReportSpecification.java | 39 ----------
 .../cn/reporting/TestReportingSpecifications.java  | 84 ++++++++++++++++++++++
 .../TestTellerListReportSpecification.java         | 39 ----------
 .../TestTellerTransactionReportSpecification.java  | 39 ----------
 10 files changed, 125 insertions(+), 276 deletions(-)


[fineract-cn-reporting] 19/47: Merge pull request #2 from skylabaseInc/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit a3dee1ef565088425a545357e5c6abb8230ffbdd
Merge: fe4f978 096a62c
Author: Markus Geiß <ma...@apache.org>
AuthorDate: Wed Sep 6 19:12:49 2017 +0200

    Merge pull request #2 from skylabaseInc/develop
    
    Deposit, Teller, Loan and Income state report updates

 .gitignore                                         |   2 +
 .../io/mifos/reporting/api/v1/domain/Sample.java   |  20 ++
 .../TestSavingListReportSpecification.java         |  21 ++
 .../DepositListReportSpecification.java            | 377 +++++++++++++++++++++
 .../IncomeStatementReportSpecification.java        | 221 ++++++++++++
 .../specification/LoanListReportSpecification.java | 295 ++++++++++++++++
 ...llerCashierDailyBalanceReportSpecification.java |  72 ++++
 .../TellerListReportSpecification.java             | 221 ++++++++++++
 8 files changed, 1229 insertions(+)


[fineract-cn-reporting] 29/47: Merge pull request #2 from Izakey/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 4396958da4fafd5843fdaa1de752b1cd992cfa5a
Merge: 9b36fe4 35817cd
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Fri Mar 16 11:46:36 2018 +0100

    Merge pull request #2 from Izakey/develop
    
    Updated copyright information in reporting

 HEADER                                             | 25 +++++++++++--------
 NOTICE.txt                                         |  5 ++++
 README.md                                          |  2 +-
 .../io/mifos/reporting/api/v1/EventConstants.java  | 25 +++++++++++--------
 .../reporting/api/v1/PermittableGroupIds.java      | 25 +++++++++++--------
 .../reporting/api/v1/client/ReportManager.java     | 25 +++++++++++--------
 .../api/v1/client/ReportNotFoundException.java     | 25 +++++++++++--------
 .../client/ReportParameterValidationException.java | 25 +++++++++++--------
 .../api/v1/domain/AutoCompleteResource.java        | 25 +++++++++++--------
 .../reporting/api/v1/domain/DisplayableField.java  | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Footer.java   | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Header.java   | 25 +++++++++++--------
 .../reporting/api/v1/domain/QueryParameter.java    | 25 +++++++++++--------
 .../reporting/api/v1/domain/ReportDefinition.java  | 25 +++++++++++--------
 .../mifos/reporting/api/v1/domain/ReportPage.java  | 25 +++++++++++--------
 .../reporting/api/v1/domain/ReportRequest.java     | 25 +++++++++++--------
 .../java/io/mifos/reporting/api/v1/domain/Row.java | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Type.java     | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Value.java    | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Sample.java   | 25 +++++++++++--------
 .../mifos/reporting/api/v1/domain/SampleTest.java  | 25 +++++++++++--------
 .../AbstractReportingSpecificationTest.java        | 25 +++++++++++--------
 .../TestBalanceSheetReportSpecification.java       | 25 +++++++++++--------
 .../TestCustomerListReportSpecification.java       | 25 +++++++++++--------
 .../TestDepositListReportSpecification.java        | 25 +++++++++++--------
 .../TestIncomeStatementReportSpecification.java    | 25 +++++++++++--------
 .../reporting/TestLoanListReportSpecification.java | 25 +++++++++++--------
 .../TestTellerListReportSpecification.java         | 25 +++++++++++--------
 .../TestTellerTransactionReportSpecification.java  | 25 +++++++++++--------
 component-test/src/main/resources/logback-test.xml | 25 +++++++++++--------
 .../reporting/service/ReportingApplication.java    | 25 +++++++++++--------
 .../reporting/service/ReportingConfiguration.java  | 25 +++++++++++--------
 .../mifos/reporting/service/ServiceConstants.java  | 25 +++++++++++--------
 .../provider/ReportSpecificationProvider.java      | 25 +++++++++++--------
 .../service/internal/repository/DummyEntity.java   | 25 +++++++++++--------
 .../internal/repository/DummyRepository.java       | 25 +++++++++++--------
 .../BalanceSheetReportSpecification.java           | 25 +++++++++++--------
 .../CustomerListReportSpecification.java           | 25 +++++++++++--------
 .../DepositListReportSpecification.java            | 25 +++++++++++--------
 .../IncomeStatementReportSpecification.java        | 25 +++++++++++--------
 .../specification/LoanListReportSpecification.java | 25 +++++++++++--------
 .../OfficeListReportSpecification.java             | 25 +++++++++++--------
 .../TellerListReportSpecification.java             | 25 +++++++++++--------
 .../TellerTransactionReportSpecification.java      | 25 +++++++++++--------
 .../service/rest/ReportingRestController.java      | 25 +++++++++++--------
 .../reporting/service/spi/CriteriaBuilder.java     | 25 +++++++++++--------
 .../service/spi/DisplayableFieldBuilder.java       | 25 +++++++++++--------
 .../service/spi/QueryParameterBuilder.java         | 25 +++++++++++--------
 .../io/mifos/reporting/service/spi/Report.java     | 25 +++++++++++--------
 .../reporting/service/spi/ReportSpecification.java | 25 +++++++++++--------
 service/src/main/resources/ESAPI.properties        | 29 ++++++++++++----------
 service/src/main/resources/application.yml         | 25 +++++++++++--------
 service/src/main/resources/bootstrap.yml           | 25 +++++++++++--------
 service/src/main/resources/logback.xml             | 29 ++++++++++++----------
 service/src/main/resources/validation.properties   | 29 ++++++++++++----------
 shared.gradle                                      |  2 --
 56 files changed, 754 insertions(+), 592 deletions(-)


[fineract-cn-reporting] 22/47: LicenseFormat and clean up dead code

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit c35f4b963e317d78306e1b20a245ff4172ba608d
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Fri Sep 29 17:13:07 2017 +0100

    LicenseFormat and clean up dead code
---
 .../BalanceSheetReportSpecification.java           |   4 -
 .../EmployeeListReportSpecification.java           | 278 ---------------------
 .../IncomeStatementReportSpecification.java        |  11 +-
 .../specification/LoanListReportSpecification.java |   5 +-
 .../TellerListReportSpecification.java             |   4 +-
 .../TellerTransactionReportSpecification.java      |   2 +-
 6 files changed, 5 insertions(+), 299 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
index d8a25d5..1c6810e 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
@@ -41,9 +41,7 @@ public class BalanceSheetReportSpecification implements ReportSpecification {
     private static final String TYPE = "Type";
     private static final String IDENTIFIER = "Identifier";
     private static final String NAME = "Name";
-    private static final String HOLDER = "Holder";
     private static final String BALANCE = "Balance";
-    private static final String STATE = "State";
 
     private final Logger logger;
 
@@ -123,9 +121,7 @@ public class BalanceSheetReportSpecification implements ReportSpecification {
         this.accountingColumnMapping.put(TYPE, "acc.a_type");
         this.accountingColumnMapping.put(IDENTIFIER, "acc.identifier");
         this.accountingColumnMapping.put(NAME, "acc.a_name");
-        this.accountingColumnMapping.put(HOLDER, "acc.holders");
         this.accountingColumnMapping.put(BALANCE, "acc.balance");
-        this.accountingColumnMapping.put(STATE, "acc.a_state");
 
         this.allColumnMapping.putAll(accountingColumnMapping);
     }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/EmployeeListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/EmployeeListReportSpecification.java
deleted file mode 100644
index be1a58b..0000000
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/EmployeeListReportSpecification.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright 2017 The Mifos Initiative.
- *
- * Licensed 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 io.mifos.reporting.service.internal.specification;
-
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
-import io.mifos.reporting.api.v1.domain.*;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.*;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
-import java.time.Clock;
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@Report(category = "Organization", identifier = "Employee")
-public class EmployeeListReportSpecification implements ReportSpecification {
-
-    private static final String USERNAME = "Username";
-    private static final String FIRST_NAME = "First Name";
-    private static final String MIDDLE_NAME = "Middle Name";
-    private static final String LAST_NAME = "Last Name";
-    private static final String CREATED_BY = "Created By";
-
-    private static final String OFFICE = "Office Id";
-    private static final String OFFICE_NAME = "Office Name";
-
-    private final Logger logger;
-
-    private final EntityManager entityManager;
-
-    private final HashMap<String, String> employeeColumnMapping = new HashMap<>();
-    private final HashMap<String, String> officeColumnMapping = new HashMap<>();
-    private final HashMap<String, String> allColumnMapping = new HashMap<>();
-
-
-    @Autowired
-    public EmployeeListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
-                                           final EntityManager entityManager) {
-        super();
-        this.logger = logger;
-        this.entityManager = entityManager;
-        this.initializeMapping();
-    }
-
-    @Override
-    public ReportDefinition getReportDefinition() {
-        final ReportDefinition reportDefinition = new ReportDefinition();
-        reportDefinition.setIdentifier("Employee");
-        reportDefinition.setName("Employee Listing");
-        reportDefinition.setDescription("List of all employees.");
-        reportDefinition.setQueryParameters(this.buildQueryParameters());
-        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
-        return reportDefinition;
-    }
-
-    @Override
-    public ReportPage generateReport(final ReportRequest reportRequest, final int pageIndex, final int size) {
-        final ReportDefinition reportDefinition = this.getReportDefinition();
-        this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
-
-        final ReportPage reportPage = new ReportPage();
-        reportPage.setName(reportDefinition.getName());
-        reportPage.setDescription(reportDefinition.getDescription());
-        reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
-
-        final Query customerQuery = this.entityManager.createNativeQuery(this.buildEmployeeQuery(reportRequest, pageIndex, size));
-        final List<?> customerResultList =  customerQuery.getResultList();
-        reportPage.setRows(this.buildRows(reportRequest, customerResultList));
-
-        reportPage.setHasMore(
-                !this.entityManager.createNativeQuery(this.buildEmployeeQuery(reportRequest, pageIndex + 1, size))
-                        .getResultList().isEmpty()
-        );
-
-        reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
-        reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
-        return reportPage;
-    }
-
-    @Override
-    public void validate(final ReportRequest reportRequest) throws IllegalArgumentException {
-        final ArrayList<String> unknownFields =  new ArrayList<>();
-        reportRequest.getQueryParameters().forEach(queryParameter -> {
-            if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
-                unknownFields.add(queryParameter.getName());
-            }
-        });
-
-        reportRequest.getDisplayableFields().forEach(displayableField -> {
-            if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
-                unknownFields.add(displayableField.getName());
-            }
-        });
-
-        if (!unknownFields.isEmpty()) {
-            throw new IllegalArgumentException(
-                    "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
-            );
-        }
-    }
-
-    private void initializeMapping() {
-        this.employeeColumnMapping.put(USERNAME, "he.identifier");
-        this.employeeColumnMapping.put(FIRST_NAME, "he.given_name");
-        this.employeeColumnMapping.put(MIDDLE_NAME, "he.middle_name");
-        this.employeeColumnMapping.put(LAST_NAME, "he.surname");
-        this.employeeColumnMapping.put(CREATED_BY, "he.created_by");
-        this.employeeColumnMapping.put(OFFICE, "he.assigned_office_id");
-
-        this.officeColumnMapping.put(OFFICE_NAME, "ho.a_name");
-
-        this.allColumnMapping.putAll(employeeColumnMapping);
-        this.allColumnMapping.putAll(officeColumnMapping);
-    }
-
-    private Header createHeader(final List<DisplayableField> displayableFields) {
-        final Header header = new Header();
-        header.setColumnNames(
-                displayableFields
-                        .stream()
-                        .map(DisplayableField::getName)
-                        .collect(Collectors.toList())
-        );
-        return header;
-    }
-
-
-    private List<Row> buildRows(final ReportRequest reportRequest, final List<?> employeeResultList) {
-        final ArrayList<Row> rows = new ArrayList<>();
-
-        employeeResultList.forEach(result -> {
-            final Row row = new Row();
-            row.setValues(new ArrayList<>());
-
-            final String officeIdentifier;
-
-            if (result instanceof Object[]) {
-                final Object[] resultValues = (Object[]) result;
-
-                officeIdentifier = resultValues[0].toString();
-
-                for (final Object resultValue : resultValues) {
-                    final Value value = new Value();
-                    if (resultValue != null) {
-                        value.setValues(new String[]{resultValue.toString()});
-                    } else {
-                        value.setValues(new String[]{});
-                    }
-
-                    row.getValues().add(value);
-                }
-            } else {
-                officeIdentifier = result.toString();
-
-                final Value value = new Value();
-                value.setValues(new String[]{result.toString()});
-                row.getValues().add(value);
-            }
-
-            final String officeQueryString = this.buildOfficeQuery(reportRequest, officeIdentifier);
-            if (officeQueryString != null) {
-                final Query officeQuery = this.entityManager.createNativeQuery(officeQueryString);
-                final List<?> resultList = officeQuery.getResultList();
-                final Value officeValue = new Value();
-                officeValue.setValues(new String[]{resultList.get(0).toString()});
-                row.getValues().add(officeValue);
-            }
-
-            rows.add(row);
-        });
-
-        return rows;
-    }
-
-    private List<QueryParameter> buildQueryParameters() {
-        return Arrays.asList(
-                //QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
-                //QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
-        );
-    }
-
-    private List<DisplayableField> buildDisplayableFields() {
-        return Arrays.asList(
-                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(USERNAME, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(CREATED_BY, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(OFFICE_NAME, Type.TEXT).mandatory().build()
-        );
-    }
-
-    private String buildEmployeeQuery(final ReportRequest reportRequest, int pageIndex, int size) {
-        final StringBuilder query = new StringBuilder("SELECT ");
-
-        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
-        final ArrayList<String> columns = new ArrayList<>();
-        displayableFields.forEach(displayableField -> {
-            final String column = this.employeeColumnMapping.get(displayableField.getName());
-            if (column != null) {
-                columns.add(column);
-            }
-        });
-
-        query.append(columns.stream().collect(Collectors.joining(", ")))
-                .append(" FROM ")
-                .append("horus_employees he ");
-
-        final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
-        if (!queryParameters.isEmpty()) {
-            final ArrayList<String> criteria = new ArrayList<>();
-            queryParameters.forEach(queryParameter -> {
-                if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
-                    criteria.add(
-                            CriteriaBuilder.buildCriteria(this.employeeColumnMapping.get(queryParameter.getName()), queryParameter)
-                    );
-                }
-            });
-
-            if (!criteria.isEmpty()) {
-                query.append(" WHERE ");
-                query.append(criteria.stream().collect(Collectors.joining(" AND ")));
-            }
-
-        }
-        query.append(" ORDER BY he.identifier");
-
-        query.append(" LIMIT ");
-        query.append(size);
-        if (pageIndex > 0) {
-            query.append(" OFFSET ");
-            query.append(size * pageIndex);
-        }
-
-        return query.toString();
-    }
-
-    private String buildOfficeQuery(final ReportRequest reportRequest, final String officeIdentifier) {
-        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
-        final ArrayList<String> columns = new ArrayList<>();
-        displayableFields.forEach(displayableField -> {
-            final String column = this.officeColumnMapping.get(displayableField.getName());
-            if (column != null) {
-                columns.add(column);
-            }
-        });
-        if (!columns.isEmpty()) {
-        return "SELECT DISTINCT " + columns.get(0).toString() + " " +
-                "FROM horus_offices ho " +
-                "LEFT JOIN horus_employees he on ho.id = he.assigned_office_id " +
-                "WHERE he.assigned_office_id ='" + officeIdentifier + "' ";
-        }
-        return null;
-    }
-}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
index 00c6472..c535d22 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -41,9 +41,7 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
     private static final String TYPE = "Type";
     private static final String IDENTIFIER = "Identifier";
     private static final String NAME = "Name";
-    private static final String HOLDER = "Holder";
     private static final String BALANCE = "Balance";
-    private static final String STATE = "State";
 
     private final Logger logger;
 
@@ -123,9 +121,7 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
         this.accountColumnMapping.put(TYPE, "acc.a_type");
         this.accountColumnMapping.put(IDENTIFIER, "acc.identifier");
         this.accountColumnMapping.put(NAME, "acc.a_name");
-        this.accountColumnMapping.put(HOLDER, "acc.holders");
         this.accountColumnMapping.put(BALANCE, "acc.balance");
-        this.accountColumnMapping.put(STATE, "acc.a_state");
 
         this.allColumnMapping.putAll(accountColumnMapping);
     }
@@ -290,16 +286,11 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
                 DisplayableFieldBuilder.create(TYPE, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(IDENTIFIER, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(NAME, Type.TEXT).mandatory().build(),
-                //DisplayableFieldBuilder.create(HOLDER, Type.TEXT).build(),
                 DisplayableFieldBuilder.create(BALANCE, Type.TEXT).mandatory().build()
-               // DisplayableFieldBuilder.create(STATE, Type.TEXT).mandatory().build()
         );
     }
 
     private List<QueryParameter> buildQueryParameters() {
-        return Arrays.asList(
-               // QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
-                //QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
-        );
+        return Arrays.asList();
     }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
index fcd6d8b..4c71929 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
@@ -274,10 +274,7 @@ public class LoanListReportSpecification implements ReportSpecification {
     }
 
     private List<QueryParameter> buildQueryParameters() {
-        return Arrays.asList(
-                //QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build()
-                //QueryParameterBuilder.create(LOAN_STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
-        );
+        return Arrays.asList();
     }
 
     private String buildCustomerQuery(final ReportRequest reportRequest, int pageIndex, int size){
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
index 7f33edb..33cc53c 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
@@ -84,7 +84,7 @@ public class TellerListReportSpecification implements ReportSpecification {
 
         final Query tellerQuery = this.entityManager.createNativeQuery(this.buildTellerQuery(reportRequest, pageIndex, size));
         final List<?> tellerResultList =  tellerQuery.getResultList();
-        reportPage.setRows(this.buildRows(reportRequest, tellerResultList));
+        reportPage.setRows(this.buildRows(tellerResultList));
 
         reportPage.setHasMore(
                 !this.entityManager.createNativeQuery(this.buildTellerQuery(reportRequest, pageIndex + 1, size))
@@ -140,7 +140,7 @@ public class TellerListReportSpecification implements ReportSpecification {
         return header;
     }
 
-    private List<Row> buildRows(ReportRequest reportRequest, List<?> tellerResultList) {
+    private List<Row> buildRows(final List<?> tellerResultList) {
         final ArrayList<Row> rows = new ArrayList<>();
         tellerResultList.forEach(result -> {
             final Row row = new Row();
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
index e24f622..245f3ad 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
@@ -154,7 +154,7 @@ public class TellerTransactionReportSpecification implements ReportSpecification
     }
 
 
-    private List<Row> buildRows(ReportRequest reportRequest, List<?> tellerResultList) {
+    private List<Row> buildRows(final ReportRequest reportRequest, final List<?> tellerResultList) {
         final ArrayList<Row> rows = new ArrayList<>();
 
         tellerResultList.forEach(result -> {


[fineract-cn-reporting] 11/47: Add closed deposit account reports: add last activity to Deposit Account listing

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit d802834ba9fbf2ace30b41a1a010622266b46d37
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Fri Aug 25 14:28:38 2017 +0100

    Add closed deposit account reports: add last activity to Deposit Account listing
---
 .../SavingListReportSpecification.java             | 67 +++++++++++++++++++++-
 1 file changed, 64 insertions(+), 3 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
index a5cf74b..1e8ccbe 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
@@ -32,6 +32,7 @@ public class SavingListReportSpecification implements ReportSpecification {
     private static final String STATE = "State";
     private static final String OFFICE = "Office";
     private static final String DATE_RANGE = "Date created";
+    private static final String LAST_ACCOUNT_ACTIVITY = "Last account activity";
 
     private final EntityManager entityManager;
 
@@ -57,8 +58,8 @@ public class SavingListReportSpecification implements ReportSpecification {
 
         final ReportDefinition reportDefinition = new ReportDefinition();
         reportDefinition.setIdentifier("Listing");
-        reportDefinition.setName("Saving Listing");
-        reportDefinition.setDescription("List of all savings.");
+        reportDefinition.setName("Deposit Account Listing");
+        reportDefinition.setDescription("List of all deposit accounts.");
         reportDefinition.setQueryParameters(this.buildQueryParameters());
         reportDefinition.setDisplayableFields(this.buildDisplayableFields());
         return reportDefinition;
@@ -133,6 +134,7 @@ public class SavingListReportSpecification implements ReportSpecification {
         this.accountColumnMapping.put(ACCOUNT_NUMBER, "pi.customer_identifier, pi.account_identifier");
         this.accountColumnMapping.put(STATE, " pi.a_state");
         this.accountColumnMapping.put(ACCOUNT_TYPE, "pi.product_definition_id");
+        this.accountColumnMapping.put(LAST_ACCOUNT_ACTIVITY, "acc_entry.transaction_date, acc_entry.message, acc_entry.amount, acc_entry.balance");
         this.accountColumnMapping.put(DATE_RANGE, "pi.created_on");
 
         this.allColumnMapping.putAll(customerColumnMapping);
@@ -157,7 +159,7 @@ public class SavingListReportSpecification implements ReportSpecification {
         depositAccountResultList.forEach(result -> {
             final Row row = new Row();
             row.setValues(new ArrayList<>());
-
+            //Get the customer identifier to use for join queries.
             final String customerIdentifier;
 
             if (result instanceof Object[]) {
@@ -183,6 +185,31 @@ public class SavingListReportSpecification implements ReportSpecification {
                 row.getValues().add(value);
             }
 
+            final String accountIdentifier;
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues = (Object[]) result;
+
+                accountIdentifier = resultValues[2].toString();
+
+                for (final Object resultValue : resultValues) {
+                    final Value value = new Value();
+                    if (resultValue != null) {
+                        value.setValues(new String[]{resultValue.toString()});
+                    } else {
+                        value.setValues(new String[]{});
+                    }
+
+                    row.getValues().add(value);
+                }
+            } else {
+
+                accountIdentifier = result.toString();
+                final Value value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
             final Query customerQuery = this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, customerIdentifier));
             final List<?> accountResultList = customerQuery.getResultList();
             final ArrayList<String> values = new ArrayList<>();
@@ -206,6 +233,20 @@ public class SavingListReportSpecification implements ReportSpecification {
                 row.getValues().add(officeValue);
             }
 
+            final Query lastAccountActivivityQueryString = this.entityManager.createNativeQuery(this.buildLastAccountActivity(reportRequest, accountIdentifier));
+            final List<?> lastActivityResultList = lastAccountActivivityQueryString.getResultList();
+            final ArrayList<String> val = new ArrayList<>();
+            lastActivityResultList.forEach( lastActivityResult -> {
+                if (lastActivityResult instanceof Object[]){
+                    final Object[] lastActivityResultValues = (Object[]) lastActivityResult;
+                    final String lastActivityValue = lastActivityResultValues[1].toString();
+                    val.add(lastActivityValue);
+                }
+            });
+            final Value lastActivityValue = new Value();
+            lastActivityValue.setValues(val.toArray(new String[values.size()]));
+            row.getValues().add(lastActivityValue);
+            
             rows.add(row);
         });
 
@@ -295,6 +336,22 @@ public class SavingListReportSpecification implements ReportSpecification {
                 "ORDER BY cst.identifier";
     }
 
+    private String buildLastAccountActivity(final ReportRequest reportRequest, final String accountIdentifier){
+        final List<DisplayableField> displayableFields = new ArrayList<>();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.accountColumnMapping.get(displayableField.getName());
+            if(column != null){
+                columns.add(column);
+            }
+        });
+
+        return "SELECT " + columns.stream().collect(Collectors.joining(",")) + ""  +
+                "FROM thoth_account_entries acc_entry" +
+                "WHERE acc_entry.account_id ='" + accountIdentifier + "'" +
+                "ORDER BY acc_entry.transaction_date";
+    }
+
     private List<DisplayableField> buildDisplayableFields() {
 
         return Arrays.asList(
@@ -303,6 +360,10 @@ public class SavingListReportSpecification implements ReportSpecification {
                 DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
                 DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).build(),
                 DisplayableFieldBuilder.create(ACCOUNT_NUMBER, Type.TEXT).mandatory().build(),
+
+                DisplayableFieldBuilder.create(STATE,Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LAST_ACCOUNT_ACTIVITY, Type.DATE).build(),
+
                 DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(OFFICE, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(DATE_RANGE, Type.TEXT).build()


[fineract-cn-reporting] 03/47: added first report

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit dc8dc1f2522d106a86a804e296af1802ed285587
Author: mgeiss <mg...@mifos.org>
AuthorDate: Thu Jul 6 11:04:00 2017 +0200

    added first report
---
 .../reporting/api/v1/PermittableGroupIds.java      |   3 +-
 .../reporting/api/v1/client/ReportManager.java     |  14 ++
 .../mifos/reporting/api/v1/domain/ReportPage.java  |  19 +-
 .../io/mifos/reporting/api/v1/domain/Value.java    |  10 +-
 service/build.gradle                               |   3 +-
 .../reporting/service/ReportingConfiguration.java  |   7 +-
 .../provider/ReportSpecificationProvider.java      |  12 ++
 .../CustomerListReportSpecification.java           | 197 +++++++++++++++++++--
 .../service/rest/ReportingRestController.java      |  24 ++-
 .../reporting/service/spi/CriteriaBuilder.java     |  83 +++++++++
 .../reporting/service/spi/ReportSpecification.java |   2 +-
 11 files changed, 327 insertions(+), 47 deletions(-)

diff --git a/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java b/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
index d0a3bed..8e28149 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
@@ -17,6 +17,5 @@ package io.mifos.reporting.api.v1;
 
 @SuppressWarnings("unused")
 public interface PermittableGroupIds {
-  String SAMPLE_MANAGEMENT = "reporting__v1__samples";
-  String SELF_MANAGEMENT = "reporting__v1__self";
+  String REPORT_MANAGEMENT = "reporting__v1__general";
 }
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
index 50a1b6c..950ba6b 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
@@ -18,12 +18,15 @@ package io.mifos.reporting.api.v1.client;
 import io.mifos.core.api.annotation.ThrowsException;
 import io.mifos.core.api.annotation.ThrowsExceptions;
 import io.mifos.core.api.util.CustomFeignClientsConfiguration;
+import io.mifos.core.lang.ServiceException;
+import io.mifos.reporting.api.v1.PermittableGroupIds;
 import io.mifos.reporting.api.v1.domain.ReportDefinition;
 import io.mifos.reporting.api.v1.domain.ReportPage;
 import io.mifos.reporting.api.v1.domain.ReportRequest;
 import org.springframework.cloud.netflix.feign.FeignClient;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -69,4 +72,15 @@ public interface ReportManager {
                             @RequestBody final ReportRequest reportRequest,
                             @RequestParam(value = "pageIndex", required = false) final Integer pageIndex,
                             @RequestParam(value = "size", required = false) final Integer size);
+
+  @RequestMapping(
+      value = "categories/{category}/definitions/{identifier}",
+      method = RequestMethod.GET,
+      produces = MediaType.ALL_VALUE,
+      consumes = MediaType.APPLICATION_JSON_VALUE)
+  @ThrowsExceptions({
+      @ThrowsException(status = HttpStatus.NOT_FOUND, exception = ReportNotFoundException.class)
+  })
+  ReportDefinition findReportDefinition(@PathVariable("category") final String category,
+                                        @PathVariable("identifier") final String identifier);
 }
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
index 90db8f7..2bd088f 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
@@ -26,8 +26,7 @@ public class ReportPage {
   private Header header;
   private List<Row> rows;
   private Footer footer;
-  private Integer totalPages;
-  private Long totalElements;
+  private boolean hasMore;
 
   public ReportPage() {
     super();
@@ -89,19 +88,11 @@ public class ReportPage {
     this.footer = footer;
   }
 
-  public Integer getTotalPages() {
-    return this.totalPages;
+  public void setHasMore(final boolean hasMore) {
+    this.hasMore = hasMore;
   }
 
-  public void setTotalPages(final Integer totalPages) {
-    this.totalPages = totalPages;
-  }
-
-  public Long getTotalElements() {
-    return this.totalElements;
-  }
-
-  public void setTotalElements(final Long totalElements) {
-    this.totalElements = totalElements;
+  public boolean isHasMore() {
+    return hasMore;
   }
 }
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
index a94be09..6887781 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
@@ -17,19 +17,19 @@ package io.mifos.reporting.api.v1.domain;
 
 public class Value {
 
-  private String value;
+  private String[] values;
   private Type type;
 
   public Value() {
     super();
   }
 
-  public String getValue() {
-    return this.value;
+  public String[] getValues() {
+    return this.values;
   }
 
-  public void setValue(final String value) {
-    this.value = value;
+  public void setValues(final String[] values) {
+    this.values = values;
   }
 
   public Type getType() {
diff --git a/service/build.gradle b/service/build.gradle
index 9b9708a..7f74364 100644
--- a/service/build.gradle
+++ b/service/build.gradle
@@ -38,7 +38,8 @@ dependencies {
             [group: 'io.mifos.core', name: 'cassandra', version: versions.frameworkcassandra],
             [group: 'io.mifos.core', name: 'mariadb', version: versions.frameworkmariadb],
             [group: 'io.mifos.core', name: 'command', version: versions.frameworkcommand],
-            [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator]
+            [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator],
+            [group: 'org.owasp.esapi', name: 'esapi', version: '2.1.0.1']
     )
 }
 
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
index f0ab979..6bf4fed 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
@@ -27,7 +27,6 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 
@@ -42,11 +41,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
 @EnableServiceException
 @ComponentScan({
     "io.mifos.reporting.service.rest",
-    "io.mifos.reporting.service.internal",
-    "io.mifos.reporting.service.repository"
-})
-@EnableJpaRepositories({
-    "io.mifos.reporting.service.repository"
+    "io.mifos.reporting.service.internal"
 })
 public class ReportingConfiguration extends WebMvcConfigurerAdapter {
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java b/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
index 7ef4871..3c9b646 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
@@ -92,4 +92,16 @@ public class ReportSpecificationProvider implements ApplicationContextAware {
   private String buildKeyForSpecificationCache(final String category, final String identifier) {
     return category + "~" + identifier;
   }
+
+  public Optional<ReportDefinition> findReportDefinition(final String category, final String identifier) {
+    final List<ReportDefinition> reportDefinitions = this.reportCategoryCache.get(category);
+    if (reportDefinitions != null) {
+      return reportDefinitions
+          .stream()
+          .filter(reportDefinition -> reportDefinition.getIdentifier().equals(identifier))
+          .findAny();
+    } else {
+      return Optional.empty();
+    }
+  }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
index b166b53..f56657f 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
@@ -15,13 +15,19 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.DateConverter;
 import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Header;
 import io.mifos.reporting.api.v1.domain.QueryParameter;
 import io.mifos.reporting.api.v1.domain.ReportDefinition;
 import io.mifos.reporting.api.v1.domain.ReportPage;
 import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Row;
 import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.api.v1.domain.Value;
 import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.CriteriaBuilder;
 import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
 import io.mifos.reporting.service.spi.QueryParameterBuilder;
 import io.mifos.reporting.service.spi.Report;
@@ -30,6 +36,11 @@ import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.text.DecimalFormat;
+import java.time.Clock;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -40,12 +51,17 @@ import java.util.stream.Collectors;
 public class CustomerListReportSpecification implements ReportSpecification {
 
   private final Logger logger;
-  private final HashMap<String, String> columnMapping = new HashMap<>();
+  private final EntityManager entityManager;
+  private final HashMap<String, String> customerColumnMapping = new HashMap<>();
+  private final HashMap<String, String> addressColumnMapping = new HashMap<>();
+  private final HashMap<String, String> accountColumnMapping = new HashMap<>();
 
   @Autowired
-  public CustomerListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+  public CustomerListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                         final EntityManager entityManager) {
     super();
     this.logger = logger;
+    this.entityManager = entityManager;
     this.initializeMapping();
   }
 
@@ -61,21 +77,40 @@ public class CustomerListReportSpecification implements ReportSpecification {
   }
 
   @Override
-  public ReportPage generateReport(final ReportRequest reportRequest) {
-    return null;
+  public ReportPage generateReport(final ReportRequest reportRequest, final int pageIndex, final int size) {
+    final ReportDefinition reportDefinition = this.getReportDefinition();
+    this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
+
+    final ReportPage reportPage = new ReportPage();
+    reportPage.setName(reportDefinition.getName());
+    reportPage.setDescription(reportDefinition.getDescription());
+    reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
+
+    final Query customerQuery = this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, pageIndex, size));
+    final List<?> customerResultList =  customerQuery.getResultList();
+    reportPage.setRows(this.buildRows(reportRequest, customerResultList));
+
+    reportPage.setHasMore(
+        !this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, pageIndex + 1, size))
+            .getResultList().isEmpty()
+    );
+
+    reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
+    reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+    return reportPage;
   }
 
   @Override
   public void validate(final ReportRequest reportRequest) throws IllegalArgumentException {
     final ArrayList<String> unknownFields =  new ArrayList<>();
     reportRequest.getQueryParameters().forEach(queryParameter -> {
-      if (!this.columnMapping.keySet().contains(queryParameter.getName())) {
+      if (!this.customerColumnMapping.keySet().contains(queryParameter.getName())) {
         unknownFields.add(queryParameter.getName());
       }
     });
 
     reportRequest.getDisplayableFields().forEach(displayableField -> {
-      if (!this.columnMapping.keySet().contains(displayableField.getName())) {
+      if (!this.customerColumnMapping.keySet().contains(displayableField.getName())) {
         unknownFields.add(displayableField.getName());
       }
     });
@@ -88,15 +123,71 @@ public class CustomerListReportSpecification implements ReportSpecification {
   }
 
   private void initializeMapping() {
-    this.columnMapping.put("Date Range", "createdBy");
-    this.columnMapping.put("State", "currentState");
-    this.columnMapping.put("Customer", "identifier");
-    this.columnMapping.put("Account number", "identifier");
-    this.columnMapping.put("First name", "givenName");
-    this.columnMapping.put("Middle Name", "middleName");
-    this.columnMapping.put("Last Name", "surname");
-    this.columnMapping.put("Balance", "balance");
-    this.columnMapping.put("Address", "address");
+    this.customerColumnMapping.put("Date Range", "cst.created_on");
+    this.customerColumnMapping.put("State", "cst.current_state");
+    this.customerColumnMapping.put("Customer", "cst.identifier");
+    this.customerColumnMapping.put("First name", "cst.given_name");
+    this.customerColumnMapping.put("Middle Name", "cst.middle_name");
+    this.customerColumnMapping.put("Last Name", "cst.surname");
+
+    this.accountColumnMapping.put("Account number", "acc.identifier, acc.balance");
+
+    this.addressColumnMapping.put("Address", "CONCAT(adr.street, ', ', adr.postal_code, ', ', adr.city)");
+  }
+
+  private Header createHeader(final List<DisplayableField> displayableFields) {
+    final Header header = new Header();
+    header.setColumnNames(
+        displayableFields
+            .stream()
+            .map(DisplayableField::getName)
+            .collect(Collectors.toList())
+    );
+    return header;
+  }
+
+  private List<Row> buildRows(final ReportRequest reportRequest, final List<?> customerResultList) {
+    final ArrayList<Row> rows = new ArrayList<>();
+
+    customerResultList.forEach(result -> {
+      final Row row = new Row();
+      row.setValues(new ArrayList<>());
+      final Object[] resultValues = (Object[]) result;
+      for (final Object resultValue : resultValues) {
+        final Value value = new Value();
+        value.setValues(new String[]{resultValue.toString()});
+        row.getValues().add(value);
+      }
+
+      final DecimalFormat decimalFormat = new DecimalFormat(".##");
+      final Query accountQuery = this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, resultValues[0].toString()));
+      final List<?> accountResultList = accountQuery.getResultList();
+      final ArrayList<String> values = new ArrayList<>();
+      accountResultList.forEach(accountResult -> {
+        if (accountResult instanceof Object[]) {
+          final Object[] accountResultValues = (Object[]) accountResult;
+          final String accountValue = accountResultValues[0].toString() + " (" +
+              decimalFormat.format(Double.valueOf(accountResultValues[1].toString())) + ")";
+          values.add(accountValue);
+        }
+      });
+      final Value accountValue = new Value();
+      accountValue.setValues(values.toArray(new String[values.size()]));
+      row.getValues().add(accountValue);
+
+      final String addressQueryString = this.buildAddressQuery(reportRequest, resultValues[0].toString());
+      if (addressQueryString != null) {
+        final Query addressQuery = this.entityManager.createNativeQuery(addressQueryString);
+        final List<?> resultList = addressQuery.getResultList();
+        final Value addressValue = new Value();
+        addressValue.setValues(new String[]{resultList.get(0).toString()});
+        row.getValues().add(addressValue);
+      }
+
+      rows.add(row);
+    });
+
+    return rows;
   }
 
   private List<QueryParameter> buildQueryParameters() {
@@ -113,8 +204,82 @@ public class CustomerListReportSpecification implements ReportSpecification {
         DisplayableFieldBuilder.create("Middle name", Type.TEXT).build(),
         DisplayableFieldBuilder.create("Last name", Type.TEXT).build(),
         DisplayableFieldBuilder.create("Account number", Type.TEXT).mandatory().build(),
-        DisplayableFieldBuilder.create("Balance", Type.NUMBER).build(),
         DisplayableFieldBuilder.create("Address", Type.TEXT).build()
     );
   }
+
+  private String buildCustomerQuery(final ReportRequest reportRequest, int pageIndex, int size) {
+    final StringBuilder query = new StringBuilder("SELECT ");
+
+    final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+    final ArrayList<String> columns = new ArrayList<>();
+    displayableFields.forEach(displayableField -> {
+      final String column = this.customerColumnMapping.get(displayableField.getName());
+      if (column != null) {
+        columns.add(column);
+      }
+    });
+
+    query.append(columns.stream().collect(Collectors.joining(", ")))
+        .append(" FROM ")
+        .append("maat_customers cst ");
+
+    final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
+    if (!queryParameters.isEmpty()) {
+      query.append(" WHERE ");
+      final ArrayList<String> criteria = new ArrayList<>();
+      queryParameters.forEach(queryParameter -> criteria.add(
+          CriteriaBuilder.buildCriteria(this.customerColumnMapping.get(queryParameter.getName()), queryParameter))
+      );
+      query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+    }
+    query.append(" ORDER BY cst.identifier");
+
+    query.append(" LIMIT ");
+    query.append(size);
+    if (pageIndex > 0) {
+      query.append(" OFFSET ");
+      query.append(size * pageIndex);
+    }
+
+    return query.toString();
+  }
+
+  private String buildAccountQuery(final ReportRequest reportRequest, final String customerIdentifier) {
+    final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+    final ArrayList<String> columns = new ArrayList<>();
+    displayableFields.forEach(displayableField -> {
+      final String column = this.accountColumnMapping.get(displayableField.getName());
+      if (column != null) {
+        columns.add(column);
+      }
+    });
+
+    return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
+        "FROM thoth_accounts acc " +
+            "LEFT JOIN maat_customers cst on acc.holders = cst.identifier " +
+        "WHERE cst.identifier ='" + customerIdentifier + "' " +
+        "ORDER BY acc.identifier";
+  }
+
+  private String buildAddressQuery(final ReportRequest reportRequest, final String customerIdentifier) {
+
+    final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+    final ArrayList<String> columns = new ArrayList<>();
+    displayableFields.forEach(displayableField -> {
+      final String column = this.addressColumnMapping.get(displayableField.getName());
+      if (column != null) {
+        columns.add(column);
+      }
+    });
+
+    if (!columns.isEmpty()) {
+      return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
+          "FROM thoth_accounts acc " +
+              "LEFT JOIN maat_customers cst on acc.holders = cst.identifier " +
+          "WHERE cst.identifier ='" + customerIdentifier + "' " +
+          "ORDER BY acc.identifier";
+    }
+    return null;
+  }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
index 16307c5..a23e355 100644
--- a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
+++ b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
@@ -18,6 +18,7 @@ package io.mifos.reporting.service.rest;
 import io.mifos.anubis.annotation.AcceptedTokenType;
 import io.mifos.anubis.annotation.Permittable;
 import io.mifos.core.lang.ServiceException;
+import io.mifos.reporting.api.v1.PermittableGroupIds;
 import io.mifos.reporting.api.v1.domain.ReportDefinition;
 import io.mifos.reporting.api.v1.domain.ReportPage;
 import io.mifos.reporting.api.v1.domain.ReportRequest;
@@ -66,9 +67,10 @@ public class ReportingRestController {
   public
   @ResponseBody
   ResponseEntity<Void> initialize() {
-    return ResponseEntity.accepted().build();
+    return ResponseEntity.ok().build();
   }
 
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.REPORT_MANAGEMENT)
   @RequestMapping(
       value = "/categories",
       method = RequestMethod.GET,
@@ -80,6 +82,7 @@ public class ReportingRestController {
     return ResponseEntity.ok(this.reportSpecificationProvider.getAvailableCategories());
   }
 
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.REPORT_MANAGEMENT)
   @RequestMapping(
       value = "categories/{category}",
       method = RequestMethod.GET,
@@ -90,6 +93,7 @@ public class ReportingRestController {
     return ResponseEntity.ok(this.reportSpecificationProvider.getAvailableReports(category));
   }
 
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.REPORT_MANAGEMENT)
   @RequestMapping(
       value = "/categories/{category}/reports/{identifier}",
       method = RequestMethod.POST,
@@ -114,9 +118,25 @@ public class ReportingRestController {
         throw ServiceException.badRequest(iaex.getMessage());
       }
 
-      return ResponseEntity.ok(reportSpecification.generateReport(reportRequest));
+      return ResponseEntity.ok(reportSpecification.generateReport(reportRequest, pageIndex, size));
     } else {
       throw ServiceException.notFound("Report {0} not found.", identifier);
     }
   }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.REPORT_MANAGEMENT)
+  @RequestMapping(
+      value = "categories/{category}/definitions/{identifier}",
+      method = RequestMethod.GET,
+      produces = MediaType.APPLICATION_JSON_VALUE,
+      consumes = MediaType.ALL_VALUE)
+  public
+  ResponseEntity<ReportDefinition> findReportDefinition(
+      @PathVariable("category") final String category,
+      @PathVariable("identifier") final String identifier) {
+    return ResponseEntity.ok(
+        this.reportSpecificationProvider.findReportDefinition(category, identifier)
+            .orElseThrow(() -> ServiceException.notFound("Report definition {0} not found.", identifier))
+    );
+  }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
new file mode 100644
index 0000000..a0dc841
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.spi;
+
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import org.owasp.esapi.ESAPI;
+import org.owasp.esapi.Encoder;
+import org.owasp.esapi.codecs.MySQLCodec;
+import org.springframework.util.StringUtils;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class CriteriaBuilder {
+
+  // https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
+  private static final Encoder ENCODER = ESAPI.encoder();
+  private static final MySQLCodec MY_SQL_CODEC = new MySQLCodec(MySQLCodec.Mode.ANSI);
+
+  private CriteriaBuilder() {
+    super();
+  }
+
+  public static String buildCriteria(final String field, final QueryParameter queryParameter) {
+    final StringBuilder criteria = new StringBuilder(field);
+
+    switch (queryParameter.getOperator()) {
+      case EQUALS:
+        criteria.append(" = '");
+        criteria.append(CriteriaBuilder.ENCODER.encodeForSQL(CriteriaBuilder.MY_SQL_CODEC, queryParameter.getValue()));
+        criteria.append("'");
+        break;
+      case LIKE:
+        criteria.append(" LIKE '%");
+        criteria.append(CriteriaBuilder.ENCODER.encodeForSQL(CriteriaBuilder.MY_SQL_CODEC, queryParameter.getValue()));
+        criteria.append("%'");
+        break;
+      case GREATER:
+        criteria.append(" > '");
+        criteria.append(CriteriaBuilder.ENCODER.encodeForSQL(CriteriaBuilder.MY_SQL_CODEC, queryParameter.getValue()));
+        criteria.append("'");
+        break;
+      case LESSER:
+        criteria.append(" < '");
+        criteria.append(CriteriaBuilder.ENCODER.encodeForSQL(CriteriaBuilder.MY_SQL_CODEC, queryParameter.getValue()));
+        criteria.append("'");
+        break;
+      case IN:
+        criteria.append(" in (");
+        final Set<String> strings = StringUtils.commaDelimitedListToSet(queryParameter.getValue());
+        criteria.append(
+            strings
+                .stream()
+                .map(s -> "'" + CriteriaBuilder.ENCODER.encodeForSQL(CriteriaBuilder.MY_SQL_CODEC, s) + "'")
+                .collect(Collectors.joining(","))
+        );
+        break;
+      case BETWEEN:
+        final String[] splitString = queryParameter.getValue().split("\\.\\.");
+        criteria.append(" BETWEEN '");
+        criteria.append(CriteriaBuilder.ENCODER.encodeForSQL(CriteriaBuilder.MY_SQL_CODEC, splitString[0]));
+        criteria.append("' AND '");
+        criteria.append(CriteriaBuilder.ENCODER.encodeForSQL(CriteriaBuilder.MY_SQL_CODEC, splitString[1]));
+        criteria.append("'");
+        break;
+    }
+
+    return criteria.toString();
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
index 3502b94..0508411 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
@@ -23,7 +23,7 @@ public interface ReportSpecification {
 
   ReportDefinition getReportDefinition();
 
-  ReportPage generateReport(final ReportRequest reportRequest);
+  ReportPage generateReport(final ReportRequest reportRequest, int pageIndex, int size);
 
   void validate(final ReportRequest reportRequest) throws IllegalArgumentException;
 }


[fineract-cn-reporting] 26/47: Merge pull request #1 from myrle-krantz/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 9b36fe471e98d3448517b9aa0c7250066c792cd1
Merge: de1fa38 b7f357e
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Feb 26 18:35:09 2018 +0100

    Merge pull request #1 from myrle-krantz/develop
    
    updating artifact ids to apache fineract from mifos io

 api/build.gradle            |  4 ++--
 build.gradle                |  2 +-
 component-test/build.gradle | 12 ++++++------
 service/build.gradle        | 14 +++++++-------
 shared.gradle               |  4 ++--
 5 files changed, 18 insertions(+), 18 deletions(-)


[fineract-cn-reporting] 37/47: Put unit tests together in single test class and use unique Egyptian god shu for reporting service test user

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 1d0699a7fcaa3522d8bff5fc1b8e39b5006d7011
Author: Isaac Kamga <u2...@gmail.com>
AuthorDate: Sun Oct 14 15:07:18 2018 +0100

    Put unit tests together in single test class and use unique Egyptian god shu for reporting service test user
---
 .../AbstractReportingSpecificationTest.java        |  2 +-
 .../cn/reporting/SuiteTestEnvironment.java         | 40 +++++++++++
 .../TestBalanceSheetReportSpecification.java       | 40 -----------
 .../TestCustomerListReportSpecification.java       | 40 -----------
 .../TestDepositListReportSpecification.java        | 39 ----------
 .../TestIncomeStatementReportSpecification.java    | 39 ----------
 .../reporting/TestLoanListReportSpecification.java | 39 ----------
 .../cn/reporting/TestReportingSpecifications.java  | 84 ++++++++++++++++++++++
 .../TestTellerListReportSpecification.java         | 39 ----------
 .../TestTellerTransactionReportSpecification.java  | 39 ----------
 10 files changed, 125 insertions(+), 276 deletions(-)

diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
index 528bad0..ed375b7 100644
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
@@ -52,7 +52,7 @@ import org.springframework.test.context.junit4.SpringRunner;
     webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
     classes = {AbstractReportingSpecificationTest.TestConfiguration.class}
 )
-public class AbstractReportingSpecificationTest {
+public class AbstractReportingSpecificationTest extends SuiteTestEnvironment {
   private static final String APP_NAME = "reporting-v1";
   public static final String LOGGER_NAME = "test-logger";
 
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/SuiteTestEnvironment.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/SuiteTestEnvironment.java
new file mode 100644
index 0000000..9a65c5f
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/SuiteTestEnvironment.java
@@ -0,0 +1,40 @@
+/*
+ * 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.cn.reporting;
+
+import org.apache.fineract.cn.test.env.TestEnvironment;
+import org.apache.fineract.cn.test.fixture.cassandra.CassandraInitializer;
+import org.apache.fineract.cn.test.fixture.mariadb.MariaDBInitializer;
+import org.junit.ClassRule;
+import org.junit.rules.RuleChain;
+import org.junit.rules.RunExternalResourceOnce;
+import org.junit.rules.TestRule;
+
+public class SuiteTestEnvironment {
+  static final String APP_NAME = "reporting-v1";
+  static final TestEnvironment testEnvironment = new TestEnvironment(APP_NAME);
+  static final CassandraInitializer cassandraInitializer = new CassandraInitializer();
+  static final MariaDBInitializer mariaDBInitializer = new MariaDBInitializer();
+
+  @ClassRule
+  public static TestRule orderClassRules = RuleChain
+          .outerRule(new RunExternalResourceOnce(testEnvironment))
+          .around(new RunExternalResourceOnce(cassandraInitializer))
+          .around(new RunExternalResourceOnce(mariaDBInitializer));
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestBalanceSheetReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestBalanceSheetReportSpecification.java
deleted file mode 100644
index d8ae817..0000000
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestBalanceSheetReportSpecification.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.cn.reporting;
-
-import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class TestBalanceSheetReportSpecification extends AbstractReportingSpecificationTest {
-
-    public TestBalanceSheetReportSpecification() {
-        super();
-    }
-
-    @Test
-    public void shouldReturnReportDefinition() {
-        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Accounting");
-        Assert.assertTrue(
-                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Balancesheet"))
-        );
-    }
-}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestCustomerListReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestCustomerListReportSpecification.java
deleted file mode 100644
index 7fdae97..0000000
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestCustomerListReportSpecification.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.cn.reporting;
-
-import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class TestCustomerListReportSpecification extends AbstractReportingSpecificationTest {
-
-  public TestCustomerListReportSpecification() {
-    super();
-  }
-
-  @Test
-  public void shouldReturnReportDefinition() {
-    final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Customer");
-    Assert.assertTrue(
-        reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
-    );
-  }
-}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestDepositListReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestDepositListReportSpecification.java
deleted file mode 100644
index d13fcf6..0000000
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestDepositListReportSpecification.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.cn.reporting;
-
-import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class TestDepositListReportSpecification extends AbstractReportingSpecificationTest {
-    public TestDepositListReportSpecification() {
-        super();
-    }
-
-    @Test
-    public void shouldReturnReportDefinition() {
-        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Deposit");
-        Assert.assertTrue(
-                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
-        );
-    }
-}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestIncomeStatementReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestIncomeStatementReportSpecification.java
deleted file mode 100644
index d919828..0000000
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestIncomeStatementReportSpecification.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.cn.reporting;
-
-import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class TestIncomeStatementReportSpecification extends AbstractReportingSpecificationTest {
-    public TestIncomeStatementReportSpecification() {
-        super();
-    }
-
-    @Test
-    public void shouldReturnReportDefinition() {
-        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Accounting");
-        Assert.assertTrue(
-                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Incomestatement"))
-        );
-    }
-}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestLoanListReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestLoanListReportSpecification.java
deleted file mode 100644
index 49075cf..0000000
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestLoanListReportSpecification.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.cn.reporting;
-
-import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class TestLoanListReportSpecification extends AbstractReportingSpecificationTest{
-    public TestLoanListReportSpecification() {
-        super();
-    }
-
-    @Test
-    public void shouldReturnReportDefinition() {
-        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Loan");
-        Assert.assertTrue(
-                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
-        );
-    }
-}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestReportingSpecifications.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestReportingSpecifications.java
new file mode 100644
index 0000000..4c0c73c
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestReportingSpecifications.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.cn.reporting;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestReportingSpecifications extends AbstractReportingSpecificationTest {
+
+  @Test
+  public void shouldReturnBalanceSheetReportDefinition() {
+    final List<ReportDefinition> balanceSheetReportDefinitions = super.testSubject.fetchReportDefinitions("Accounting");
+    Assert.assertTrue(
+            balanceSheetReportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Balancesheet"))
+    );
+  }
+
+  @Test
+  public void shouldReturnCustomerListReportDefinition() {
+    final List<ReportDefinition> customerListReportDefinitions = super.testSubject.fetchReportDefinitions("Customer");
+    Assert.assertTrue(
+            customerListReportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+    );
+  }
+
+  @Test
+  public void shouldReturnDepositListReportDefinition() {
+    final List<ReportDefinition> depositListReportDefinitions = super.testSubject.fetchReportDefinitions("Deposit");
+    Assert.assertTrue(
+            depositListReportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+    );
+  }
+
+  @Test
+  public void shouldReturnIncomeStatementReportDefinition() {
+    final List<ReportDefinition> incomeStatementReportDefinitions = super.testSubject.fetchReportDefinitions("Accounting");
+    Assert.assertTrue(
+            incomeStatementReportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Incomestatement"))
+    );
+  }
+
+  @Test
+  public void shouldReturnLoanListReportDefinition() {
+    final List<ReportDefinition> loanListReportDefinitions = super.testSubject.fetchReportDefinitions("Loan");
+    Assert.assertTrue(
+            loanListReportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+    );
+  }
+
+  @Test
+  public void shouldReturnTellerListReportDefinition() {
+    final List<ReportDefinition> tellerListReportDefinitions = super.testSubject.fetchReportDefinitions("Teller");
+    Assert.assertTrue(
+            tellerListReportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+    );
+  }
+
+  @Test
+  public void shouldReturnTellerTransactionReportDefinition() {
+    final List<ReportDefinition> tellerTransactionReportDefinitions = super.testSubject.fetchReportDefinitions("Teller");
+    Assert.assertTrue(
+            tellerTransactionReportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Transactions"))
+    );
+  }
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerListReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerListReportSpecification.java
deleted file mode 100644
index fe3d2f4..0000000
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerListReportSpecification.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.cn.reporting;
-
-import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class TestTellerListReportSpecification extends AbstractReportingSpecificationTest {
-    public TestTellerListReportSpecification() {
-        super();
-    }
-
-    @Test
-    public void shouldReturnReportDefinition() {
-        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Teller");
-        Assert.assertTrue(
-                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
-        );
-    }
-}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerTransactionReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerTransactionReportSpecification.java
deleted file mode 100644
index fb76bc3..0000000
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerTransactionReportSpecification.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.cn.reporting;
-
-import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class TestTellerTransactionReportSpecification extends AbstractReportingSpecificationTest {
-    public TestTellerTransactionReportSpecification() {
-        super();
-    }
-
-    @Test
-    public void shouldReturnReportDefinition() {
-        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Teller");
-        Assert.assertTrue(
-                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Transactions"))
-        );
-    }
-}


[fineract-cn-reporting] 31/47: Merge pull request #3 from myrle-krantz/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 1efffc416ee57d1826292cd6e51aba1f11b0c543
Merge: 4396958 d4f065c
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Apr 9 20:47:55 2018 +0200

    Merge pull request #3 from myrle-krantz/develop
    
    Adding rat checks.

 api/build.gradle               | 18 ++++++++++++++++++
 api/settings.gradle            | 17 +++++++++++++++++
 build.gradle                   | 24 ++++++++++++++++++++++++
 component-test/build.gradle    | 18 ++++++++++++++++++
 component-test/settings.gradle | 17 +++++++++++++++++
 service/build.gradle           | 18 ++++++++++++++++++
 service/settings.gradle        | 17 +++++++++++++++++
 settings.gradle                | 17 +++++++++++++++++
 shared.gradle                  | 30 ++++++++++++++++++++++++++++++
 9 files changed, 176 insertions(+)


[fineract-cn-reporting] 25/47: updating artifact ids to apache fineract from mifos io

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit b7f357e8404289811c41a7b3a4eeff5a8f0a8c70
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Feb 26 18:14:56 2018 +0100

    updating artifact ids to apache fineract from mifos io
---
 api/build.gradle            |  4 ++--
 build.gradle                |  2 +-
 component-test/build.gradle | 12 ++++++------
 service/build.gradle        | 14 +++++++-------
 shared.gradle               |  4 ++--
 5 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/api/build.gradle b/api/build.gradle
index 17c6648..1ed9d2b 100644
--- a/api/build.gradle
+++ b/api/build.gradle
@@ -17,13 +17,13 @@ apply from: '../shared.gradle'
 dependencies {
     compile(
             [group: 'org.springframework.cloud', name: 'spring-cloud-starter-feign'],
-            [group: 'io.mifos.core', name: 'api', version: versions.frameworkapi],
+            [group: 'org.apache.fineract.cn', name: 'api', version: versions.frameworkapi],
             [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator],
             [group: 'org.hibernate', name: 'hibernate-validator-annotation-processor', version: versions.validator]
     )
 
     testCompile(
-            [group: 'io.mifos.core', name: 'test', version: versions.frameworktest],
+            [group: 'org.apache.fineract.cn', name: 'test', version: versions.frameworktest],
     )
 }
 
diff --git a/build.gradle b/build.gradle
index b30bd55..b82a3b2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,4 +1,4 @@
-group 'io.mifos'
+group 'org.apache.fineract.cn'
 
 task publishApiToMavenLocal {
     dependsOn gradle.includedBuild('api').task(':publishToMavenLocal')
diff --git a/component-test/build.gradle b/component-test/build.gradle
index c2925eb..04f63bb 100644
--- a/component-test/build.gradle
+++ b/component-test/build.gradle
@@ -19,12 +19,12 @@ apply from: '../shared.gradle'
 
 dependencies {
     compile(
-            [group: 'io.mifos.reporting', name: 'api', version: project.version],
-            [group: 'io.mifos.reporting', name: 'service', version: project.version],
-            [group: 'io.mifos.anubis', name: 'test', version: versions.frameworkanubis],
-            [group: 'io.mifos.core', name: 'api', version: versions.frameworkapi],
-            [group: 'io.mifos.core', name: 'test', version: versions.frameworktest],
-            [group: 'io.mifos.core', name: 'lang', version: versions.frameworklang],
+            [group: 'org.apache.fineract.cn.reporting', name: 'api', version: project.version],
+            [group: 'org.apache.fineract.cn.reporting', name: 'service', version: project.version],
+            [group: 'org.apache.fineract.cn.anubis', name: 'test', version: versions.frameworkanubis],
+            [group: 'org.apache.fineract.cn', name: 'api', version: versions.frameworkapi],
+            [group: 'org.apache.fineract.cn', name: 'test', version: versions.frameworktest],
+            [group: 'org.apache.fineract.cn', name: 'lang', version: versions.frameworklang],
             [group: 'org.springframework.boot', name: 'spring-boot-starter-test']
     )
 }
diff --git a/service/build.gradle b/service/build.gradle
index 7f74364..a5d5eea 100644
--- a/service/build.gradle
+++ b/service/build.gradle
@@ -30,14 +30,14 @@ dependencies {
             [group: 'org.springframework.cloud', name: 'spring-cloud-starter-config'],
             [group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka'],
             [group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'],
-            [group: 'io.mifos.reporting', name: 'api', version: project.version],
-            [group: 'io.mifos.anubis', name: 'library', version: versions.frameworkanubis],
+            [group: 'org.apache.fineract.cn.reporting', name: 'api', version: project.version],
+            [group: 'org.apache.fineract.cn.anubis', name: 'library', version: versions.frameworkanubis],
             [group: 'com.google.code.gson', name: 'gson'],
-            [group: 'io.mifos.core', name: 'lang', version: versions.frameworklang],
-            [group: 'io.mifos.core', name: 'async', version: versions.frameworkasync],
-            [group: 'io.mifos.core', name: 'cassandra', version: versions.frameworkcassandra],
-            [group: 'io.mifos.core', name: 'mariadb', version: versions.frameworkmariadb],
-            [group: 'io.mifos.core', name: 'command', version: versions.frameworkcommand],
+            [group: 'org.apache.fineract.cn', name: 'lang', version: versions.frameworklang],
+            [group: 'org.apache.fineract.cn', name: 'async', version: versions.frameworkasync],
+            [group: 'org.apache.fineract.cn', name: 'cassandra', version: versions.frameworkcassandra],
+            [group: 'org.apache.fineract.cn', name: 'mariadb', version: versions.frameworkmariadb],
+            [group: 'org.apache.fineract.cn', name: 'command', version: versions.frameworkcommand],
             [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator],
             [group: 'org.owasp.esapi', name: 'esapi', version: '2.1.0.1']
     )
diff --git a/shared.gradle b/shared.gradle
index 9d5ff45..c4a540c 100644
--- a/shared.gradle
+++ b/shared.gradle
@@ -1,4 +1,4 @@
-group 'io.mifos.reporting'
+group 'org.apache.fineract.cn.reporting'
 version '0.1.0-BUILD-SNAPSHOT'
 
 ext.versions = [
@@ -66,4 +66,4 @@ license {
     }
     ext.year = Calendar.getInstance().get(Calendar.YEAR)
     ext.name = 'The Mifos Initiative'
-}
\ No newline at end of file
+}


[fineract-cn-reporting] 20/47: Merge pull request #1 from markusgeiss/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 5f1f0f6cb3a35464404706b04ee73ee599bdf276
Merge: fe4f978 a3dee1e
Author: Markus Geiss <ma...@kuelap.io>
AuthorDate: Wed Sep 6 19:14:22 2017 +0200

    Merge pull request #1 from markusgeiss/develop
    
    some new reports

 .gitignore                                         |   2 +
 .../io/mifos/reporting/api/v1/domain/Sample.java   |  20 ++
 .../TestSavingListReportSpecification.java         |  21 ++
 .../DepositListReportSpecification.java            | 377 +++++++++++++++++++++
 .../IncomeStatementReportSpecification.java        | 221 ++++++++++++
 .../specification/LoanListReportSpecification.java | 295 ++++++++++++++++
 ...llerCashierDailyBalanceReportSpecification.java |  72 ++++
 .../TellerListReportSpecification.java             | 221 ++++++++++++
 8 files changed, 1229 insertions(+)


[fineract-cn-reporting] 24/47: Merge branch 'develop' of https://github.com/mifosio/reporting into develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit de1fa388c9935299c8e35a009647c9e8065a455c
Merge: 5f1f0f6 129db80
Author: mgeiss <mg...@mifos.org>
AuthorDate: Wed Oct 4 08:36:35 2017 +0200

    Merge branch 'develop' of https://github.com/mifosio/reporting into develop

 .../io/mifos/reporting/api/v1/domain/Sample.java   |  15 +
 .../TestBalanceSheetReportSpecification.java       |  37 +++
 .../TestDepositListReportSpecification.java        |  36 ++
 .../TestIncomeStatementReportSpecification.java    |  36 ++
 .../reporting/TestLoanListReportSpecification.java |  36 ++
 .../TestSavingListReportSpecification.java         |  21 --
 .../TestTellerListReportSpecification.java         |  36 ++
 .../TestTellerTransactionReportSpecification.java  |  36 ++
 gradle/wrapper/gradle-wrapper.properties           |   4 +-
 gradlew                                            |   0
 .../service/internal/repository/DummyEntity.java   |   2 +-
 .../internal/repository/DummyRepository.java       |   2 +-
 .../BalanceSheetReportSpecification.java           | 364 ++++++++++++++++++++
 .../DepositListReportSpecification.java            | 294 ++++++++--------
 .../IncomeStatementReportSpecification.java        | 165 ++++++---
 .../specification/LoanListReportSpecification.java | 155 ++++++---
 .../OfficeListReportSpecification.java             | 278 ++++++++++++++++
 ...llerCashierDailyBalanceReportSpecification.java |  72 ----
 .../TellerListReportSpecification.java             |  19 +-
 .../TellerTransactionReportSpecification.java      | 370 +++++++++++++++++++++
 service/src/main/resources/ESAPI.properties        |  62 +---
 service/src/main/resources/validation.properties   |  18 +-
 22 files changed, 1676 insertions(+), 382 deletions(-)


[fineract-cn-reporting] 17/47: refactor and added mandatory fields to prevent nulls

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit d5d6db5768fa4508b9680546a6d9cbe11ff749d6
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Sun Sep 3 12:50:14 2017 +0100

    refactor and added mandatory fields to prevent nulls
---
 .gitignore                                         |  2 ++
 .../io/mifos/reporting/api/v1/domain/Sample.java   | 20 ++++++++++++++++++
 ...on.java => DepositListReportSpecification.java} | 24 +++++++++++-----------
 .../IncomeStatementReportSpecification.java        |  8 ++++----
 4 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/.gitignore b/.gitignore
index f9d7cba..1ef178c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@ gradle-app.setting
 *.log
 
 *.toDelete
+*.class
+out/
\ No newline at end of file
diff --git a/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java b/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
new file mode 100644
index 0000000..ba800f4
--- /dev/null
+++ b/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
@@ -0,0 +1,20 @@
+package io.mifos.reporting.api.v1.domain;
+
+public class Sample {
+    private Object identifier;
+    private Object payload;
+    public Sample(){
+        super();
+    }
+    public static Sample create(String xxxx, String yyy) {
+        return new Sample();
+    }
+
+    public void setIdentifier(Object identifier) {
+        this.identifier = identifier;
+    }
+
+    public void setPayload(String payload) {
+        this.payload = payload;
+    }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
similarity index 98%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
rename to service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
index 1820df5..b25aa88 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/SavingListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
@@ -20,7 +20,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 @Report(category = "Deposit", identifier = "Listing")
-public class SavingListReportSpecification implements ReportSpecification {
+public class DepositListReportSpecification implements ReportSpecification {
 
     private static final String CUSTOMER = "Customer";
     private static final String FIRST_NAME = "First name";
@@ -46,7 +46,7 @@ public class SavingListReportSpecification implements ReportSpecification {
 
 
     @Autowired
-    public SavingListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, final EntityManager entityManager) {
+    public DepositListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, final EntityManager entityManager) {
         this.entityManager = entityManager;
         this.logger = logger;
         this.initializeMapping();
@@ -91,13 +91,6 @@ public class SavingListReportSpecification implements ReportSpecification {
         return reportPage;
     }
 
-    private List<QueryParameter> buildQueryParameters() {
-        return Arrays.asList(
-                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
-                QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
-        );
-    }
-
     @Override
     public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
         final ArrayList<String> unknownFields = new ArrayList<>();
@@ -367,12 +360,19 @@ public class SavingListReportSpecification implements ReportSpecification {
                 DisplayableFieldBuilder.create(STATE,Type.TEXT).build(),
                 DisplayableFieldBuilder.create(LAST_ACCOUNT_ACTIVITY, Type.DATE).build(),
 
-                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(DATE_RANGE, Type.TEXT).build()
+                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(DATE_RANGE, Type.DATE).build()
         );
 
     }
 
+    private List<QueryParameter> buildQueryParameters() {
+        return Arrays.asList(
+                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+        );
+    }
+
 
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
index da4c9df..3992d16 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -177,11 +177,11 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
     private List<DisplayableField> buildDisplayableFields() {
         return Arrays.asList(
                 DisplayableFieldBuilder.create(TYPE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(IDENTIFIER, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(IDENTIFIER, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(NAME, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(HOLDER, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(BALANCE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(STATE, Type.TEXT).build()
+                DisplayableFieldBuilder.create(BALANCE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(STATE, Type.TEXT).mandatory().build()
         );
     }
 


[fineract-cn-reporting] 07/47: only add where if criteria available added trialing 00 if no decimals available

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit fe4f978fe82830e0d3dd19539a5c75a188647520
Author: mgeiss <mg...@mifos.org>
AuthorDate: Sat Jul 8 05:24:59 2017 +0200

    only add where if criteria available
    added trialing 00 if no decimals available
---
 .../internal/specification/CustomerListReportSpecification.java  | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
index c799f68..90bfbd9 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
@@ -193,7 +193,7 @@ public class CustomerListReportSpecification implements ReportSpecification {
         row.getValues().add(value);
       }
 
-      final DecimalFormat decimalFormat = new DecimalFormat("0.##");
+      final DecimalFormat decimalFormat = new DecimalFormat("0.00");
       final Query accountQuery = this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, customerIdentifier));
       final List<?> accountResultList = accountQuery.getResultList();
       final ArrayList<String> values = new ArrayList<>();
@@ -260,7 +260,6 @@ public class CustomerListReportSpecification implements ReportSpecification {
 
     final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
     if (!queryParameters.isEmpty()) {
-      query.append(" WHERE ");
       final ArrayList<String> criteria = new ArrayList<>();
       queryParameters.forEach(queryParameter -> {
         if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
@@ -270,7 +269,11 @@ public class CustomerListReportSpecification implements ReportSpecification {
         }
       });
 
-      query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+      if (!criteria.isEmpty()) {
+        query.append(" WHERE ");
+        query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+      }
+
     }
     query.append(" ORDER BY cst.identifier");
 


[fineract-cn-reporting] 01/47: pushed API implementation

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 5036e5669dda97859f26a60ac8cd4bf9180c7def
Author: mgeiss <mg...@mifos.org>
AuthorDate: Fri Jun 30 14:01:50 2017 +0200

    pushed API implementation
---
 .gitignore                                         |  16 ++
 HEADER                                             |  13 ++
 LICENSE                                            | 201 +++++++++++++++++++++
 README.md                                          |  25 +++
 api/build.gradle                                   |  39 ++++
 api/settings.gradle                                |   1 +
 .../io/mifos/reporting/api/v1/EventConstants.java  |  24 +++
 .../reporting/api/v1/PermittableGroupIds.java      |  22 +++
 .../reporting/api/v1/client/ReportManager.java     |  72 ++++++++
 .../api/v1/client/ReportNotFoundException.java     |  19 ++
 .../client/ReportParameterValidationException.java |  19 ++
 .../api/v1/domain/AutoCompleteResource.java        |  44 +++++
 .../reporting/api/v1/domain/DisplayableField.java  |  51 ++++++
 .../io/mifos/reporting/api/v1/domain/Footer.java   |  35 ++++
 .../io/mifos/reporting/api/v1/domain/Header.java   |  35 ++++
 .../reporting/api/v1/domain/QueryParameter.java    |  87 +++++++++
 .../reporting/api/v1/domain/ReportDefinition.java  |  71 ++++++++
 .../mifos/reporting/api/v1/domain/ReportPage.java  | 107 +++++++++++
 .../reporting/api/v1/domain/ReportRequest.java     |  44 +++++
 .../java/io/mifos/reporting/api/v1/domain/Row.java |  35 ++++
 .../io/mifos/reporting/api/v1/domain/Type.java     |  22 +++
 .../io/mifos/reporting/api/v1/domain/Value.java    |  42 +++++
 .../mifos/reporting/api/v1/domain/SampleTest.java  |  55 ++++++
 build.gradle                                       |  36 ++++
 component-test/build.gradle                        |  38 ++++
 component-test/settings.gradle                     |   1 +
 component-test/src/main/resources/logback-test.xml |  59 ++++++
 gradle/wrapper/gradle-wrapper.jar                  | Bin 0 -> 54212 bytes
 gradle/wrapper/gradle-wrapper.properties           |   6 +
 gradlew                                            | 172 ++++++++++++++++++
 gradlew.bat                                        |  84 +++++++++
 service/build.gradle                               |  63 +++++++
 service/settings.gradle                            |   1 +
 .../reporting/service/ReportingApplication.java    |  29 +++
 .../reporting/service/ReportingConfiguration.java  |  67 +++++++
 .../mifos/reporting/service/ServiceConstants.java  |  20 ++
 .../service/internal/service/ReportingService.java |  34 ++++
 .../service/rest/ReportingRestController.java      |  48 +++++
 service/src/main/resources/application.yml         |  66 +++++++
 service/src/main/resources/bootstrap.yml           |  19 ++
 .../db/migrations/mariadb/V1__initial_setup.sql    |  22 +++
 service/src/main/resources/logback.xml             |  55 ++++++
 settings.gradle                                    |   6 +
 shared.gradle                                      |  69 +++++++
 44 files changed, 1974 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f9d7cba
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,16 @@
+.gradle
+.idea
+build/
+target/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+*.iml
+
+*.log
+
+*.toDelete
diff --git a/HEADER b/HEADER
new file mode 100644
index 0000000..4b2eadf
--- /dev/null
+++ b/HEADER
@@ -0,0 +1,13 @@
+Copyright ${year} ${name}.
+
+Licensed 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.
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed 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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..dfc7228
--- /dev/null
+++ b/README.md
@@ -0,0 +1,25 @@
+# Mifos I/O Reporting
+
+[![Join the chat at https://gitter.im/mifos-initiative/mifos.io](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mifos-initiative/mifos.io?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+This project provides simple reporting capabilities.
+
+## Versioning
+The version numbers follow the [Semantic Versioning](http://semver.org/) scheme.
+
+In addition to MAJOR.MINOR.PATCH the following postfixes are used to indicate the development state.
+
+* BUILD-SNAPSHOT - A release currently in development. 
+* M - A _milestone_ release include specific sets of functions and are released as soon as the functionality is complete.
+* RC - A _release candidate_ is a version with potential to be a final product, considered _code complete_.
+* RELEASE - _General availability_ indicates that this release is the best available version and is recommended for all usage.
+
+The versioning layout is {MAJOR}.{MINOR}.{PATCH}-{INDICATOR}[.{PATCH}]. Only milestones and release candidates can  have patch versions. Some examples:
+
+1.2.3.BUILD-SNAPSHOT  
+1.3.5.M.1  
+1.5.7.RC.2  
+2.0.0.RELEASE
+
+## License
+See [LICENSE](LICENSE) file.
diff --git a/api/build.gradle b/api/build.gradle
new file mode 100644
index 0000000..17c6648
--- /dev/null
+++ b/api/build.gradle
@@ -0,0 +1,39 @@
+buildscript {
+    repositories {
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE'
+    }
+}
+
+plugins {
+    id "com.github.hierynomus.license" version "0.13.1"
+}
+
+apply from: '../shared.gradle'
+
+dependencies {
+    compile(
+            [group: 'org.springframework.cloud', name: 'spring-cloud-starter-feign'],
+            [group: 'io.mifos.core', name: 'api', version: versions.frameworkapi],
+            [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator],
+            [group: 'org.hibernate', name: 'hibernate-validator-annotation-processor', version: versions.validator]
+    )
+
+    testCompile(
+            [group: 'io.mifos.core', name: 'test', version: versions.frameworktest],
+    )
+}
+
+publishing {
+    publications {
+        api(MavenPublication) {
+            from components.java
+            groupId project.group
+            artifactId project.name
+            version project.version
+        }
+    }
+}
diff --git a/api/settings.gradle b/api/settings.gradle
new file mode 100644
index 0000000..7c8e3dc
--- /dev/null
+++ b/api/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'api'
\ No newline at end of file
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java b/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
new file mode 100644
index 0000000..a2bbc3f
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1;
+
+@SuppressWarnings("unused")
+public interface EventConstants {
+
+  String DESTINATION = "reporting-v1";
+  String SELECTOR_NAME = "operation";
+
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java b/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
new file mode 100644
index 0000000..d0a3bed
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1;
+
+@SuppressWarnings("unused")
+public interface PermittableGroupIds {
+  String SAMPLE_MANAGEMENT = "reporting__v1__samples";
+  String SELF_MANAGEMENT = "reporting__v1__self";
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
new file mode 100644
index 0000000..50a1b6c
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.client;
+
+import io.mifos.core.api.annotation.ThrowsException;
+import io.mifos.core.api.annotation.ThrowsExceptions;
+import io.mifos.core.api.util.CustomFeignClientsConfiguration;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@SuppressWarnings("unused")
+@FeignClient(value="reporting-v1", path="/reporting/v1", configuration = CustomFeignClientsConfiguration.class)
+public interface ReportManager {
+
+  @RequestMapping(
+          value = "/categories",
+          method = RequestMethod.GET,
+          produces = MediaType.ALL_VALUE,
+          consumes = MediaType.APPLICATION_JSON_VALUE
+  )
+  List<String> fetchCategories();
+
+  @RequestMapping(
+          value = "/categories/{category}",
+          method = RequestMethod.GET,
+          produces = MediaType.ALL_VALUE,
+          consumes = MediaType.APPLICATION_JSON_VALUE)
+  @ThrowsExceptions({
+      @ThrowsException(status = HttpStatus.NOT_FOUND, exception = ReportNotFoundException.class),
+  })
+  List<ReportDefinition> fetchReportDefinitions(@PathVariable("category") final String category);
+
+  @RequestMapping(
+      value = "/categories/{category}/reports/{identifier}",
+      method = RequestMethod.POST,
+      produces = MediaType.APPLICATION_JSON_VALUE,
+      consumes = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ThrowsExceptions({
+      @ThrowsException(status = HttpStatus.NOT_FOUND, exception = ReportNotFoundException.class),
+      @ThrowsException(status = HttpStatus.BAD_REQUEST, exception = ReportParameterValidationException.class)
+  })
+  ReportPage generateReport(@PathVariable("category") final String category,
+                            @PathVariable("identifier") final String identifier,
+                            @RequestBody final ReportRequest reportRequest,
+                            @RequestParam(value = "pageIndex", required = false) final Integer pageIndex,
+                            @RequestParam(value = "size", required = false) final Integer size);
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java
new file mode 100644
index 0000000..4bbbec2
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.client;
+
+public class ReportNotFoundException extends RuntimeException {
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java
new file mode 100644
index 0000000..103922a
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.client;
+
+public class ReportParameterValidationException extends RuntimeException {
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java
new file mode 100644
index 0000000..7dbebba
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+import java.util.List;
+
+public class AutoCompleteResource {
+
+  private String path;
+  private List<String> terms;
+
+  public AutoCompleteResource() {
+    super();
+  }
+
+  public String getPath() {
+    return this.path;
+  }
+
+  public void setPath(final String path) {
+    this.path = path;
+  }
+
+  public List<String> getTerms() {
+    return this.terms;
+  }
+
+  public void setTerms(final List<String> terms) {
+    this.terms = terms;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java
new file mode 100644
index 0000000..0e40dbe
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+public class DisplayableField {
+
+  private String name;
+  private Type type;
+  private Boolean mandatory;
+
+  public DisplayableField() {
+    super();
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public Type getType() {
+    return this.type;
+  }
+
+  public void setType(final Type type) {
+    this.type = type;
+  }
+
+  public Boolean getMandatory() {
+    return this.mandatory;
+  }
+
+  public void setMandatory(final Boolean mandatory) {
+    this.mandatory = mandatory;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java
new file mode 100644
index 0000000..918699e
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+import java.util.List;
+
+public class Footer {
+
+  private List<Value> values;
+
+  public Footer() {
+    super();
+  }
+
+  public List<Value> getValues() {
+    return this.values;
+  }
+
+  public void setValues(final List<Value> values) {
+    this.values = values;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java
new file mode 100644
index 0000000..e153c68
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+import java.util.List;
+
+public class Header {
+
+  private List<String> columnNames;
+
+  public Header() {
+    super();
+  }
+
+  public List<String> getColumnNames() {
+    return this.columnNames;
+  }
+
+  public void setColumnNames(final List<String> columnNames) {
+    this.columnNames = columnNames;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java
new file mode 100644
index 0000000..70ec286
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+public class QueryParameter {
+
+  public enum Operator {
+    EQUALS,
+    IN,
+    LIKE,
+    BETWEEN,
+    GREATER,
+    LESSER
+  }
+
+  private String name;
+  private Type type;
+  private Operator operator;
+  private String value;
+  private Boolean mandatory;
+  private AutoCompleteResource autoCompleteResource;
+
+  public QueryParameter() {
+    super();
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public Type getType() {
+    return this.type;
+  }
+
+  public void setType(final Type type) {
+    this.type = type;
+  }
+
+  public Operator getOperator() {
+    return this.operator;
+  }
+
+  public void setOperator(final Operator operator) {
+    this.operator = operator;
+  }
+
+  public String getValue() {
+    return this.value;
+  }
+
+  public void setValue(final String value) {
+    this.value = value;
+  }
+
+  public Boolean getMandatory() {
+    return this.mandatory;
+  }
+
+  public void setMandatory(final Boolean mandatory) {
+    this.mandatory = mandatory;
+  }
+
+  public AutoCompleteResource getAutoCompleteResource() {
+    return this.autoCompleteResource;
+  }
+
+  public void setAutoCompleteResource(final AutoCompleteResource autoCompleteResource) {
+    this.autoCompleteResource = autoCompleteResource;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java
new file mode 100644
index 0000000..03898f8
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+import java.util.List;
+
+public class ReportDefinition {
+
+  private String identifier;
+  private String name;
+  private String description;
+  private List<QueryParameter> queryParameters;
+  private List<DisplayableField> displayableFields;
+
+  public ReportDefinition() {
+    super();
+  }
+
+  public String getIdentifier() {
+    return this.identifier;
+  }
+
+  public void setIdentifier(final String identifier) {
+    this.identifier = identifier;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public String getDescription() {
+    return this.description;
+  }
+
+  public void setDescription(final String description) {
+    this.description = description;
+  }
+
+  public List<QueryParameter> getQueryParameters() {
+    return this.queryParameters;
+  }
+
+  public void setQueryParameters(final List<QueryParameter> queryParameters) {
+    this.queryParameters = queryParameters;
+  }
+
+  public List<DisplayableField> getDisplayableFields() {
+    return this.displayableFields;
+  }
+
+  public void setDisplayableFields(final List<DisplayableField> displayableFields) {
+    this.displayableFields = displayableFields;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
new file mode 100644
index 0000000..90db8f7
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+import java.util.List;
+
+public class ReportPage {
+
+  private String name;
+  private String description;
+  private String generatedOn;
+  private String generatedBy;
+  private Header header;
+  private List<Row> rows;
+  private Footer footer;
+  private Integer totalPages;
+  private Long totalElements;
+
+  public ReportPage() {
+    super();
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public String getDescription() {
+    return this.description;
+  }
+
+  public void setDescription(final String description) {
+    this.description = description;
+  }
+
+  public String getGeneratedOn() {
+    return this.generatedOn;
+  }
+
+  public void setGeneratedOn(final String generatedOn) {
+    this.generatedOn = generatedOn;
+  }
+
+  public String getGeneratedBy() {
+    return this.generatedBy;
+  }
+
+  public void setGeneratedBy(final String generatedBy) {
+    this.generatedBy = generatedBy;
+  }
+
+  public Header getHeader() {
+    return this.header;
+  }
+
+  public void setHeader(final Header header) {
+    this.header = header;
+  }
+
+  public List<Row> getRows() {
+    return this.rows;
+  }
+
+  public void setRows(final List<Row> rows) {
+    this.rows = rows;
+  }
+
+  public Footer getFooter() {
+    return this.footer;
+  }
+
+  public void setFooter(final Footer footer) {
+    this.footer = footer;
+  }
+
+  public Integer getTotalPages() {
+    return this.totalPages;
+  }
+
+  public void setTotalPages(final Integer totalPages) {
+    this.totalPages = totalPages;
+  }
+
+  public Long getTotalElements() {
+    return this.totalElements;
+  }
+
+  public void setTotalElements(final Long totalElements) {
+    this.totalElements = totalElements;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java
new file mode 100644
index 0000000..199cf08
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+import java.util.List;
+
+public class ReportRequest {
+
+  private List<QueryParameter> queryParameters;
+  private List<DisplayableField> displayableFields;
+
+  public ReportRequest() {
+    super();
+  }
+
+  public List<QueryParameter> getQueryParameters() {
+    return this.queryParameters;
+  }
+
+  public void setQueryParameters(final List<QueryParameter> queryParameters) {
+    this.queryParameters = queryParameters;
+  }
+
+  public List<DisplayableField> getDisplayableFields() {
+    return this.displayableFields;
+  }
+
+  public void setDisplayableFields(final List<DisplayableField> displayableFields) {
+    this.displayableFields = displayableFields;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java
new file mode 100644
index 0000000..576cbcc
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+import java.util.List;
+
+public class Row {
+
+  private List<Value> values;
+
+  public Row() {
+    super();
+  }
+
+  public List<Value> getValues() {
+    return this.values;
+  }
+
+  public void setValues(final List<Value> values) {
+    this.values = values;
+  }
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java
new file mode 100644
index 0000000..20f46c9
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+public enum Type {
+  TEXT,
+  NUMBER,
+  DATE
+}
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
new file mode 100644
index 0000000..a94be09
--- /dev/null
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+public class Value {
+
+  private String value;
+  private Type type;
+
+  public Value() {
+    super();
+  }
+
+  public String getValue() {
+    return this.value;
+  }
+
+  public void setValue(final String value) {
+    this.value = value;
+  }
+
+  public Type getType() {
+    return this.type;
+  }
+
+  public void setType(final Type type) {
+    this.type = type;
+  }
+}
diff --git a/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java b/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java
new file mode 100644
index 0000000..2a304cc
--- /dev/null
+++ b/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
+
+import io.mifos.core.test.domain.ValidationTest;
+import io.mifos.core.test.domain.ValidationTestCase;
+import org.apache.commons.lang.RandomStringUtils;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class SampleTest extends ValidationTest<Sample> {
+
+  public SampleTest(ValidationTestCase<Sample> testCase) {
+    super(testCase);
+  }
+
+  @Override
+  protected Sample createValidTestSubject() {
+    return Sample.create("xxxx", "yyy");
+  }
+
+  @Parameterized.Parameters
+  public static Collection testCases() {
+    final Collection<ValidationTestCase> ret = new ArrayList<>();
+    ret.add(new ValidationTestCase<Sample>("basicCase")
+            .adjustment(x -> {})
+            .valid(true));
+    ret.add(new ValidationTestCase<Sample>("nullIdentifier")
+            .adjustment(x -> x.setIdentifier(null))
+            .valid(false));
+    ret.add(new ValidationTestCase<Sample>("tooShortIdentifier")
+            .adjustment(x -> x.setIdentifier("z"))
+            .valid(false));
+    ret.add(new ValidationTestCase<Sample>("tooLongPayload")
+            .adjustment(x -> x.setPayload(RandomStringUtils.randomAlphanumeric(513)))
+            .valid(false));
+    return ret;
+  }
+
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..b30bd55
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,36 @@
+group 'io.mifos'
+
+task publishApiToMavenLocal {
+    dependsOn gradle.includedBuild('api').task(':publishToMavenLocal')
+}
+
+task publishServiceToMavenLocal {
+    mustRunAfter publishApiToMavenLocal
+    dependsOn gradle.includedBuild('service').task(':publishToMavenLocal')
+}
+
+task publishComponentTestToMavenLocal {
+    mustRunAfter publishApiToMavenLocal
+    mustRunAfter publishServiceToMavenLocal
+    dependsOn gradle.includedBuild('component-test').task(':publishToMavenLocal')
+}
+
+task publishToMavenLocal {
+    group 'all'
+    dependsOn publishApiToMavenLocal
+    dependsOn publishServiceToMavenLocal
+    dependsOn publishComponentTestToMavenLocal
+}
+
+task prepareForTest {
+    group 'all'
+    dependsOn publishToMavenLocal
+    dependsOn gradle.includedBuild('component-test').task(':build')
+}
+
+task licenseFormat {
+    group 'all'
+    dependsOn gradle.includedBuild('api').task(':licenseFormat')
+    dependsOn gradle.includedBuild('service').task(':licenseFormat')
+    dependsOn gradle.includedBuild('component-test').task(':licenseFormat')
+}
diff --git a/component-test/build.gradle b/component-test/build.gradle
new file mode 100644
index 0000000..c2925eb
--- /dev/null
+++ b/component-test/build.gradle
@@ -0,0 +1,38 @@
+buildscript {
+    ext {
+        springBootVersion = '1.4.1.RELEASE'
+    }
+
+    repositories {
+        jcenter()
+    }
+
+    dependencies {
+        classpath ("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+    }
+}
+
+plugins {
+    id "com.github.hierynomus.license" version "0.13.1"
+}
+apply from: '../shared.gradle'
+
+dependencies {
+    compile(
+            [group: 'io.mifos.reporting', name: 'api', version: project.version],
+            [group: 'io.mifos.reporting', name: 'service', version: project.version],
+            [group: 'io.mifos.anubis', name: 'test', version: versions.frameworkanubis],
+            [group: 'io.mifos.core', name: 'api', version: versions.frameworkapi],
+            [group: 'io.mifos.core', name: 'test', version: versions.frameworktest],
+            [group: 'io.mifos.core', name: 'lang', version: versions.frameworklang],
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-test']
+    )
+}
+
+publishing {
+    publications {
+        mavenJava(MavenPublication) {
+            from components.java
+        }
+    }
+}
diff --git a/component-test/settings.gradle b/component-test/settings.gradle
new file mode 100644
index 0000000..07867cb
--- /dev/null
+++ b/component-test/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'component-test'
\ No newline at end of file
diff --git a/component-test/src/main/resources/logback-test.xml b/component-test/src/main/resources/logback-test.xml
new file mode 100644
index 0000000..2473b99
--- /dev/null
+++ b/component-test/src/main/resources/logback-test.xml
@@ -0,0 +1,59 @@
+<!--
+
+    Copyright 2017 The Mifos Initiative.
+
+    Licensed 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.
+
+-->
+<configuration>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logs/reporting.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>logs/archive/reporting.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>7</maxHistory>
+            <totalSizeCap>2GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="ch" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="org" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="io" level="DEBUG">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="net" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <root level="WARN">
+        <appender-ref ref="FILE"/>
+    </root>
+</configuration>
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..400f155
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..2888922
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Mar 17 17:54:20 CET 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..4453cce
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save ( ) {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/service/build.gradle b/service/build.gradle
new file mode 100644
index 0000000..9b9708a
--- /dev/null
+++ b/service/build.gradle
@@ -0,0 +1,63 @@
+buildscript {
+    ext {
+        springBootVersion = '1.4.1.RELEASE'
+    }
+
+    repositories {
+        jcenter()
+    }
+
+    dependencies {
+        classpath ("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+    }
+}
+
+plugins {
+    id "com.github.hierynomus.license" version "0.13.1"
+}
+
+apply from: '../shared.gradle'
+
+apply plugin: 'spring-boot'
+
+springBoot {
+    executable = true
+    classifier = 'boot'
+}
+
+dependencies {
+    compile(
+            [group: 'org.springframework.cloud', name: 'spring-cloud-starter-config'],
+            [group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka'],
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'],
+            [group: 'io.mifos.reporting', name: 'api', version: project.version],
+            [group: 'io.mifos.anubis', name: 'library', version: versions.frameworkanubis],
+            [group: 'com.google.code.gson', name: 'gson'],
+            [group: 'io.mifos.core', name: 'lang', version: versions.frameworklang],
+            [group: 'io.mifos.core', name: 'async', version: versions.frameworkasync],
+            [group: 'io.mifos.core', name: 'cassandra', version: versions.frameworkcassandra],
+            [group: 'io.mifos.core', name: 'mariadb', version: versions.frameworkmariadb],
+            [group: 'io.mifos.core', name: 'command', version: versions.frameworkcommand],
+            [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator]
+    )
+}
+
+publishToMavenLocal.dependsOn bootRepackage
+
+publishing {
+    publications {
+        service(MavenPublication) {
+            from components.java
+            groupId project.group
+            artifactId project.name
+            version project.version
+        }
+        bootService(MavenPublication) {
+            // "boot" jar
+            artifact ("$buildDir/libs/$project.name-$version-boot.jar")
+            groupId project.group
+            artifactId ("$project.name-boot")
+            version project.version
+        }
+    }
+}
diff --git a/service/settings.gradle b/service/settings.gradle
new file mode 100644
index 0000000..081feb4
--- /dev/null
+++ b/service/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'service'
\ No newline at end of file
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java b/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java
new file mode 100644
index 0000000..8f4ae05
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service;
+
+import org.springframework.boot.SpringApplication;
+
+public class ReportingApplication {
+
+  public ReportingApplication() {
+    super();
+  }
+
+  public static void main(String[] args) {
+    SpringApplication.run(ReportingConfiguration.class, args);
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
new file mode 100644
index 0000000..58dd263
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service;
+
+import io.mifos.anubis.config.EnableAnubis;
+import io.mifos.core.cassandra.config.EnableCassandra;
+import io.mifos.core.lang.config.EnableServiceException;
+import io.mifos.core.lang.config.EnableTenantContext;
+import io.mifos.core.mariadb.config.EnableMariaDB;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@SuppressWarnings("WeakerAccess")
+@Configuration
+@EnableAutoConfiguration
+@EnableDiscoveryClient
+@EnableTenantContext
+@EnableCassandra
+@EnableMariaDB
+@EnableAnubis
+@EnableServiceException
+@ComponentScan({
+    "io.mifos.reporting.service.rest",
+    "io.mifos.reporting.service.internal.service",
+    "io.mifos.reporting.service.repository",
+    "io.mifos.reporting.service.internal.provider"
+})
+@EnableJpaRepositories({
+    "io.mifos.reporting.service.repository"
+})
+public class ReportingConfiguration extends WebMvcConfigurerAdapter {
+
+  public ReportingConfiguration() {
+    super();
+  }
+
+  @Bean(name = ServiceConstants.LOGGER_NAME)
+  public Logger logger() {
+    return LoggerFactory.getLogger(ServiceConstants.LOGGER_NAME);
+  }
+
+  @Override
+  public void configurePathMatch(final PathMatchConfigurer configurer) {
+    configurer.setUseSuffixPatternMatch(Boolean.FALSE);
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java b/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java
new file mode 100644
index 0000000..0cc54b5
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service;
+
+public interface ServiceConstants {
+  String LOGGER_NAME = "reporting-logger";
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java b/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java
new file mode 100644
index 0000000..620dff3
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.service;
+
+import io.mifos.reporting.service.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ReportingService {
+
+  private final Logger logger;
+
+  @Autowired
+  public ReportingService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+    super();
+    this.logger = logger;
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
new file mode 100644
index 0000000..d639ae7
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.rest;
+
+import io.mifos.anubis.annotation.AcceptedTokenType;
+import io.mifos.anubis.annotation.Permittable;
+import io.mifos.core.command.gateway.CommandGateway;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.internal.service.ReportingService;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@SuppressWarnings("unused")
+@RestController
+@RequestMapping("/")
+public class ReportingRestController {
+
+  private final Logger logger;
+  private final CommandGateway commandGateway;
+  private final ReportingService reportingService;
+
+  @Autowired
+  public ReportingRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                 final CommandGateway commandGateway,
+                                 final ReportingService reportingService) {
+    super();
+    this.logger = logger;
+    this.commandGateway = commandGateway;
+    this.reportingService = reportingService;
+  }
+}
diff --git a/service/src/main/resources/application.yml b/service/src/main/resources/application.yml
new file mode 100644
index 0000000..4adf77d
--- /dev/null
+++ b/service/src/main/resources/application.yml
@@ -0,0 +1,66 @@
+#
+# Copyright 2017 The Mifos Initiative.
+#
+# Licensed 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.
+#
+
+spring:
+  cloud:
+    discovery:
+      enabled: false
+    config:
+      enabled: false
+
+eureka:
+  client:
+    serviceUrl:
+      defaultZone: http://localhost:8761/eureka/
+
+server:
+  port: 8081
+  contextPath: /reporting/v1/*
+
+cassandra:
+  clusterName: staging_cluster
+  contactPoints: 127.0.0.1:9042,127.0.0.2:9042,127.0.0.3:9042
+  keyspace: seshat
+  cl:
+    read: LOCAL_QUORUM
+    write: LOCAL_QUORUM
+    delete: LOCAL_QUORUM
+
+mariadb:
+  driverClass: org.mariadb.jdbc.Driver
+  database: seshat
+  host: localhost
+  port: 3306
+  user: root
+  password: mysql
+
+bonecp:
+  idleMaxAgeInMinutes: 240
+  idleConnectionTestPeriodInMinutes: 60
+  maxConnectionsPerPartition: 10
+  minConnectionsPerPartition: 1
+  partitionCount: 2
+  acquireIncrement: 5
+  statementsCacheSize: 100
+
+async:
+  corePoolSize: 32
+  maxPoolSize: 16384
+  queueCapacity: 0
+  threadName: async-processor-
+
+flyway:
+  enabled: false
diff --git a/service/src/main/resources/bootstrap.yml b/service/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..fbf1a04
--- /dev/null
+++ b/service/src/main/resources/bootstrap.yml
@@ -0,0 +1,19 @@
+#
+# Copyright 2017 The Mifos Initiative.
+#
+# Licensed 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.
+#
+
+spring:
+    application:
+        name: reporting-v1
diff --git a/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql b/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
new file mode 100644
index 0000000..fb1b54e
--- /dev/null
+++ b/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
@@ -0,0 +1,22 @@
+--
+-- Copyright 2017 The Mifos Initiative.
+--
+-- Licensed 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.
+--
+
+CREATE TABLE template_samples (
+  id BIGINT NOT NULL AUTO_INCREMENT,
+  identifier VARCHAR(8) NOT NULL,
+  payload VARCHAR(512) NULL,
+  CONSTRAINT template_samples_pk PRIMARY KEY (id)
+);
diff --git a/service/src/main/resources/logback.xml b/service/src/main/resources/logback.xml
new file mode 100644
index 0000000..75132d7
--- /dev/null
+++ b/service/src/main/resources/logback.xml
@@ -0,0 +1,55 @@
+<!--
+
+    Copyright 2017 The Mifos Initiative.
+
+    Licensed 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.
+
+-->
+<configuration>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logs/reporting.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>logs/archive/reporting.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>7</maxHistory>
+            <totalSizeCap>2GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com" level="ERROR">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="org" level="ERROR">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="io" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="net" level="ERROR">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <root level="ERROR">
+        <appender-ref ref="FILE"/>
+    </root>
+</configuration>
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..7c66673
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,6 @@
+rootProject.name = 'reporting'
+
+includeBuild 'api'
+includeBuild 'service'
+includeBuild 'component-test'
+
diff --git a/shared.gradle b/shared.gradle
new file mode 100644
index 0000000..9d5ff45
--- /dev/null
+++ b/shared.gradle
@@ -0,0 +1,69 @@
+group 'io.mifos.reporting'
+version '0.1.0-BUILD-SNAPSHOT'
+
+ext.versions = [
+        frameworkapi : '0.1.0-BUILD-SNAPSHOT',
+        frameworklang : '0.1.0-BUILD-SNAPSHOT',
+        frameworkasync : '0.1.0-BUILD-SNAPSHOT',
+        frameworkcassandra : '0.1.0-BUILD-SNAPSHOT',
+        frameworkmariadb : '0.1.0-BUILD-SNAPSHOT',
+        frameworkcommand : '0.1.0-BUILD-SNAPSHOT',
+        frameworktest: '0.1.0-BUILD-SNAPSHOT',
+        frameworkanubis: '0.1.0-BUILD-SNAPSHOT',
+        validator : '5.3.0.Final'
+]
+
+apply plugin: 'java'
+apply plugin: 'idea'
+apply plugin: 'maven-publish'
+apply plugin: 'io.spring.dependency-management'
+
+tasks.withType(JavaCompile) {
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+repositories {
+    jcenter()
+    mavenLocal()
+}
+
+dependencyManagement {
+    imports {
+        mavenBom 'io.spring.platform:platform-bom:Athens-RELEASE'
+        mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Camden.SR1'
+    }
+}
+
+// override certain dependency provided by Spring platform using newer releases
+ext['cassandra.version'] = '3.6'
+ext['cassandra-driver.version'] = '3.1.2'
+ext['activemq.version'] = '5.13.2'
+ext['spring-data-releasetrain.version'] = 'Gosling-SR2A'
+
+dependencies {
+    compile(
+            [group: 'com.google.code.findbugs', name: 'jsr305']
+    )
+
+    testCompile(
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-test']
+    )
+}
+
+jar {
+    from sourceSets.main.allSource
+}
+
+license {
+    header rootProject.file('../HEADER')
+    strictCheck true
+    mapping {
+        java = 'SLASHSTAR_STYLE'
+        xml = 'XML_STYLE'
+        yml = 'SCRIPT_STYLE'
+        yaml = 'SCRIPT_STYLE'
+    }
+    ext.year = Calendar.getInstance().get(Calendar.YEAR)
+    ext.name = 'The Mifos Initiative'
+}
\ No newline at end of file


[fineract-cn-reporting] 21/47: More Updates

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 2408d218a7aa88d427b13f5f64d0459c6a12bfe8
Author: Awasum Yannick <ya...@gmail.com>
AuthorDate: Fri Sep 29 16:25:42 2017 +0100

    More Updates
    
    Update Loan, Deposit, Teller, Income stat and balance sheet reports
---
 .../io/mifos/reporting/api/v1/domain/Sample.java   |  15 +
 .../TestBalanceSheetReportSpecification.java       |  37 +++
 .../TestDepositListReportSpecification.java        |  36 ++
 .../TestIncomeStatementReportSpecification.java    |  36 ++
 .../reporting/TestLoanListReportSpecification.java |  36 ++
 .../TestSavingListReportSpecification.java         |  21 --
 .../TestTellerListReportSpecification.java         |  36 ++
 .../TestTellerTransactionReportSpecification.java  |  36 ++
 gradle/wrapper/gradle-wrapper.properties           |   4 +-
 gradlew                                            |   0
 .../service/internal/repository/DummyEntity.java   |   2 +-
 .../internal/repository/DummyRepository.java       |   2 +-
 .../BalanceSheetReportSpecification.java           | 368 ++++++++++++++++++++
 .../DepositListReportSpecification.java            | 294 ++++++++--------
 ...n.java => EmployeeListReportSpecification.java} | 191 +++++------
 .../IncomeStatementReportSpecification.java        | 162 ++++++---
 .../specification/LoanListReportSpecification.java | 154 ++++++---
 .../OfficeListReportSpecification.java             | 278 ++++++++++++++++
 ...llerCashierDailyBalanceReportSpecification.java |  72 ----
 .../TellerListReportSpecification.java             |  15 +
 .../TellerTransactionReportSpecification.java      | 370 +++++++++++++++++++++
 service/src/main/resources/ESAPI.properties        |  62 +---
 service/src/main/resources/validation.properties   |  18 +-
 23 files changed, 1769 insertions(+), 476 deletions(-)

diff --git a/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java b/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
index ba800f4..6f63318 100644
--- a/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
+++ b/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.api.v1.domain;
 
 public class Sample {
diff --git a/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java
new file mode 100644
index 0000000..3e81b69
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestBalanceSheetReportSpecification extends AbstractReportingSpecificationTest {
+
+    public TestBalanceSheetReportSpecification() {
+        super();
+    }
+
+    @Test
+    public void shouldReturnReportDefinition() {
+        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Accounting");
+        Assert.assertTrue(
+                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Balancesheet"))
+        );
+    }
+}
diff --git a/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java
new file mode 100644
index 0000000..cf49e91
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestDepositListReportSpecification extends AbstractReportingSpecificationTest {
+    public TestDepositListReportSpecification() {
+        super();
+    }
+
+    @Test
+    public void shouldReturnReportDefinition() {
+        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Deposit");
+        Assert.assertTrue(
+                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+        );
+    }
+}
diff --git a/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java
new file mode 100644
index 0000000..4d3a69b
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestIncomeStatementReportSpecification extends AbstractReportingSpecificationTest {
+    public TestIncomeStatementReportSpecification() {
+        super();
+    }
+
+    @Test
+    public void shouldReturnReportDefinition() {
+        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Accounting");
+        Assert.assertTrue(
+                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Incomestatement"))
+        );
+    }
+}
diff --git a/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java
new file mode 100644
index 0000000..40fff05
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestLoanListReportSpecification extends AbstractReportingSpecificationTest{
+    public TestLoanListReportSpecification() {
+        super();
+    }
+
+    @Test
+    public void shouldReturnReportDefinition() {
+        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Loan");
+        Assert.assertTrue(
+                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+        );
+    }
+}
diff --git a/component-test/src/main/java/io/mifos/reporting/TestSavingListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestSavingListReportSpecification.java
deleted file mode 100644
index 4627617..0000000
--- a/component-test/src/main/java/io/mifos/reporting/TestSavingListReportSpecification.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package io.mifos.reporting;
-
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-
-public class TestSavingListReportSpecification extends AbstractReportingSpecificationTest {
-    public TestSavingListReportSpecification() {
-        super();
-    }
-
-    @Test
-    public void shouldReturnReportDefinition() {
-        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Deposit");
-        Assert.assertTrue(
-                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
-        );
-    }
-}
diff --git a/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java
new file mode 100644
index 0000000..4b17f3b
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestTellerListReportSpecification extends AbstractReportingSpecificationTest {
+    public TestTellerListReportSpecification() {
+        super();
+    }
+
+    @Test
+    public void shouldReturnReportDefinition() {
+        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Teller");
+        Assert.assertTrue(
+                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing"))
+        );
+    }
+}
diff --git a/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java
new file mode 100644
index 0000000..6ea4da5
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting;
+
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestTellerTransactionReportSpecification extends AbstractReportingSpecificationTest {
+    public TestTellerTransactionReportSpecification() {
+        super();
+    }
+
+    @Test
+    public void shouldReturnReportDefinition() {
+        final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Teller");
+        Assert.assertTrue(
+                reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Transactions"))
+        );
+    }
+}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2888922..988e7e1 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Mar 17 17:54:20 CET 2017
+#Sun Sep 10 13:58:36 WAT 2017
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
index 0f36a7e..2e53063 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 The Mifos Initiative.
+ * Copyright 2017 The Mifos Initiative.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
index 20baf0e..0c70de7 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 The Mifos Initiative.
+ * Copyright 2017 The Mifos Initiative.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
new file mode 100644
index 0000000..d8a25d5
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
+
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.DateConverter;
+import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.*;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.math.BigDecimal;
+import java.time.Clock;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Report(category = "Accounting", identifier = "Balancesheet")
+public class BalanceSheetReportSpecification implements ReportSpecification {
+
+    private static final String DATE_RANGE = "Date range";
+    private static final String TYPE = "Type";
+    private static final String IDENTIFIER = "Identifier";
+    private static final String NAME = "Name";
+    private static final String HOLDER = "Holder";
+    private static final String BALANCE = "Balance";
+    private static final String STATE = "State";
+
+    private final Logger logger;
+
+    private final EntityManager entityManager;
+
+    private final HashMap<String, String> accountingColumnMapping = new HashMap<>();
+    private final HashMap<String, String> allColumnMapping = new HashMap<>();
+
+
+    public BalanceSheetReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                              final EntityManager entityManager){
+        super();
+        this.logger = logger;
+        this.entityManager = entityManager;
+        this.initializeMapping();
+    }
+
+    @Override
+    public ReportDefinition getReportDefinition() {
+        final ReportDefinition reportDefinition = new ReportDefinition();
+        reportDefinition.setIdentifier("Balancesheet");
+        reportDefinition.setName("Balance Sheet");
+        reportDefinition.setDescription("Balance Sheet Report");
+        reportDefinition.setQueryParameters(this.buildQueryParameters());
+        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+        return reportDefinition;
+    }
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        final ReportDefinition reportDefinition = this.getReportDefinition();
+        this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
+
+        final ReportPage reportPage = new ReportPage();
+        reportPage.setName(reportDefinition.getName());
+        reportPage.setDescription(reportDefinition.getDescription());
+        reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
+
+        final Query accountQuery = this.entityManager.createNativeQuery(this.buildAssetQuery(reportRequest, pageIndex, size));
+        final List<?> accountResultList =  accountQuery.getResultList();
+        reportPage.setRows(this.buildRows(reportRequest, accountResultList));
+
+        reportPage.setHasMore(
+                !this.entityManager.createNativeQuery(this.buildAssetQuery(reportRequest, pageIndex + 1, size))
+                        .getResultList().isEmpty()
+        );
+
+        reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
+        reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+        return reportPage;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+        final ArrayList<String> unknownFields =  new ArrayList<>();
+        reportRequest.getQueryParameters().forEach(queryParameter -> {
+            if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
+                unknownFields.add(queryParameter.getName());
+            }
+        });
+
+        reportRequest.getDisplayableFields().forEach(displayableField -> {
+            if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
+                unknownFields.add(displayableField.getName());
+            }
+        });
+
+        if (!unknownFields.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
+            );
+        }
+    }
+
+    private void initializeMapping() {
+        this.accountingColumnMapping.put(DATE_RANGE, "acc.created_on");
+        this.accountingColumnMapping.put(TYPE, "acc.a_type");
+        this.accountingColumnMapping.put(IDENTIFIER, "acc.identifier");
+        this.accountingColumnMapping.put(NAME, "acc.a_name");
+        this.accountingColumnMapping.put(HOLDER, "acc.holders");
+        this.accountingColumnMapping.put(BALANCE, "acc.balance");
+        this.accountingColumnMapping.put(STATE, "acc.a_state");
+
+        this.allColumnMapping.putAll(accountingColumnMapping);
+    }
+
+    private Header createHeader(List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+    private List<Row> buildRows(ReportRequest reportRequest, List<?> accountResultList) {
+        final ArrayList<Row> rows = new ArrayList<>();
+
+        final Row totalAssetRow = new Row();
+        totalAssetRow.setValues(new ArrayList<>());
+
+        final Value subAssetTotal = new Value();
+
+        final BigDecimal[] assetSubTotal = {new BigDecimal("0.000")};
+
+        accountResultList.forEach(result -> {
+
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues;
+                resultValues = (Object[]) result;
+
+                for (int i = 0; i < resultValues.length; i++){
+                    final Value assetValue = new Value();
+                    if (resultValues[i] != null){
+                        assetValue.setValues(new String[]{resultValues[i].toString()});
+                    }else assetValue.setValues(new String[]{});
+
+                    row.getValues().add(assetValue);
+
+                    assetSubTotal[0] = assetSubTotal[0].add((BigDecimal)resultValues[3]);
+
+                }
+            } else {
+                final Value value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
+            rows.add(row);
+        });
+
+        subAssetTotal.setValues(new String[]{new StringBuilder().append("TOTAL ASSETS ").append(assetSubTotal[0]).toString()});
+        totalAssetRow.getValues().add(subAssetTotal);
+
+        rows.add(totalAssetRow);
+
+
+        final String liabilityQueryString = this.buildLiabilityQuery(reportRequest);
+        final Query liabilityQuery = this.entityManager.createNativeQuery(liabilityQueryString);
+        final List<?> liabilityResultList = liabilityQuery.getResultList();
+
+        final Row totalLiabilityRow = new Row();
+        totalLiabilityRow.setValues(new ArrayList<>());
+        final Value subLiabilityTotal = new Value();
+
+        final BigDecimal[] liabilitySubTotal = {new BigDecimal("0.000")};
+
+        liabilityResultList.forEach(result -> {
+
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues;
+                resultValues = (Object[]) result;
+
+                for (int i = 0; i < resultValues.length; i++){
+                    final Value liabilityValue = new Value();
+                    if (resultValues[i] != null) liabilityValue.setValues(new String[]{resultValues[i].toString()});
+                    else liabilityValue.setValues(new String[]{});
+
+                    row.getValues().add(liabilityValue);
+
+                    liabilitySubTotal[0] = liabilitySubTotal[0].add((BigDecimal)resultValues[3]);
+
+                }
+            } else {
+                final Value value;
+                value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
+            rows.add(row);
+        });
+
+        subLiabilityTotal.setValues(new String[]{new StringBuilder().append("TOTAL LIABILITIES ").append(liabilitySubTotal[0]).toString()});
+        totalLiabilityRow.getValues().add(subLiabilityTotal);
+        rows.add(totalLiabilityRow);
+
+
+
+        final String equityQueryString = this.buildEquityQuery(reportRequest);
+        final Query equityQuery = this.entityManager.createNativeQuery(equityQueryString);
+        final List<?> equityResultList = equityQuery.getResultList();
+
+        final Row totalEquityRow = new Row();
+        totalEquityRow.setValues(new ArrayList<>());
+        final Value subEquityTotal = new Value();
+
+        final Row totalLiabilityAndEquityRow = new Row();
+        totalLiabilityAndEquityRow.setValues(new ArrayList<>());
+        final Value totalLiabilityAndEquityValue = new Value();
+
+        final BigDecimal[] equitySubTotal = {new BigDecimal("0.000")};
+
+        equityResultList.forEach(result -> {
+
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues;
+                resultValues = (Object[]) result;
+
+                for (int i = 0; i < resultValues.length; i++){
+                    final Value equityValue = new Value();
+                    if (resultValues[i] != null) equityValue.setValues(new String[]{resultValues[i].toString()});
+                    else equityValue.setValues(new String[]{});
+
+                    row.getValues().add(equityValue);
+
+                    equitySubTotal[0] = equitySubTotal[0].add((BigDecimal)resultValues[3]);
+
+                }
+            } else {
+                final Value value;
+                value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
+            rows.add(row);
+        });
+
+        subEquityTotal.setValues(new String[]{new StringBuilder().append("TOTAL EQUITY ").append(equitySubTotal[0]).toString()});
+        totalEquityRow.getValues().add(subEquityTotal);
+        rows.add(totalEquityRow);
+
+
+        final BigDecimal liabilityAndEquity = liabilitySubTotal[0].add(equitySubTotal[0]);
+        totalLiabilityAndEquityValue.setValues(new String[]{new StringBuilder().append("TOTAL LIABILITIES and EQUITY ").append(liabilityAndEquity).toString()});
+        totalLiabilityAndEquityRow.getValues().add(totalLiabilityAndEquityValue);
+        rows.add(totalLiabilityAndEquityRow);
+
+        return rows;
+    }
+
+    private String buildAssetQuery(final ReportRequest reportRequest, int pageIndex, int size) {
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.accountingColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("thoth_accounts acc ")
+                .append("WHERE acc.a_type = 'ASSET' ");
+
+        query.append(" ORDER BY acc.identifier");
+
+        return query.toString();
+    }
+
+    private String buildLiabilityQuery(final ReportRequest reportRequest) {
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.accountingColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("thoth_accounts acc ")
+                .append("WHERE acc.a_type = 'LIABILITY' ");
+
+        query.append(" ORDER BY acc.identifier");
+
+        return query.toString();
+    }
+
+    private String buildEquityQuery(final ReportRequest reportRequest) {
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.accountingColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("thoth_accounts acc ")
+                .append("WHERE acc.a_type = 'EQUITY' ");
+
+        query.append(" ORDER BY acc.identifier");
+
+        return query.toString();
+    }
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return Arrays.asList(
+                DisplayableFieldBuilder.create(TYPE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(IDENTIFIER, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(NAME, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(BALANCE, Type.TEXT).mandatory().build()
+        );
+    }
+
+    private List<QueryParameter> buildQueryParameters() {
+        return Arrays.asList();
+    }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
index 42dabfa..8e37df7 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
 
 import io.mifos.core.api.util.UserContextHolder;
@@ -22,26 +37,25 @@ import java.util.stream.Collectors;
 @Report(category = "Deposit", identifier = "Listing")
 public class DepositListReportSpecification implements ReportSpecification {
 
-    private static final String CUSTOMER = "Customer";
-    private static final String FIRST_NAME = "First name";
-    private static final String MIDDLE_NAME = "Middle name";
-    private static final String LAST_NAME = "Last name";
-    private static final String EMPLOYEE = "Employee";
-    private static final String ACCOUNT_NUMBER = "Account number";
-    private static final String ACCOUNT_TYPE = "Account type";
-    private static final String STATE = "State";
+    private static final String CUSTOMER = "Customer Account";
+    private static final String FIRST_NAME = "First Name";
+    private static final String MIDDLE_NAME = "Middle Name";
+    private static final String LAST_NAME = "Last Name";
+    private static final String EMPLOYEE = "Created By";
+    private static final String ACCOUNT_NUMBER = "Deposit Account";
+    private static final String PRODUCT = "Product";
+    private static final String ACCOUNT_TYPE = "Deposit Type";
+    private static final String STATE = "Status";
     private static final String OFFICE = "Office";
-    private static final String DATE_RANGE = "Date created";
-    private static final String LAST_ACCOUNT_ACTIVITY = "Last account activity";
+    private static final String DATE_RANGE = "Date Created";
 
     private final EntityManager entityManager;
 
     private final Logger logger;
 
     private final HashMap<String, String> customerColumnMapping = new HashMap<>();
-    private final HashMap<String, String> accountColumnMapping = new HashMap<>();
-    private final HashMap<String, String> officeColumnMapping = new HashMap<>();
-    private final HashMap<String, String> employeeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> depositAccountColumnMapping = new HashMap<>();
+    private final HashMap<String, String> depositProductColumnMapping = new HashMap<>();
     private final HashMap<String, String> allColumnMapping = new HashMap<>();
 
 
@@ -75,14 +89,13 @@ public class DepositListReportSpecification implements ReportSpecification {
         reportPage.setDescription(reportDefinition.getDescription());
         reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
 
-        final Query depositAccountQuery = this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, pageIndex, size));
-
-        final List<?> depositAccountResultList = depositAccountQuery.getResultList();
-        reportPage.setRows(this.buildRows(reportRequest, depositAccountResultList));
+        final Query customerQuery = this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, pageIndex, size));
 
+        final List<?> customerResultList = customerQuery.getResultList();
+        reportPage.setRows(this.buildRows(reportRequest, customerResultList));
 
         reportPage.setHasMore(
-                !this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, pageIndex + 1, size))
+                !this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, pageIndex + 1, size))
                         .getResultList().isEmpty()
         );
 
@@ -119,21 +132,19 @@ public class DepositListReportSpecification implements ReportSpecification {
         this.customerColumnMapping.put(FIRST_NAME, "cst.given_name");
         this.customerColumnMapping.put(MIDDLE_NAME, "cst.middle_name");
         this.customerColumnMapping.put(LAST_NAME, "cst.surname");
+        this.customerColumnMapping.put(OFFICE, "cst.assigned_office");
 
-        this.officeColumnMapping.put(OFFICE, "cst.assigned_office");
-
-        this.employeeColumnMapping.put(EMPLOYEE, "pi.created_by");
+        this.depositAccountColumnMapping.put(EMPLOYEE, "pi.created_by");
+        this.depositAccountColumnMapping.put(ACCOUNT_NUMBER, "pi.account_identifier");
+        this.depositAccountColumnMapping.put(STATE, "pi.a_state");
+        this.depositAccountColumnMapping.put(PRODUCT, "pi.product_definition_id");
+        this.depositAccountColumnMapping.put(DATE_RANGE, "pi.created_on");
 
-        this.accountColumnMapping.put(ACCOUNT_NUMBER, "pi.customer_identifier, pi.account_identifier");
-        this.accountColumnMapping.put(STATE, " pi.a_state");
-        this.accountColumnMapping.put(ACCOUNT_TYPE, "pi.product_definition_id");
-        this.accountColumnMapping.put(LAST_ACCOUNT_ACTIVITY, "acc_entry.transaction_date, acc_entry.message, acc_entry.amount, acc_entry.balance");
-        this.accountColumnMapping.put(DATE_RANGE, "pi.created_on");
+        this.depositProductColumnMapping.put(ACCOUNT_TYPE, "pd.a_name, pd.a_type");
 
         this.allColumnMapping.putAll(customerColumnMapping);
-        this.allColumnMapping.putAll(officeColumnMapping);
-        this.allColumnMapping.putAll(employeeColumnMapping);
-        this.allColumnMapping.putAll(accountColumnMapping);
+        this.allColumnMapping.putAll(depositProductColumnMapping);
+        this.allColumnMapping.putAll(depositAccountColumnMapping);
     }
     private Header createHeader(final List<DisplayableField> displayableFields) {
         final Header header = new Header();
@@ -146,13 +157,13 @@ public class DepositListReportSpecification implements ReportSpecification {
         return header;
     }
 
+    private List<Row> buildRows(final ReportRequest reportRequest, final List<?> customerResultList) {
+        final ArrayList<Row> rows = new ArrayList<>();
 
-    private List<Row> buildRows(final ReportRequest reportRequest, final List<?> depositAccountResultList) {
-        final ArrayList<Row> rows =new ArrayList<>();
-        depositAccountResultList.forEach(result -> {
+        customerResultList.forEach(result -> {
             final Row row = new Row();
             row.setValues(new ArrayList<>());
-            //Get the customer identifier to use for join queries.
+
             final String customerIdentifier;
 
             if (result instanceof Object[]) {
@@ -162,86 +173,104 @@ public class DepositListReportSpecification implements ReportSpecification {
 
                 for (final Object resultValue : resultValues) {
                     final Value value = new Value();
-                    if (resultValue != null)
+                    if (resultValue != null) {
                         value.setValues(new String[]{resultValue.toString()});
-                    else {
+                    } else {
                         value.setValues(new String[]{});
                     }
 
                     row.getValues().add(value);
                 }
             } else {
-
                 customerIdentifier = result.toString();
-                final Value value;
-                value = new Value();
+
+                final Value value = new Value();
                 value.setValues(new String[]{result.toString()});
                 row.getValues().add(value);
             }
 
-            final String accountIdentifier;
+            final Query accountQuery = this.entityManager.createNativeQuery(this.buildDepositAccountQuery(reportRequest, customerIdentifier));
+            final List<?> accountResultList = accountQuery.getResultList();
 
-            if (result instanceof Object[]) {
-                final Object[] resultValues = (Object[]) result;
+            final ArrayList<String> products = new ArrayList<>();
+            final ArrayList<String> depositAccountNumber = new ArrayList<>();
+            final ArrayList<String> depositType = new ArrayList<>();
+            final ArrayList<String> status = new ArrayList<>();
+            final ArrayList<String> createdBy = new ArrayList<>();
+            final ArrayList<String> dateCreated = new ArrayList<>();
 
-                accountIdentifier = resultValues[2].toString();
+            accountResultList.forEach(accountResult -> {
 
-                for (final Object resultValue : resultValues) {
-                    final Value value;
-                    value = new Value();
-                    if (resultValue != null)
-                        value.setValues(new String[]{resultValue.toString()});
-                    else {
-                        value.setValues(new String[]{});
-                    }
+                final String productIdentifier;
+                if (accountResult instanceof Object[]) {
+                    final Object[] accountResultValues = (Object[]) accountResult;
 
-                    row.getValues().add(value);
-                }
-            } else {
+                    productIdentifier = accountResultValues[0].toString();
 
-                accountIdentifier = result.toString();
-                final Value value = new Value();
-                value.setValues(new String[]{result.toString()});
-                row.getValues().add(value);
-            }
+                    final Query depositProductQuery = this.entityManager.createNativeQuery(this.buildDepositProductQuery(reportRequest, productIdentifier));
+                    final List<?> depositProductResultList = depositProductQuery.getResultList();
 
-            final Query customerQuery = this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, customerIdentifier));
-            final List<?> accountResultList = customerQuery.getResultList();
-            final ArrayList<String> values = new ArrayList<>();
-            accountResultList.forEach(customerResult -> {
-                if (customerResult instanceof Object[]) {
-                    final Object[] customerResultValues = (Object[]) customerResult;
-                    final String customerValue = customerResultValues[0].toString();
-                    values.add(customerValue);
-                }
-            });
-            final Value customerValue = new Value();
-            customerValue.setValues(values.toArray(new String[values.size()]));
-            row.getValues().add(customerValue);
-
-            final String officeQueryString = this.buildOfficeQuery(reportRequest, customerIdentifier);
-            if (officeQueryString != null) {
-                final Query officeQuery;
-                officeQuery = this.entityManager.createNativeQuery(officeQueryString);
-                final List<?> resultList = officeQuery.getResultList();
-                final Value officeValue = new Value();
-                officeValue.setValues(new String[]{resultList.get(0).toString()});
-                row.getValues().add(officeValue);
-            }
+                    depositProductResultList.forEach(product -> {
+                        final Object[] productResultValues = (Object[]) product;
+
+                        for (int i = 0; i < productResultValues.length; i++) {
+
+                            if (i == 0 && productResultValues[0] != null) {
+                                products.add(productResultValues[0].toString());
+                            }
+
+                            if (i == 1 && productResultValues[1] != null) {
+                                depositType.add(productResultValues[1].toString());
+                            }
+
+                        }
+                    });
+
+
+                    for (int i = 1; i < accountResultValues.length ; i++) {
+                        if (i == 1 && accountResultValues[1] != null){
+                            depositAccountNumber.add(accountResultValues[1].toString());
+                        }
 
-            final Query lastAccountActivivityQueryString = this.entityManager.createNativeQuery(this.buildLastAccountActivity(reportRequest, accountIdentifier));
-            final List<?> lastActivityResultList = lastAccountActivivityQueryString.getResultList();
-            final ArrayList<String> val = new ArrayList<>();
-            lastActivityResultList.forEach( lastActivityResult -> {
-                if (lastActivityResult instanceof Object[]){
-                    final Object[] lastActivityResultValues = (Object[]) lastActivityResult;
-                    final String lastActivityValue = lastActivityResultValues[1].toString();
-                    val.add(lastActivityValue);
+                        if (i == 2  && accountResultValues[2] != null){
+                            status.add(accountResultValues[2].toString());
+                        }
+
+                        if (i == 3 && accountResultValues[3] != null){
+                            createdBy.add(accountResultValues[3].toString());
+                        }
+
+                        if (i == 4 && accountResultValues[4] != null){
+                            dateCreated.add(accountResultValues[4].toString());
+                        }
+
+                    }
                 }
             });
-            final Value lastActivityValue = new Value();
-            lastActivityValue.setValues(val.toArray(new String[values.size()]));
-            row.getValues().add(lastActivityValue);
+
+            final Value productValue = new Value();
+            productValue.setValues(products.toArray(new String[products.size()]));
+            row.getValues().add(productValue);
+
+            final Value depositTypeValue = new Value();
+            depositTypeValue.setValues(depositType.toArray(new String[depositAccountNumber.size()]));
+            row.getValues().add(depositTypeValue);
+
+            final Value depositAccountNumberValue = new Value();
+            depositAccountNumberValue.setValues(depositAccountNumber.toArray(new String[depositType.size()]));
+            row.getValues().add(depositAccountNumberValue);
+
+            final Value statusValue = new Value();
+            statusValue.setValues(status.toArray(new String[status.size()]));
+            row.getValues().add(statusValue);
+
+            final Value createdByValue = new Value();
+            createdByValue.setValues(createdBy.toArray(new String[createdBy.size()]));
+            row.getValues().add(createdByValue);
+
+            final Value dateCreatedValue = new Value();
+            dateCreatedValue.setValues(dateCreated.toArray(new String[dateCreated.size()]));
+            row.getValues().add(dateCreatedValue);
 
             rows.add(row);
         });
@@ -249,13 +278,14 @@ public class DepositListReportSpecification implements ReportSpecification {
         return rows;
     }
 
-    private String buildAccountQuery(final ReportRequest reportRequest, int pageIndex, int size) {
+    private String buildCustomerQuery(final ReportRequest reportRequest, int pageIndex, int size) {
         final StringBuilder query = new StringBuilder("SELECT ");
 
-        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final List<DisplayableField> displayableFields;
+        displayableFields = reportRequest.getDisplayableFields();
         final ArrayList<String> columns = new ArrayList<>();
         displayableFields.forEach(displayableField -> {
-            final String column = this.accountColumnMapping.get(displayableField.getName());
+            final String column = this.customerColumnMapping.get(displayableField.getName());
             if (column != null) {
                 columns.add(column);
             }
@@ -263,17 +293,15 @@ public class DepositListReportSpecification implements ReportSpecification {
 
         query.append(columns.stream().collect(Collectors.joining(", ")))
                 .append(" FROM ")
-                .append("shed_product_instances pi");
+                .append("maat_customers cst ");
+
         final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
         if (!queryParameters.isEmpty()) {
             final ArrayList<String> criteria = new ArrayList<>();
             queryParameters.forEach(queryParameter -> {
-                if (queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
-                    criteria.add(
-                            CriteriaBuilder.buildCriteria(this.accountColumnMapping.get(queryParameter.getName()), queryParameter)
-                    );
+                if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
                     criteria.add(
-                            CriteriaBuilder.buildCriteria(this.employeeColumnMapping.get(queryParameter.getName()), queryParameter)
+                            CriteriaBuilder.buildCriteria(this.customerColumnMapping.get(queryParameter.getName()), queryParameter)
                     );
                 }
             });
@@ -284,7 +312,7 @@ public class DepositListReportSpecification implements ReportSpecification {
             }
 
         }
-        query.append(" ORDER BY pi.customer_identifier");
+        query.append(" ORDER BY cst.identifier");
 
         query.append(" LIMIT ");
         query.append(size);
@@ -294,74 +322,56 @@ public class DepositListReportSpecification implements ReportSpecification {
         }
 
         return query.toString();
-
-        // return "SELECT ... FROM shed_product_instances pi";
-
-    }
-
-    private String buildCustomerQuery(final ReportRequest reportRequest, final String customerIdentifier) {
-            final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
-            final ArrayList<String> columns = new ArrayList<>();
-            displayableFields.forEach(displayableField -> {
-                final String column = this.customerColumnMapping.get(displayableField.getName());
-                if (column != null) {
-                    columns.add(column);
-                }
-            });
-        return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
-                "FROM maat_customers cst " +
-                "LEFT JOIN shed_product_instances pi on cst.identifier = pi.customer_identifier " +
-                "WHERE pi.customer_identifier ='" + customerIdentifier + "' " +
-                "ORDER BY cst.identifier";
     }
 
-    private String buildOfficeQuery(final ReportRequest reportRequest, final String customerIdentifier) {
+    private String buildDepositAccountQuery(final ReportRequest reportRequest, final String customerIdentifier) {
         final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
         final ArrayList<String> columns = new ArrayList<>();
         displayableFields.forEach(displayableField -> {
-            final String column = this.officeColumnMapping.get(displayableField.getName());
+            final String column = this.depositAccountColumnMapping.get(displayableField.getName());
             if (column != null) {
                 columns.add(column);
             }
         });
 
         return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
-                "FROM maat_customers cst " +
+                "FROM shed_product_instances pi " +
+                "LEFT JOIN maat_customers cst on pi.customer_identifier = cst.identifier " +
                 "WHERE cst.identifier ='" + customerIdentifier + "' " +
-                "ORDER BY cst.identifier";
+                "ORDER BY pi.account_identifier";
     }
 
-    private String buildLastAccountActivity(final ReportRequest reportRequest, final String accountIdentifier){
-        final List<DisplayableField> displayableFields = new ArrayList<>();
+    private String buildDepositProductQuery(final ReportRequest reportRequest, final String productIdentifier){
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
         final ArrayList<String> columns = new ArrayList<>();
         displayableFields.forEach(displayableField -> {
-            final String column = this.accountColumnMapping.get(displayableField.getName());
-            if(column != null){
+            final String column = this.depositProductColumnMapping.get(displayableField.getName());
+            if (column != null) {
                 columns.add(column);
             }
         });
 
-        return "SELECT " + columns.stream().collect(Collectors.joining(",")) + ""  +
-                "FROM thoth_account_entries acc_entry" +
-                "WHERE acc_entry.account_id ='" + accountIdentifier + "'" +
-                "ORDER BY acc_entry.transaction_date";
+        return "SELECT DISTINCT " + columns.stream().collect(Collectors.joining(", ")) + " " +
+                "FROM shed_product_definitions pd " +
+                "LEFT JOIN shed_product_instances pi on pd.id = pi.product_definition_id " +
+                "WHERE pi.product_definition_id ='" + productIdentifier + "' ";
     }
 
     private List<DisplayableField> buildDisplayableFields() {
 
         return Arrays.asList(
                 DisplayableFieldBuilder.create(CUSTOMER, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(ACCOUNT_NUMBER, Type.TEXT).mandatory().build(),
-
-                DisplayableFieldBuilder.create(STATE,Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LAST_ACCOUNT_ACTIVITY, Type.DATE).build(),
-
-                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(OFFICE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(DATE_RANGE, Type.DATE).build()
+
+                DisplayableFieldBuilder.create(PRODUCT, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(ACCOUNT_TYPE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(ACCOUNT_NUMBER, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(STATE,Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(DATE_RANGE, Type.DATE).mandatory().build()
         );
 
     }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/EmployeeListReportSpecification.java
similarity index 51%
copy from service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
copy to service/src/main/java/io/mifos/reporting/service/internal/specification/EmployeeListReportSpecification.java
index 0b6509b..be1a58b 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/EmployeeListReportSpecification.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
 
 import io.mifos.core.api.util.UserContextHolder;
@@ -11,7 +26,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
-import java.text.DecimalFormat;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -20,35 +34,30 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
 
-@Report(category = "Loan", identifier = "Listing")
-public class LoanListReportSpecification implements ReportSpecification {
+@Report(category = "Organization", identifier = "Employee")
+public class EmployeeListReportSpecification implements ReportSpecification {
 
-    private static final String DATE_RANGE = "Date created";
-    private static final String CUSTOMER = "Customer";
-    private static final String FIRST_NAME = "First name";
-    private static final String MIDDLE_NAME = "Middle name";
-    private static final String LAST_NAME = "Last name";
-    private static final String EMPLOYEE = "Employee";
-    private static final String LOAN_STATE = "State";
-    private static final String LOAN_ACCOUNT_NUMBER = "Account number";
-    private static final String LOAN_TYPE = "Account type";
-    private static final String LOAN_TERM = "Loan term";
-    private static final String OFFICE = "Office";
+    private static final String USERNAME = "Username";
+    private static final String FIRST_NAME = "First Name";
+    private static final String MIDDLE_NAME = "Middle Name";
+    private static final String LAST_NAME = "Last Name";
+    private static final String CREATED_BY = "Created By";
 
+    private static final String OFFICE = "Office Id";
+    private static final String OFFICE_NAME = "Office Name";
 
     private final Logger logger;
 
     private final EntityManager entityManager;
 
-    private final HashMap<String, String> customerColumnMapping = new HashMap<>();
-    private final HashMap<String, String> loanColumnMapping = new HashMap<>();
-    private final HashMap<String, String> officeColumnMapping = new HashMap<>();
     private final HashMap<String, String> employeeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> officeColumnMapping = new HashMap<>();
     private final HashMap<String, String> allColumnMapping = new HashMap<>();
 
+
     @Autowired
-    public LoanListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
-                                       final EntityManager entityManager) {
+    public EmployeeListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                           final EntityManager entityManager) {
         super();
         this.logger = logger;
         this.entityManager = entityManager;
@@ -58,16 +67,16 @@ public class LoanListReportSpecification implements ReportSpecification {
     @Override
     public ReportDefinition getReportDefinition() {
         final ReportDefinition reportDefinition = new ReportDefinition();
-        reportDefinition.setIdentifier("Listing");
-        reportDefinition.setName("Loan Account Listing");
-        reportDefinition.setDescription("List of all loan accounts.");
+        reportDefinition.setIdentifier("Employee");
+        reportDefinition.setName("Employee Listing");
+        reportDefinition.setDescription("List of all employees.");
         reportDefinition.setQueryParameters(this.buildQueryParameters());
         reportDefinition.setDisplayableFields(this.buildDisplayableFields());
         return reportDefinition;
     }
 
     @Override
-    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+    public ReportPage generateReport(final ReportRequest reportRequest, final int pageIndex, final int size) {
         final ReportDefinition reportDefinition = this.getReportDefinition();
         this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
 
@@ -76,13 +85,12 @@ public class LoanListReportSpecification implements ReportSpecification {
         reportPage.setDescription(reportDefinition.getDescription());
         reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
 
-        final Query customerQuery;
-        customerQuery = this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, pageIndex, size));
+        final Query customerQuery = this.entityManager.createNativeQuery(this.buildEmployeeQuery(reportRequest, pageIndex, size));
         final List<?> customerResultList =  customerQuery.getResultList();
         reportPage.setRows(this.buildRows(reportRequest, customerResultList));
 
         reportPage.setHasMore(
-                !this.entityManager.createNativeQuery(this.buildCustomerQuery(reportRequest, pageIndex + 1, size))
+                !this.entityManager.createNativeQuery(this.buildEmployeeQuery(reportRequest, pageIndex + 1, size))
                         .getResultList().isEmpty()
         );
 
@@ -92,7 +100,7 @@ public class LoanListReportSpecification implements ReportSpecification {
     }
 
     @Override
-    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+    public void validate(final ReportRequest reportRequest) throws IllegalArgumentException {
         final ArrayList<String> unknownFields =  new ArrayList<>();
         reportRequest.getQueryParameters().forEach(queryParameter -> {
             if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
@@ -114,29 +122,20 @@ public class LoanListReportSpecification implements ReportSpecification {
     }
 
     private void initializeMapping() {
-        this.customerColumnMapping.put(CUSTOMER, "cst.identifier");
-        this.customerColumnMapping.put(FIRST_NAME, "cst.given_name");
-        this.customerColumnMapping.put(MIDDLE_NAME, "cst.middle_name");
-        this.customerColumnMapping.put(LAST_NAME, "cst.surname");
-        this.customerColumnMapping.put(OFFICE, "cst.assigned_office");
-
-        this.loanColumnMapping.put(DATE_RANGE, "cases.created_on");
-        this.loanColumnMapping.put(LOAN_STATE, "cases.current_state");
-        this.loanColumnMapping.put(LOAN_TYPE, "cases.product_identifier");
-        this.loanColumnMapping.put(EMPLOYEE, "cases.created_by");
-        this.loanColumnMapping.put(LOAN_TERM,
-                "il_cases.term_range_temporal_unit, " +
-                "il_cases.term_range_minimum, " +
-                "il_cases.term_range_maximum, " +
-                "il_cases.balance_range_maximum");
-
-        this.loanColumnMapping.put(LOAN_ACCOUNT_NUMBER, "il_cases.case_id");
-
-        this.allColumnMapping.putAll(customerColumnMapping);
-        this.allColumnMapping.putAll(loanColumnMapping);
+        this.employeeColumnMapping.put(USERNAME, "he.identifier");
+        this.employeeColumnMapping.put(FIRST_NAME, "he.given_name");
+        this.employeeColumnMapping.put(MIDDLE_NAME, "he.middle_name");
+        this.employeeColumnMapping.put(LAST_NAME, "he.surname");
+        this.employeeColumnMapping.put(CREATED_BY, "he.created_by");
+        this.employeeColumnMapping.put(OFFICE, "he.assigned_office_id");
+
+        this.officeColumnMapping.put(OFFICE_NAME, "ho.a_name");
+
+        this.allColumnMapping.putAll(employeeColumnMapping);
+        this.allColumnMapping.putAll(officeColumnMapping);
     }
 
-    private Header createHeader(List<DisplayableField> displayableFields) {
+    private Header createHeader(final List<DisplayableField> displayableFields) {
         final Header header = new Header();
         header.setColumnNames(
                 displayableFields
@@ -147,20 +146,20 @@ public class LoanListReportSpecification implements ReportSpecification {
         return header;
     }
 
-    private List<Row> buildRows(ReportRequest reportRequest, List<?> customerResultList) {
+
+    private List<Row> buildRows(final ReportRequest reportRequest, final List<?> employeeResultList) {
         final ArrayList<Row> rows = new ArrayList<>();
 
-        customerResultList.forEach(result -> {
+        employeeResultList.forEach(result -> {
             final Row row = new Row();
             row.setValues(new ArrayList<>());
 
-            final String customerIdentifier;
+            final String officeIdentifier;
 
             if (result instanceof Object[]) {
-                final Object[] resultValues;
-                resultValues = (Object[]) result;
+                final Object[] resultValues = (Object[]) result;
 
-                customerIdentifier = resultValues[0].toString();
+                officeIdentifier = resultValues[0].toString();
 
                 for (final Object resultValue : resultValues) {
                     final Value value = new Value();
@@ -173,29 +172,21 @@ public class LoanListReportSpecification implements ReportSpecification {
                     row.getValues().add(value);
                 }
             } else {
-                customerIdentifier = result.toString();
+                officeIdentifier = result.toString();
 
                 final Value value = new Value();
                 value.setValues(new String[]{result.toString()});
                 row.getValues().add(value);
             }
 
-            final DecimalFormat decimalFormat = new DecimalFormat("0.00");
-            final Query accountQuery = this.entityManager.createNativeQuery(this.buildLoanAccountQuery(reportRequest, customerIdentifier));
-            final List<?> accountResultList = accountQuery.getResultList();
-            final ArrayList<String> values = new ArrayList<>();
-            accountResultList.forEach(accountResult -> {
-                if (accountResult instanceof Object[]) {
-                    final Object[] accountResultValues;
-                    accountResultValues = (Object[]) accountResult;
-                    final String accountValue = accountResultValues[0].toString() + " (" +
-                            decimalFormat.format(Double.valueOf(accountResultValues[1].toString())) + ")";
-                    values.add(accountValue);
-                }
-            });
-            final Value accountValue = new Value();
-            accountValue.setValues(values.toArray(new String[values.size()]));
-            row.getValues().add(accountValue);
+            final String officeQueryString = this.buildOfficeQuery(reportRequest, officeIdentifier);
+            if (officeQueryString != null) {
+                final Query officeQuery = this.entityManager.createNativeQuery(officeQueryString);
+                final List<?> resultList = officeQuery.getResultList();
+                final Value officeValue = new Value();
+                officeValue.setValues(new String[]{resultList.get(0).toString()});
+                row.getValues().add(officeValue);
+            }
 
             rows.add(row);
         });
@@ -203,36 +194,32 @@ public class LoanListReportSpecification implements ReportSpecification {
         return rows;
     }
 
-    private List<DisplayableField> buildDisplayableFields() {
+    private List<QueryParameter> buildQueryParameters() {
         return Arrays.asList(
-                DisplayableFieldBuilder.create(CUSTOMER, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LOAN_TYPE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LOAN_ACCOUNT_NUMBER, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LOAN_STATE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LOAN_TERM, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).build()
+                //QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                //QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
         );
     }
 
-    private List<QueryParameter> buildQueryParameters() {
+    private List<DisplayableField> buildDisplayableFields() {
         return Arrays.asList(
-                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
-                QueryParameterBuilder.create(LOAN_STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(USERNAME, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(CREATED_BY, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(OFFICE_NAME, Type.TEXT).mandatory().build()
         );
     }
 
-    private String buildCustomerQuery(final ReportRequest reportRequest, int pageIndex, int size){
+    private String buildEmployeeQuery(final ReportRequest reportRequest, int pageIndex, int size) {
         final StringBuilder query = new StringBuilder("SELECT ");
 
         final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
         final ArrayList<String> columns = new ArrayList<>();
         displayableFields.forEach(displayableField -> {
-            final String column;
-            column = this.customerColumnMapping.get(displayableField.getName());
+            final String column = this.employeeColumnMapping.get(displayableField.getName());
             if (column != null) {
                 columns.add(column);
             }
@@ -240,15 +227,15 @@ public class LoanListReportSpecification implements ReportSpecification {
 
         query.append(columns.stream().collect(Collectors.joining(", ")))
                 .append(" FROM ")
-                .append("maat_customers cst ");
+                .append("horus_employees he ");
 
         final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
         if (!queryParameters.isEmpty()) {
             final ArrayList<String> criteria = new ArrayList<>();
             queryParameters.forEach(queryParameter -> {
-                if((queryParameter.getValue() != null) && !queryParameter.getValue().isEmpty()) {
+                if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
                     criteria.add(
-                            CriteriaBuilder.buildCriteria(this.customerColumnMapping.get(queryParameter.getName()), queryParameter)
+                            CriteriaBuilder.buildCriteria(this.employeeColumnMapping.get(queryParameter.getName()), queryParameter)
                     );
                 }
             });
@@ -259,7 +246,7 @@ public class LoanListReportSpecification implements ReportSpecification {
             }
 
         }
-        query.append(" ORDER BY cst.identifier");
+        query.append(" ORDER BY he.identifier");
 
         query.append(" LIMIT ");
         query.append(size);
@@ -271,25 +258,21 @@ public class LoanListReportSpecification implements ReportSpecification {
         return query.toString();
     }
 
-    private String buildLoanAccountQuery(final ReportRequest reportRequest, final String customerIdentifier){
+    private String buildOfficeQuery(final ReportRequest reportRequest, final String officeIdentifier) {
         final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
         final ArrayList<String> columns = new ArrayList<>();
         displayableFields.forEach(displayableField -> {
-            final String column = this.loanColumnMapping.get(displayableField.getName());
+            final String column = this.officeColumnMapping.get(displayableField.getName());
             if (column != null) {
                 columns.add(column);
             }
         });
-
-        return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
-                "FROM bastet_il_cases il_cases " +
-                "LEFT JOIN maat_customers cst on il_cases.customer_identifier = cst.identifier " +
-                "WHERE cst.identifier ='" + customerIdentifier + "' " +
-                "ORDER BY il_cases.cases_id";
-    }
-
-    //Need this for getting details from cases table
-    private String buildLoanCaseQuery(final ReportRequest reportRequest, final String customerIdentifier){
+        if (!columns.isEmpty()) {
+        return "SELECT DISTINCT " + columns.get(0).toString() + " " +
+                "FROM horus_offices ho " +
+                "LEFT JOIN horus_employees he on ho.id = he.assigned_office_id " +
+                "WHERE he.assigned_office_id ='" + officeIdentifier + "' ";
+        }
         return null;
     }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
index 91669ec..00c6472 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
 
 import io.mifos.core.api.util.UserContextHolder;
@@ -10,6 +25,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
+import java.math.BigDecimal;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -50,7 +66,7 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
         final ReportDefinition reportDefinition = new ReportDefinition();
         reportDefinition.setIdentifier("Incomestatement");
         reportDefinition.setName("Income Statement");
-        reportDefinition.setDescription("Income statement listing.");
+        reportDefinition.setDescription("Income statement report");
         reportDefinition.setQueryParameters(this.buildQueryParameters());
         reportDefinition.setDisplayableFields(this.buildDisplayableFields());
         return reportDefinition;
@@ -127,7 +143,16 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
 
     private List<Row> buildRows(ReportRequest reportRequest, List<?> accountResultList) {
         final ArrayList<Row> rows = new ArrayList<>();
+        
+        final Row totalRevenueRow = new Row();
+        totalRevenueRow.setValues(new ArrayList<>());
+
+        final Value subRevenueTotal = new Value();
+
+        final BigDecimal[] revenueSubTotal = {new BigDecimal("0.000")};
+
         accountResultList.forEach(result -> {
+
             final Row row = new Row();
             row.setValues(new ArrayList<>());
 
@@ -135,28 +160,88 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
                 final Object[] resultValues;
                 resultValues = (Object[]) result;
 
-                for(final Object resultVal : resultValues) {
-                    final Value val;
-                    val = new Value();
+                for (int i = 0; i < resultValues.length; i++){
+                    final Value revValue = new Value();
+                    if (resultValues[i] != null){
+                        revValue.setValues(new String[]{resultValues[i].toString()});
+                    }else revValue.setValues(new String[]{});
+
+                    row.getValues().add(revValue);
+
+                    revenueSubTotal[0] = revenueSubTotal[0].add((BigDecimal)resultValues[3]);
 
-                    if (resultVal != null) {
-                        val.setValues(new String[]{resultVal.toString()});
-                    } else val.setValues(new String[]{});
-                    
-                    row.getValues().add(val);
                 }
             } else {
                 final Value value = new Value();
                 value.setValues(new String[]{result.toString()});
                 row.getValues().add(value);
             }
+
             rows.add(row);
         });
 
+        subRevenueTotal.setValues(new String[]{new StringBuilder().append("TOTAL REVENUES ").append(revenueSubTotal[0]).toString()});
+        totalRevenueRow.getValues().add(subRevenueTotal);
+
+        rows.add(totalRevenueRow);
+
+
+        final String expenseQueryString = this.buildExpenseQuery(reportRequest);
+        final Query expenseQuery = this.entityManager.createNativeQuery(expenseQueryString);
+        final List<?> expenseResultList = expenseQuery.getResultList();
+
+        final Row totalExpenseRow = new Row();
+        totalExpenseRow.setValues(new ArrayList<>());
+        final Value subExpenseTotal = new Value();
+
+        final Row netIncomeRow = new Row();
+        netIncomeRow.setValues(new ArrayList<>());
+        final Value netIncomeTotal = new Value();
+
+        final BigDecimal[] expenseSubTotal = {new BigDecimal("0.000")};
+
+        expenseResultList.forEach(result -> {
+
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues;
+                resultValues = (Object[]) result;
+
+                for (int i = 0; i < resultValues.length; i++){
+                    final Value expValue = new Value();
+                    if (resultValues[i] != null) expValue.setValues(new String[]{resultValues[i].toString()});
+                    else expValue.setValues(new String[]{});
+
+                    row.getValues().add(expValue);
+
+                    expenseSubTotal[0] = expenseSubTotal[0].add((BigDecimal)resultValues[3]);
+
+                }
+            } else {
+                final Value value;
+                value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
+            rows.add(row);
+        });
+
+        subExpenseTotal.setValues(new String[]{new StringBuilder().append("TOTAL EXPENSES ").append(expenseSubTotal[0]).toString()});
+        totalExpenseRow.getValues().add(subExpenseTotal);
+        rows.add(totalExpenseRow);
+
+        final BigDecimal netIncome = revenueSubTotal[0].subtract(expenseSubTotal[0]);
+        netIncomeTotal.setValues(new String[]{new StringBuilder().append("NET INCOME ").append(netIncome).toString()});
+        netIncomeRow.getValues().add(netIncomeTotal);
+        rows.add(netIncomeRow);
+
         return rows;
     }
 
-    private String buildAccountQuery(ReportRequest reportRequest, int pageIndex, int size) {
+    private String buildAccountQuery(final ReportRequest reportRequest, int pageIndex, int size) {
         final StringBuilder query = new StringBuilder("SELECT ");
 
         final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
@@ -170,52 +255,51 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
 
         query.append(columns.stream().collect(Collectors.joining(", ")))
                 .append(" FROM ")
-                .append("thoth_accounts acc ");
-
-        final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
-        if (!queryParameters.isEmpty()) {
-            final ArrayList<String> criteria = new ArrayList<>();
-            queryParameters.forEach(queryParameter -> {
-                if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
-                    criteria.add(
-                            CriteriaBuilder.buildCriteria(this.accountColumnMapping.get(queryParameter.getName()), queryParameter)
-                    );
-                }
-            });
+                .append("thoth_accounts acc ")
+                .append("WHERE acc.a_type = 'REVENUE' ");
+
+        query.append(" ORDER BY acc.identifier");
+
+        return query.toString();
+    }
+
+    private String buildExpenseQuery(final ReportRequest reportRequest) {
+        final StringBuilder query = new StringBuilder("SELECT ");
 
-            if (!criteria.isEmpty()) {
-                query.append(" WHERE ");
-                query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.accountColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
             }
+        });
 
-        }
-        query.append(" ORDER BY acc.identifier");
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("thoth_accounts acc ")
+                .append("WHERE acc.a_type = 'EXPENSE' ");
 
-        query.append(" LIMIT ");
-        query.append(size);
-        if (pageIndex > 0) {
-            query.append(" OFFSET ");
-            query.append(size * pageIndex);
-        }
+        query.append(" ORDER BY acc.identifier");
 
         return query.toString();
     }
 
     private List<DisplayableField> buildDisplayableFields() {
         return Arrays.asList(
-                DisplayableFieldBuilder.create(TYPE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(TYPE, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(IDENTIFIER, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(NAME, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(HOLDER, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(BALANCE, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(STATE, Type.TEXT).mandatory().build()
+                //DisplayableFieldBuilder.create(HOLDER, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(BALANCE, Type.TEXT).mandatory().build()
+               // DisplayableFieldBuilder.create(STATE, Type.TEXT).mandatory().build()
         );
     }
 
     private List<QueryParameter> buildQueryParameters() {
         return Arrays.asList(
-                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
-                QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+               // QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                //QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
         );
     }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
index 0b6509b..fcd6d8b 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
 
 import io.mifos.core.api.util.UserContextHolder;
@@ -11,7 +26,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
-import java.text.DecimalFormat;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -23,18 +37,22 @@ import java.util.stream.Collectors;
 @Report(category = "Loan", identifier = "Listing")
 public class LoanListReportSpecification implements ReportSpecification {
 
-    private static final String DATE_RANGE = "Date created";
+
     private static final String CUSTOMER = "Customer";
-    private static final String FIRST_NAME = "First name";
-    private static final String MIDDLE_NAME = "Middle name";
-    private static final String LAST_NAME = "Last name";
-    private static final String EMPLOYEE = "Employee";
-    private static final String LOAN_STATE = "State";
-    private static final String LOAN_ACCOUNT_NUMBER = "Account number";
-    private static final String LOAN_TYPE = "Account type";
-    private static final String LOAN_TERM = "Loan term";
+    private static final String FIRST_NAME = "First Name";
+    private static final String MIDDLE_NAME = "Middle Name";
+    private static final String LAST_NAME = "Last Name";
+    private static final String LOAN_TERM = "Loan Term";
+    private static final String TIME_UNIT = "Time Unit";
     private static final String OFFICE = "Office";
+    private static final String PRINCIPAL = "Principal";
+    private static final String CASE = "Case Id";
 
+    private static final String LOAN = "Loan";
+    private static final String PRODUCT = "Type";
+    private static final String STATE = "State";
+    private static final String DATE_RANGE = "Created On";
+    private static final String EMPLOYEE = "Created By";
 
     private final Logger logger;
 
@@ -42,8 +60,7 @@ public class LoanListReportSpecification implements ReportSpecification {
 
     private final HashMap<String, String> customerColumnMapping = new HashMap<>();
     private final HashMap<String, String> loanColumnMapping = new HashMap<>();
-    private final HashMap<String, String> officeColumnMapping = new HashMap<>();
-    private final HashMap<String, String> employeeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> caseColumnMapping = new HashMap<>();
     private final HashMap<String, String> allColumnMapping = new HashMap<>();
 
     @Autowired
@@ -120,20 +137,20 @@ public class LoanListReportSpecification implements ReportSpecification {
         this.customerColumnMapping.put(LAST_NAME, "cst.surname");
         this.customerColumnMapping.put(OFFICE, "cst.assigned_office");
 
-        this.loanColumnMapping.put(DATE_RANGE, "cases.created_on");
-        this.loanColumnMapping.put(LOAN_STATE, "cases.current_state");
-        this.loanColumnMapping.put(LOAN_TYPE, "cases.product_identifier");
-        this.loanColumnMapping.put(EMPLOYEE, "cases.created_by");
-        this.loanColumnMapping.put(LOAN_TERM,
-                "il_cases.term_range_temporal_unit, " +
-                "il_cases.term_range_minimum, " +
-                "il_cases.term_range_maximum, " +
-                "il_cases.balance_range_maximum");
+        this.loanColumnMapping.put(LOAN_TERM, "il_cases.term_range_maximum");
+        this.loanColumnMapping.put(TIME_UNIT, "il_cases.term_range_temporal_unit");
+        this.loanColumnMapping.put(PRINCIPAL, "il_cases.balance_range_maximum");
+        this.loanColumnMapping.put(CASE, "il_cases.case_id");
 
-        this.loanColumnMapping.put(LOAN_ACCOUNT_NUMBER, "il_cases.case_id");
+        this.caseColumnMapping.put(LOAN, "cases.identifier");
+        this.caseColumnMapping.put(PRODUCT, "cases.product_identifier");
+        this.caseColumnMapping.put(STATE, "cases.current_state");
+        this.caseColumnMapping.put(DATE_RANGE, "cases.created_on");
+        this.caseColumnMapping.put(EMPLOYEE, "cases.created_by");
 
         this.allColumnMapping.putAll(customerColumnMapping);
         this.allColumnMapping.putAll(loanColumnMapping);
+        this.allColumnMapping.putAll(caseColumnMapping);
     }
 
     private Header createHeader(List<DisplayableField> displayableFields) {
@@ -180,22 +197,55 @@ public class LoanListReportSpecification implements ReportSpecification {
                 row.getValues().add(value);
             }
 
-            final DecimalFormat decimalFormat = new DecimalFormat("0.00");
             final Query accountQuery = this.entityManager.createNativeQuery(this.buildLoanAccountQuery(reportRequest, customerIdentifier));
             final List<?> accountResultList = accountQuery.getResultList();
-            final ArrayList<String> values = new ArrayList<>();
+
             accountResultList.forEach(accountResult -> {
+
+                final String caseIdentifier;
+
                 if (accountResult instanceof Object[]) {
                     final Object[] accountResultValues;
                     accountResultValues = (Object[]) accountResult;
-                    final String accountValue = accountResultValues[0].toString() + " (" +
-                            decimalFormat.format(Double.valueOf(accountResultValues[1].toString())) + ")";
-                    values.add(accountValue);
+
+                    caseIdentifier = accountResultValues[0].toString();
+
+                    for (final Object loan: accountResultValues) {
+                        final Value value = new Value();
+                        if (loan != null) {
+                            value.setValues(new String[]{loan.toString()});
+                        } else {
+                            value.setValues(new String[]{});
+                        }
+
+                        row.getValues().add(value);
+                    }
+                }else {
+                    caseIdentifier = accountResult.toString();
+
+                    final Value value = new Value();
+                    value.setValues(new String[]{accountResult.toString()});
+                    row.getValues().add(value);
                 }
+
+                final Query caseQuery = this.entityManager.createNativeQuery(this.buildCaseQuery(reportRequest, caseIdentifier));
+
+                final List<?> caseResultList = caseQuery.getResultList();
+
+                caseResultList.forEach(loanCase -> {
+                    final Object[] loanCaseResultValues = (Object[]) loanCase;
+
+                    for (final Object loan : loanCaseResultValues) {
+                        final Value value = new Value();
+                        if (loan != null) {
+                            value.setValues(new String[]{loan.toString()});
+                        } else {
+                            value.setValues(new String[]{});
+                        }
+                        row.getValues().add(value);
+                    }
+                });
             });
-            final Value accountValue = new Value();
-            accountValue.setValues(values.toArray(new String[values.size()]));
-            row.getValues().add(accountValue);
 
             rows.add(row);
         });
@@ -206,22 +256,27 @@ public class LoanListReportSpecification implements ReportSpecification {
     private List<DisplayableField> buildDisplayableFields() {
         return Arrays.asList(
                 DisplayableFieldBuilder.create(CUSTOMER, Type.TEXT).mandatory().build(),
-                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).mandatory().build(),
                 DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LOAN_TYPE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LOAN_ACCOUNT_NUMBER, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LOAN_STATE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(LOAN_TERM, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).build(),
-                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).build()
+                DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(CASE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(PRINCIPAL, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(LOAN_TERM, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(TIME_UNIT, Type.TEXT).mandatory().build(),
+
+                DisplayableFieldBuilder.create(LOAN, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(STATE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(PRODUCT, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(DATE_RANGE, Type.TEXT).mandatory().build()
         );
     }
 
     private List<QueryParameter> buildQueryParameters() {
         return Arrays.asList(
-                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
-                QueryParameterBuilder.create(LOAN_STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+                //QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build()
+                //QueryParameterBuilder.create(LOAN_STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
         );
     }
 
@@ -285,11 +340,22 @@ public class LoanListReportSpecification implements ReportSpecification {
                 "FROM bastet_il_cases il_cases " +
                 "LEFT JOIN maat_customers cst on il_cases.customer_identifier = cst.identifier " +
                 "WHERE cst.identifier ='" + customerIdentifier + "' " +
-                "ORDER BY il_cases.cases_id";
+                "ORDER BY il_cases.case_id";
     }
 
-    //Need this for getting details from cases table
-    private String buildLoanCaseQuery(final ReportRequest reportRequest, final String customerIdentifier){
-        return null;
+    private String buildCaseQuery(final ReportRequest reportRequest, final String caseIdentifier){
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.caseColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
+                "FROM bastet_cases cases " +
+                "LEFT JOIN bastet_il_cases il_cases on cases.id = il_cases.case_id " +
+                "WHERE il_cases.case_id ='" + caseIdentifier + "' ";
     }
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
new file mode 100644
index 0000000..9b06000
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
+
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.DateConverter;
+import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.*;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.time.Clock;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+@Report(category = "Organization", identifier = "Office")
+public class OfficeListReportSpecification implements ReportSpecification {
+
+    private static final String OFFICE = "Identifier";
+    private static final String OFFICE_NAME = "Office";
+    private static final String DESCRIPTION = "Description";
+    private static final String CREATED_BY = "Created By";
+   // private static final String STREET = "Street";
+    //private static final String CITY = "City";
+   // private static final String REGION = "Region";
+   // private static final String POSTAL_CODE = "Postal Code";
+   // private static final String COUNTRY = "Country";
+    private static final String ADDRESS = "Address";
+
+    private final Logger logger;
+
+    private final EntityManager entityManager;
+    private final HashMap<String, String> officeColumnMapping = new HashMap<>();
+    private final HashMap<String, String> addressColumnMapping = new HashMap<>();
+    private final HashMap<String, String> allColumnMapping = new HashMap<>();
+
+    @Autowired
+    public OfficeListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                           final EntityManager entityManager) {
+        super();
+        this.logger = logger;
+        this.entityManager = entityManager;
+        this.initializeMapping();
+    }
+
+    @Override
+    public ReportDefinition getReportDefinition() {
+        final ReportDefinition reportDefinition = new ReportDefinition();
+        reportDefinition.setIdentifier("Office");
+        reportDefinition.setName("Office Listing");
+        reportDefinition.setDescription("List of all Offices.");
+        reportDefinition.setQueryParameters(this.buildQueryParameters());
+        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+        return reportDefinition;
+    }
+
+    @Override
+    public ReportPage generateReport(final ReportRequest reportRequest, final int pageIndex, final int size) {
+        final ReportDefinition reportDefinition = this.getReportDefinition();
+        this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
+
+        final ReportPage reportPage = new ReportPage();
+        reportPage.setName(reportDefinition.getName());
+        reportPage.setDescription(reportDefinition.getDescription());
+        reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
+
+        final Query customerQuery = this.entityManager.createNativeQuery(this.buildOfficeQuery(reportRequest, pageIndex, size));
+        final List<?> customerResultList =  customerQuery.getResultList();
+        reportPage.setRows(this.buildRows(reportRequest, customerResultList));
+
+        reportPage.setHasMore(
+                !this.entityManager.createNativeQuery(this.buildOfficeQuery(reportRequest, pageIndex + 1, size))
+                        .getResultList().isEmpty()
+        );
+
+        reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
+        reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+        return reportPage;
+    }
+
+    @Override
+    public void validate(final ReportRequest reportRequest) throws IllegalArgumentException {
+        final ArrayList<String> unknownFields =  new ArrayList<>();
+        reportRequest.getQueryParameters().forEach(queryParameter -> {
+            if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
+                unknownFields.add(queryParameter.getName());
+            }
+        });
+
+        reportRequest.getDisplayableFields().forEach(displayableField -> {
+            if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
+                unknownFields.add(displayableField.getName());
+            }
+        });
+
+        if (!unknownFields.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
+            );
+        }
+    }
+
+    private void initializeMapping() {
+        this.officeColumnMapping.put(OFFICE, "ho.id");
+        this.officeColumnMapping.put(OFFICE_NAME, "ho.a_name");
+        this.officeColumnMapping.put(DESCRIPTION, "ho.description");
+        this.officeColumnMapping.put(CREATED_BY, "ho.created_by");
+
+        this.addressColumnMapping.put(ADDRESS, "CONCAT(IFNULL(ha.street, ', '), " +
+                "IFNULL(ha.postal_code, ', '), IFNULL(ha.city, ', ')," +
+                " IFNULL(ha.region, ', '), IFNULL(ha.country, ','))");
+
+        this.allColumnMapping.putAll(officeColumnMapping);
+        this.allColumnMapping.putAll(addressColumnMapping);
+    }
+
+    private Header createHeader(final List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+    private List<QueryParameter> buildQueryParameters() {
+        return Arrays.asList(
+                //QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                //QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+        );
+    }
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return Arrays.asList(
+                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(OFFICE_NAME, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(DESCRIPTION, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(CREATED_BY, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(ADDRESS, Type.TEXT).mandatory().build()
+        );
+    }
+
+    private List<Row> buildRows(final ReportRequest reportRequest, final List<?> officeResultList) {
+        final ArrayList<Row> rows = new ArrayList<>();
+
+        officeResultList.forEach(result -> {
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            final String officeIdentifier;
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues = (Object[]) result;
+
+                officeIdentifier = resultValues[0].toString();
+
+                for (final Object resultValue : resultValues) {
+                    final Value value = new Value();
+                    if (resultValue != null) {
+                        value.setValues(new String[]{resultValue.toString()});
+                    } else {
+                        value.setValues(new String[]{});
+                    }
+
+                    row.getValues().add(value);
+                }
+            } else {
+                officeIdentifier = result.toString();
+
+                final Value value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
+            final String addressQueryString = this.buildAddressQuery(reportRequest, officeIdentifier);
+            if (addressQueryString != null) {
+                final Query addressQuery = this.entityManager.createNativeQuery(addressQueryString);
+                final List<?> resultList = addressQuery.getResultList();
+                final Value addressValue = new Value();
+                addressValue.setValues(new String[]{resultList.get(0).toString()});
+                row.getValues().add(addressValue);
+            }
+
+            rows.add(row);
+        });
+
+        return rows;
+    }
+
+    private String buildOfficeQuery(final ReportRequest reportRequest, int pageIndex, int size) {
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.officeColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("horus_offices ho ");
+
+        final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
+        if (!queryParameters.isEmpty()) {
+            final ArrayList<String> criteria = new ArrayList<>();
+            queryParameters.forEach(queryParameter -> {
+                if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
+                    criteria.add(
+                            CriteriaBuilder.buildCriteria(this.officeColumnMapping.get(queryParameter.getName()), queryParameter)
+                    );
+                }
+            });
+
+            if (!criteria.isEmpty()) {
+                query.append(" WHERE ");
+                query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+            }
+
+        }
+        query.append(" ORDER BY ho.a_name");
+
+        query.append(" LIMIT ");
+        query.append(size);
+        if (pageIndex > 0) {
+            query.append(" OFFSET ");
+            query.append(size * pageIndex);
+        }
+
+        return query.toString();
+    }
+
+    private String buildAddressQuery(final ReportRequest reportRequest, final String officeIdentifier) {
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.addressColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        if (!columns.isEmpty()) {
+            return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
+                    "FROM horus_addresses ha " +
+                    "LEFT JOIN horus_offices ho on ha.office_id = ho.id " +
+                    "WHERE ho.id ='" + officeIdentifier + "' ";
+        }
+        return null;
+    }
+}
+
+
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerCashierDailyBalanceReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerCashierDailyBalanceReportSpecification.java
deleted file mode 100644
index 591351e..0000000
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerCashierDailyBalanceReportSpecification.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.*;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import java.util.List;
-
-@Report(category = "Teller" , identifier = "Transaction")
-public class TellerCashierDailyBalanceReportSpecification implements ReportSpecification {
-
-    private static final String TOTAL_CASH_ON_HAND = "Cash on hand";
-    private static final String TOTAL_CASH_RECEIVED = "Cash received";
-    private static final String TOTAL_CASH_DISBURSED = "Cash Disbursed";
-    private static final String TOTAL_NEGOTIABLE_INSTRUMENT_RECEIVED = "Negotiable instrument received";
-    private static final String TOTAL_CHEQUES_RECEIVED = "Total cheques received";
-    private static final String TELLER = "Teller";
-    private static final String EMPLOYEE = "Employee";
-    private static final String OFFICE = "Office";
-    private static final String CASHDRAW_LIMIT = "Cashdraw limit";
-
-    private final Logger logger;
-
-    private final EntityManager entityManager;
-
-    @Autowired
-    public TellerCashierDailyBalanceReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
-                                           final EntityManager entityManager) {
-        super();
-        this.logger = logger;
-        this.entityManager = entityManager;
-        this.initializeMapping();
-    }
-
-    private void initializeMapping() {
-    }
-
-    @Override
-    public ReportDefinition getReportDefinition() {
-        final ReportDefinition reportDefinition = new ReportDefinition();
-        reportDefinition.setIdentifier("Transactions");
-        reportDefinition.setName("Teller transactions");
-        reportDefinition.setDescription("List total teller/cashier transactions.");
-        reportDefinition.setQueryParameters(this.buildQueryParameters());
-        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
-        return reportDefinition;
-    }
-
-    private List<DisplayableField> buildDisplayableFields() {
-        return null;
-    }
-
-    private List<QueryParameter> buildQueryParameters() {
-
-        return null;
-    }
-
-    @Override
-    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
-        return null;
-    }
-
-    @Override
-    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
-
-    }
-}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
index 9c854e0..7f33edb 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
 
 import io.mifos.core.api.util.UserContextHolder;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
new file mode 100644
index 0000000..e24f622
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.specification;
+
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.DateConverter;
+import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.service.ServiceConstants;
+import io.mifos.reporting.service.spi.*;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.time.Clock;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Report(category = "Teller", identifier = "Transactions")
+public class TellerTransactionReportSpecification implements ReportSpecification {
+
+    private static final String TELLER_ID = "Teller Id";
+    private static final String TELLER = "Teller";
+    private static final String TRANSACTION_TYPE = "Transaction Type";
+    private static final String TRANSACTION_DATE = "Transaction Date";
+    private static final String CUSTOMER = "Customer";
+    private static final String SOURCE = "Source Account";
+    private static final String TARGET = "Target Account";
+    private static final String CLERK = "Clerk";
+    private static final String AMOUNT = "Amount";
+    private static final String STATUS = "Status";
+
+    private final Logger logger;
+
+    private final EntityManager entityManager;
+    private final HashMap<String, String> tellerColumnMapping = new HashMap<>();
+    private final HashMap<String, String> transactionColumnMapping = new HashMap<>();
+    private final HashMap<String, String> allColumnMapping = new HashMap<>();
+
+    @Autowired
+    public TellerTransactionReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                                final EntityManager entityManager) {
+        super();
+        this.logger = logger;
+        this.entityManager = entityManager;
+        this.initializeMapping();
+    }
+
+    @Override
+    public ReportDefinition getReportDefinition() {
+        final ReportDefinition reportDefinition = new ReportDefinition();
+        reportDefinition.setIdentifier("Transactions");
+        reportDefinition.setName("Teller Transactions");
+        reportDefinition.setDescription("List all teller-cashier transactions.");
+        reportDefinition.setQueryParameters(this.buildQueryParameters());
+        reportDefinition.setDisplayableFields(this.buildDisplayableFields());
+        return reportDefinition;
+    }
+
+
+    @Override
+    public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
+        final ReportDefinition reportDefinition = this.getReportDefinition();
+        this.logger.info("Generating report {0}.", reportDefinition.getIdentifier());
+
+        final ReportPage reportPage = new ReportPage();
+        reportPage.setName(reportDefinition.getName());
+        reportPage.setDescription(reportDefinition.getDescription());
+        reportPage.setHeader(this.createHeader(reportRequest.getDisplayableFields()));
+
+        final Query tellerQuery = this.entityManager.createNativeQuery(this.buildTellerQuery(reportRequest, pageIndex, size));
+        final List<?> tellerResultList = tellerQuery.getResultList();
+        reportPage.setRows(this.buildRows(reportRequest, tellerResultList));
+
+        reportPage.setHasMore(
+                !this.entityManager.createNativeQuery(this.buildTellerQuery(reportRequest, pageIndex + 1, size))
+                        .getResultList().isEmpty()
+        );
+
+        reportPage.setGeneratedBy(UserContextHolder.checkedGetUser());
+        reportPage.setGeneratedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+        return reportPage;
+    }
+
+    @Override
+    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
+        final ArrayList<String> unknownFields = new ArrayList<>();
+        reportRequest.getQueryParameters().forEach(queryParameter -> {
+            if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
+                unknownFields.add(queryParameter.getName());
+            }
+        });
+
+        reportRequest.getDisplayableFields().forEach(displayableField -> {
+            if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
+                unknownFields.add(displayableField.getName());
+            }
+        });
+
+        if (!unknownFields.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
+            );
+        }
+    }
+
+
+    private void initializeMapping() {
+        this.tellerColumnMapping.put(TELLER_ID, "teller.id");
+        this.tellerColumnMapping.put(TELLER, "teller.identifier");
+
+        this.transactionColumnMapping.put(TRANSACTION_TYPE, "trx.transaction_type");
+        this.transactionColumnMapping.put(TRANSACTION_DATE, "trx.transaction_date");
+        this.transactionColumnMapping.put(CUSTOMER, "trx.customer_identifier");
+        this.transactionColumnMapping.put(SOURCE, "trx.customer_account_identifier");
+        this.transactionColumnMapping.put(TARGET, "trx.target_account_identifier");
+        this.transactionColumnMapping.put(CLERK, "trx.clerk");
+        this.transactionColumnMapping.put(AMOUNT, "trx.amount");
+        this.transactionColumnMapping.put(STATUS, "trx.a_state");
+
+        this.allColumnMapping.putAll(tellerColumnMapping);
+        this.allColumnMapping.putAll(transactionColumnMapping);
+
+    }
+
+
+    private Header createHeader(final List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+
+    private List<Row> buildRows(ReportRequest reportRequest, List<?> tellerResultList) {
+        final ArrayList<Row> rows = new ArrayList<>();
+
+        tellerResultList.forEach(result -> {
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            final String tellerIdentifier;
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues = (Object[]) result;
+
+                tellerIdentifier = resultValues[0].toString();
+
+                for (final Object resultValue : resultValues) {
+                    final Value value = new Value();
+                    if (resultValue != null) {
+                        value.setValues(new String[]{resultValue.toString()});
+                    } else {
+                        value.setValues(new String[]{});
+                    }
+
+                    row.getValues().add(value);
+                }
+            } else {
+                tellerIdentifier = result.toString();
+
+                final Value value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+
+            final String transactionQueryString = this.buildTellerTransactionQuery(reportRequest, tellerIdentifier);
+
+            final Query transactionQuery = this.entityManager.createNativeQuery(transactionQueryString);
+            final List<?> resultList = transactionQuery.getResultList();
+
+            final ArrayList<String> transactionType = new ArrayList<>();
+            final ArrayList<String> transactionDate = new ArrayList<>();
+            final ArrayList<String> customer = new ArrayList<>();
+            final ArrayList<String> source = new ArrayList<>();
+            final ArrayList<String> target = new ArrayList<>();
+            final ArrayList<String> clerk = new ArrayList<>();
+            final ArrayList<String> amount = new ArrayList<>();
+            final ArrayList<String> status = new ArrayList<>();
+            resultList.forEach(transaction -> {
+                        final Object[] transactionValue = (Object[]) transaction;
+
+                        for (int i = 0; i < transactionValue.length; i++) {
+                            if (i == 0 && transactionValue[0] != null) {
+                                transactionType.add(transactionValue[0].toString());
+                            }
+
+                            if (i == 1 && transactionValue[1] != null) {
+                                transactionDate.add(transactionValue[1].toString());
+                            }
+
+                            if (i == 2 && transactionValue[2] != null) {
+                                customer.add(transactionValue[2].toString());
+                            }
+
+                            if (i == 3 && transactionValue[3] != null) {
+                                source.add(transactionValue[3].toString());
+                            }
+
+                            if (i == 4 && transactionValue[4] != null) {
+                                target.add(transactionValue[4].toString());
+                            }
+                            if (i == 5 && transactionValue[5] != null) {
+                                clerk.add(transactionValue[5].toString());
+                            }
+                            if (i == 6 && transactionValue[6] != null) {
+                                amount.add(transactionValue[6].toString());
+                            }
+                            if (i == 7 && transactionValue[7] != null) {
+                                status.add(transactionValue[7].toString());
+                            }
+                        }
+                    }
+            );
+
+            final Value transactionTypeValue = new Value();
+            transactionTypeValue.setValues(transactionType.toArray(new String[transactionType.size()]));
+            row.getValues().add(transactionTypeValue);
+
+            final Value transactionDateValue = new Value();
+            transactionDateValue.setValues(transactionDate.toArray(new String[transactionDate.size()]));
+            row.getValues().add(transactionDateValue);
+
+            final Value customerValue = new Value();
+            customerValue.setValues(customer.toArray(new String[customer.size()]));
+            row.getValues().add(customerValue);
+
+            final Value sourceValue = new Value();
+            sourceValue.setValues(source.toArray(new String[source.size()]));
+            row.getValues().add(sourceValue);
+
+            final Value targetValue = new Value();
+            targetValue.setValues(target.toArray(new String[target.size()]));
+            row.getValues().add(targetValue);
+
+            final Value clerkValue = new Value();
+            clerkValue.setValues(clerk.toArray(new String[clerk.size()]));
+            row.getValues().add(clerkValue);
+
+            final Value amountValue = new Value();
+            amountValue.setValues(amount.toArray(new String[amount.size()]));
+            row.getValues().add(amountValue);
+
+            final Value statusValue = new Value();
+            statusValue.setValues(status.toArray(new String[status.size()]));
+            row.getValues().add(statusValue);
+
+            rows.add(row);
+        });
+
+        return rows;
+    }
+
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return Arrays.asList(
+                DisplayableFieldBuilder.create(TELLER_ID, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(TELLER, Type.TEXT).mandatory().build(),
+
+                DisplayableFieldBuilder.create(TRANSACTION_TYPE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(TRANSACTION_DATE, Type.DATE).mandatory().build(),
+                DisplayableFieldBuilder.create(CUSTOMER, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(SOURCE, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(TARGET, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(CLERK, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(AMOUNT, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(STATUS, Type.TEXT).mandatory().build()
+        );
+    }
+
+    private List<QueryParameter> buildQueryParameters() {
+        return Arrays.asList(
+                QueryParameterBuilder.create(TRANSACTION_DATE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                QueryParameterBuilder.create(STATUS, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+        );
+    }
+
+    private String buildTellerQuery(ReportRequest reportRequest, int pageIndex, int size) {
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.tellerColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("tajet_teller teller ");
+
+        query.append(" ORDER BY teller.id");
+
+        query.append(" LIMIT ");
+        query.append(size);
+        if (pageIndex > 0) {
+            query.append(" OFFSET ");
+            query.append(size * pageIndex);
+        }
+
+        return query.toString();
+    }
+
+    private String buildTellerTransactionQuery(final ReportRequest reportRequest, final String tellerIdentifier) {
+
+        final StringBuilder query = new StringBuilder("SELECT ");
+
+        final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
+        final ArrayList<String> columns = new ArrayList<>();
+        displayableFields.forEach(displayableField -> {
+            final String column = this.transactionColumnMapping.get(displayableField.getName());
+            if (column != null) {
+                columns.add(column);
+            }
+        });
+
+        query.append(columns.stream().collect(Collectors.joining(", ")))
+                .append(" FROM ")
+                .append("tajet_teller_transactions trx " +
+                        "LEFT JOIN tajet_teller teller on trx.teller_id = teller.id ");
+
+        query.append("WHERE teller.id ='" + tellerIdentifier + "'");
+
+        final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
+        if (!queryParameters.isEmpty()) {
+            final ArrayList<String> criteria = new ArrayList<>();
+            queryParameters.forEach(queryParameter -> {
+                if (queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
+                    criteria.add(
+                            CriteriaBuilder.buildCriteria(this.transactionColumnMapping.get(queryParameter.getName()), queryParameter)
+                    );
+                }
+            });
+
+            if (!criteria.isEmpty()) {
+                query.append(" AND ");
+                query.append(criteria.stream().collect(Collectors.joining(" AND ")));
+            }
+
+        }
+
+        return query.toString();
+    }
+
+
+}
diff --git a/service/src/main/resources/ESAPI.properties b/service/src/main/resources/ESAPI.properties
index 1dedfe6..d9a26e3 100644
--- a/service/src/main/resources/ESAPI.properties
+++ b/service/src/main/resources/ESAPI.properties
@@ -1,54 +1,18 @@
 #
-# OWASP Enterprise Security API (ESAPI) Properties file -- PRODUCTION Version
-#
-# This file is part of the Open Web Application Security Project (OWASP)
-# Enterprise Security API (ESAPI) project. For details, please see
-# http://www.owasp.org/index.php/ESAPI.
-#
-# Copyright (c) 2008,2009 - The OWASP Foundation
-#
-# DISCUSS: This may cause a major backwards compatibility issue, etc. but
-#		   from a name space perspective, we probably should have prefaced
-#		   all the property names with ESAPI or at least OWASP. Otherwise
-#		   there could be problems is someone loads this properties file into
-#		   the System properties.  We could also put this file into the
-#		   esapi.jar file (perhaps as a ResourceBundle) and then allow an external
-#		   ESAPI properties be defined that would overwrite these defaults.
-#		   That keeps the application's properties relatively simple as usually
-#		   they will only want to override a few properties. If looks like we
-#		   already support multiple override levels of this in the
-#		   DefaultSecurityConfiguration class, but I'm suggesting placing the
-#		   defaults in the esapi.jar itself. That way, if the jar is signed,
-#		   we could detect if those properties had been tampered with. (The
-#		   code to check the jar signatures is pretty simple... maybe 70-90 LOC,
-#		   but off course there is an execution penalty (similar to the way
-#		   that the separate sunjce.jar used to be when a class from it was
-#		   first loaded). Thoughts?
-###############################################################################
-#
-# WARNING: Operating system protection should be used to lock down the .esapi
-# resources directory and all the files inside and all the directories all the
-# way up to the root directory of the file system.  Note that if you are using
-# file-based implementations, that some files may need to be read-write as they
-# get updated dynamically.
-#
-# Before using, be sure to update the MasterKey and MasterSalt as described below.
-# N.B.: If you had stored data that you have previously encrypted with ESAPI 1.4,
-#		you *must* FIRST decrypt it using ESAPI 1.4 and then (if so desired)
-#		re-encrypt it with ESAPI 2.0. If you fail to do this, you will NOT be
-#		able to decrypt your data with ESAPI 2.0.
-#
-#		YOU HAVE BEEN WARNED!!! More details are in the ESAPI 2.0 Release Notes.
+# Copyright 2017 The Mifos Initiative.
+#
+# Licensed 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.
 #
-#===========================================================================
-# ESAPI Configuration
-#
-# If true, then print all the ESAPI properties set here when they are loaded.
-# If false, they are not printed. Useful to reduce output when running JUnit tests.
-# If you need to troubleshoot a properties related problem, turning this on may help.
-# This is 'false' in the src/test/resources/.esapi version. It is 'true' by
-# default for reasons of backward compatibility with earlier ESAPI versions.
-ESAPI.printProperties=true
 
 # ESAPI is designed to be easily extensible. You can use the reference implementation
 # or implement your own providers to take advantage of your enterprise's security
diff --git a/service/src/main/resources/validation.properties b/service/src/main/resources/validation.properties
index 0e9e2d3..02dea07 100644
--- a/service/src/main/resources/validation.properties
+++ b/service/src/main/resources/validation.properties
@@ -1,3 +1,19 @@
+#
+# Copyright 2017 The Mifos Initiative.
+#
+# Licensed 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.
+#
+
 # The ESAPI validator does many security checks on input, such as canonicalization
 # and whitelist validation. Note that all of these validation rules are applied *after*
 # canonicalization. Double-encoded characters (even with different encodings involved,
@@ -22,7 +38,7 @@
 #
 
 Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$
-# 2 majuscules, 3 minuscules, 2 chiffres, 1 caract�re sp�cial,
+# 2 majuscules, 3 minuscules, 2 chiffres, 1 caract�re sp�cial,
 Validator.Password=^(?=.*[A-Z].*[A-Z])(?=.*[.:,;-_+"'?!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8,20}$
 Validator.Digit=^[0-9]{1,20}$
 Validator.Email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$


[fineract-cn-reporting] 33/47: Adjusting to package name changes in upstream repositories.

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit e6aec098f6ecadc99aa29c41ad8e0fdfdf470e1b
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Apr 16 15:07:08 2018 +0200

    Adjusting to package name changes in upstream repositories.
---
 .../reporting/api/v1/client/ReportManager.java     | 12 +++------
 .../AbstractReportingSpecificationTest.java        | 17 ++++++------
 .../reporting/service/ReportingConfiguration.java  | 14 +++++-----
 .../BalanceSheetReportSpecification.java           | 27 ++++++++++++-------
 .../CustomerListReportSpecification.java           | 15 +++++------
 .../DepositListReportSpecification.java            | 31 +++++++++++++++-------
 .../IncomeStatementReportSpecification.java        | 27 ++++++++++++-------
 .../specification/LoanListReportSpecification.java | 30 ++++++++++++++-------
 .../OfficeListReportSpecification.java             | 30 ++++++++++++++-------
 .../TellerListReportSpecification.java             | 31 +++++++++++++++-------
 .../TellerTransactionReportSpecification.java      | 31 +++++++++++++++-------
 .../service/rest/ReportingRestController.java      | 17 ++++++------
 12 files changed, 173 insertions(+), 109 deletions(-)

diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
index 4f78218..0bcd6af 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
@@ -18,26 +18,22 @@
  */
 package io.mifos.reporting.api.v1.client;
 
-import io.mifos.core.api.annotation.ThrowsException;
-import io.mifos.core.api.annotation.ThrowsExceptions;
-import io.mifos.core.api.util.CustomFeignClientsConfiguration;
-import io.mifos.core.lang.ServiceException;
-import io.mifos.reporting.api.v1.PermittableGroupIds;
 import io.mifos.reporting.api.v1.domain.ReportDefinition;
 import io.mifos.reporting.api.v1.domain.ReportPage;
 import io.mifos.reporting.api.v1.domain.ReportRequest;
+import java.util.List;
+import org.apache.fineract.cn.api.annotation.ThrowsException;
+import org.apache.fineract.cn.api.annotation.ThrowsExceptions;
+import org.apache.fineract.cn.api.util.CustomFeignClientsConfiguration;
 import org.springframework.cloud.netflix.feign.FeignClient;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 
-import java.util.List;
-
 @SuppressWarnings("unused")
 @FeignClient(value="reporting-v1", path="/reporting/v1", configuration = CustomFeignClientsConfiguration.class)
 public interface ReportManager {
diff --git a/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java b/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
index b6282d9..b6d3012 100644
--- a/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
+++ b/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
@@ -18,15 +18,16 @@
  */
 package io.mifos.reporting;
 
-import io.mifos.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
-import io.mifos.core.api.context.AutoUserContext;
-import io.mifos.core.lang.ApplicationName;
-import io.mifos.core.test.env.TestEnvironment;
-import io.mifos.core.test.fixture.TenantDataStoreContextTestRule;
-import io.mifos.core.test.fixture.cassandra.CassandraInitializer;
-import io.mifos.core.test.fixture.mariadb.MariaDBInitializer;
 import io.mifos.reporting.api.v1.client.ReportManager;
 import io.mifos.reporting.service.ReportingConfiguration;
+import java.security.interfaces.RSAPrivateKey;
+import org.apache.fineract.cn.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
+import org.apache.fineract.cn.api.context.AutoUserContext;
+import org.apache.fineract.cn.lang.ApplicationName;
+import org.apache.fineract.cn.test.env.TestEnvironment;
+import org.apache.fineract.cn.test.fixture.TenantDataStoreContextTestRule;
+import org.apache.fineract.cn.test.fixture.cassandra.CassandraInitializer;
+import org.apache.fineract.cn.test.fixture.mariadb.MariaDBInitializer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
@@ -46,8 +47,6 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.test.context.junit4.SpringRunner;
 
-import java.security.interfaces.RSAPrivateKey;
-
 @RunWith(SpringRunner.class)
 @SpringBootTest(
     webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
index cf7708c..77310e3 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
@@ -18,13 +18,13 @@
  */
 package io.mifos.reporting.service;
 
-import io.mifos.anubis.config.EnableAnubis;
-import io.mifos.core.cassandra.config.EnableCassandra;
-import io.mifos.core.command.config.EnableCommandProcessing;
-import io.mifos.core.lang.config.EnableApplicationName;
-import io.mifos.core.lang.config.EnableServiceException;
-import io.mifos.core.lang.config.EnableTenantContext;
-import io.mifos.core.mariadb.config.EnableMariaDB;
+import org.apache.fineract.cn.anubis.config.EnableAnubis;
+import org.apache.fineract.cn.cassandra.config.EnableCassandra;
+import org.apache.fineract.cn.command.config.EnableCommandProcessing;
+import org.apache.fineract.cn.lang.config.EnableApplicationName;
+import org.apache.fineract.cn.lang.config.EnableServiceException;
+import org.apache.fineract.cn.lang.config.EnableTenantContext;
+import org.apache.fineract.cn.mariadb.config.EnableMariaDB;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
index aed5953..0723acc 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
@@ -18,16 +18,19 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
-import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Header;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Row;
+import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.api.v1.domain.Value;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.*;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
+import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
 import java.math.BigDecimal;
 import java.time.Clock;
 import java.time.LocalDateTime;
@@ -36,6 +39,12 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 @Report(category = "Accounting", identifier = "Balancesheet")
 public class BalanceSheetReportSpecification implements ReportSpecification {
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
index cbb45d6..cee7ee2 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
@@ -18,8 +18,6 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
 import io.mifos.reporting.api.v1.domain.DisplayableField;
 import io.mifos.reporting.api.v1.domain.Header;
 import io.mifos.reporting.api.v1.domain.QueryParameter;
@@ -35,12 +33,6 @@ import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
 import io.mifos.reporting.service.spi.QueryParameterBuilder;
 import io.mifos.reporting.service.spi.Report;
 import io.mifos.reporting.service.spi.ReportSpecification;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
 import java.text.DecimalFormat;
 import java.time.Clock;
 import java.time.LocalDateTime;
@@ -49,6 +41,13 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 @Report(category = "Customer", identifier = "Listing")
 public class CustomerListReportSpecification implements ReportSpecification {
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
index 458a081..1cdfd8e 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
@@ -18,17 +18,21 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
-import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Header;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Row;
+import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.api.v1.domain.Value;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.*;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
+import io.mifos.reporting.service.spi.CriteriaBuilder;
+import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
+import io.mifos.reporting.service.spi.QueryParameterBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -36,6 +40,13 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 @Report(category = "Deposit", identifier = "Listing")
 public class DepositListReportSpecification implements ReportSpecification {
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
index 7f5c678..eb76f70 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -18,16 +18,19 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
-import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Header;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Row;
+import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.api.v1.domain.Value;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.*;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
+import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
 import java.math.BigDecimal;
 import java.time.Clock;
 import java.time.LocalDateTime;
@@ -36,6 +39,12 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 @Report(category = "Accounting", identifier = "Incomestatement")
 public class IncomeStatementReportSpecification implements ReportSpecification {
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
index 6017321..f747322 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
@@ -18,17 +18,20 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
-import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Header;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Row;
+import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.api.v1.domain.Value;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.*;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
+import io.mifos.reporting.service.spi.CriteriaBuilder;
+import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -36,6 +39,13 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 @Report(category = "Loan", identifier = "Listing")
 public class LoanListReportSpecification implements ReportSpecification {
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
index f1c118d..b9abe66 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
@@ -18,17 +18,20 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
-import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Header;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Row;
+import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.api.v1.domain.Value;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.*;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
+import io.mifos.reporting.service.spi.CriteriaBuilder;
+import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -36,6 +39,13 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 @Report(category = "Organization", identifier = "Office")
 public class OfficeListReportSpecification implements ReportSpecification {
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
index a00db8f..bfdf746 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
@@ -18,17 +18,21 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
-import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Header;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Row;
+import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.api.v1.domain.Value;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.*;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
+import io.mifos.reporting.service.spi.CriteriaBuilder;
+import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
+import io.mifos.reporting.service.spi.QueryParameterBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -36,6 +40,13 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 @Report(category = "Teller" , identifier = "Listing")
 public class TellerListReportSpecification implements ReportSpecification {
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
index c196e92..3bbb4b6 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
@@ -18,17 +18,21 @@
  */
 package io.mifos.reporting.service.internal.specification;
 
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.core.lang.DateConverter;
-import io.mifos.reporting.api.v1.domain.*;
+import io.mifos.reporting.api.v1.domain.DisplayableField;
+import io.mifos.reporting.api.v1.domain.Header;
+import io.mifos.reporting.api.v1.domain.QueryParameter;
+import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import io.mifos.reporting.api.v1.domain.ReportPage;
+import io.mifos.reporting.api.v1.domain.ReportRequest;
+import io.mifos.reporting.api.v1.domain.Row;
+import io.mifos.reporting.api.v1.domain.Type;
+import io.mifos.reporting.api.v1.domain.Value;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.*;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
+import io.mifos.reporting.service.spi.CriteriaBuilder;
+import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
+import io.mifos.reporting.service.spi.QueryParameterBuilder;
+import io.mifos.reporting.service.spi.Report;
+import io.mifos.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -36,6 +40,13 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 @Report(category = "Teller", identifier = "Transactions")
 public class TellerTransactionReportSpecification implements ReportSpecification {
diff --git a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
index 7970f8a..310dbfa 100644
--- a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
+++ b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
@@ -20,12 +20,6 @@ package io.mifos.reporting.service.rest;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
-import io.mifos.anubis.annotation.AcceptedTokenType;
-import io.mifos.anubis.annotation.Permittable;
-import io.mifos.core.lang.ApplicationName;
-import io.mifos.core.lang.ServiceException;
-import io.mifos.core.lang.TenantContextHolder;
-import io.mifos.core.lang.config.TenantHeaderFilter;
 import io.mifos.reporting.api.v1.EventConstants;
 import io.mifos.reporting.api.v1.PermittableGroupIds;
 import io.mifos.reporting.api.v1.domain.ReportDefinition;
@@ -34,6 +28,14 @@ import io.mifos.reporting.api.v1.domain.ReportRequest;
 import io.mifos.reporting.service.ServiceConstants;
 import io.mifos.reporting.service.internal.provider.ReportSpecificationProvider;
 import io.mifos.reporting.service.spi.ReportSpecification;
+import java.util.List;
+import java.util.Optional;
+import org.apache.fineract.cn.anubis.annotation.AcceptedTokenType;
+import org.apache.fineract.cn.anubis.annotation.Permittable;
+import org.apache.fineract.cn.lang.ApplicationName;
+import org.apache.fineract.cn.lang.ServiceException;
+import org.apache.fineract.cn.lang.TenantContextHolder;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -48,9 +50,6 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.util.List;
-import java.util.Optional;
-
 @SuppressWarnings("unused")
 @RestController
 @RequestMapping("/")


[fineract-cn-reporting] 05/47: Refactor address query to use address table Add dummy entity to give EntityManagerFactory a package folder to load entities. This is a workaround to prevent an error described here: https://github.com/spring-projects/spring-boot/issues/6635 Extract string fields into constants Add needed property files for OWASP library Removed example migration sql

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit f93d9e6e09d6fa31c82f308442828662638e47d6
Author: Mark <ma...@gmail.com>
AuthorDate: Fri Jul 7 16:35:53 2017 +0200

    Refactor address query to use address table
    Add dummy entity to give EntityManagerFactory a package folder to load entities. This is a workaround to prevent an error described here: https://github.com/spring-projects/spring-boot/issues/6635
    Extract string fields into constants
    Add needed property files for OWASP library
    Removed example migration sql
---
 .../reporting/service/ReportingConfiguration.java  |   2 +
 .../service/internal/repository/DummyEntity.java   |  38 ++
 .../internal/repository/DummyRepository.java       |  23 ++
 .../CustomerListReportSpecification.java           | 100 +++--
 .../reporting/service/spi/CriteriaBuilder.java     |  15 +-
 service/src/main/resources/ESAPI.properties        | 452 +++++++++++++++++++++
 .../db/migrations/mariadb/V1__initial_setup.sql    |  22 -
 service/src/main/resources/validation.properties   |  32 ++
 8 files changed, 629 insertions(+), 55 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
index e3b03c9..1289d02 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
@@ -29,6 +29,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 
@@ -43,6 +44,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
 @EnableMariaDB
 @EnableAnubis
 @EnableServiceException
+@EnableJpaRepositories(basePackages = { "io.mifos.reporting.service.internal.repository" })
 @ComponentScan({
     "io.mifos.reporting.service.rest",
     "io.mifos.reporting.service.internal"
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
new file mode 100644
index 0000000..0f36a7e
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.repository;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class DummyEntity {
+
+  @Id
+  private Long id;
+
+  public DummyEntity() {
+    super();
+  }
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
new file mode 100644
index 0000000..20baf0e
--- /dev/null
+++ b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.reporting.service.internal.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface DummyRepository extends JpaRepository<DummyEntity, Long> {
+}
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
index f56657f..c799f68 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
@@ -50,11 +50,22 @@ import java.util.stream.Collectors;
 @Report(category = "Customer", identifier = "Listing")
 public class CustomerListReportSpecification implements ReportSpecification {
 
+  private static final String DATE_RANGE = "Date range";
+  private static final String STATE = "State";
+  private static final String CUSTOMER = "Customer";
+  private static final String FIRST_NAME = "First name";
+  private static final String MIDDLE_NAME = "Middle name";
+  private static final String LAST_NAME = "Last name";
+  private static final String ACCOUNT_NUMBER = "Account number";
+  private static final String ADDRESS = "Address";
+
   private final Logger logger;
+
   private final EntityManager entityManager;
   private final HashMap<String, String> customerColumnMapping = new HashMap<>();
   private final HashMap<String, String> addressColumnMapping = new HashMap<>();
   private final HashMap<String, String> accountColumnMapping = new HashMap<>();
+  private final HashMap<String, String> allColumnMapping = new HashMap<>();
 
   @Autowired
   public CustomerListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
@@ -104,13 +115,13 @@ public class CustomerListReportSpecification implements ReportSpecification {
   public void validate(final ReportRequest reportRequest) throws IllegalArgumentException {
     final ArrayList<String> unknownFields =  new ArrayList<>();
     reportRequest.getQueryParameters().forEach(queryParameter -> {
-      if (!this.customerColumnMapping.keySet().contains(queryParameter.getName())) {
+      if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
         unknownFields.add(queryParameter.getName());
       }
     });
 
     reportRequest.getDisplayableFields().forEach(displayableField -> {
-      if (!this.customerColumnMapping.keySet().contains(displayableField.getName())) {
+      if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
         unknownFields.add(displayableField.getName());
       }
     });
@@ -123,16 +134,20 @@ public class CustomerListReportSpecification implements ReportSpecification {
   }
 
   private void initializeMapping() {
-    this.customerColumnMapping.put("Date Range", "cst.created_on");
-    this.customerColumnMapping.put("State", "cst.current_state");
-    this.customerColumnMapping.put("Customer", "cst.identifier");
-    this.customerColumnMapping.put("First name", "cst.given_name");
-    this.customerColumnMapping.put("Middle Name", "cst.middle_name");
-    this.customerColumnMapping.put("Last Name", "cst.surname");
+    this.customerColumnMapping.put(DATE_RANGE, "cst.created_on");
+    this.customerColumnMapping.put(STATE, "cst.current_state");
+    this.customerColumnMapping.put(CUSTOMER, "cst.identifier");
+    this.customerColumnMapping.put(FIRST_NAME, "cst.given_name");
+    this.customerColumnMapping.put(MIDDLE_NAME, "cst.middle_name");
+    this.customerColumnMapping.put(LAST_NAME, "cst.surname");
 
-    this.accountColumnMapping.put("Account number", "acc.identifier, acc.balance");
+    this.accountColumnMapping.put(ACCOUNT_NUMBER, "acc.identifier, acc.balance");
 
-    this.addressColumnMapping.put("Address", "CONCAT(adr.street, ', ', adr.postal_code, ', ', adr.city)");
+    this.addressColumnMapping.put(ADDRESS, "CONCAT(adr.street, ', ', adr.postal_code, ', ', adr.city)");
+
+    this.allColumnMapping.putAll(customerColumnMapping);
+    this.allColumnMapping.putAll(accountColumnMapping);
+    this.allColumnMapping.putAll(addressColumnMapping);
   }
 
   private Header createHeader(final List<DisplayableField> displayableFields) {
@@ -152,15 +167,34 @@ public class CustomerListReportSpecification implements ReportSpecification {
     customerResultList.forEach(result -> {
       final Row row = new Row();
       row.setValues(new ArrayList<>());
-      final Object[] resultValues = (Object[]) result;
-      for (final Object resultValue : resultValues) {
+
+      final String customerIdentifier;
+
+      if (result instanceof Object[]) {
+        final Object[] resultValues = (Object[]) result;
+
+        customerIdentifier = resultValues[0].toString();
+
+        for (final Object resultValue : resultValues) {
+          final Value value = new Value();
+          if (resultValue != null) {
+            value.setValues(new String[]{resultValue.toString()});
+          } else {
+            value.setValues(new String[]{});
+          }
+
+          row.getValues().add(value);
+        }
+      } else {
+        customerIdentifier = result.toString();
+
         final Value value = new Value();
-        value.setValues(new String[]{resultValue.toString()});
+        value.setValues(new String[]{result.toString()});
         row.getValues().add(value);
       }
 
-      final DecimalFormat decimalFormat = new DecimalFormat(".##");
-      final Query accountQuery = this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, resultValues[0].toString()));
+      final DecimalFormat decimalFormat = new DecimalFormat("0.##");
+      final Query accountQuery = this.entityManager.createNativeQuery(this.buildAccountQuery(reportRequest, customerIdentifier));
       final List<?> accountResultList = accountQuery.getResultList();
       final ArrayList<String> values = new ArrayList<>();
       accountResultList.forEach(accountResult -> {
@@ -175,7 +209,7 @@ public class CustomerListReportSpecification implements ReportSpecification {
       accountValue.setValues(values.toArray(new String[values.size()]));
       row.getValues().add(accountValue);
 
-      final String addressQueryString = this.buildAddressQuery(reportRequest, resultValues[0].toString());
+      final String addressQueryString = this.buildAddressQuery(reportRequest, customerIdentifier);
       if (addressQueryString != null) {
         final Query addressQuery = this.entityManager.createNativeQuery(addressQueryString);
         final List<?> resultList = addressQuery.getResultList();
@@ -192,19 +226,19 @@ public class CustomerListReportSpecification implements ReportSpecification {
 
   private List<QueryParameter> buildQueryParameters() {
     return Arrays.asList(
-        QueryParameterBuilder.create("Date range", Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
-        QueryParameterBuilder.create("State", Type.TEXT).operator(QueryParameter.Operator.IN).build()
+        QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+        QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
     );
   }
 
   private List<DisplayableField> buildDisplayableFields() {
     return Arrays.asList(
-        DisplayableFieldBuilder.create("Customer", Type.TEXT).mandatory().build(),
-        DisplayableFieldBuilder.create("First name", Type.TEXT).build(),
-        DisplayableFieldBuilder.create("Middle name", Type.TEXT).build(),
-        DisplayableFieldBuilder.create("Last name", Type.TEXT).build(),
-        DisplayableFieldBuilder.create("Account number", Type.TEXT).mandatory().build(),
-        DisplayableFieldBuilder.create("Address", Type.TEXT).build()
+        DisplayableFieldBuilder.create(CUSTOMER, Type.TEXT).mandatory().build(),
+        DisplayableFieldBuilder.create(FIRST_NAME, Type.TEXT).build(),
+        DisplayableFieldBuilder.create(MIDDLE_NAME, Type.TEXT).build(),
+        DisplayableFieldBuilder.create(LAST_NAME, Type.TEXT).build(),
+        DisplayableFieldBuilder.create(ACCOUNT_NUMBER, Type.TEXT).mandatory().build(),
+        DisplayableFieldBuilder.create(ADDRESS, Type.TEXT).build()
     );
   }
 
@@ -228,9 +262,14 @@ public class CustomerListReportSpecification implements ReportSpecification {
     if (!queryParameters.isEmpty()) {
       query.append(" WHERE ");
       final ArrayList<String> criteria = new ArrayList<>();
-      queryParameters.forEach(queryParameter -> criteria.add(
-          CriteriaBuilder.buildCriteria(this.customerColumnMapping.get(queryParameter.getName()), queryParameter))
-      );
+      queryParameters.forEach(queryParameter -> {
+        if(queryParameter.getValue() != null && !queryParameter.getValue().isEmpty()) {
+          criteria.add(
+            CriteriaBuilder.buildCriteria(this.customerColumnMapping.get(queryParameter.getName()), queryParameter)
+          );
+        }
+      });
+
       query.append(criteria.stream().collect(Collectors.joining(" AND ")));
     }
     query.append(" ORDER BY cst.identifier");
@@ -275,10 +314,9 @@ public class CustomerListReportSpecification implements ReportSpecification {
 
     if (!columns.isEmpty()) {
       return "SELECT " + columns.stream().collect(Collectors.joining(", ")) + " " +
-          "FROM thoth_accounts acc " +
-              "LEFT JOIN maat_customers cst on acc.holders = cst.identifier " +
-          "WHERE cst.identifier ='" + customerIdentifier + "' " +
-          "ORDER BY acc.identifier";
+          "FROM maat_addresses adr " +
+              "LEFT JOIN maat_customers cst on adr.id = cst.address_id " +
+          "WHERE cst.identifier ='" + customerIdentifier + "' ";
     }
     return null;
   }
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
index a0dc841..53157b6 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
@@ -27,8 +27,18 @@ import java.util.stream.Collectors;
 public class CriteriaBuilder {
 
   // https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
-  private static final Encoder ENCODER = ESAPI.encoder();
-  private static final MySQLCodec MY_SQL_CODEC = new MySQLCodec(MySQLCodec.Mode.ANSI);
+  public static Encoder ENCODER;
+  public static MySQLCodec MY_SQL_CODEC;
+
+  static {
+    // TODO move this code into bean
+    try {
+      ENCODER = ESAPI.encoder();
+      MY_SQL_CODEC = new MySQLCodec(MySQLCodec.Mode.ANSI);
+    } catch(final Exception e) {
+      System.out.println(e.getMessage());
+    }
+  }
 
   private CriteriaBuilder() {
     super();
@@ -67,6 +77,7 @@ public class CriteriaBuilder {
                 .map(s -> "'" + CriteriaBuilder.ENCODER.encodeForSQL(CriteriaBuilder.MY_SQL_CODEC, s) + "'")
                 .collect(Collectors.joining(","))
         );
+        criteria.append(")");
         break;
       case BETWEEN:
         final String[] splitString = queryParameter.getValue().split("\\.\\.");
diff --git a/service/src/main/resources/ESAPI.properties b/service/src/main/resources/ESAPI.properties
new file mode 100644
index 0000000..1dedfe6
--- /dev/null
+++ b/service/src/main/resources/ESAPI.properties
@@ -0,0 +1,452 @@
+#
+# OWASP Enterprise Security API (ESAPI) Properties file -- PRODUCTION Version
+#
+# This file is part of the Open Web Application Security Project (OWASP)
+# Enterprise Security API (ESAPI) project. For details, please see
+# http://www.owasp.org/index.php/ESAPI.
+#
+# Copyright (c) 2008,2009 - The OWASP Foundation
+#
+# DISCUSS: This may cause a major backwards compatibility issue, etc. but
+#		   from a name space perspective, we probably should have prefaced
+#		   all the property names with ESAPI or at least OWASP. Otherwise
+#		   there could be problems is someone loads this properties file into
+#		   the System properties.  We could also put this file into the
+#		   esapi.jar file (perhaps as a ResourceBundle) and then allow an external
+#		   ESAPI properties be defined that would overwrite these defaults.
+#		   That keeps the application's properties relatively simple as usually
+#		   they will only want to override a few properties. If looks like we
+#		   already support multiple override levels of this in the
+#		   DefaultSecurityConfiguration class, but I'm suggesting placing the
+#		   defaults in the esapi.jar itself. That way, if the jar is signed,
+#		   we could detect if those properties had been tampered with. (The
+#		   code to check the jar signatures is pretty simple... maybe 70-90 LOC,
+#		   but off course there is an execution penalty (similar to the way
+#		   that the separate sunjce.jar used to be when a class from it was
+#		   first loaded). Thoughts?
+###############################################################################
+#
+# WARNING: Operating system protection should be used to lock down the .esapi
+# resources directory and all the files inside and all the directories all the
+# way up to the root directory of the file system.  Note that if you are using
+# file-based implementations, that some files may need to be read-write as they
+# get updated dynamically.
+#
+# Before using, be sure to update the MasterKey and MasterSalt as described below.
+# N.B.: If you had stored data that you have previously encrypted with ESAPI 1.4,
+#		you *must* FIRST decrypt it using ESAPI 1.4 and then (if so desired)
+#		re-encrypt it with ESAPI 2.0. If you fail to do this, you will NOT be
+#		able to decrypt your data with ESAPI 2.0.
+#
+#		YOU HAVE BEEN WARNED!!! More details are in the ESAPI 2.0 Release Notes.
+#
+#===========================================================================
+# ESAPI Configuration
+#
+# If true, then print all the ESAPI properties set here when they are loaded.
+# If false, they are not printed. Useful to reduce output when running JUnit tests.
+# If you need to troubleshoot a properties related problem, turning this on may help.
+# This is 'false' in the src/test/resources/.esapi version. It is 'true' by
+# default for reasons of backward compatibility with earlier ESAPI versions.
+ESAPI.printProperties=true
+
+# ESAPI is designed to be easily extensible. You can use the reference implementation
+# or implement your own providers to take advantage of your enterprise's security
+# infrastructure. The functions in ESAPI are referenced using the ESAPI locator, like:
+#
+#    String ciphertext =
+#		ESAPI.encryptor().encrypt("Secret message");   // Deprecated in 2.0
+#    CipherText cipherText =
+#		ESAPI.encryptor().encrypt(new PlainText("Secret message")); // Preferred
+#
+# Below you can specify the classname for the provider that you wish to use in your
+# application. The only requirement is that it implement the appropriate ESAPI interface.
+# This allows you to switch security implementations in the future without rewriting the
+# entire application.
+#
+# ExperimentalAccessController requires ESAPI-AccessControlPolicy.xml in .esapi directory
+ESAPI.AccessControl=org.owasp.esapi.reference.DefaultAccessController
+# FileBasedAuthenticator requires users.txt file in .esapi directory
+ESAPI.Authenticator=org.owasp.esapi.reference.FileBasedAuthenticator
+ESAPI.Encoder=org.owasp.esapi.reference.DefaultEncoder
+ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor
+
+ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor
+ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities
+ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector
+# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html
+ESAPI.Logger=org.owasp.esapi.reference.Log4JLogFactory
+#ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory
+ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer
+ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator
+
+#===========================================================================
+# ESAPI Authenticator
+#
+Authenticator.AllowedLoginAttempts=3
+Authenticator.MaxOldPasswordHashes=13
+Authenticator.UsernameParameterName=username
+Authenticator.PasswordParameterName=password
+# RememberTokenDuration (in days)
+Authenticator.RememberTokenDuration=14
+# Session Timeouts (in minutes)
+Authenticator.IdleTimeoutDuration=20
+Authenticator.AbsoluteTimeoutDuration=120
+
+#===========================================================================
+# ESAPI Encoder
+#
+# ESAPI canonicalizes input before validation to prevent bypassing filters with encoded attacks.
+# Failure to canonicalize input is a very common mistake when implementing validation schemes.
+# Canonicalization is automatic when using the ESAPI Validator, but you can also use the
+# following code to canonicalize data.
+#
+#      ESAPI.Encoder().canonicalize( "%22hello world&#x22;" );
+#
+# Multiple encoding is when a single encoding format is applied multiple times. Allowing
+# multiple encoding is strongly discouraged.
+Encoder.AllowMultipleEncoding=false
+
+# Mixed encoding is when multiple different encoding formats are applied, or when
+# multiple formats are nested. Allowing multiple encoding is strongly discouraged.
+Encoder.AllowMixedEncoding=false
+
+# The default list of codecs to apply when canonicalizing untrusted data. The list should include the codecs
+# for all downstream interpreters or decoders. For example, if the data is likely to end up in a URL, HTML, or
+# inside JavaScript, then the list of codecs below is appropriate. The order of the list is not terribly important.
+Encoder.DefaultCodecList=HTMLEntityCodec,PercentCodec,JavaScriptCodec
+
+
+#===========================================================================
+# ESAPI Encryption
+#
+# The ESAPI Encryptor provides basic cryptographic functions with a simplified API.
+# To get started, generate a new key using java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor
+# There is not currently any support for key rotation, so be careful when changing your key and salt as it
+# will invalidate all signed, encrypted, and hashed data.
+#
+# WARNING: Not all combinations of algorithms and key lengths are supported.
+# If you choose to use a key length greater than 128, you MUST download the
+# unlimited strength policy files and install in the lib directory of your JRE/JDK.
+# See http://java.sun.com/javase/downloads/index.jsp for more information.
+#
+# Backward compatibility with ESAPI Java 1.4 is supported by the two deprecated API
+# methods, Encryptor.encrypt(String) and Encryptor.decrypt(String). However, whenever
+# possible, these methods should be avoided as they use ECB cipher mode, which in almost
+# all circumstances a poor choice because of it's weakness. CBC cipher mode is the default
+# for the new Encryptor encrypt / decrypt methods for ESAPI Java 2.0.  In general, you
+# should only use this compatibility setting if you have persistent data encrypted with
+# version 1.4 and even then, you should ONLY set this compatibility mode UNTIL
+# you have decrypted all of your old encrypted data and then re-encrypted it with
+# ESAPI 2.0 using CBC mode. If you have some reason to mix the deprecated 1.4 mode
+# with the new 2.0 methods, make sure that you use the same cipher algorithm for both
+# (256-bit AES was the default for 1.4; 128-bit is the default for 2.0; see below for
+# more details.) Otherwise, you will have to use the new 2.0 encrypt / decrypt methods
+# where you can specify a SecretKey. (Note that if you are using the 256-bit AES,
+# that requires downloading the special jurisdiction policy files mentioned above.)
+#
+#		***** IMPORTANT: Do NOT forget to replace these with your own values! *****
+# To calculate these values, you can run:
+#		java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor
+#
+Encryptor.MasterKey=tzfztf56ftv
+Encryptor.MasterSalt=123456ztrewq
+
+# Provides the default JCE provider that ESAPI will "prefer" for its symmetric
+# encryption and hashing. (That is it will look to this provider first, but it
+# will defer to other providers if the requested algorithm is not implemented
+# by this provider.) If left unset, ESAPI will just use your Java VM's current
+# preferred JCE provider, which is generally set in the file
+# "$JAVA_HOME/jre/lib/security/java.security".
+#
+# The main intent of this is to allow ESAPI symmetric encryption to be
+# used with a FIPS 140-2 compliant crypto-module. For details, see the section
+# "Using ESAPI Symmetric Encryption with FIPS 140-2 Cryptographic Modules" in
+# the ESAPI 2.0 Symmetric Encryption User Guide, at:
+# http://owasp-esapi-java.googlecode.com/svn/trunk/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html
+# However, this property also allows you to easily use an alternate JCE provider
+# such as "Bouncy Castle" without having to make changes to "java.security".
+# See Javadoc for SecurityProviderLoader for further details. If you wish to use
+# a provider that is not known to SecurityProviderLoader, you may specify the
+# fully-qualified class name of the JCE provider class that implements
+# java.security.Provider. If the name contains a '.', this is interpreted as
+# a fully-qualified class name that implements java.security.Provider.
+#
+# NOTE: Setting this property has the side-effect of changing it in your application
+#       as well, so if you are using JCE in your application directly rather than
+#       through ESAPI (you wouldn't do that, would you? ;-), it will change the
+#       preferred JCE provider there as well.
+#
+# Default: Keeps the JCE provider set to whatever JVM sets it to.
+Encryptor.PreferredJCEProvider=
+
+# AES is the most widely used and strongest encryption algorithm. This
+# should agree with your Encryptor.CipherTransformation property.
+# By default, ESAPI Java 1.4 uses "PBEWithMD5AndDES" and which is
+# very weak. It is essentially a password-based encryption key, hashed
+# with MD5 around 1K times and then encrypted with the weak DES algorithm
+# (56-bits) using ECB mode and an unspecified padding (it is
+# JCE provider specific, but most likely "NoPadding"). However, 2.0 uses
+# "AES/CBC/PKCSPadding". If you want to change these, change them here.
+# Warning: This property does not control the default reference implementation for
+#		   ESAPI 2.0 using JavaEncryptor. Also, this property will be dropped
+#		   in the future.
+# @deprecated
+Encryptor.EncryptionAlgorithm=AES
+#		For ESAPI Java 2.0 - New encrypt / decrypt methods use this.
+Encryptor.CipherTransformation=AES/CBC/PKCS5Padding
+
+# Applies to ESAPI 2.0 and later only!
+# Comma-separated list of cipher modes that provide *BOTH*
+# confidentiality *AND* message authenticity. (NIST refers to such cipher
+# modes as "combined modes" so that's what we shall call them.) If any of these
+# cipher modes are used then no MAC is calculated and stored
+# in the CipherText upon encryption. Likewise, if one of these
+# cipher modes is used with decryption, no attempt will be made
+# to validate the MAC contained in the CipherText object regardless
+# of whether it contains one or not. Since the expectation is that
+# these cipher modes support support message authenticity already,
+# injecting a MAC in the CipherText object would be at best redundant.
+#
+# Note that as of JDK 1.5, the SunJCE provider does not support *any*
+# of these cipher modes. Of these listed, only GCM and CCM are currently
+# NIST approved. YMMV for other JCE providers. E.g., Bouncy Castle supports
+# GCM and CCM with "NoPadding" mode, but not with "PKCS5Padding" or other
+# padding modes.
+Encryptor.cipher_modes.combined_modes=GCM,CCM,IAPM,EAX,OCB,CWC
+
+# Applies to ESAPI 2.0 and later only!
+# Additional cipher modes allowed for ESAPI 2.0 encryption. These
+# cipher modes are in _addition_ to those specified by the property
+# 'Encryptor.cipher_modes.combined_modes'.
+# Note: We will add support for streaming modes like CFB & OFB once
+# we add support for 'specified' to the property 'Encryptor.ChooseIVMethod'
+# (probably in ESAPI 2.1).
+# DISCUSS: Better name?
+Encryptor.cipher_modes.additional_allowed=CBC
+
+# 128-bit is almost always sufficient and appears to be more resistant to
+# related key attacks than is 256-bit AES. Use '_' to use default key size
+# for cipher algorithms (where it makes sense because the algorithm supports
+# a variable key size). Key length must agree to what's provided as the
+# cipher transformation, otherwise this will be ignored after logging a
+# warning.
+#
+# NOTE: This is what applies BOTH ESAPI 1.4 and 2.0. See warning above about mixing!
+Encryptor.EncryptionKeyLength=128
+
+# Because 2.0 uses CBC mode by default, it requires an initialization vector (IV).
+# (All cipher modes except ECB require an IV.) There are two choices: we can either
+# use a fixed IV known to both parties or allow ESAPI to choose a random IV. While
+# the IV does not need to be hidden from adversaries, it is important that the
+# adversary not be allowed to choose it. Also, random IVs are generally much more
+# secure than fixed IVs. (In fact, it is essential that feed-back cipher modes
+# such as CFB and OFB use a different IV for each encryption with a given key so
+# in such cases, random IVs are much preferred. By default, ESAPI 2.0 uses random
+# IVs. If you wish to use 'fixed' IVs, set 'Encryptor.ChooseIVMethod=fixed' and
+# uncomment the Encryptor.fixedIV.
+#
+# Valid values:		random|fixed|specified		'specified' not yet implemented; planned for 2.1
+Encryptor.ChooseIVMethod=random
+# If you choose to use a fixed IV, then you must place a fixed IV here that
+# is known to all others who are sharing your secret key. The format should
+# be a hex string that is the same length as the cipher block size for the
+# cipher algorithm that you are using. The following is an *example* for AES
+# from an AES test vector for AES-128/CBC as described in:
+# NIST Special Publication 800-38A (2001 Edition)
+# "Recommendation for Block Cipher Modes of Operation".
+# (Note that the block size for AES is 16 bytes == 128 bits.)
+#
+Encryptor.fixedIV=0x000102030405060708090a0b0c0d0e0f
+
+# Whether or not CipherText should use a message authentication code (MAC) with it.
+# This prevents an adversary from altering the IV as well as allowing a more
+# fool-proof way of determining the decryption failed because of an incorrect
+# key being supplied. This refers to the "separate" MAC calculated and stored
+# in CipherText, not part of any MAC that is calculated as a result of a
+# "combined mode" cipher mode.
+#
+# If you are using ESAPI with a FIPS 140-2 cryptographic module, you *must* also
+# set this property to false.
+Encryptor.CipherText.useMAC=true
+
+# Whether or not the PlainText object may be overwritten and then marked
+# eligible for garbage collection. If not set, this is still treated as 'true'.
+Encryptor.PlainText.overwrite=true
+
+# Do not use DES except in a legacy situations. 56-bit is way too small key size.
+#Encryptor.EncryptionKeyLength=56
+#Encryptor.EncryptionAlgorithm=DES
+
+# TripleDES is considered strong enough for most purposes.
+#	Note:	There is also a 112-bit version of DESede. Using the 168-bit version
+#			requires downloading the special jurisdiction policy from Sun.
+#Encryptor.EncryptionKeyLength=168
+#Encryptor.EncryptionAlgorithm=DESede
+
+Encryptor.HashAlgorithm=SHA-512
+Encryptor.HashIterations=1024
+Encryptor.DigitalSignatureAlgorithm=SHA1withDSA
+Encryptor.DigitalSignatureKeyLength=1024
+Encryptor.RandomAlgorithm=SHA1PRNG
+Encryptor.CharacterEncoding=UTF-8
+
+# This is the Pseudo Random Function (PRF) that ESAPI's Key Derivation Function
+# (KDF) normally uses. Note this is *only* the PRF used for ESAPI's KDF and
+# *not* what is used for ESAPI's MAC. (Currently, HmacSHA1 is always used for
+# the MAC, mostly to keep the overall size at a minimum.)
+#
+# Currently supported choices for JDK 1.5 and 1.6 are:
+#	HmacSHA1 (160 bits), HmacSHA256 (256 bits), HmacSHA384 (384 bits), and
+#	HmacSHA512 (512 bits).
+# Note that HmacMD5 is *not* supported for the PRF used by the KDF even though
+# the JDKs support it.  See the ESAPI 2.0 Symmetric Encryption User Guide
+# further details.
+Encryptor.KDF.PRF=HmacSHA256
+#===========================================================================
+# ESAPI HttpUtilties
+#
+# The HttpUtilities provide basic protections to HTTP requests and responses. Primarily these methods
+# protect against malicious data from attackers, such as unprintable characters, escaped characters,
+# and other simple attacks. The HttpUtilities also provides utility methods for dealing with cookies,
+# headers, and CSRF tokens.
+#
+# Default file upload location (remember to escape backslashes with \\)
+HttpUtilities.UploadDir=C:\\ESAPI\\testUpload
+HttpUtilities.UploadTempDir=C:\\temp
+# Force flags on cookies, if you use HttpUtilities to set cookies
+HttpUtilities.ForceHttpOnlySession=false
+HttpUtilities.ForceSecureSession=false
+HttpUtilities.ForceHttpOnlyCookies=true
+HttpUtilities.ForceSecureCookies=true
+# Maximum size of HTTP headers
+HttpUtilities.MaxHeaderSize=4096
+# File upload configuration
+HttpUtilities.ApprovedUploadExtensions=.zip,.pdf,.doc,.docx,.ppt,.pptx,.tar,.gz,.tgz,.rar,.war,.jar,.ear,.xls,.rtf,.properties,.java,.class,.txt,.xml,.jsp,.jsf,.exe,.dll
+HttpUtilities.MaxUploadFileBytes=500000000
+# Using UTF-8 throughout your stack is highly recommended. That includes your database driver,
+# container, and any other technologies you may be using. Failure to do this may expose you
+# to Unicode transcoding injection attacks. Use of UTF-8 does not hinder internationalization.
+HttpUtilities.ResponseContentType=text/html; charset=UTF-8
+# This is the name of the cookie used to represent the HTTP session
+# Typically this will be the default "JSESSIONID"
+HttpUtilities.HttpSessionIdName=JSESSIONID
+
+
+
+#===========================================================================
+# ESAPI Executor
+# CHECKME - Not sure what this is used for, but surely it should be made OS independent.
+Executor.WorkingDirectory=C:\\Windows\\Temp
+Executor.ApprovedExecutables=C:\\Windows\\System32\\cmd.exe,C:\\Windows\\System32\\runas.exe
+
+
+#===========================================================================
+# ESAPI Logging
+# Set the application name if these logs are combined with other applications
+Logger.ApplicationName=ExampleApplication
+# If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true
+Logger.LogEncodingRequired=false
+# Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments.
+Logger.LogApplicationName=true
+# Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments.
+Logger.LogServerIP=true
+# LogFileName, the name of the logging file. Provide a full directory path (e.g., C:\\ESAPI\\ESAPI_logging_file) if you
+# want to place it in a specific directory.
+Logger.LogFileName=ESAPI_logging_file
+# MaxLogFileSize, the max size (in bytes) of a single log file before it cuts over to a new one (default is 10,000,000)
+Logger.MaxLogFileSize=10000000
+
+
+#===========================================================================
+# ESAPI Intrusion Detection
+#
+# Each event has a base to which .count, .interval, and .action are added
+# The IntrusionException will fire if we receive "count" events within "interval" seconds
+# The IntrusionDetector is configurable to take the following actions: log, logout, and disable
+#  (multiple actions separated by commas are allowed e.g. event.test.actions=log,disable
+#
+# Custom Events
+# Names must start with "event." as the base
+# Use IntrusionDetector.addEvent( "test" ) in your code to trigger "event.test" here
+# You can also disable intrusion detection completely by changing
+# the following parameter to true
+#
+IntrusionDetector.Disable=false
+#
+IntrusionDetector.event.test.count=2
+IntrusionDetector.event.test.interval=10
+IntrusionDetector.event.test.actions=disable,log
+
+# Exception Events
+# All EnterpriseSecurityExceptions are registered automatically
+# Call IntrusionDetector.getInstance().addException(e) for Exceptions that do not extend EnterpriseSecurityException
+# Use the fully qualified classname of the exception as the base
+
+# any intrusion is an attack
+IntrusionDetector.org.owasp.esapi.errors.IntrusionException.count=1
+IntrusionDetector.org.owasp.esapi.errors.IntrusionException.interval=1
+IntrusionDetector.org.owasp.esapi.errors.IntrusionException.actions=log,disable,logout
+
+# for test purposes
+# CHECKME: Shouldn't there be something in the property name itself that designates
+#		   that these are for testing???
+IntrusionDetector.org.owasp.esapi.errors.IntegrityException.count=10
+IntrusionDetector.org.owasp.esapi.errors.IntegrityException.interval=5
+IntrusionDetector.org.owasp.esapi.errors.IntegrityException.actions=log,disable,logout
+
+# rapid validation errors indicate scans or attacks in progress
+# org.owasp.esapi.errors.ValidationException.count=10
+# org.owasp.esapi.errors.ValidationException.interval=10
+# org.owasp.esapi.errors.ValidationException.actions=log,logout
+
+# sessions jumping between hosts indicates session hijacking
+IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.count=2
+IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.interval=10
+IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.actions=log,logout
+
+
+#===========================================================================
+# ESAPI Validation
+#
+# The ESAPI Validator works on regular expressions with defined names. You can define names
+# either here, or you may define application specific patterns in a separate file defined below.
+# This allows enterprises to specify both organizational standards as well as application specific
+# validation rules.
+#
+Validator.ConfigurationFile=validation.properties
+
+# Validators used by ESAPI
+Validator.AccountName=^[a-zA-Z0-9]{3,20}$
+Validator.SystemCommand=^[a-zA-Z\\-\\/]{1,64}$
+Validator.RoleName=^[a-z]{1,20}$
+
+#the word TEST below should be changed to your application
+#name - only relative URL's are supported
+Validator.Redirect=^\\/test.*$
+
+# Global HTTP Validation Rules
+# Values with Base64 encoded data (e.g. encrypted state) will need at least [a-zA-Z0-9\/+=]
+Validator.HTTPScheme=^(http|https)$
+Validator.HTTPServerName=^[a-zA-Z0-9_.\\-]*$
+Validator.HTTPParameterName=^[a-zA-Z0-9_]{1,32}$
+Validator.HTTPParameterValue=^[a-zA-Z0-9.\\-\\/+=@_ ]*$
+Validator.HTTPCookieName=^[a-zA-Z0-9\\-_]{1,32}$
+Validator.HTTPCookieValue=^[a-zA-Z0-9\\-\\/+=_ ]*$
+Validator.HTTPHeaderName=^[a-zA-Z0-9\\-_]{1,32}$
+Validator.HTTPHeaderValue=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$
+Validator.HTTPContextPath=^\\/?[a-zA-Z0-9.\\-\\/_]*$
+Validator.HTTPServletPath=^[a-zA-Z0-9.\\-\\/_]*$
+Validator.HTTPPath=^[a-zA-Z0-9.\\-_]*$
+Validator.HTTPQueryString=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ %]*$
+Validator.HTTPURI=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$
+Validator.HTTPURL=^.*$
+Validator.HTTPJSESSIONID=^[A-Z0-9]{10,30}$
+
+# Validation of file related input
+Validator.FileName=^[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
+Validator.DirectoryName=^[a-zA-Z0-9:/\\\\!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
+
+# Validation of dates. Controls whether or not 'lenient' dates are accepted.
+# See DataFormat.setLenient(boolean flag) for further details.
+Validator.AcceptLenientDates=false
\ No newline at end of file
diff --git a/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql b/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
deleted file mode 100644
index fb1b54e..0000000
--- a/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
+++ /dev/null
@@ -1,22 +0,0 @@
---
--- Copyright 2017 The Mifos Initiative.
---
--- Licensed 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.
---
-
-CREATE TABLE template_samples (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  identifier VARCHAR(8) NOT NULL,
-  payload VARCHAR(512) NULL,
-  CONSTRAINT template_samples_pk PRIMARY KEY (id)
-);
diff --git a/service/src/main/resources/validation.properties b/service/src/main/resources/validation.properties
new file mode 100644
index 0000000..0e9e2d3
--- /dev/null
+++ b/service/src/main/resources/validation.properties
@@ -0,0 +1,32 @@
+# The ESAPI validator does many security checks on input, such as canonicalization
+# and whitelist validation. Note that all of these validation rules are applied *after*
+# canonicalization. Double-encoded characters (even with different encodings involved,
+# are never allowed.
+#
+# To use:
+#
+# First set up a pattern below. You can choose any name you want, prefixed by the word
+# "Validation." For example:
+#   Validation.Email=^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
+#
+# Then you can validate in your code against the pattern like this:
+#     ESAPI.validator().isValidInput("User Email", input, "Email", maxLength, allowNull);
+# Where maxLength and allowNull are set for you needs, respectively.
+#
+# But note, when you use boolean variants of validation functions, you lose critical
+# canonicalization. It is preferable to use the "get" methods (which throw exceptions) and
+# and use the returned user input which is in canonical form. Consider the following:
+#
+# try {
+#    someObject.setEmail(ESAPI.validator().getValidInput("User Email", input, "Email", maxLength, allowNull));
+#
+
+Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$
+# 2 majuscules, 3 minuscules, 2 chiffres, 1 caract�re sp�cial,
+Validator.Password=^(?=.*[A-Z].*[A-Z])(?=.*[.:,;-_+"'?!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8,20}$
+Validator.Digit=^[0-9]{1,20}$
+Validator.Email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
+Validator.IPAddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
+Validator.URL=^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\:\\'\\/\\\\\\+=&amp;%\\$#_]*)?$
+Validator.CreditCard=^(\\d{4}[- ]?){3}\\d{4}$
+Validator.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$
\ No newline at end of file


[fineract-cn-reporting] 04/47: added message for MQ

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 73acc99fd211585939a89555c02795f24887ecbe
Author: mgeiss <mg...@mifos.org>
AuthorDate: Thu Jul 6 12:01:16 2017 +0200

    added message for MQ
---
 .../io/mifos/reporting/api/v1/EventConstants.java  |  2 ++
 .../reporting/service/ReportingConfiguration.java  |  4 +++
 .../service/rest/ReportingRestController.java      | 32 +++++++++++++++++++++-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java b/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
index a2bbc3f..a80adec 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
@@ -21,4 +21,6 @@ public interface EventConstants {
   String DESTINATION = "reporting-v1";
   String SELECTOR_NAME = "operation";
 
+  String INITIALIZE = "initialize";
+  String SELECTOR_INITIALIZE = SELECTOR_NAME + " = '" + INITIALIZE + "'";
 }
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
index 6bf4fed..e3b03c9 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
@@ -17,6 +17,8 @@ package io.mifos.reporting.service;
 
 import io.mifos.anubis.config.EnableAnubis;
 import io.mifos.core.cassandra.config.EnableCassandra;
+import io.mifos.core.command.config.EnableCommandProcessing;
+import io.mifos.core.lang.config.EnableApplicationName;
 import io.mifos.core.lang.config.EnableServiceException;
 import io.mifos.core.lang.config.EnableTenantContext;
 import io.mifos.core.mariadb.config.EnableMariaDB;
@@ -34,6 +36,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
 @Configuration
 @EnableAutoConfiguration
 @EnableDiscoveryClient
+@EnableApplicationName
+@EnableCommandProcessing
 @EnableTenantContext
 @EnableCassandra
 @EnableMariaDB
diff --git a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
index a23e355..dc5c02f 100644
--- a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
+++ b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
@@ -15,9 +15,15 @@
  */
 package io.mifos.reporting.service.rest;
 
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import io.mifos.anubis.annotation.AcceptedTokenType;
 import io.mifos.anubis.annotation.Permittable;
+import io.mifos.core.lang.ApplicationName;
 import io.mifos.core.lang.ServiceException;
+import io.mifos.core.lang.TenantContextHolder;
+import io.mifos.core.lang.config.TenantHeaderFilter;
+import io.mifos.reporting.api.v1.EventConstants;
 import io.mifos.reporting.api.v1.PermittableGroupIds;
 import io.mifos.reporting.api.v1.domain.ReportDefinition;
 import io.mifos.reporting.api.v1.domain.ReportPage;
@@ -30,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.jms.core.JmsTemplate;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -48,13 +55,19 @@ public class ReportingRestController {
 
   private final Logger logger;
   private final ReportSpecificationProvider reportSpecificationProvider;
+  private final ApplicationName applicationName;
+  private final JmsTemplate jmsTemplate;
 
   @Autowired
   public ReportingRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
-                                 final ReportSpecificationProvider reportSpecificationProvider) {
+                                 final ReportSpecificationProvider reportSpecificationProvider,
+                                 final ApplicationName applicationName,
+                                 final JmsTemplate jmsTemplate) {
     super();
     this.logger = logger;
     this.reportSpecificationProvider = reportSpecificationProvider;
+    this.applicationName = applicationName;
+    this.jmsTemplate = jmsTemplate;
   }
 
   @Permittable(value = AcceptedTokenType.SYSTEM)
@@ -67,6 +80,23 @@ public class ReportingRestController {
   public
   @ResponseBody
   ResponseEntity<Void> initialize() {
+    final Gson gson = new GsonBuilder().create();
+    this.jmsTemplate.convertAndSend(
+        gson.toJson(this.applicationName.getVersionString()),
+        message -> {
+          if (TenantContextHolder.identifier().isPresent()) {
+            message.setStringProperty(
+                TenantHeaderFilter.TENANT_HEADER,
+                TenantContextHolder.checkedGetIdentifier());
+          }
+          message.setStringProperty(
+              EventConstants.SELECTOR_NAME,
+              EventConstants.INITIALIZE
+          );
+          return message;
+        }
+    );
+
     return ResponseEntity.ok().build();
   }
 


[fineract-cn-reporting] 14/47: Complete Teller Listing Report Spec

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit e01fd9f7fdc6398a0861f22bb8bf053544250b1d
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Mon Aug 28 11:37:09 2017 +0100

    Complete Teller Listing Report Spec
---
 .../TellerListReportSpecification.java             | 143 ++++++++++++++-------
 1 file changed, 96 insertions(+), 47 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
index 3c51c85..9c854e0 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
@@ -4,9 +4,7 @@ import io.mifos.core.api.util.UserContextHolder;
 import io.mifos.core.lang.DateConverter;
 import io.mifos.reporting.api.v1.domain.*;
 import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.CriteriaBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+import io.mifos.reporting.service.spi.*;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -16,6 +14,7 @@ import javax.persistence.Query;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -23,16 +22,12 @@ import java.util.stream.Collectors;
 @Report(category = "Teller" , identifier = "Listing")
 public class TellerListReportSpecification implements ReportSpecification {
 
-   // private static final String TOTAL_CASH_ON_HAND = "Cash on hand";
-   // private static final String TOTAL_CASH_RECEIVED = "Cash received";
-   // private static final String TOTAL_CASH_DISBURSED = "Cash Disbursed";
-   // private static final String TOTAL_NEGOTIABLE_INSTRUMENT_RECEIVED = "Negotiable instrument received";
-   // private static final String TOTAL_CHEQUES_RECEIVED = "Total cheques received";
     private static final String TELLER = "Teller";
     private static final String EMPLOYEE = "Employee";
     private static final String OFFICE = "Office";
     private static final String CASHDRAW_LIMIT = "Cashdraw limit";
     private static final String STATE = "State";
+    private static final String DATE_RANGE = "Date";
 
     private final Logger logger;
 
@@ -51,16 +46,6 @@ public class TellerListReportSpecification implements ReportSpecification {
         this.initializeMapping();
     }
 
-    private void initializeMapping() {
-        this.tellerColumnMapping.put(TELLER, "tl.identifier");
-        this.tellerColumnMapping.put(OFFICE, "tl.office_identifier");
-        this.tellerColumnMapping.put(CASHDRAW_LIMIT, "tl.cashdraw_limit");
-        this.tellerColumnMapping.put(EMPLOYEE, "tl.assigned_employee_identifier");
-        this.tellerColumnMapping.put(STATE, "tl.a_state");
-
-        this.allColumnMapping.putAll(tellerColumnMapping);
-    }
-
     @Override
     public ReportDefinition getReportDefinition() {
         final ReportDefinition reportDefinition = new ReportDefinition();
@@ -72,14 +57,6 @@ public class TellerListReportSpecification implements ReportSpecification {
         return reportDefinition;
     }
 
-    private List<DisplayableField> buildDisplayableFields() {
-        return null;
-    }
-
-    private List<QueryParameter> buildQueryParameters() {
-        return null;
-    }
-
     @Override
     public ReportPage generateReport(ReportRequest reportRequest, int pageIndex, int size) {
         final ReportDefinition reportDefinition = this.getReportDefinition();
@@ -104,6 +81,99 @@ public class TellerListReportSpecification implements ReportSpecification {
         return reportPage;
     }
 
+    @Override
+    public void validate(final ReportRequest reportRequest) throws IllegalArgumentException {
+        final ArrayList<String> unknownFields =  new ArrayList<>();
+        reportRequest.getQueryParameters().forEach(queryParameter -> {
+            if (!this.allColumnMapping.keySet().contains(queryParameter.getName())) {
+                unknownFields.add(queryParameter.getName());
+            }
+        });
+
+        reportRequest.getDisplayableFields().forEach(displayableField -> {
+            if (!this.allColumnMapping.keySet().contains(displayableField.getName())) {
+                unknownFields.add(displayableField.getName());
+            }
+        });
+
+        if (!unknownFields.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", "))
+            );
+        }
+    }
+
+    private void initializeMapping() {
+        this.tellerColumnMapping.put(TELLER, "tl.identifier");
+        this.tellerColumnMapping.put(OFFICE, "tl.office_identifier");
+        this.tellerColumnMapping.put(CASHDRAW_LIMIT, "tl.cashdraw_limit");
+        this.tellerColumnMapping.put(EMPLOYEE, "tl.assigned_employee_identifier");
+        this.tellerColumnMapping.put(STATE, "tl.a_state");
+        this.tellerColumnMapping.put(DATE_RANGE, "tl.created_on");
+
+        this.allColumnMapping.putAll(tellerColumnMapping);
+    }
+
+    private Header createHeader(List<DisplayableField> displayableFields) {
+        final Header header = new Header();
+        header.setColumnNames(
+                displayableFields
+                        .stream()
+                        .map(DisplayableField::getName)
+                        .collect(Collectors.toList())
+        );
+        return header;
+    }
+
+    private List<Row> buildRows(ReportRequest reportRequest, List<?> tellerResultList) {
+        final ArrayList<Row> rows = new ArrayList<>();
+        tellerResultList.forEach(result -> {
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+            
+            if (result instanceof Object[]) {
+                final Object[] resultValues = (Object[]) result;
+
+                for(final Object resultVal : resultValues) {
+                    final Value val;
+                    val = new Value();
+
+                    if (resultVal != null) {
+                        val.setValues(new String[]{resultVal.toString()});
+                    } else {
+                        val.setValues(new String[]{});
+                    }
+
+                    row.getValues().add(val);
+                }
+            } else {
+                final Value value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+            rows.add(row);
+        });
+
+        return rows;
+    }
+
+    private List<QueryParameter> buildQueryParameters() {
+        return Arrays.asList(
+                QueryParameterBuilder.create(DATE_RANGE, Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(),
+                QueryParameterBuilder.create(STATE, Type.TEXT).operator(QueryParameter.Operator.IN).build()
+        );
+    }
+
+    private List<DisplayableField> buildDisplayableFields() {
+        return Arrays.asList(
+                DisplayableFieldBuilder.create(TELLER, Type.TEXT).mandatory().build(),
+                DisplayableFieldBuilder.create(OFFICE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(EMPLOYEE, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(CASHDRAW_LIMIT, Type.TEXT).build(),
+                DisplayableFieldBuilder.create(STATE, Type.TEXT).build()
+        );
+    }
+
     private String buildTellerQuery(ReportRequest reportRequest, int pageIndex, int size) {
         final StringBuilder query = new StringBuilder("SELECT ");
 
@@ -148,25 +218,4 @@ public class TellerListReportSpecification implements ReportSpecification {
 
         return query.toString();
     }
-
-    private List<Row> buildRows(ReportRequest reportRequest, List<?> tellerResultList) {
-    return null;
-    }
-
-    private Header createHeader(List<DisplayableField> displayableFields) {
-        final Header header = new Header();
-        header.setColumnNames(
-                displayableFields
-                        .stream()
-                        .map(DisplayableField::getName)
-                        .collect(Collectors.toList())
-        );
-        return header;
-    }
-
-    @Override
-    public void validate(ReportRequest reportRequest) throws IllegalArgumentException {
-
-    }
-    
 }


[fineract-cn-reporting] 40/47: Merge pull request #6 from Izakey/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 1e50d2dbc8e1535dbbdc7bc017b19872fc05f31c
Merge: 2c300e9 2304cdb
Author: Isaac Kamga <u2...@gmail.com>
AuthorDate: Mon Oct 15 22:25:24 2018 +0100

    Merge pull request #6 from Izakey/develop
    
    Add test suite to enable one-click run for reporting service's component-test

 .../AbstractReportingSpecificationTest.java        | 26 +------------------
 .../cn/reporting/SuiteTestEnvironment.java         | 18 ++++++++------
 .../apache/fineract/cn/reporting/TestSuite.java    | 29 ++++++++++++++++++++++
 3 files changed, 41 insertions(+), 32 deletions(-)


[fineract-cn-reporting] 34/47: Change package names from mifos to apache fineract.

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit e4cccd465604c3eb241ca81bc7198f4fba6938bc
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Apr 16 15:13:10 2018 +0200

    Change package names from mifos to apache fineract.
---
 .../cn}/reporting/api/v1/EventConstants.java       |  2 +-
 .../cn}/reporting/api/v1/PermittableGroupIds.java  |  2 +-
 .../cn}/reporting/api/v1/client/ReportManager.java |  8 ++---
 .../api/v1/client/ReportNotFoundException.java     |  2 +-
 .../client/ReportParameterValidationException.java |  2 +-
 .../api/v1/domain/AutoCompleteResource.java        |  2 +-
 .../reporting/api/v1/domain/DisplayableField.java  |  2 +-
 .../cn}/reporting/api/v1/domain/Footer.java        |  2 +-
 .../cn}/reporting/api/v1/domain/Header.java        |  2 +-
 .../reporting/api/v1/domain/QueryParameter.java    |  2 +-
 .../reporting/api/v1/domain/ReportDefinition.java  |  2 +-
 .../cn}/reporting/api/v1/domain/ReportPage.java    |  2 +-
 .../cn}/reporting/api/v1/domain/ReportRequest.java |  2 +-
 .../fineract/cn}/reporting/api/v1/domain/Row.java  |  2 +-
 .../fineract/cn}/reporting/api/v1/domain/Type.java |  2 +-
 .../cn}/reporting/api/v1/domain/Value.java         |  2 +-
 .../AbstractReportingSpecificationTest.java        |  8 ++---
 .../TestBalanceSheetReportSpecification.java       |  4 +--
 .../TestCustomerListReportSpecification.java       |  4 +--
 .../TestDepositListReportSpecification.java        |  4 +--
 .../TestIncomeStatementReportSpecification.java    |  4 +--
 .../reporting/TestLoanListReportSpecification.java |  4 +--
 .../TestTellerListReportSpecification.java         |  4 +--
 .../TestTellerTransactionReportSpecification.java  |  4 +--
 .../reporting/service/ReportingApplication.java    |  2 +-
 .../reporting/service/ReportingConfiguration.java  |  9 +++---
 .../cn}/reporting/service/ServiceConstants.java    |  2 +-
 .../provider/ReportSpecificationProvider.java      | 10 +++----
 .../service/internal/repository/DummyEntity.java   |  2 +-
 .../internal/repository/DummyRepository.java       |  2 +-
 .../BalanceSheetReportSpecification.java           | 30 +++++++++----------
 .../CustomerListReportSpecification.java           | 34 +++++++++++-----------
 .../DepositListReportSpecification.java            | 34 +++++++++++-----------
 .../IncomeStatementReportSpecification.java        | 30 +++++++++----------
 .../specification/LoanListReportSpecification.java | 32 ++++++++++----------
 .../OfficeListReportSpecification.java             | 32 ++++++++++----------
 .../TellerListReportSpecification.java             | 34 +++++++++++-----------
 .../TellerTransactionReportSpecification.java      | 34 +++++++++++-----------
 .../service/rest/ReportingRestController.java      | 18 ++++++------
 .../cn}/reporting/service/spi/CriteriaBuilder.java |  4 +--
 .../service/spi/DisplayableFieldBuilder.java       |  6 ++--
 .../service/spi/QueryParameterBuilder.java         |  8 ++---
 .../fineract/cn}/reporting/service/spi/Report.java |  2 +-
 .../reporting/service/spi/ReportSpecification.java |  8 ++---
 44 files changed, 204 insertions(+), 203 deletions(-)

diff --git a/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/EventConstants.java
similarity index 95%
rename from api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/EventConstants.java
index c274750..85bcc82 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/EventConstants.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1;
+package org.apache.fineract.cn.reporting.api.v1;
 
 @SuppressWarnings("unused")
 public interface EventConstants {
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/PermittableGroupIds.java
similarity index 95%
rename from api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/PermittableGroupIds.java
index b3363a3..8a46016 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/PermittableGroupIds.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1;
+package org.apache.fineract.cn.reporting.api.v1;
 
 @SuppressWarnings("unused")
 public interface PermittableGroupIds {
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportManager.java
similarity index 93%
rename from api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportManager.java
index 0bcd6af..8cf82d5 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportManager.java
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.client;
+package org.apache.fineract.cn.reporting.api.v1.client;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
 import java.util.List;
 import org.apache.fineract.cn.api.annotation.ThrowsException;
 import org.apache.fineract.cn.api.annotation.ThrowsExceptions;
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportNotFoundException.java
similarity index 93%
rename from api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportNotFoundException.java
index dc1ea5a..e508e73 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportNotFoundException.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.client;
+package org.apache.fineract.cn.reporting.api.v1.client;
 
 public class ReportNotFoundException extends RuntimeException {
 }
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportParameterValidationException.java
similarity index 94%
rename from api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportParameterValidationException.java
index 52a7b1e..e60b5da 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/client/ReportParameterValidationException.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.client;
+package org.apache.fineract.cn.reporting.api.v1.client;
 
 public class ReportParameterValidationException extends RuntimeException {
 }
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/AutoCompleteResource.java
similarity index 95%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/AutoCompleteResource.java
index b72db87..9594d2c 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/AutoCompleteResource.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 import java.util.List;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/DisplayableField.java
similarity index 96%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/DisplayableField.java
index 5a11707..8942a58 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/DisplayableField.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 public class DisplayableField {
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Footer.java
similarity index 95%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Footer.java
index 06bc5d2..951e160 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Footer.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 import java.util.List;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Header.java
similarity index 95%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Header.java
index b2eca21..370e743 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Header.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 import java.util.List;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/QueryParameter.java
similarity index 97%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/QueryParameter.java
index ba03e8b..4330edb 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/QueryParameter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 public class QueryParameter {
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportDefinition.java
similarity index 97%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportDefinition.java
index 898252c..c75b5cb 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportDefinition.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 import java.util.List;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportPage.java
similarity index 97%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportPage.java
index 5720e5d..e73478e 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportPage.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 import java.util.List;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportRequest.java
similarity index 96%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportRequest.java
index 596574b..db46a72 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/ReportRequest.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 import java.util.List;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Row.java
similarity index 95%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Row.java
index 22e631d..7db5c62 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Row.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 import java.util.List;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Type.java
similarity index 93%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Type.java
index 45abcf3..ff66347 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Type.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 public enum Type {
   TEXT,
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Value.java
similarity index 95%
rename from api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
rename to api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Value.java
index d9c1b6a..ff904b8 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
+++ b/api/src/main/java/org/apache/fineract/cn/reporting/api/v1/domain/Value.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.api.v1.domain;
+package org.apache.fineract.cn.reporting.api.v1.domain;
 
 public class Value {
 
diff --git a/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
similarity index 94%
rename from component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
rename to component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
index b6d3012..528bad0 100644
--- a/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting;
+package org.apache.fineract.cn.reporting;
 
-import io.mifos.reporting.api.v1.client.ReportManager;
-import io.mifos.reporting.service.ReportingConfiguration;
+import org.apache.fineract.cn.reporting.api.v1.client.ReportManager;
+import org.apache.fineract.cn.reporting.service.ReportingConfiguration;
 import java.security.interfaces.RSAPrivateKey;
 import org.apache.fineract.cn.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
 import org.apache.fineract.cn.api.context.AutoUserContext;
@@ -57,7 +57,7 @@ public class AbstractReportingSpecificationTest {
   public static final String LOGGER_NAME = "test-logger";
 
   @Configuration
-  @EnableFeignClients(basePackages = {"io.mifos.reporting.api.v1.client"})
+  @EnableFeignClients(basePackages = {"org.apache.fineract.cn.reporting.api.v1.client"})
   @RibbonClient(name = APP_NAME)
   @Import({ReportingConfiguration.class})
   public static class TestConfiguration {
diff --git a/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestBalanceSheetReportSpecification.java
similarity index 92%
rename from component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java
rename to component-test/src/main/java/org/apache/fineract/cn/reporting/TestBalanceSheetReportSpecification.java
index a64b19c..d8ae817 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestBalanceSheetReportSpecification.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting;
+package org.apache.fineract.cn.reporting;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestCustomerListReportSpecification.java
similarity index 92%
rename from component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java
rename to component-test/src/main/java/org/apache/fineract/cn/reporting/TestCustomerListReportSpecification.java
index fdef649..7fdae97 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestCustomerListReportSpecification.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting;
+package org.apache.fineract.cn.reporting;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestDepositListReportSpecification.java
similarity index 92%
rename from component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java
rename to component-test/src/main/java/org/apache/fineract/cn/reporting/TestDepositListReportSpecification.java
index 092b365..d13fcf6 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestDepositListReportSpecification.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting;
+package org.apache.fineract.cn.reporting;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestIncomeStatementReportSpecification.java
similarity index 92%
rename from component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java
rename to component-test/src/main/java/org/apache/fineract/cn/reporting/TestIncomeStatementReportSpecification.java
index f65dfe6..d919828 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestIncomeStatementReportSpecification.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting;
+package org.apache.fineract.cn.reporting;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestLoanListReportSpecification.java
similarity index 92%
rename from component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java
rename to component-test/src/main/java/org/apache/fineract/cn/reporting/TestLoanListReportSpecification.java
index 346444b..49075cf 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestLoanListReportSpecification.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting;
+package org.apache.fineract.cn.reporting;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerListReportSpecification.java
similarity index 92%
rename from component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java
rename to component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerListReportSpecification.java
index 419f0f2..fe3d2f4 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerListReportSpecification.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting;
+package org.apache.fineract.cn.reporting;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerTransactionReportSpecification.java
similarity index 92%
rename from component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java
rename to component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerTransactionReportSpecification.java
index 75eba2b..fb76bc3 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestTellerTransactionReportSpecification.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting;
+package org.apache.fineract.cn.reporting;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/ReportingApplication.java
similarity index 95%
rename from service/src/main/java/io/mifos/reporting/service/ReportingApplication.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/ReportingApplication.java
index 02b0d84..b753877 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/ReportingApplication.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service;
+package org.apache.fineract.cn.reporting.service;
 
 import org.springframework.boot.SpringApplication;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/ReportingConfiguration.java
similarity index 90%
rename from service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/ReportingConfiguration.java
index 77310e3..bc71177 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/ReportingConfiguration.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service;
+package org.apache.fineract.cn.reporting.service;
 
 import org.apache.fineract.cn.anubis.config.EnableAnubis;
 import org.apache.fineract.cn.cassandra.config.EnableCassandra;
@@ -47,10 +47,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
 @EnableMariaDB
 @EnableAnubis
 @EnableServiceException
-@EnableJpaRepositories(basePackages = { "io.mifos.reporting.service.internal.repository" })
+@EnableJpaRepositories(basePackages = {
+    "org.apache.fineract.cn.reporting.service.internal.repository"})
 @ComponentScan({
-    "io.mifos.reporting.service.rest",
-    "io.mifos.reporting.service.internal"
+    "org.apache.fineract.cn.reporting.service.rest",
+    "org.apache.fineract.cn.reporting.service.internal"
 })
 public class ReportingConfiguration extends WebMvcConfigurerAdapter {
 
diff --git a/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/ServiceConstants.java
similarity index 94%
rename from service/src/main/java/io/mifos/reporting/service/ServiceConstants.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/ServiceConstants.java
index b5cb983..ccceb46 100644
--- a/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/ServiceConstants.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service;
+package org.apache.fineract.cn.reporting.service;
 
 public interface ServiceConstants {
   String LOGGER_NAME = "reporting-logger";
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/provider/ReportSpecificationProvider.java
similarity index 93%
rename from service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/provider/ReportSpecificationProvider.java
index f6393ff..da21c30 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/provider/ReportSpecificationProvider.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.provider;
+package org.apache.fineract.cn.reporting.service.internal.provider;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import org.slf4j.Logger;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/repository/DummyEntity.java
similarity index 93%
rename from service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/repository/DummyEntity.java
index 05e080a..670ab5d 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/repository/DummyEntity.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.repository;
+package org.apache.fineract.cn.reporting.service.internal.repository;
 
 import javax.persistence.Entity;
 import javax.persistence.Id;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/repository/DummyRepository.java
similarity index 93%
rename from service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/repository/DummyRepository.java
index bdca566..f5640f3 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/repository/DummyRepository.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.repository;
+package org.apache.fineract.cn.reporting.service.internal.repository;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/BalanceSheetReportSpecification.java
similarity index 93%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/BalanceSheetReportSpecification.java
index 0723acc..17f32cf 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/BalanceSheetReportSpecification.java
@@ -16,21 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Header;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.api.v1.domain.Row;
-import io.mifos.reporting.api.v1.domain.Type;
-import io.mifos.reporting.api.v1.domain.Value;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+package org.apache.fineract.cn.reporting.service.internal.specification;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Header;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.Row;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.Value;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.DisplayableFieldBuilder;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.math.BigDecimal;
 import java.time.Clock;
 import java.time.LocalDateTime;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/CustomerListReportSpecification.java
similarity index 92%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/CustomerListReportSpecification.java
index cee7ee2..cb654fb 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/CustomerListReportSpecification.java
@@ -16,23 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Header;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.api.v1.domain.Row;
-import io.mifos.reporting.api.v1.domain.Type;
-import io.mifos.reporting.api.v1.domain.Value;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.CriteriaBuilder;
-import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
-import io.mifos.reporting.service.spi.QueryParameterBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+package org.apache.fineract.cn.reporting.service.internal.specification;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Header;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.Row;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.Value;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.CriteriaBuilder;
+import org.apache.fineract.cn.reporting.service.spi.DisplayableFieldBuilder;
+import org.apache.fineract.cn.reporting.service.spi.QueryParameterBuilder;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.text.DecimalFormat;
 import java.time.Clock;
 import java.time.LocalDateTime;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/DepositListReportSpecification.java
similarity index 94%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/DepositListReportSpecification.java
index 1cdfd8e..24fb94b 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/DepositListReportSpecification.java
@@ -16,23 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Header;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.api.v1.domain.Row;
-import io.mifos.reporting.api.v1.domain.Type;
-import io.mifos.reporting.api.v1.domain.Value;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.CriteriaBuilder;
-import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
-import io.mifos.reporting.service.spi.QueryParameterBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+package org.apache.fineract.cn.reporting.service.internal.specification;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Header;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.Row;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.Value;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.CriteriaBuilder;
+import org.apache.fineract.cn.reporting.service.spi.DisplayableFieldBuilder;
+import org.apache.fineract.cn.reporting.service.spi.QueryParameterBuilder;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/IncomeStatementReportSpecification.java
similarity index 92%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/IncomeStatementReportSpecification.java
index eb76f70..2b54880 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -16,21 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Header;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.api.v1.domain.Row;
-import io.mifos.reporting.api.v1.domain.Type;
-import io.mifos.reporting.api.v1.domain.Value;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+package org.apache.fineract.cn.reporting.service.internal.specification;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Header;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.Row;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.Value;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.DisplayableFieldBuilder;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.math.BigDecimal;
 import java.time.Clock;
 import java.time.LocalDateTime;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/LoanListReportSpecification.java
similarity index 93%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/LoanListReportSpecification.java
index f747322..457fe64 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/LoanListReportSpecification.java
@@ -16,22 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Header;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.api.v1.domain.Row;
-import io.mifos.reporting.api.v1.domain.Type;
-import io.mifos.reporting.api.v1.domain.Value;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.CriteriaBuilder;
-import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+package org.apache.fineract.cn.reporting.service.internal.specification;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Header;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.Row;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.Value;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.CriteriaBuilder;
+import org.apache.fineract.cn.reporting.service.spi.DisplayableFieldBuilder;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/OfficeListReportSpecification.java
similarity index 92%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/OfficeListReportSpecification.java
index b9abe66..fdbb6e9 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/OfficeListReportSpecification.java
@@ -16,22 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Header;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.api.v1.domain.Row;
-import io.mifos.reporting.api.v1.domain.Type;
-import io.mifos.reporting.api.v1.domain.Value;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.CriteriaBuilder;
-import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+package org.apache.fineract.cn.reporting.service.internal.specification;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Header;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.Row;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.Value;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.CriteriaBuilder;
+import org.apache.fineract.cn.reporting.service.spi.DisplayableFieldBuilder;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/TellerListReportSpecification.java
similarity index 89%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/TellerListReportSpecification.java
index bfdf746..2652f9b 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/TellerListReportSpecification.java
@@ -16,23 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Header;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.api.v1.domain.Row;
-import io.mifos.reporting.api.v1.domain.Type;
-import io.mifos.reporting.api.v1.domain.Value;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.CriteriaBuilder;
-import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
-import io.mifos.reporting.service.spi.QueryParameterBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+package org.apache.fineract.cn.reporting.service.internal.specification;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Header;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.Row;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.Value;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.CriteriaBuilder;
+import org.apache.fineract.cn.reporting.service.spi.DisplayableFieldBuilder;
+import org.apache.fineract.cn.reporting.service.spi.QueryParameterBuilder;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/TellerTransactionReportSpecification.java
similarity index 93%
rename from service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/TellerTransactionReportSpecification.java
index 3bbb4b6..b797fd5 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/internal/specification/TellerTransactionReportSpecification.java
@@ -16,23 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.internal.specification;
-
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Header;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.api.v1.domain.Row;
-import io.mifos.reporting.api.v1.domain.Type;
-import io.mifos.reporting.api.v1.domain.Value;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.spi.CriteriaBuilder;
-import io.mifos.reporting.service.spi.DisplayableFieldBuilder;
-import io.mifos.reporting.service.spi.QueryParameterBuilder;
-import io.mifos.reporting.service.spi.Report;
-import io.mifos.reporting.service.spi.ReportSpecification;
+package org.apache.fineract.cn.reporting.service.internal.specification;
+
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Header;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.Row;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.Value;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.spi.CriteriaBuilder;
+import org.apache.fineract.cn.reporting.service.spi.DisplayableFieldBuilder;
+import org.apache.fineract.cn.reporting.service.spi.QueryParameterBuilder;
+import org.apache.fineract.cn.reporting.service.spi.Report;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
diff --git a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/rest/ReportingRestController.java
similarity index 91%
rename from service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/rest/ReportingRestController.java
index 310dbfa..49691a6 100644
--- a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/rest/ReportingRestController.java
@@ -16,18 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.rest;
+package org.apache.fineract.cn.reporting.service.rest;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
-import io.mifos.reporting.api.v1.EventConstants;
-import io.mifos.reporting.api.v1.PermittableGroupIds;
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
-import io.mifos.reporting.service.ServiceConstants;
-import io.mifos.reporting.service.internal.provider.ReportSpecificationProvider;
-import io.mifos.reporting.service.spi.ReportSpecification;
+import org.apache.fineract.cn.reporting.api.v1.EventConstants;
+import org.apache.fineract.cn.reporting.api.v1.PermittableGroupIds;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.service.ServiceConstants;
+import org.apache.fineract.cn.reporting.service.internal.provider.ReportSpecificationProvider;
+import org.apache.fineract.cn.reporting.service.spi.ReportSpecification;
 import java.util.List;
 import java.util.Optional;
 import org.apache.fineract.cn.anubis.annotation.AcceptedTokenType;
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/CriteriaBuilder.java
similarity index 96%
rename from service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/spi/CriteriaBuilder.java
index 30a2c09..3ef8002 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/CriteriaBuilder.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.spi;
+package org.apache.fineract.cn.reporting.service.spi;
 
-import io.mifos.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
 import org.owasp.esapi.ESAPI;
 import org.owasp.esapi.Encoder;
 import org.owasp.esapi.codecs.MySQLCodec;
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/DisplayableFieldBuilder.java
similarity index 89%
rename from service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/spi/DisplayableFieldBuilder.java
index eba5094..4a089e3 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/DisplayableFieldBuilder.java
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.spi;
+package org.apache.fineract.cn.reporting.service.spi;
 
-import io.mifos.reporting.api.v1.domain.DisplayableField;
-import io.mifos.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.DisplayableField;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
 
 public class DisplayableFieldBuilder {
 
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/QueryParameterBuilder.java
similarity index 90%
rename from service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/spi/QueryParameterBuilder.java
index 23eece5..aade86e 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/QueryParameterBuilder.java
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.spi;
+package org.apache.fineract.cn.reporting.service.spi;
 
-import io.mifos.reporting.api.v1.domain.AutoCompleteResource;
-import io.mifos.reporting.api.v1.domain.QueryParameter;
-import io.mifos.reporting.api.v1.domain.Type;
+import org.apache.fineract.cn.reporting.api.v1.domain.AutoCompleteResource;
+import org.apache.fineract.cn.reporting.api.v1.domain.QueryParameter;
+import org.apache.fineract.cn.reporting.api.v1.domain.Type;
 
 import java.util.Arrays;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/Report.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/Report.java
similarity index 95%
rename from service/src/main/java/io/mifos/reporting/service/spi/Report.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/spi/Report.java
index 4268f0b..acc0f77 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/Report.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/Report.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.spi;
+package org.apache.fineract.cn.reporting.service.spi;
 
 import org.springframework.stereotype.Component;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/ReportSpecification.java
similarity index 80%
rename from service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
rename to service/src/main/java/org/apache/fineract/cn/reporting/service/spi/ReportSpecification.java
index 3511815..2fe0bd0 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
+++ b/service/src/main/java/org/apache/fineract/cn/reporting/service/spi/ReportSpecification.java
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package io.mifos.reporting.service.spi;
+package org.apache.fineract.cn.reporting.service.spi;
 
-import io.mifos.reporting.api.v1.domain.ReportDefinition;
-import io.mifos.reporting.api.v1.domain.ReportPage;
-import io.mifos.reporting.api.v1.domain.ReportRequest;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportDefinition;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportPage;
+import org.apache.fineract.cn.reporting.api.v1.domain.ReportRequest;
 
 public interface ReportSpecification {
 


[fineract-cn-reporting] 44/47: Merge pull request #9 from Anh3h/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 59aade71f4ecf96fac7b61f69a2642566bbc8337
Merge: 162148a b8c9615
Author: Ang3h Courage <co...@gmail.com>
AuthorDate: Wed May 29 13:19:56 2019 -0400

    Merge pull request #9 from Anh3h/develop
    
    Add Docker configuration

 .dockerignore | 17 +++++++++++++++++
 .gitignore    |  4 +++-
 Dockerfile    | 31 +++++++++++++++++++++++++++++++
 shared.gradle |  3 ++-
 4 files changed, 53 insertions(+), 2 deletions(-)


[fineract-cn-reporting] 46/47: FINCN-170 fix jar path

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 65c2237ed00cc870ad9059fdb9cb688b9998f30f
Author: Juhan Aasaru <Ju...@nortal.com>
AuthorDate: Mon Aug 19 19:59:09 2019 +0300

    FINCN-170 fix jar path
---
 Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Dockerfile b/Dockerfile
index 3bfe1bb..131a4ce 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -32,7 +32,7 @@ ENV server.max-http-header-size=16384 \
     server.port=$reporting_port
 
 WORKDIR /tmp
-COPY --from=builder /builddir/service/build/libs/reporting-service-boot-0.1.0-BUILD-SNAPSHOT.jar ./reporting-service-boot.jar
+COPY --from=builder /builddir/service/build/libs/service-0.1.0-BUILD-SNAPSHOT-boot.jar ./reporting-service-boot.jar
 ENV server.port=$reporting_port
 
 CMD ["java", "-jar", "reporting-service-boot.jar"]


[fineract-cn-reporting] 39/47: Add test suite to reporting service's component-test

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 2304cdbf9277b433ba30fd8510f0e2b27d467b88
Author: Isaac Kamga <u2...@gmail.com>
AuthorDate: Mon Oct 15 22:17:25 2018 +0100

    Add test suite to reporting service's component-test
---
 .../AbstractReportingSpecificationTest.java        | 26 +------------------
 .../cn/reporting/SuiteTestEnvironment.java         | 18 ++++++++------
 .../apache/fineract/cn/reporting/TestSuite.java    | 29 ++++++++++++++++++++++
 3 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
index ed375b7..cd9a56c 100644
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/AbstractReportingSpecificationTest.java
@@ -23,17 +23,10 @@ import org.apache.fineract.cn.reporting.service.ReportingConfiguration;
 import java.security.interfaces.RSAPrivateKey;
 import org.apache.fineract.cn.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
 import org.apache.fineract.cn.api.context.AutoUserContext;
-import org.apache.fineract.cn.lang.ApplicationName;
-import org.apache.fineract.cn.test.env.TestEnvironment;
-import org.apache.fineract.cn.test.fixture.TenantDataStoreContextTestRule;
-import org.apache.fineract.cn.test.fixture.cassandra.CassandraInitializer;
-import org.apache.fineract.cn.test.fixture.mariadb.MariaDBInitializer;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.ClassRule;
+
 import org.junit.Rule;
-import org.junit.rules.RuleChain;
-import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -71,20 +64,6 @@ public class AbstractReportingSpecificationTest extends SuiteTestEnvironment {
     }
   }
 
-  static final String TEST_USER = "homer";
-
-  private final static TestEnvironment testEnvironment = new TestEnvironment(APP_NAME);
-  private final static CassandraInitializer cassandraInitializer = new CassandraInitializer();
-  private final static MariaDBInitializer mariaDBInitializer = new MariaDBInitializer();
-  final static TenantDataStoreContextTestRule tenantDataStoreContext = TenantDataStoreContextTestRule.forRandomTenantName(cassandraInitializer, mariaDBInitializer);
-
-  @ClassRule
-  public static TestRule orderClassRules = RuleChain
-      .outerRule(testEnvironment)
-      .around(cassandraInitializer)
-      .around(mariaDBInitializer)
-      .around(tenantDataStoreContext);
-
   @Rule
   public final TenantApplicationSecurityEnvironmentTestRule tenantApplicationSecurityEnvironment
       = new TenantApplicationSecurityEnvironmentTestRule(testEnvironment, this::waitForInitialize);
@@ -95,9 +74,6 @@ public class AbstractReportingSpecificationTest extends SuiteTestEnvironment {
   ReportManager testSubject;
 
   @Autowired
-  private ApplicationName applicationName;
-
-  @Autowired
   @Qualifier(LOGGER_NAME)
   Logger logger;
 
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/SuiteTestEnvironment.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/SuiteTestEnvironment.java
index 9a65c5f..e3be870 100644
--- a/component-test/src/main/java/org/apache/fineract/cn/reporting/SuiteTestEnvironment.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/SuiteTestEnvironment.java
@@ -19,22 +19,26 @@
 package org.apache.fineract.cn.reporting;
 
 import org.apache.fineract.cn.test.env.TestEnvironment;
+import org.apache.fineract.cn.test.fixture.TenantDataStoreContextTestRule;
 import org.apache.fineract.cn.test.fixture.cassandra.CassandraInitializer;
 import org.apache.fineract.cn.test.fixture.mariadb.MariaDBInitializer;
 import org.junit.ClassRule;
 import org.junit.rules.RuleChain;
-import org.junit.rules.RunExternalResourceOnce;
 import org.junit.rules.TestRule;
 
 public class SuiteTestEnvironment {
   static final String APP_NAME = "reporting-v1";
-  static final TestEnvironment testEnvironment = new TestEnvironment(APP_NAME);
-  static final CassandraInitializer cassandraInitializer = new CassandraInitializer();
-  static final MariaDBInitializer mariaDBInitializer = new MariaDBInitializer();
+  static final String TEST_USER = "shu";
+
+  public final static TestEnvironment testEnvironment = new TestEnvironment(APP_NAME);
+  private final static CassandraInitializer cassandraInitializer = new CassandraInitializer();
+  private final static MariaDBInitializer mariaDBInitializer = new MariaDBInitializer();
+  final static TenantDataStoreContextTestRule tenantDataStoreContext = TenantDataStoreContextTestRule.forRandomTenantName(cassandraInitializer, mariaDBInitializer);
 
   @ClassRule
   public static TestRule orderClassRules = RuleChain
-          .outerRule(new RunExternalResourceOnce(testEnvironment))
-          .around(new RunExternalResourceOnce(cassandraInitializer))
-          .around(new RunExternalResourceOnce(mariaDBInitializer));
+          .outerRule(testEnvironment)
+          .around(cassandraInitializer)
+          .around(mariaDBInitializer)
+          .around(tenantDataStoreContext);
 }
diff --git a/component-test/src/main/java/org/apache/fineract/cn/reporting/TestSuite.java b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestSuite.java
new file mode 100644
index 0000000..17782b4
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/reporting/TestSuite.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.cn.reporting;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+        TestReportingSpecifications.class
+})
+public class TestSuite {
+}


[fineract-cn-reporting] 35/47: Removing last references to mifos.

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit cf41f64c0be35e5d095310372afe3b9d6ca9577b
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Apr 16 15:13:53 2018 +0200

    Removing last references to mifos.
---
 README.md | 2 --
 1 file changed, 2 deletions(-)

diff --git a/README.md b/README.md
index 602a578..62f18d4 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,5 @@
 # Apache Fineract CN Reporting
 
-[![Join the chat at https://gitter.im/mifos-initiative/mifos.io](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mifos-initiative/mifos.io?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-
 This project provides simple reporting capabilities.
 
 ## Versioning


[fineract-cn-reporting] 43/47: Add Docker configuration

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit b8c96155f97d3b26cd40c5a8b6ed8f6cef06030e
Author: Anh3h <co...@gmail.com>
AuthorDate: Mon May 20 15:58:32 2019 -0400

    Add Docker configuration
---
 .dockerignore | 17 +++++++++++++++++
 .gitignore    |  4 +++-
 Dockerfile    | 31 +++++++++++++++++++++++++++++++
 shared.gradle |  3 ++-
 4 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..8d88495
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,17 @@
+api/
+component-test/
+gradle/
+gradlew.bat
+LICENSE
+README.md
+settings.gradle
+build.gradle
+docs/
+gradlew
+HEADER
+NOTICE.txt
+service/
+.git/
+.gradle/
+.gitignore
+shared.gradle
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1ef178c..4103254 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,4 +15,6 @@ gradle-app.setting
 
 *.toDelete
 *.class
-out/
\ No newline at end of file
+out/
+
+*.jar
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..7079e8b
--- /dev/null
+++ b/Dockerfile
@@ -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.
+#
+FROM openjdk:8-jdk-alpine
+
+ARG reporting_port=2029
+
+ENV server.max-http-header-size=16384 \
+    cassandra.clusterName="Test Cluster" \
+    server.port=$reporting_port
+
+WORKDIR /tmp
+COPY reporting-service-boot-0.1.0-BUILD-SNAPSHOT.jar .
+ENV server.port=$reporting_port
+
+CMD ["java", "-jar", "reporting-service-boot-0.1.0-BUILD-SNAPSHOT.jar"]
diff --git a/shared.gradle b/shared.gradle
index 98f7948..49949e9 100644
--- a/shared.gradle
+++ b/shared.gradle
@@ -109,6 +109,7 @@ rat {
             "**/build/**",
             "gradlew",
             "gradlew.bat",
-            "README.md"
+            "README.md",
+            "**/.dockerignore/**"
     ]
 }


[fineract-cn-reporting] 06/47: Merge pull request #1 from crain/develop

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit c1916214cddec2719588367be085df317ccbf522
Merge: 73acc99 f93d9e6
Author: Mark <cr...@users.noreply.github.com>
AuthorDate: Fri Jul 7 16:37:00 2017 +0200

    Merge pull request #1 from crain/develop
    
    Refactoring

 .../reporting/service/ReportingConfiguration.java  |   2 +
 .../service/internal/repository/DummyEntity.java   |  38 ++
 .../internal/repository/DummyRepository.java       |  23 ++
 .../CustomerListReportSpecification.java           | 100 +++--
 .../reporting/service/spi/CriteriaBuilder.java     |  15 +-
 service/src/main/resources/ESAPI.properties        | 452 +++++++++++++++++++++
 .../db/migrations/mariadb/V1__initial_setup.sql    |  22 -
 service/src/main/resources/validation.properties   |  32 ++
 8 files changed, 629 insertions(+), 55 deletions(-)


[fineract-cn-reporting] 18/47: refactor add income state build rows, fix nullables

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 096a62c1ddfd48ddb462ba19f41c10d4cf12a8b1
Author: Awasum Yannick <aw...@skylabase.com>
AuthorDate: Sun Sep 3 15:16:43 2017 +0100

    refactor add income state build rows, fix nullables
---
 .../DepositListReportSpecification.java            |  5 ++--
 .../IncomeStatementReportSpecification.java        | 31 ++++++++++++++++++++--
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
index b25aa88..42dabfa 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
@@ -255,8 +255,7 @@ public class DepositListReportSpecification implements ReportSpecification {
         final List<DisplayableField> displayableFields = reportRequest.getDisplayableFields();
         final ArrayList<String> columns = new ArrayList<>();
         displayableFields.forEach(displayableField -> {
-            final String column = this.accountColumnMapping.get(displayableField.getName())
-                    + this.employeeColumnMapping.get(displayableField.getName());
+            final String column = this.accountColumnMapping.get(displayableField.getName());
             if (column != null) {
                 columns.add(column);
             }
@@ -264,7 +263,7 @@ public class DepositListReportSpecification implements ReportSpecification {
 
         query.append(columns.stream().collect(Collectors.joining(", ")))
                 .append(" FROM ")
-                .append("shed_product_instances pi ");
+                .append("shed_product_instances pi");
         final List<QueryParameter> queryParameters = reportRequest.getQueryParameters();
         if (!queryParameters.isEmpty()) {
             final ArrayList<String> criteria = new ArrayList<>();
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
index 3992d16..91669ec 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -125,8 +125,35 @@ public class IncomeStatementReportSpecification implements ReportSpecification {
         return header;
     }
 
-    private List<Row> buildRows(ReportRequest reportRequest, List<?> customerResultList) {
-        return null;
+    private List<Row> buildRows(ReportRequest reportRequest, List<?> accountResultList) {
+        final ArrayList<Row> rows = new ArrayList<>();
+        accountResultList.forEach(result -> {
+            final Row row = new Row();
+            row.setValues(new ArrayList<>());
+
+            if (result instanceof Object[]) {
+                final Object[] resultValues;
+                resultValues = (Object[]) result;
+
+                for(final Object resultVal : resultValues) {
+                    final Value val;
+                    val = new Value();
+
+                    if (resultVal != null) {
+                        val.setValues(new String[]{resultVal.toString()});
+                    } else val.setValues(new String[]{});
+                    
+                    row.getValues().add(val);
+                }
+            } else {
+                final Value value = new Value();
+                value.setValues(new String[]{result.toString()});
+                row.getValues().add(value);
+            }
+            rows.add(row);
+        });
+
+        return rows;
     }
 
     private String buildAccountQuery(ReportRequest reportRequest, int pageIndex, int size) {


[fineract-cn-reporting] 45/47: FINCN-170 create multi-stage Docker build

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 13ecc2a6c460ddd837cbb44358dc36dec17afd7f
Author: Juhan Aasaru <Ju...@nortal.com>
AuthorDate: Mon Aug 19 19:39:50 2019 +0300

    FINCN-170 create multi-stage Docker build
---
 .dockerignore | 10 ----------
 Dockerfile    | 13 ++++++++++---
 2 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/.dockerignore b/.dockerignore
index 8d88495..a3b6dc5 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,17 +1,7 @@
-api/
-component-test/
-gradle/
-gradlew.bat
 LICENSE
 README.md
-settings.gradle
-build.gradle
 docs/
-gradlew
 HEADER
 NOTICE.txt
-service/
 .git/
-.gradle/
 .gitignore
-shared.gradle
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 7079e8b..3bfe1bb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -16,7 +16,14 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-FROM openjdk:8-jdk-alpine
+FROM openjdk:8-jdk-alpine AS builder
+RUN mkdir builddir
+COPY . builddir
+WORKDIR builddir
+RUN ./gradlew publishToMavenLocal
+
+
+FROM openjdk:8-jdk-alpine AS runner
 
 ARG reporting_port=2029
 
@@ -25,7 +32,7 @@ ENV server.max-http-header-size=16384 \
     server.port=$reporting_port
 
 WORKDIR /tmp
-COPY reporting-service-boot-0.1.0-BUILD-SNAPSHOT.jar .
+COPY --from=builder /builddir/service/build/libs/reporting-service-boot-0.1.0-BUILD-SNAPSHOT.jar ./reporting-service-boot.jar
 ENV server.port=$reporting_port
 
-CMD ["java", "-jar", "reporting-service-boot-0.1.0-BUILD-SNAPSHOT.jar"]
+CMD ["java", "-jar", "reporting-service-boot.jar"]


[fineract-cn-reporting] 47/47: Merge pull request #10 from aasaru/multi-stage-docker-build

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 4792359fe4afaed9ddd98a7b45fc7f76d8f7b9bb
Merge: 59aade7 65c2237
Author: Awasum Yannick <aw...@apache.org>
AuthorDate: Mon Sep 2 21:43:41 2019 +0100

    Merge pull request #10 from aasaru/multi-stage-docker-build
    
    FINCN-170 create multi-stage Docker build

 .dockerignore | 10 ----------
 Dockerfile    | 13 ++++++++++---
 2 files changed, 10 insertions(+), 13 deletions(-)


[fineract-cn-reporting] 32/47: Removing navel-gazing test

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 689fc6e1c97fa6dbe2246063b52bca9d7a99e3f5
Author: Myrle Krantz <my...@apache.org>
AuthorDate: Mon Apr 16 14:53:05 2018 +0200

    Removing navel-gazing test
---
 .../io/mifos/reporting/api/v1/domain/Sample.java   | 38 --------------
 .../mifos/reporting/api/v1/domain/SampleTest.java  | 58 ----------------------
 2 files changed, 96 deletions(-)

diff --git a/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java b/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
deleted file mode 100644
index ac319d1..0000000
--- a/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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 io.mifos.reporting.api.v1.domain;
-
-public class Sample {
-    private Object identifier;
-    private Object payload;
-    public Sample(){
-        super();
-    }
-    public static Sample create(String xxxx, String yyy) {
-        return new Sample();
-    }
-
-    public void setIdentifier(Object identifier) {
-        this.identifier = identifier;
-    }
-
-    public void setPayload(String payload) {
-        this.payload = payload;
-    }
-}
diff --git a/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java b/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java
deleted file mode 100644
index 2bdb53b..0000000
--- a/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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 io.mifos.reporting.api.v1.domain;
-
-import io.mifos.core.test.domain.ValidationTest;
-import io.mifos.core.test.domain.ValidationTestCase;
-import org.apache.commons.lang.RandomStringUtils;
-import org.junit.runners.Parameterized;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-public class SampleTest extends ValidationTest<Sample> {
-
-  public SampleTest(ValidationTestCase<Sample> testCase) {
-    super(testCase);
-  }
-
-  @Override
-  protected Sample createValidTestSubject() {
-    return Sample.create("xxxx", "yyy");
-  }
-
-  @Parameterized.Parameters
-  public static Collection testCases() {
-    final Collection<ValidationTestCase> ret = new ArrayList<>();
-    ret.add(new ValidationTestCase<Sample>("basicCase")
-            .adjustment(x -> {})
-            .valid(true));
-    ret.add(new ValidationTestCase<Sample>("nullIdentifier")
-            .adjustment(x -> x.setIdentifier(null))
-            .valid(false));
-    ret.add(new ValidationTestCase<Sample>("tooShortIdentifier")
-            .adjustment(x -> x.setIdentifier("z"))
-            .valid(false));
-    ret.add(new ValidationTestCase<Sample>("tooLongPayload")
-            .adjustment(x -> x.setPayload(RandomStringUtils.randomAlphanumeric(513)))
-            .valid(false));
-    return ret;
-  }
-
-}
\ No newline at end of file


[fineract-cn-reporting] 42/47: Merge pull request #7 from aasaru/artifactory

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit 162148acde09c64c16f0e666465090a189da9141
Merge: 1e50d2d c608895
Author: Awasum Yannick <aw...@apache.org>
AuthorDate: Tue Apr 30 09:20:24 2019 +0100

    Merge pull request #7 from aasaru/artifactory
    
    FINCN-148 build with travis-ci.com and upload artifacts to Artifactory

 .travis.yml                 | 30 +++++++++++++++++++
 README.md                   |  2 +-
 api/build.gradle            |  3 +-
 build.gradle                |  8 +++++
 component-test/build.gradle |  4 ++-
 service/build.gradle        |  5 ++--
 shared.gradle               | 17 +++++++++++
 travis.sh                   | 71 +++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 135 insertions(+), 5 deletions(-)


[fineract-cn-reporting] 27/47: Updated copyright information in reporting

Posted by aw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

awasum pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git

commit f61acd9c411b4028540f5d58c3ae318699afab77
Author: Isaac Kamga <u2...@gmail.com>
AuthorDate: Fri Mar 2 22:20:04 2018 +0100

    Updated copyright information in reporting
---
 HEADER                                             | 25 +++++++++++--------
 NOTICE.txt                                         |  5 ++++
 README.md                                          |  2 +-
 .../io/mifos/reporting/api/v1/EventConstants.java  | 25 +++++++++++--------
 .../reporting/api/v1/PermittableGroupIds.java      | 25 +++++++++++--------
 .../reporting/api/v1/client/ReportManager.java     | 25 +++++++++++--------
 .../api/v1/client/ReportNotFoundException.java     | 25 +++++++++++--------
 .../client/ReportParameterValidationException.java | 25 +++++++++++--------
 .../api/v1/domain/AutoCompleteResource.java        | 25 +++++++++++--------
 .../reporting/api/v1/domain/DisplayableField.java  | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Footer.java   | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Header.java   | 25 +++++++++++--------
 .../reporting/api/v1/domain/QueryParameter.java    | 25 +++++++++++--------
 .../reporting/api/v1/domain/ReportDefinition.java  | 25 +++++++++++--------
 .../mifos/reporting/api/v1/domain/ReportPage.java  | 25 +++++++++++--------
 .../reporting/api/v1/domain/ReportRequest.java     | 25 +++++++++++--------
 .../java/io/mifos/reporting/api/v1/domain/Row.java | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Type.java     | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Value.java    | 25 +++++++++++--------
 .../io/mifos/reporting/api/v1/domain/Sample.java   | 25 +++++++++++--------
 .../mifos/reporting/api/v1/domain/SampleTest.java  | 25 +++++++++++--------
 .../AbstractReportingSpecificationTest.java        | 25 +++++++++++--------
 .../TestBalanceSheetReportSpecification.java       | 25 +++++++++++--------
 .../TestCustomerListReportSpecification.java       | 25 +++++++++++--------
 .../TestDepositListReportSpecification.java        | 25 +++++++++++--------
 .../TestIncomeStatementReportSpecification.java    | 25 +++++++++++--------
 .../reporting/TestLoanListReportSpecification.java | 25 +++++++++++--------
 .../TestTellerListReportSpecification.java         | 25 +++++++++++--------
 .../TestTellerTransactionReportSpecification.java  | 25 +++++++++++--------
 component-test/src/main/resources/logback-test.xml | 25 +++++++++++--------
 .../reporting/service/ReportingApplication.java    | 25 +++++++++++--------
 .../reporting/service/ReportingConfiguration.java  | 25 +++++++++++--------
 .../mifos/reporting/service/ServiceConstants.java  | 25 +++++++++++--------
 .../provider/ReportSpecificationProvider.java      | 25 +++++++++++--------
 .../service/internal/repository/DummyEntity.java   | 25 +++++++++++--------
 .../internal/repository/DummyRepository.java       | 25 +++++++++++--------
 .../BalanceSheetReportSpecification.java           | 25 +++++++++++--------
 .../CustomerListReportSpecification.java           | 25 +++++++++++--------
 .../DepositListReportSpecification.java            | 25 +++++++++++--------
 .../IncomeStatementReportSpecification.java        | 25 +++++++++++--------
 .../specification/LoanListReportSpecification.java | 25 +++++++++++--------
 .../OfficeListReportSpecification.java             | 25 +++++++++++--------
 .../TellerListReportSpecification.java             | 25 +++++++++++--------
 .../TellerTransactionReportSpecification.java      | 25 +++++++++++--------
 .../service/rest/ReportingRestController.java      | 25 +++++++++++--------
 .../reporting/service/spi/CriteriaBuilder.java     | 25 +++++++++++--------
 .../service/spi/DisplayableFieldBuilder.java       | 25 +++++++++++--------
 .../service/spi/QueryParameterBuilder.java         | 25 +++++++++++--------
 .../io/mifos/reporting/service/spi/Report.java     | 25 +++++++++++--------
 .../reporting/service/spi/ReportSpecification.java | 25 +++++++++++--------
 service/src/main/resources/ESAPI.properties        | 29 ++++++++++++----------
 service/src/main/resources/application.yml         | 25 +++++++++++--------
 service/src/main/resources/bootstrap.yml           | 25 +++++++++++--------
 service/src/main/resources/logback.xml             | 29 ++++++++++++----------
 service/src/main/resources/validation.properties   | 29 ++++++++++++----------
 shared.gradle                                      |  2 +-
 56 files changed, 755 insertions(+), 591 deletions(-)

diff --git a/HEADER b/HEADER
index 4b2eadf..90705e0 100644
--- a/HEADER
+++ b/HEADER
@@ -1,13 +1,16 @@
-Copyright ${year} ${name}.
+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
 
-Licensed 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
 
-   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.
\ No newline at end of file
+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.
\ No newline at end of file
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..80313f7
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Fineract CN Reporting
+Copyright [2017-2018] The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
diff --git a/README.md b/README.md
index dfc7228..602a578 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Mifos I/O Reporting
+# Apache Fineract CN Reporting
 
 [![Join the chat at https://gitter.im/mifos-initiative/mifos.io](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mifos-initiative/mifos.io?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java b/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
index a80adec..c274750 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/EventConstants.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java b/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
index 8e28149..b3363a3 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/PermittableGroupIds.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
index 950ba6b..4f78218 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportManager.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.client;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java
index 4bbbec2..dc1ea5a 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportNotFoundException.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.client;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java
index 103922a..52a7b1e 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/client/ReportParameterValidationException.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.client;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java
index 7dbebba..b72db87 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/AutoCompleteResource.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java
index 0e40dbe..5a11707 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/DisplayableField.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java
index 918699e..06bc5d2 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Footer.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java
index e153c68..b2eca21 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Header.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java
index 70ec286..ba03e8b 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/QueryParameter.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java
index 03898f8..898252c 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportDefinition.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
index 2bd088f..5720e5d 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportPage.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java
index 199cf08..596574b 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/ReportRequest.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java
index 576cbcc..22e631d 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Row.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java
index 20f46c9..45abcf3 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Type.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java b/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
index 6887781..d9c1b6a 100644
--- a/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
+++ b/api/src/main/java/io/mifos/reporting/api/v1/domain/Value.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java b/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
index 6f63318..ac319d1 100644
--- a/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
+++ b/api/src/test/java/io/mifos/reporting/api/v1/domain/Sample.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java b/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java
index 2a304cc..2bdb53b 100644
--- a/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java
+++ b/api/src/test/java/io/mifos/reporting/api/v1/domain/SampleTest.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.api.v1.domain;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java b/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
index 47fc8a7..b6282d9 100644
--- a/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
+++ b/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java
index 3e81b69..a64b19c 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java
+++ b/component-test/src/main/java/io/mifos/reporting/TestBalanceSheetReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java
index dfabeaf..fdef649 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java
+++ b/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java
index cf49e91..092b365 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java
+++ b/component-test/src/main/java/io/mifos/reporting/TestDepositListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java
index 4d3a69b..f65dfe6 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java
+++ b/component-test/src/main/java/io/mifos/reporting/TestIncomeStatementReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java
index 40fff05..346444b 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java
+++ b/component-test/src/main/java/io/mifos/reporting/TestLoanListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java
index 4b17f3b..419f0f2 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java
+++ b/component-test/src/main/java/io/mifos/reporting/TestTellerListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting;
 
diff --git a/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java b/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java
index 6ea4da5..75eba2b 100644
--- a/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java
+++ b/component-test/src/main/java/io/mifos/reporting/TestTellerTransactionReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting;
 
diff --git a/component-test/src/main/resources/logback-test.xml b/component-test/src/main/resources/logback-test.xml
index 735b8e5..a3c21c7 100644
--- a/component-test/src/main/resources/logback-test.xml
+++ b/component-test/src/main/resources/logback-test.xml
@@ -1,18 +1,21 @@
 <!--
 
-    Copyright 2017 The Mifos Initiative.
+    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
 
-    Licensed 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
 
-       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.
+    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.
 
 -->
 <configuration>
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java b/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java
index 8f4ae05..02b0d84 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingApplication.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
index 1289d02..cf7708c 100644
--- a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
+++ b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java b/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java
index 0cc54b5..b5cb983 100644
--- a/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java
+++ b/service/src/main/java/io/mifos/reporting/service/ServiceConstants.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java b/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
index 3c9b646..f6393ff 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.provider;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
index 2e53063..05e080a 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyEntity.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.repository;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
index 0c70de7..bdca566 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/repository/DummyRepository.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.repository;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
index 1c6810e..aed5953 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/BalanceSheetReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.specification;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
index 90bfbd9..cbb45d6 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.specification;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
index 8e37df7..458a081 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/DepositListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.specification;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
index c535d22..7f5c678 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/IncomeStatementReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.specification;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
index 4c71929..6017321 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/LoanListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.specification;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
index 9b06000..f1c118d 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/OfficeListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.specification;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
index 33cc53c..a00db8f 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerListReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.specification;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
index 245f3ad..c196e92 100644
--- a/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/TellerTransactionReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.internal.specification;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
index dc5c02f..7970f8a 100644
--- a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
+++ b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.rest;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
index 53157b6..30a2c09 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/CriteriaBuilder.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.spi;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java
index 987ad9b..eba5094 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.spi;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java
index 00251f3..23eece5 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.spi;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/Report.java b/service/src/main/java/io/mifos/reporting/service/spi/Report.java
index ec40ec8..4268f0b 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/Report.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/Report.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.spi;
 
diff --git a/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
index 0508411..3511815 100644
--- a/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
+++ b/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java
@@ -1,17 +1,20 @@
 /*
- * Copyright 2017 The Mifos Initiative.
+ * 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
  *
- * Licensed 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
  *
- *    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.
+ * 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 io.mifos.reporting.service.spi;
 
diff --git a/service/src/main/resources/ESAPI.properties b/service/src/main/resources/ESAPI.properties
index d9a26e3..38f0b44 100644
--- a/service/src/main/resources/ESAPI.properties
+++ b/service/src/main/resources/ESAPI.properties
@@ -1,17 +1,20 @@
 #
-# Copyright 2017 The Mifos Initiative.
-#
-# Licensed 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.
+# 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.
 #
 
 # ESAPI is designed to be easily extensible. You can use the reference implementation
diff --git a/service/src/main/resources/application.yml b/service/src/main/resources/application.yml
index 4adf77d..a209538 100644
--- a/service/src/main/resources/application.yml
+++ b/service/src/main/resources/application.yml
@@ -1,17 +1,20 @@
 #
-# Copyright 2017 The Mifos Initiative.
+# 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
 #
-# Licensed 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
 #
-#    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.
+# 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.
 #
 
 spring:
diff --git a/service/src/main/resources/bootstrap.yml b/service/src/main/resources/bootstrap.yml
index fbf1a04..923d09e 100644
--- a/service/src/main/resources/bootstrap.yml
+++ b/service/src/main/resources/bootstrap.yml
@@ -1,17 +1,20 @@
 #
-# Copyright 2017 The Mifos Initiative.
+# 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
 #
-# Licensed 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
 #
-#    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.
+# 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.
 #
 
 spring:
diff --git a/service/src/main/resources/logback.xml b/service/src/main/resources/logback.xml
index 75132d7..252f94e 100644
--- a/service/src/main/resources/logback.xml
+++ b/service/src/main/resources/logback.xml
@@ -1,18 +1,21 @@
 <!--
 
-    Copyright 2017 The Mifos Initiative.
-
-    Licensed 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.
+    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.
 
 -->
 <configuration>
diff --git a/service/src/main/resources/validation.properties b/service/src/main/resources/validation.properties
index 02dea07..b229c8c 100644
--- a/service/src/main/resources/validation.properties
+++ b/service/src/main/resources/validation.properties
@@ -1,17 +1,20 @@
 #
-# Copyright 2017 The Mifos Initiative.
-#
-# Licensed 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.
+# 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.
 #
 
 # The ESAPI validator does many security checks on input, such as canonicalization
diff --git a/shared.gradle b/shared.gradle
index c4a540c..d189c84 100644
--- a/shared.gradle
+++ b/shared.gradle
@@ -65,5 +65,5 @@ license {
         yaml = 'SCRIPT_STYLE'
     }
     ext.year = Calendar.getInstance().get(Calendar.YEAR)
-    ext.name = 'The Mifos Initiative'
+    ext.name = 'The Apache Software Foundation'
 }