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

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

commit 6384b85d61fe9b1c4abb4b7f5a8d44d5bed1cf92
Author: mgeiss <[email protected]>
AuthorDate: Tue Oct 10 11:16:08 2017 +0200

    added income statement implementation
    added ledger total value
---
 .../accounting/api/v1/domain/IncomeStatement.java  |  11 +-
 .../api/v1/domain/IncomeStatementSection.java      |  17 ++-
 .../io/mifos/accounting/api/v1/domain/Ledger.java  |  10 ++
 .../io/mifos/accounting/TestIncomeStatement.java   | 152 +++++++++++++++++++++
 .../accounting/util/JournalEntryGenerator.java     |  12 +-
 component-test/src/main/resources/logback-test.xml |   2 +-
 .../AddAmountToLedgerTotalCommand.java}            |  26 ++--
 .../command/handler/AccountCommandHandler.java     |  18 +++
 .../command/handler/LedgerCommandHandler.java      |  29 +++-
 .../command/handler/MigrationCommandHandler.java   |  53 ++++++-
 .../service/internal/mapper/LedgerMapper.java      |   4 +
 .../internal/repository/AccountRepository.java     |   3 +
 .../service/internal/repository/LedgerEntity.java  |  11 ++
 .../internal/repository/LedgerRepository.java      |   2 +
 .../internal/service/IncomeStatementService.java   |  81 +++++++++++
 .../internal/service/TrialBalanceService.java      |  57 ++++----
 .../service/rest/IncomeStatementController.java    |  53 +++++++
 .../mariadb/V9__add_total_value_ledger.sql         |  17 +++
 18 files changed, 496 insertions(+), 62 deletions(-)

diff --git 
a/api/src/main/java/io/mifos/accounting/api/v1/domain/IncomeStatement.java 
b/api/src/main/java/io/mifos/accounting/api/v1/domain/IncomeStatement.java
index a96c9ca..8ed5678 100644
--- a/api/src/main/java/io/mifos/accounting/api/v1/domain/IncomeStatement.java
+++ b/api/src/main/java/io/mifos/accounting/api/v1/domain/IncomeStatement.java
@@ -19,6 +19,7 @@ import org.hibernate.validator.constraints.NotEmpty;
 
 import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.List;
 
 public class IncomeStatement {
@@ -26,7 +27,7 @@ public class IncomeStatement {
   @NotEmpty
   private String date;
   @NotEmpty
-  private List<IncomeStatementSection> incomeStatementSections;
+  private List<IncomeStatementSection> incomeStatementSections = new 
ArrayList<>();
   @NotNull
   private BigDecimal grossProfit;
   @NotNull
@@ -50,10 +51,6 @@ public class IncomeStatement {
     return this.incomeStatementSections;
   }
 
-  public void setIncomeStatementSections(final List<IncomeStatementSection> 
incomeStatementSections) {
-    this.incomeStatementSections = incomeStatementSections;
-  }
-
   public BigDecimal getGrossProfit() {
     return this.grossProfit;
   }
@@ -77,4 +74,8 @@ public class IncomeStatement {
   public void setNetIncome(final BigDecimal netIncome) {
     this.netIncome = netIncome;
   }
+
+  public void add(final IncomeStatementSection incomeStatementSection) {
+    this.incomeStatementSections.add(incomeStatementSection);
+  }
 }
diff --git 
a/api/src/main/java/io/mifos/accounting/api/v1/domain/IncomeStatementSection.java
 
b/api/src/main/java/io/mifos/accounting/api/v1/domain/IncomeStatementSection.java
index c1ba67d..cbe21f9 100644
--- 
a/api/src/main/java/io/mifos/accounting/api/v1/domain/IncomeStatementSection.java
+++ 
b/api/src/main/java/io/mifos/accounting/api/v1/domain/IncomeStatementSection.java
@@ -19,22 +19,24 @@ import org.hibernate.validator.constraints.NotEmpty;
 
 import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.List;
 
 public class IncomeStatementSection {
 
-  enum Type {
+  public enum Type {
     INCOME,
     EXPENSES
   }
 
   @NotEmpty
   private Type type;
+  @NotEmpty
   private String description;
   @NotEmpty
-  private List<IncomeStatementEntry> incomeStatementEntries;
+  private List<IncomeStatementEntry> incomeStatementEntries = new 
ArrayList<>();
   @NotNull
-  private BigDecimal subtotal;
+  private BigDecimal subtotal = BigDecimal.ZERO;
 
   public IncomeStatementSection() {
     super();
@@ -60,15 +62,12 @@ public class IncomeStatementSection {
     return this.incomeStatementEntries;
   }
 
-  public void setIncomeStatementEntries(final List<IncomeStatementEntry> 
incomeStatementEntries) {
-    this.incomeStatementEntries = incomeStatementEntries;
-  }
-
   public BigDecimal getSubtotal() {
     return this.subtotal;
   }
 
-  public void setSubtotal(final BigDecimal subtotal) {
-    this.subtotal = subtotal;
+  public void add(final IncomeStatementEntry incomeStatementEntry) {
+    this.incomeStatementEntries.add(incomeStatementEntry);
+    this.subtotal = this.subtotal.add(incomeStatementEntry.getValue());
   }
 }
diff --git a/api/src/main/java/io/mifos/accounting/api/v1/domain/Ledger.java 
b/api/src/main/java/io/mifos/accounting/api/v1/domain/Ledger.java
index 3c58ad2..a9a08f3 100644
--- a/api/src/main/java/io/mifos/accounting/api/v1/domain/Ledger.java
+++ b/api/src/main/java/io/mifos/accounting/api/v1/domain/Ledger.java
@@ -20,6 +20,7 @@ import org.hibernate.validator.constraints.NotEmpty;
 
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
 import java.util.List;
 
 @SuppressWarnings({"unused"})
@@ -35,6 +36,7 @@ public final class Ledger {
   private String parentLedgerIdentifier;
   @Valid
   private List<Ledger> subLedgers;
+  private BigDecimal totalValue;
   private String createdOn;
   private String createdBy;
   private String lastModifiedOn;
@@ -94,6 +96,14 @@ public final class Ledger {
     this.subLedgers = subLedgers;
   }
 
+  public BigDecimal getTotalValue() {
+    return this.totalValue;
+  }
+
+  public void setTotalValue(final BigDecimal totalValue) {
+    this.totalValue = totalValue;
+  }
+
   public String getCreatedOn() {
     return this.createdOn;
   }
diff --git 
a/component-test/src/main/java/io/mifos/accounting/TestIncomeStatement.java 
b/component-test/src/main/java/io/mifos/accounting/TestIncomeStatement.java
new file mode 100644
index 0000000..801c492
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/accounting/TestIncomeStatement.java
@@ -0,0 +1,152 @@
+/*
+ * 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.accounting;
+
+import io.mifos.accounting.api.v1.EventConstants;
+import io.mifos.accounting.api.v1.domain.Account;
+import io.mifos.accounting.api.v1.domain.AccountType;
+import io.mifos.accounting.api.v1.domain.IncomeStatement;
+import io.mifos.accounting.api.v1.domain.JournalEntry;
+import io.mifos.accounting.api.v1.domain.Ledger;
+import io.mifos.accounting.util.AccountGenerator;
+import io.mifos.accounting.util.JournalEntryGenerator;
+import io.mifos.accounting.util.LedgerGenerator;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+
+public class TestIncomeStatement extends AbstractAccountingTest {
+
+  public TestIncomeStatement() {
+    super();
+  }
+
+  @Test
+  public void shouldReturnIncomeStatement() throws Exception {
+    this.fixtures();
+    this.sampleJournalEntries();
+
+    final BigDecimal expectedGrossProfit = BigDecimal.valueOf(350.00D);
+    final BigDecimal expectedTotalExpenses = BigDecimal.valueOf(125.00D);
+    final BigDecimal expectedNetIncome = 
expectedGrossProfit.subtract(expectedTotalExpenses);
+
+    final IncomeStatement incomeStatement = 
super.testSubject.getIncomeStatement();
+    
Assert.assertTrue(incomeStatement.getGrossProfit().compareTo(expectedGrossProfit)
 == 0);
+    
Assert.assertTrue(incomeStatement.getTotalExpenses().compareTo(expectedTotalExpenses)
 == 0);
+    
Assert.assertTrue(incomeStatement.getNetIncome().compareTo(expectedNetIncome) 
== 0);
+  }
+
+  private void fixtures() throws Exception {
+    final Ledger incomeLedger = LedgerGenerator.createLedger("1000", 
AccountType.REVENUE);
+    incomeLedger.setName("Income");
+    super.testSubject.createLedger(incomeLedger);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, 
incomeLedger.getIdentifier()));
+
+    final Ledger incomeSubLedger1100 = LedgerGenerator.createLedger("1100", 
AccountType.REVENUE);
+    
incomeSubLedger1100.setParentLedgerIdentifier(incomeLedger.getParentLedgerIdentifier());
+    incomeSubLedger1100.setName("Income From Loans");
+    super.testSubject.addSubLedger(incomeLedger.getIdentifier(), 
incomeSubLedger1100);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, 
incomeSubLedger1100.getIdentifier()));
+
+    final Ledger incomeSubLedger1300 = LedgerGenerator.createLedger("1300", 
AccountType.REVENUE);
+    
incomeSubLedger1300.setParentLedgerIdentifier(incomeLedger.getParentLedgerIdentifier());
+    incomeSubLedger1300.setName("Fees and Charges");
+    super.testSubject.addSubLedger(incomeLedger.getIdentifier(), 
incomeSubLedger1300);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, 
incomeSubLedger1300.getIdentifier()));
+
+    final Account account1110 =
+        AccountGenerator.createAccount(incomeSubLedger1100.getIdentifier(), 
"1110", AccountType.REVENUE);
+    super.testSubject.createAccount(account1110);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, 
account1110.getIdentifier()));
+
+    final Account account1310 =
+        AccountGenerator.createAccount(incomeSubLedger1300.getIdentifier(), 
"1310", AccountType.REVENUE);
+    super.testSubject.createAccount(account1310);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, 
account1310.getIdentifier()));
+
+    final Ledger expenseLedger = LedgerGenerator.createLedger("3000", 
AccountType.EXPENSE);
+    expenseLedger.setName("Expenses");
+    super.testSubject.createLedger(expenseLedger);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, 
expenseLedger.getIdentifier()));
+
+    final Ledger expenseSubLedger3500 = LedgerGenerator.createLedger("3500", 
AccountType.EXPENSE);
+    
expenseSubLedger3500.setParentLedgerIdentifier(expenseLedger.getParentLedgerIdentifier());
+    expenseSubLedger3500.setName("Annual Meeting Expenses");
+    super.testSubject.addSubLedger(expenseLedger.getIdentifier(), 
expenseSubLedger3500);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, 
expenseSubLedger3500.getIdentifier()));
+
+    final Ledger expenseSubLedger3700 = LedgerGenerator.createLedger("3700", 
AccountType.EXPENSE);
+    
expenseSubLedger3700.setParentLedgerIdentifier(expenseLedger.getParentLedgerIdentifier());
+    expenseSubLedger3700.setName("Interest (Dividend) Expense");
+    super.testSubject.addSubLedger(expenseLedger.getIdentifier(), 
expenseSubLedger3700);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, 
expenseSubLedger3700.getIdentifier()));
+
+    final Account account3510 =
+        AccountGenerator.createAccount(expenseSubLedger3500.getIdentifier(), 
"3510", AccountType.EXPENSE);
+    super.testSubject.createAccount(account3510);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, 
account3510.getIdentifier()));
+
+    final Account account3710 =
+        AccountGenerator.createAccount(expenseSubLedger3700.getIdentifier(), 
"3710", AccountType.EXPENSE);
+    super.testSubject.createAccount(account3710);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, 
account3710.getIdentifier()));
+
+    final Ledger assetLedger = LedgerGenerator.createLedger("7000", 
AccountType.ASSET);
+    super.testSubject.createLedger(assetLedger);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, 
assetLedger.getIdentifier()));
+
+    final Account assetAccount =
+        AccountGenerator.createAccount(assetLedger.getIdentifier(), "7010", 
AccountType.ASSET);
+    super.testSubject.createAccount(assetAccount);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, 
assetAccount.getIdentifier()));
+
+    final Ledger liabilityLedger = LedgerGenerator.createLedger("8000", 
AccountType.LIABILITY);
+    super.testSubject.createLedger(liabilityLedger);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, 
liabilityLedger.getIdentifier()));
+
+    final Account liabilityAccount =
+        AccountGenerator.createAccount(liabilityLedger.getIdentifier(), 
"8010", AccountType.LIABILITY);
+    super.testSubject.createAccount(liabilityAccount);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, 
liabilityAccount.getIdentifier()));
+  }
+
+  private void sampleJournalEntries() throws Exception {
+    final JournalEntry firstTransaction =
+        JournalEntryGenerator
+            .createRandomJournalEntry("7010", "150.00", "1110", "150.00");
+    super.testSubject.createJournalEntry(firstTransaction);
+    
Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, 
firstTransaction.getTransactionIdentifier()));
+
+    final JournalEntry secondTransaction =
+        JournalEntryGenerator
+            .createRandomJournalEntry("7010", "200.00", "1310", "200.00");
+    super.testSubject.createJournalEntry(secondTransaction);
+    
Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, 
secondTransaction.getTransactionIdentifier()));
+
+    final JournalEntry thirdTransaction =
+        JournalEntryGenerator
+            .createRandomJournalEntry("3510", "50.00", "8010", "50.00");
+    super.testSubject.createJournalEntry(thirdTransaction);
+    
Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, 
thirdTransaction.getTransactionIdentifier()));
+
+    final JournalEntry fourthTransaction =
+        JournalEntryGenerator
+            .createRandomJournalEntry("3710", "75.00", "8010", "75.00");
+    super.testSubject.createJournalEntry(fourthTransaction);
+    
Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, 
fourthTransaction.getTransactionIdentifier()));
+  }
+}
diff --git 
a/component-test/src/main/java/io/mifos/accounting/util/JournalEntryGenerator.java
 
b/component-test/src/main/java/io/mifos/accounting/util/JournalEntryGenerator.java
index 1a3a4e5..b86f344 100644
--- 
a/component-test/src/main/java/io/mifos/accounting/util/JournalEntryGenerator.java
+++ 
b/component-test/src/main/java/io/mifos/accounting/util/JournalEntryGenerator.java
@@ -38,6 +38,14 @@ public class JournalEntryGenerator {
                                                       final String 
debtorAmount,
                                                       final Account 
creditorAccount,
                                                       final String 
creditorAmount) {
+    return JournalEntryGenerator
+        .createRandomJournalEntry(debtorAccount.getIdentifier(), debtorAmount, 
creditorAccount.getIdentifier(), creditorAmount);
+  }
+
+  public static JournalEntry createRandomJournalEntry(final String 
debtorAccount,
+                                                      final String 
debtorAmount,
+                                                      final String 
creditorAccount,
+                                                      final String 
creditorAmount) {
     final JournalEntry journalEntry = new JournalEntry();
     
journalEntry.setTransactionIdentifier(RandomStringUtils.randomAlphanumeric(8));
     
journalEntry.setTransactionDate(ZonedDateTime.now(Clock.systemUTC()).format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
@@ -45,7 +53,7 @@ public class JournalEntryGenerator {
     journalEntry.setClerk("clark");
     if (debtorAccount != null) {
       final Debtor debtor = new Debtor();
-      debtor.setAccountNumber(debtorAccount.getIdentifier());
+      debtor.setAccountNumber(debtorAccount);
       debtor.setAmount(debtorAmount);
       journalEntry.setDebtors(new 
HashSet<>(Collections.singletonList(debtor)));
     } else {
@@ -53,7 +61,7 @@ public class JournalEntryGenerator {
     }
     if (creditorAccount != null) {
       final Creditor creditor = new Creditor();
-      creditor.setAccountNumber(creditorAccount.getIdentifier());
+      creditor.setAccountNumber(creditorAccount);
       creditor.setAmount(creditorAmount);
       journalEntry.setCreditors(new 
HashSet<>(Collections.singletonList(creditor)));
     } else {
diff --git a/component-test/src/main/resources/logback-test.xml 
b/component-test/src/main/resources/logback-test.xml
index ffad21f..735b8e5 100644
--- a/component-test/src/main/resources/logback-test.xml
+++ b/component-test/src/main/resources/logback-test.xml
@@ -26,7 +26,7 @@
     <logger name="com" level="OFF"/>
     <logger name="ch" level="OFF"/>
 
-    <root level="INFO">
+    <root level="DEBUG">
         <appender-ref ref="STDOUT"/>
     </root>
 </configuration>
\ No newline at end of file
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerRepository.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/command/AddAmountToLedgerTotalCommand.java
similarity index 50%
copy from 
service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerRepository.java
copy to 
service/src/main/java/io/mifos/accounting/service/internal/command/AddAmountToLedgerTotalCommand.java
index e0edce3..771f384 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerRepository.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/command/AddAmountToLedgerTotalCommand.java
@@ -13,20 +13,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.accounting.service.internal.repository;
+package io.mifos.accounting.service.internal.command;
 
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-import org.springframework.stereotype.Repository;
+import java.math.BigDecimal;
 
-import java.util.List;
+public class AddAmountToLedgerTotalCommand {
 
-@Repository
-public interface LedgerRepository extends JpaRepository<LedgerEntity, Long>, 
JpaSpecificationExecutor<LedgerEntity> {
+  private final String ledgerIdentifier;
+  private final BigDecimal amount;
 
-  List<LedgerEntity> findByParentLedgerIsNull();
+  public AddAmountToLedgerTotalCommand(final String ledgerIdentifier, final 
BigDecimal amount) {
+    super();
+    this.ledgerIdentifier = ledgerIdentifier;
+    this.amount = amount;
+  }
 
-  List<LedgerEntity> findByParentLedgerOrderByIdentifier(final LedgerEntity 
parentLedger);
+  public String ledgerIdentifier() {
+    return this.ledgerIdentifier;
+  }
 
-  LedgerEntity findByIdentifier(final String identifier);
+  public BigDecimal amount() {
+    return this.amount;
+  }
 }
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/command/handler/AccountCommandHandler.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/command/handler/AccountCommandHandler.java
index f0bab24..8c30e02 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/command/handler/AccountCommandHandler.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/command/handler/AccountCommandHandler.java
@@ -21,6 +21,7 @@ import io.mifos.accounting.api.v1.domain.AccountCommand;
 import io.mifos.accounting.api.v1.domain.AccountEntry;
 import io.mifos.accounting.api.v1.domain.AccountType;
 import io.mifos.accounting.api.v1.domain.JournalEntry;
+import 
io.mifos.accounting.service.internal.command.AddAmountToLedgerTotalCommand;
 import io.mifos.accounting.service.internal.command.BookJournalEntryCommand;
 import io.mifos.accounting.service.internal.command.CloseAccountCommand;
 import io.mifos.accounting.service.internal.command.CreateAccountCommand;
@@ -51,6 +52,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.List;
@@ -326,16 +328,21 @@ public class AccountCommandHandler {
             final String accountNumber = debtor.getAccountNumber();
             final AccountEntity accountEntity = 
this.accountRepository.findByIdentifier(accountNumber);
             final AccountType accountType = 
AccountType.valueOf(accountEntity.getType());
+            final BigDecimal amount;
             switch (accountType) {
               case ASSET:
               case EXPENSE:
                 accountEntity.setBalance(accountEntity.getBalance() + 
debtor.getAmount());
+                amount = BigDecimal.valueOf(debtor.getAmount());
                 break;
               case LIABILITY:
               case EQUITY:
               case REVENUE:
                 accountEntity.setBalance(accountEntity.getBalance() - 
debtor.getAmount());
+                amount = BigDecimal.valueOf(debtor.getAmount()).negate();
                 break;
+              default:
+                amount = BigDecimal.ZERO;
             }
             final AccountEntity savedAccountEntity = 
this.accountRepository.save(accountEntity);
             final AccountEntryEntity accountEntryEntity = new 
AccountEntryEntity();
@@ -346,6 +353,9 @@ public class AccountCommandHandler {
             accountEntryEntity.setMessage(journalEntryEntity.getMessage());
             
accountEntryEntity.setTransactionDate(journalEntryEntity.getTransactionDate());
             this.accountEntryRepository.save(accountEntryEntity);
+            this.commandGateway.process(
+                new 
AddAmountToLedgerTotalCommand(savedAccountEntity.getLedger().getIdentifier(), 
amount)
+            );
           });
       // process all creditors
       journalEntryEntity.getCreditors()
@@ -353,16 +363,21 @@ public class AccountCommandHandler {
             final String accountNumber = creditor.getAccountNumber();
             final AccountEntity accountEntity = 
this.accountRepository.findByIdentifier(accountNumber);
             final AccountType accountType = 
AccountType.valueOf(accountEntity.getType());
+            final BigDecimal amount;
             switch (accountType) {
               case ASSET:
               case EXPENSE:
                 accountEntity.setBalance(accountEntity.getBalance() - 
creditor.getAmount());
+                amount = BigDecimal.valueOf(creditor.getAmount()).negate();
                 break;
               case LIABILITY:
               case EQUITY:
               case REVENUE:
                 accountEntity.setBalance(accountEntity.getBalance() + 
creditor.getAmount());
+                amount = BigDecimal.valueOf(creditor.getAmount());
                 break;
+              default:
+                amount = BigDecimal.ZERO;
             }
             final AccountEntity savedAccountEntity = 
this.accountRepository.save(accountEntity);
             final AccountEntryEntity accountEntryEntity = new 
AccountEntryEntity();
@@ -373,6 +388,9 @@ public class AccountCommandHandler {
             accountEntryEntity.setMessage(journalEntryEntity.getMessage());
             
accountEntryEntity.setTransactionDate(journalEntryEntity.getTransactionDate());
             this.accountEntryRepository.save(accountEntryEntity);
+            this.commandGateway.process(
+                new 
AddAmountToLedgerTotalCommand(savedAccountEntity.getLedger().getIdentifier(), 
amount)
+            );
           });
       this.commandGateway.process(new 
ReleaseJournalEntryCommand(transactionIdentifier));
       return transactionIdentifier;
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/command/handler/LedgerCommandHandler.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/command/handler/LedgerCommandHandler.java
index fe88d88..4d96c8e 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/command/handler/LedgerCommandHandler.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/command/handler/LedgerCommandHandler.java
@@ -18,6 +18,7 @@ package io.mifos.accounting.service.internal.command.handler;
 import io.mifos.accounting.api.v1.EventConstants;
 import io.mifos.accounting.api.v1.domain.Ledger;
 import io.mifos.accounting.service.ServiceConstants;
+import 
io.mifos.accounting.service.internal.command.AddAmountToLedgerTotalCommand;
 import io.mifos.accounting.service.internal.command.AddSubLedgerCommand;
 import io.mifos.accounting.service.internal.command.CreateLedgerCommand;
 import io.mifos.accounting.service.internal.command.DeleteLedgerCommand;
@@ -29,12 +30,14 @@ import io.mifos.core.command.annotation.Aggregate;
 import io.mifos.core.command.annotation.CommandHandler;
 import io.mifos.core.command.annotation.CommandLogLevel;
 import io.mifos.core.command.annotation.EventEmitter;
+import io.mifos.core.command.gateway.CommandGateway;
 import io.mifos.core.lang.ServiceException;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.time.Clock;
 import java.time.LocalDateTime;
 import java.util.Collections;
@@ -46,13 +49,16 @@ public class LedgerCommandHandler {
 
   private final Logger logger;
   private final LedgerRepository ledgerRepository;
+  private final CommandGateway commandGateway;
 
   @Autowired
   public LedgerCommandHandler(@Qualifier(ServiceConstants.LOGGER_NAME) final 
Logger logger,
-                              final LedgerRepository ledgerRepository) {
+                              final LedgerRepository ledgerRepository,
+                              final CommandGateway commandGateway) {
     super();
     this.logger = logger;
     this.ledgerRepository = ledgerRepository;
+    this.commandGateway = commandGateway;
   }
 
   @Transactional
@@ -164,4 +170,25 @@ public class LedgerCommandHandler {
       }
     }
   }
+
+  @Transactional
+  @CommandHandler
+  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = 
EventConstants.PUT_LEDGER)
+  public String process(final AddAmountToLedgerTotalCommand 
addAmountToLedgerTotalCommand) {
+    final BigDecimal amount = addAmountToLedgerTotalCommand.amount();
+    if (amount.compareTo(BigDecimal.ZERO) != 0) {
+      final LedgerEntity ledger = 
this.ledgerRepository.findByIdentifier(addAmountToLedgerTotalCommand.ledgerIdentifier());
+      final BigDecimal currentTotal = ledger.getTotalValue() != null ? 
ledger.getTotalValue() : BigDecimal.ZERO;
+      ledger.setTotalValue(currentTotal.add(amount));
+      final LedgerEntity savedLedger = this.ledgerRepository.save(ledger);
+      if (savedLedger.getParentLedger() != null) {
+        this.commandGateway.process(
+            new 
AddAmountToLedgerTotalCommand(savedLedger.getParentLedger().getIdentifier(), 
amount)
+        );
+      }
+      return savedLedger.getIdentifier();
+    } else {
+      return null;
+    }
+  }
 }
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/command/handler/MigrationCommandHandler.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/command/handler/MigrationCommandHandler.java
index 82a0943..0c497bf 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/command/handler/MigrationCommandHandler.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/command/handler/MigrationCommandHandler.java
@@ -18,7 +18,12 @@ package io.mifos.accounting.service.internal.command.handler;
 import com.datastax.driver.core.DataType;
 import com.datastax.driver.core.schemabuilder.SchemaBuilder;
 import io.mifos.accounting.api.v1.EventConstants;
+import io.mifos.accounting.service.ServiceConstants;
+import 
io.mifos.accounting.service.internal.command.AddAmountToLedgerTotalCommand;
 import io.mifos.accounting.service.internal.command.InitializeServiceCommand;
+import io.mifos.accounting.service.internal.repository.AccountEntity;
+import io.mifos.accounting.service.internal.repository.AccountRepository;
+import io.mifos.accounting.service.internal.service.AccountService;
 import io.mifos.core.cassandra.core.CassandraJourney;
 import io.mifos.core.cassandra.core.CassandraJourneyFactory;
 import io.mifos.core.cassandra.core.CassandraJourneyRoute;
@@ -27,10 +32,20 @@ import io.mifos.core.command.annotation.Aggregate;
 import io.mifos.core.command.annotation.CommandHandler;
 import io.mifos.core.command.annotation.CommandLogLevel;
 import io.mifos.core.command.annotation.EventEmitter;
+import io.mifos.core.command.gateway.CommandGateway;
 import io.mifos.core.mariadb.domain.FlywayFactoryBean;
+import org.flywaydb.core.Flyway;
+import org.flywaydb.core.api.MigrationInfo;
+import org.flywaydb.core.api.MigrationInfoService;
+import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 import javax.sql.DataSource;
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
 
 @SuppressWarnings({
     "unused"
@@ -38,28 +53,45 @@ import javax.sql.DataSource;
 @Aggregate
 public class MigrationCommandHandler {
 
+  private final Logger logger;
   private final DataSource dataSource;
   private final FlywayFactoryBean flywayFactoryBean;
   private final CassandraSessionProvider cassandraSessionProvider;
   private final CassandraJourneyFactory cassandraJourneyFactory;
+  private final CommandGateway commandGateway;
+  private final AccountRepository accountRepository;
 
   @SuppressWarnings("SpringJavaAutowiringInspection")
   @Autowired
-  public MigrationCommandHandler(final DataSource dataSource,
+  public MigrationCommandHandler(@Qualifier(ServiceConstants.LOGGER_NAME) 
final Logger logger,
+                                 final DataSource dataSource,
                                  final FlywayFactoryBean flywayFactoryBean,
                                  final CassandraSessionProvider 
cassandraSessionProvider,
-                                 final CassandraJourneyFactory 
cassandraJourneyFactory) {
+                                 final CassandraJourneyFactory 
cassandraJourneyFactory,
+                                 final CommandGateway commandGateway,
+                                 final AccountRepository accountRepository) {
     super();
+    this.logger = logger;
     this.dataSource = dataSource;
     this.flywayFactoryBean = flywayFactoryBean;
     this.cassandraSessionProvider = cassandraSessionProvider;
     this.cassandraJourneyFactory = cassandraJourneyFactory;
+    this.commandGateway = commandGateway;
+    this.accountRepository = accountRepository;
   }
 
   @CommandHandler(logStart = CommandLogLevel.DEBUG, logFinish = 
CommandLogLevel.DEBUG)
   @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = 
EventConstants.INITIALIZE)
   public String initialize(final InitializeServiceCommand 
initializeServiceCommand) {
-    this.flywayFactoryBean.create(this.dataSource).migrate();
+    final Flyway flyway = this.flywayFactoryBean.create(this.dataSource);
+
+    final MigrationInfoService migrationInfoService = flyway.info();
+    final List<MigrationInfo> migrationInfoList = 
Arrays.asList(migrationInfoService.applied());
+    final boolean shouldMigrateLedgerTotals = migrationInfoList
+        .stream()
+        .noneMatch(migrationInfo -> 
migrationInfo.getVersion().getVersion().equals("9"));
+
+    flyway.migrate();
 
     final String versionNumber = "1";
 
@@ -129,6 +161,21 @@ public class MigrationCommandHandler {
     cassandraJourney.start(updateRouteVersion2);
     cassandraJourney.start(updateRouteVersion3);
 
+    if (shouldMigrateLedgerTotals) {
+      this.migrateLedgerTotals();
+    }
+
     return versionNumber;
   }
+
+  private void migrateLedgerTotals() {
+    this.logger.info("Start ledger total migration ...");
+    try (final Stream<AccountEntity> accountEntityStream = 
this.accountRepository.findByBalanceIsNot(0.00D)) {
+      accountEntityStream.forEach(accountEntity ->
+          this.commandGateway.process(
+              new 
AddAmountToLedgerTotalCommand(accountEntity.getLedger().getIdentifier(), 
BigDecimal.valueOf(accountEntity.getBalance()))
+          )
+      );
+    }
+  }
 }
\ No newline at end of file
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/mapper/LedgerMapper.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/mapper/LedgerMapper.java
index 001cf4d..9971824 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/mapper/LedgerMapper.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/mapper/LedgerMapper.java
@@ -19,6 +19,8 @@ import io.mifos.accounting.api.v1.domain.Ledger;
 import io.mifos.accounting.service.internal.repository.LedgerEntity;
 import io.mifos.core.lang.DateConverter;
 
+import java.math.BigDecimal;
+
 public class LedgerMapper {
 
   private LedgerMapper() {
@@ -41,6 +43,8 @@ public class LedgerMapper {
       
ledger.setLastModifiedOn(DateConverter.toIsoString(ledgerEntity.getLastModifiedOn()));
     }
     ledger.setShowAccountsInChart(ledgerEntity.getShowAccountsInChart());
+    final BigDecimal totalValue = ledgerEntity.getTotalValue() != null ? 
ledgerEntity.getTotalValue() : BigDecimal.ZERO;
+    ledger.setTotalValue(totalValue);
     return ledger;
   }
 }
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/repository/AccountRepository.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/repository/AccountRepository.java
index e83a7ec..e499d2c 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/repository/AccountRepository.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/repository/AccountRepository.java
@@ -24,6 +24,7 @@ import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
 import java.util.List;
+import java.util.stream.Stream;
 
 @Repository
 public interface AccountRepository extends JpaRepository<AccountEntity, Long>, 
JpaSpecificationExecutor<AccountEntity> {
@@ -36,4 +37,6 @@ public interface AccountRepository extends 
JpaRepository<AccountEntity, Long>, J
 
   @Query("SELECT CASE WHEN count(a) > 0 THEN true ELSE false END FROM 
AccountEntity a where a.referenceAccount = :accountEntity")
   Boolean existsByReference(@Param("accountEntity") final AccountEntity 
accountEntity);
+
+  Stream<AccountEntity> findByBalanceIsNot(final Double value);
 }
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerEntity.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerEntity.java
index 4ee0a9f..bdfc7e8 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerEntity.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerEntity.java
@@ -27,6 +27,7 @@ import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 @SuppressWarnings({"unused"})
@@ -49,6 +50,8 @@ public class LedgerEntity {
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "parent_ledger_id")
   private LedgerEntity parentLedger;
+  @Column(name = "total_value")
+  private BigDecimal totalValue;
   @Column(name = "created_on")
   @Convert(converter = LocalDateTimeConverter.class)
   private LocalDateTime createdOn;
@@ -114,6 +117,14 @@ public class LedgerEntity {
     this.parentLedger = parentLedger;
   }
 
+  public BigDecimal getTotalValue() {
+    return this.totalValue;
+  }
+
+  public void setTotalValue(final BigDecimal totalValue) {
+    this.totalValue = totalValue;
+  }
+
   public LocalDateTime getCreatedOn() {
     return this.createdOn;
   }
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerRepository.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerRepository.java
index e0edce3..e310ecd 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerRepository.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/repository/LedgerRepository.java
@@ -26,6 +26,8 @@ public interface LedgerRepository extends 
JpaRepository<LedgerEntity, Long>, Jpa
 
   List<LedgerEntity> findByParentLedgerIsNull();
 
+  List<LedgerEntity> findByParentLedgerIsNullAndType(final String type);
+
   List<LedgerEntity> findByParentLedgerOrderByIdentifier(final LedgerEntity 
parentLedger);
 
   LedgerEntity findByIdentifier(final String identifier);
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/service/IncomeStatementService.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/service/IncomeStatementService.java
new file mode 100644
index 0000000..b9de9f4
--- /dev/null
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/service/IncomeStatementService.java
@@ -0,0 +1,81 @@
+/*
+ * 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.accounting.service.internal.service;
+
+import io.mifos.accounting.api.v1.domain.AccountType;
+import io.mifos.accounting.api.v1.domain.IncomeStatement;
+import io.mifos.accounting.api.v1.domain.IncomeStatementEntry;
+import io.mifos.accounting.api.v1.domain.IncomeStatementSection;
+import io.mifos.accounting.service.internal.repository.LedgerRepository;
+import io.mifos.core.lang.DateConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.time.Clock;
+import java.time.LocalDateTime;
+
+@Service
+public class IncomeStatementService {
+
+  private final LedgerRepository ledgerRepository;
+
+  @Autowired
+  public IncomeStatementService(final LedgerRepository ledgerRepository) {
+    super();
+    this.ledgerRepository = ledgerRepository;
+  }
+
+  public IncomeStatement getIncomeStatement() {
+    final IncomeStatement incomeStatement = new IncomeStatement();
+    
incomeStatement.setDate(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+
+    this.createIncomeStatementSection(incomeStatement, AccountType.REVENUE, 
IncomeStatementSection.Type.INCOME);
+    this.createIncomeStatementSection(incomeStatement, AccountType.EXPENSE, 
IncomeStatementSection.Type.EXPENSES);
+
+    incomeStatement.setGrossProfit(this.calculateTotal(incomeStatement, 
IncomeStatementSection.Type.INCOME));
+    incomeStatement.setTotalExpenses(this.calculateTotal(incomeStatement, 
IncomeStatementSection.Type.EXPENSES));
+    
incomeStatement.setNetIncome(incomeStatement.getGrossProfit().subtract(incomeStatement.getTotalExpenses()));
+
+    return incomeStatement;
+  }
+
+  private void createIncomeStatementSection(final IncomeStatement 
incomeStatement, final AccountType accountType,
+                                            final IncomeStatementSection.Type 
incomeStatementType) {
+    
this.ledgerRepository.findByParentLedgerIsNullAndType(accountType.name()).forEach(ledgerEntity
 -> {
+      final IncomeStatementSection incomeStatementSection = new 
IncomeStatementSection();
+      incomeStatementSection.setType(incomeStatementType.name());
+      incomeStatementSection.setDescription(ledgerEntity.getName());
+      incomeStatement.add(incomeStatementSection);
+
+      
this.ledgerRepository.findByParentLedgerOrderByIdentifier(ledgerEntity).forEach(subLedgerEntity
 -> {
+        final IncomeStatementEntry incomeStatementEntry = new 
IncomeStatementEntry();
+        incomeStatementEntry.setDescription(subLedgerEntity.getName());
+        incomeStatementEntry.setValue(subLedgerEntity.getTotalValue());
+        incomeStatementSection.add(incomeStatementEntry);
+      });
+    });
+  }
+
+  private BigDecimal calculateTotal(final IncomeStatement incomeStatement, 
final IncomeStatementSection.Type incomeStatementType) {
+    return incomeStatement.getIncomeStatementSections()
+        .stream()
+        .filter(incomeStatementSection ->
+            
incomeStatementSection.getType().equals(incomeStatementType.name()))
+        .map(IncomeStatementSection::getSubtotal)
+        .reduce(BigDecimal.ZERO, BigDecimal::add);
+  }
+}
diff --git 
a/service/src/main/java/io/mifos/accounting/service/internal/service/TrialBalanceService.java
 
b/service/src/main/java/io/mifos/accounting/service/internal/service/TrialBalanceService.java
index ced24d7..f141dd7 100644
--- 
a/service/src/main/java/io/mifos/accounting/service/internal/service/TrialBalanceService.java
+++ 
b/service/src/main/java/io/mifos/accounting/service/internal/service/TrialBalanceService.java
@@ -19,15 +19,13 @@ import io.mifos.accounting.api.v1.domain.AccountType;
 import io.mifos.accounting.api.v1.domain.TrialBalance;
 import io.mifos.accounting.api.v1.domain.TrialBalanceEntry;
 import io.mifos.accounting.service.internal.mapper.LedgerMapper;
-import io.mifos.accounting.service.internal.repository.AccountEntity;
 import io.mifos.accounting.service.internal.repository.AccountRepository;
-import io.mifos.accounting.service.internal.repository.LedgerEntity;
 import io.mifos.accounting.service.internal.repository.LedgerRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
 import java.util.Comparator;
-import java.util.List;
 
 @Service
 public class TrialBalanceService {
@@ -45,39 +43,34 @@ public class TrialBalanceService {
 
   public TrialBalance getTrialBalance(final boolean includeEmptyEntries) {
     final TrialBalance trialBalance = new TrialBalance();
-    final List<LedgerEntity> ledgers = this.ledgerRepository.findAll();
-    if (ledgers != null) ledgers.forEach(ledgerEntity -> {
-      final List<AccountEntity> accountEntities = 
this.accountRepository.findByLedger(ledgerEntity);
-      if (accountEntities != null) {
-        final TrialBalanceEntry trialBalanceEntry = new TrialBalanceEntry();
-        trialBalanceEntry.setLedger(LedgerMapper.map(ledgerEntity));
-        switch (AccountType.valueOf(ledgerEntity.getType())) {
-          case ASSET:
-          case EXPENSE:
-            trialBalanceEntry.setType(TrialBalanceEntry.Type.DEBIT.name());
-            break;
-          case LIABILITY:
-          case EQUITY:
-          case REVENUE:
-            trialBalanceEntry.setType(TrialBalanceEntry.Type.CREDIT.name());
-            break;
-        }
-        trialBalanceEntry.setAmount(0.00D);
-        accountEntities.forEach(accountEntity ->
-                trialBalanceEntry.setAmount(trialBalanceEntry.getAmount() + 
accountEntity.getBalance()));
-        if (!includeEmptyEntries && trialBalanceEntry.getAmount() == 0.00D) {
-          //noinspection UnnecessaryReturnStatement
-          return;
-        } else {
-          trialBalance.getTrialBalanceEntries().add(trialBalanceEntry);
-        }
+    this.ledgerRepository.findAll().forEach(ledgerEntity -> {
+      final BigDecimal totalValue = ledgerEntity.getTotalValue() != null ? 
ledgerEntity.getTotalValue() : BigDecimal.ZERO;
+      if (!includeEmptyEntries && totalValue.compareTo(BigDecimal.ZERO) != 0) {
+        return;
       }
+      final TrialBalanceEntry trialBalanceEntry = new TrialBalanceEntry();
+      trialBalanceEntry.setLedger(LedgerMapper.map(ledgerEntity));
+      switch (AccountType.valueOf(ledgerEntity.getType())) {
+        case ASSET:
+        case EXPENSE:
+          trialBalanceEntry.setType(TrialBalanceEntry.Type.DEBIT.name());
+          break;
+        case LIABILITY:
+        case EQUITY:
+        case REVENUE:
+          trialBalanceEntry.setType(TrialBalanceEntry.Type.CREDIT.name());
+          break;
+      }
+      trialBalanceEntry.setAmount(totalValue.doubleValue());
+      trialBalance.getTrialBalanceEntries().add(trialBalanceEntry);
     });
 
     trialBalance.setDebitTotal(
         trialBalance.getTrialBalanceEntries()
             .stream()
-            .filter(trialBalanceEntry -> 
trialBalanceEntry.getType().equals(TrialBalanceEntry.Type.DEBIT.name()))
+            .filter(trialBalanceEntry ->
+                
trialBalanceEntry.getType().equals(TrialBalanceEntry.Type.DEBIT.name())
+                && trialBalanceEntry.getLedger().getParentLedgerIdentifier() 
== null)
             .mapToDouble(TrialBalanceEntry::getAmount)
             .sum()
     );
@@ -85,7 +78,9 @@ public class TrialBalanceService {
     trialBalance.setCreditTotal(
         trialBalance.getTrialBalanceEntries()
             .stream()
-            .filter(trialBalanceEntry -> 
trialBalanceEntry.getType().equals(TrialBalanceEntry.Type.CREDIT.name()))
+            .filter(trialBalanceEntry ->
+                
trialBalanceEntry.getType().equals(TrialBalanceEntry.Type.CREDIT.name())
+                    && 
trialBalanceEntry.getLedger().getParentLedgerIdentifier() == null)
             .mapToDouble(TrialBalanceEntry::getAmount)
             .sum()
     );
diff --git 
a/service/src/main/java/io/mifos/accounting/service/rest/IncomeStatementController.java
 
b/service/src/main/java/io/mifos/accounting/service/rest/IncomeStatementController.java
new file mode 100644
index 0000000..49028da
--- /dev/null
+++ 
b/service/src/main/java/io/mifos/accounting/service/rest/IncomeStatementController.java
@@ -0,0 +1,53 @@
+/*
+ * 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.accounting.service.rest;
+
+import io.mifos.accounting.api.v1.PermittableGroupIds;
+import io.mifos.accounting.api.v1.domain.IncomeStatement;
+import io.mifos.accounting.service.internal.service.IncomeStatementService;
+import io.mifos.anubis.annotation.AcceptedTokenType;
+import io.mifos.anubis.annotation.Permittable;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/incomestatement")
+public class IncomeStatementController {
+
+  private final IncomeStatementService incomeStatementService;
+
+  @Autowired
+  public IncomeStatementController(final IncomeStatementService 
incomeStatementService) {
+    super();
+    this.incomeStatementService = incomeStatementService;
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = 
PermittableGroupIds.THOTH_LEDGER)
+  @RequestMapping(
+      method = RequestMethod.GET,
+      produces = {MediaType.APPLICATION_JSON_VALUE},
+      consumes = {MediaType.ALL_VALUE}
+  )
+  @ResponseBody
+  public ResponseEntity<IncomeStatement> getIncomeStatement() {
+    return ResponseEntity.ok(this.incomeStatementService.getIncomeStatement());
+  }
+}
diff --git 
a/service/src/main/resources/db/migrations/mariadb/V9__add_total_value_ledger.sql
 
b/service/src/main/resources/db/migrations/mariadb/V9__add_total_value_ledger.sql
new file mode 100644
index 0000000..921597a
--- /dev/null
+++ 
b/service/src/main/resources/db/migrations/mariadb/V9__add_total_value_ledger.sql
@@ -0,0 +1,17 @@
+--
+-- 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.
+--
+
+ALTER TABLE thoth_ledgers ADD COLUMN total_value NUMERIC(15,5) NULL;
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to