You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by GitBox <gi...@apache.org> on 2018/04/23 18:28:16 UTC

[GitHub] Izakey closed pull request #5: Document the Accounting API

Izakey closed pull request #5: Document the Accounting API
URL: https://github.com/apache/fineract-cn-accounting/pull/5
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/service/build.gradle b/service/build.gradle
index 561fdfa..508a9b5 100644
--- a/service/build.gradle
+++ b/service/build.gradle
@@ -26,6 +26,7 @@ buildscript {
 
     dependencies {
         classpath ("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+        classpath("org.asciidoctor:asciidoctor-gradle-plugin:1.5.3")
     }
 }
 
@@ -37,6 +38,7 @@ plugins {
 apply from: '../shared.gradle'
 
 apply plugin: 'spring-boot'
+apply plugin: 'org.asciidoctor.convert'
 
 springBoot {
     executable = true
@@ -57,8 +59,32 @@ dependencies {
             [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.hibernate', name: 'hibernate-validator', version: versions.validator],
+            [group: 'org.apache.commons', name: 'commons-csv', version: versions.apachecsvreader],
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-web'],
+            [group: 'org.springframework.restdocs', name: 'spring-restdocs-mockmvc']
     )
+    testCompile(
+            [group: 'org.apache.fineract.cn.customer', name: 'api', version: project.version],
+            [group: 'org.apache.fineract.cn.accounting', name: 'api', version: project.version],
+            [group: 'org.apache.fineract.cn.accounting', name: 'importer', version: project.version],
+            [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.anubis', name: 'test', version: versions.frameworkanubis],
+            [group: 'org.apache.fineract.cn', name: 'lang', version: versions.frameworklang],
+            [group: 'org.springframework.restdocs', name: 'spring-restdocs-mockmvc'],
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-test'],
+            [group: 'org.apache.commons', name: 'commons-csv', version: versions.apachecsvreader],
+            [group: 'junit', name: 'junit', version: '4.12']
+    )
+}
+
+asciidoctor {
+    sourceDir 'src/doc/asciidoc/'
+    outputDir 'src/doc/html5'
+    options backend: "html", doctype: "book"
+    attributes "source-highlighter": "highlightjs", \
+                'snippets': file('src/doc/generated-snippets/')
 }
 
 publishToMavenLocal.dependsOn bootRepackage
diff --git a/service/src/doc/asciidoc/api-docs.adoc b/service/src/doc/asciidoc/api-docs.adoc
new file mode 100644
index 0000000..69c22ba
--- /dev/null
+++ b/service/src/doc/asciidoc/api-docs.adoc
@@ -0,0 +1,407 @@
+== Apache Fineract CN Financial Accounting API Documentation ==
+
+== Accounts ==
+
+==== Create An Account ====
+
+.curl-request
+include::{snippets}/test-account/should-create-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-create-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-create-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-create-account/httpie-request.adoc[]
+
+==== Get An Account ====
+
+.curl-request
+include::{snippets}/test-account/should-find-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-find-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-find-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-find-account/httpie-request.adoc[]
+
+==== Get An Account Using Alternative Account Number ====
+
+.curl-request
+include::{snippets}/test-account/should-find-account-with-alternative-account-number/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-find-account-with-alternative-account-number/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-find-account-with-alternative-account-number/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-find-account-with-alternative-account-number/httpie-request.adoc[]
+
+==== Get Accounts ====
+
+.curl-request
+include::{snippets}/test-account/should-fetch-accounts/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-fetch-accounts/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-fetch-accounts/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-fetch-accounts/httpie-request.adoc[]
+
+==== Get Account Entries ====
+
+.curl-request
+include::{snippets}/test-account/should-list-account-entries/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-list-account-entries/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-list-account-entries/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-list-account-entries/httpie-request.adoc[]
+
+== Update Account Details ==
+
+==== Update An Account ====
+
+.curl-request
+include::{snippets}/test-account/should-modify-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-modify-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-modify-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-modify-account/httpie-request.adoc[]
+
+==== Delete An Account ====
+
+.curl-request
+include::{snippets}/test-account/should-delete-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-delete-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-delete-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-delete-account/httpie-request.adoc[]
+
+== Command An Account ==
+
+==== List An Account's Commands ====
+
+.curl-request
+include::{snippets}/test-account/should-return-only-available-commands/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-return-only-available-commands/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-return-only-available-commands/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-return-only-available-commands/httpie-request.adoc[]
+
+==== Lock An Account ====
+
+.curl-request
+include::{snippets}/test-account/should-lock-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-lock-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-lock-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-lock-account/httpie-request.adoc[]
+
+==== Unlock An Account ====
+
+.curl-request
+include::{snippets}/test-account/should-unlock-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-unlock-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-unlock-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-unlock-account/httpie-request.adoc[]
+
+==== Close An Account ====
+
+.curl-request
+include::{snippets}/test-account/should-close-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-close-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-close-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-close-account/httpie-request.adoc[]
+
+==== Reopen An Account ====
+
+.curl-request
+include::{snippets}/test-account/should-reopen-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-account/should-reopen-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-account/should-reopen-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-account/should-reopen-account/httpie-request.adoc[]
+
+== Ledgers ==
+
+==== Create A Ledger ====
+
+.curl-request
+include::{snippets}/test-ledger/should-create-ledger/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-ledger/should-create-ledger/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-ledger/should-create-ledger/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-ledger/should-create-ledger/httpie-request.adoc[]
+
+==== Get A Ledger ====
+
+.curl-request
+include::{snippets}/test-ledger/should-find-ledger/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-ledger/should-find-ledger/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-ledger/should-find-ledger/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-ledger/should-find-ledger/httpie-request.adoc[]
+
+==== Get Ledgers ====
+
+.curl-request
+include::{snippets}/test-ledger/should-fetch-ledgers/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-ledger/should-fetch-ledgers/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-ledger/should-fetch-ledgers/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-ledger/should-fetch-ledgers/httpie-request.adoc[]
+
+==== Get A Ledger's Sub Ledgers ====
+
+.curl-request
+include::{snippets}/test-ledger/should-fetch-sub-ledgers/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-ledger/should-fetch-sub-ledgers/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-ledger/should-fetch-sub-ledgers/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-ledger/should-fetch-sub-ledgers/httpie-request.adoc[]
+
+==== Get A Ledger's Accounts ====
+
+.curl-request
+include::{snippets}/test-ledger/should-stream-all-accounts-belonging-to-ledger/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-ledger/should-stream-all-accounts-belonging-to-ledger/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-ledger/should-stream-all-accounts-belonging-to-ledger/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-ledger/should-stream-all-accounts-belonging-to-ledger/httpie-request.adoc[]
+
+==== Update A Ledger ====
+
+.curl-request
+include::{snippets}/test-ledger/should-modify-ledger/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-ledger/should-modify-ledger/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-ledger/should-modify-ledger/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-ledger/should-modify-ledger/httpie-request.adoc[]
+
+==== Add A Sub Ledger ====
+
+.curl-request
+include::{snippets}/test-ledger/should-add-sub-ledger/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-ledger/should-add-sub-ledger/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-ledger/should-add-sub-ledger/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-ledger/should-add-sub-ledger/httpie-request.adoc[]
+
+==== Delete A Ledger ====
+
+.curl-request
+include::{snippets}/test-ledger/should-delete-ledger/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-ledger/should-delete-ledger/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-ledger/should-delete-ledger/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-ledger/should-delete-ledger/httpie-request.adoc[]
+
+== Journals ==
+
+==== Create A Journal Entry ====
+
+.curl-request
+include::{snippets}/test-journal/should-create-journal-entry/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-journal/should-create-journal-entry/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-journal/should-create-journal-entry/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-journal/should-create-journal-entry/httpie-request.adoc[]
+
+==== Get Journal Entries Within Date Range ====
+
+.curl-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range/httpie-request.adoc[]
+
+==== Get Journal Entries Within Date Range And Account ====
+
+.curl-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range-and-account/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range-and-account/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range-and-account/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range-and-account/httpie-request.adoc[]
+
+==== Get Journal Entries Within Date Range, Account And Amount ====
+
+.curl-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/httpie-request.adoc[]
+
+== Transaction Types ==
+
+==== Create Transaction Type ====
+
+.curl-request
+include::{snippets}/test-transaction/should-create-transaction-type/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-transaction/should-create-transaction-type/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-transaction/should-create-transaction-type/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-transaction/should-create-transaction-type/httpie-request.adoc[]
+
+==== Get A Transaction Type ====
+
+.curl-request
+include::{snippets}/test-transaction/should-find-transaction-type/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-transaction/should-find-transaction-type/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-transaction/should-find-transaction-type/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-transaction/should-find-transaction-type/httpie-request.adoc[]
+
+==== Get Transaction Types ====
+
+.curl-request
+include::{snippets}/test-transaction/should-fetch-pre-configured-types/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-transaction/should-fetch-pre-configured-types/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-transaction/should-fetch-pre-configured-types/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-transaction/should-fetch-pre-configured-types/httpie-request.adoc[]
+
+==== Update A Transaction Type ====
+
+.curl-request
+include::{snippets}/test-transaction/should-change-transaction-type/curl-request.adoc[]
+
+.http-request
+include::{snippets}/test-transaction/should-change-transaction-type/http-request.adoc[]
+
+.http-response
+include::{snippets}/test-transaction/should-change-transaction-type/http-response.adoc[]
+
+.httpie-request
+include::{snippets}/test-transaction/should-change-transaction-type/httpie-request.adoc[]
+
+
diff --git a/service/src/doc/generated-snippets/test-account/should-close-account/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-close-account/curl-request.adoc
new file mode 100644
index 0000000..ae0947b
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-close-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3/commands' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d 'BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-close-account/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-close-account/http-request.adoc
new file mode 100644
index 0000000..f7be34d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-close-account/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+PUT /accounting/v1/accounts/BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3/commands HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-close-account/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-close-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-close-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-close-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-close-account/httpie-request.adoc
new file mode 100644
index 0000000..6f8afd9
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-close-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3' | http PUT 'http://localhost:8080/accounting/v1/accounts/BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3/commands' 'Accept:application/json' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-create-account/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-create-account/curl-request.adoc
new file mode 100644
index 0000000..23ef0e2
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-create-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d 'spfPmPXlY1pR0kS9SCGyiyD3OhX8rDQW'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-create-account/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-create-account/http-request.adoc
new file mode 100644
index 0000000..711e727
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-create-account/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+POST /accounting/v1/accounts HTTP/1.1
+Content-Type: application/json
+Accept: application/json
+Host: localhost:8080
+Content-Length: 32
+
+spfPmPXlY1pR0kS9SCGyiyD3OhX8rDQW
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-create-account/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-create-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-create-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-create-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-create-account/httpie-request.adoc
new file mode 100644
index 0000000..7880ef2
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-create-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'spfPmPXlY1pR0kS9SCGyiyD3OhX8rDQW' | http POST 'http://localhost:8080/accounting/v1/accounts' 'Content-Type:application/json' 'Accept:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-delete-account/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-delete-account/curl-request.adoc
new file mode 100644
index 0000000..6fc7d10
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-delete-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/UGf89ghtU7EaeEeepgvADsZARq0s0zEt' -i -X DELETE -H 'Accept: */*' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-delete-account/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-delete-account/http-request.adoc
new file mode 100644
index 0000000..ac14b25
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-delete-account/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+DELETE /accounting/v1/accounts/UGf89ghtU7EaeEeepgvADsZARq0s0zEt HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-delete-account/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-delete-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-delete-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-delete-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-delete-account/httpie-request.adoc
new file mode 100644
index 0000000..30ec748
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-delete-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http DELETE 'http://localhost:8080/accounting/v1/accounts/UGf89ghtU7EaeEeepgvADsZARq0s0zEt' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-fetch-accounts/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-fetch-accounts/curl-request.adoc
new file mode 100644
index 0000000..6461101
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-fetch-accounts/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts' -i -H 'Accept: */*'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-fetch-accounts/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-fetch-accounts/http-request.adoc
new file mode 100644
index 0000000..02d57aa
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-fetch-accounts/http-request.adoc
@@ -0,0 +1,7 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/accounts HTTP/1.1
+Accept: */*
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-fetch-accounts/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-fetch-accounts/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-fetch-accounts/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-fetch-accounts/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-fetch-accounts/httpie-request.adoc
new file mode 100644
index 0000000..f679f68
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-fetch-accounts/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/accounts' 'Accept:*/*'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/curl-request.adoc
new file mode 100644
index 0000000..a2c01d7
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/alt-account-10001' -i -H 'Accept: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/http-request.adoc
new file mode 100644
index 0000000..66e85ae
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/http-request.adoc
@@ -0,0 +1,7 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/accounts/alt-account-10001 HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/httpie-request.adoc
new file mode 100644
index 0000000..8777e1d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-find-account-with-alternative-account-number/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/accounts/alt-account-10001' 'Accept:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-find-account/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-find-account/curl-request.adoc
new file mode 100644
index 0000000..b5ea952
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-find-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/Fhy4B9BTrW6TguvV70Z2CUlekfrqLcXp' -i -H 'Accept: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-find-account/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-find-account/http-request.adoc
new file mode 100644
index 0000000..0cb8f22
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-find-account/http-request.adoc
@@ -0,0 +1,7 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/accounts/Fhy4B9BTrW6TguvV70Z2CUlekfrqLcXp HTTP/1.1
+Accept: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-find-account/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-find-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-find-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-find-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-find-account/httpie-request.adoc
new file mode 100644
index 0000000..f690884
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-find-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/accounts/Fhy4B9BTrW6TguvV70Z2CUlekfrqLcXp' 'Accept:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-list-account-entries/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-list-account-entries/curl-request.adoc
new file mode 100644
index 0000000..9a6458d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-list-account-entries/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/1sbEdwDe/entries' -i -H 'Accept: */*'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-list-account-entries/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-list-account-entries/http-request.adoc
new file mode 100644
index 0000000..e267f1e
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-list-account-entries/http-request.adoc
@@ -0,0 +1,7 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/accounts/1sbEdwDe/entries HTTP/1.1
+Accept: */*
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-list-account-entries/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-list-account-entries/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-list-account-entries/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-list-account-entries/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-list-account-entries/httpie-request.adoc
new file mode 100644
index 0000000..d89e951
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-list-account-entries/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/accounts/1sbEdwDe/entries' 'Accept:*/*'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-lock-account/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-lock-account/curl-request.adoc
new file mode 100644
index 0000000..cd2c588
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-lock-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL/commands' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d '7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-lock-account/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-lock-account/http-request.adoc
new file mode 100644
index 0000000..4b51fd3
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-lock-account/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+PUT /accounting/v1/accounts/7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL/commands HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-lock-account/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-lock-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-lock-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-lock-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-lock-account/httpie-request.adoc
new file mode 100644
index 0000000..3a37642
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-lock-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo '7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL' | http PUT 'http://localhost:8080/accounting/v1/accounts/7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL/commands' 'Accept:application/json' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-modify-account/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-modify-account/curl-request.adoc
new file mode 100644
index 0000000..0d2557e
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-modify-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d 'PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-modify-account/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-modify-account/http-request.adoc
new file mode 100644
index 0000000..67218f2
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-modify-account/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+PUT /accounting/v1/accounts/PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-modify-account/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-modify-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-modify-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-modify-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-modify-account/httpie-request.adoc
new file mode 100644
index 0000000..f1fabd3
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-modify-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo' | http PUT 'http://localhost:8080/accounting/v1/accounts/PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo' 'Accept:application/json' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-reopen-account/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-reopen-account/curl-request.adoc
new file mode 100644
index 0000000..79d8071
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-reopen-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p/commands' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d 'LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-reopen-account/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-reopen-account/http-request.adoc
new file mode 100644
index 0000000..4f67ee3
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-reopen-account/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+PUT /accounting/v1/accounts/LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p/commands HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-reopen-account/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-reopen-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-reopen-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-reopen-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-reopen-account/httpie-request.adoc
new file mode 100644
index 0000000..2f6be53
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-reopen-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p' | http PUT 'http://localhost:8080/accounting/v1/accounts/LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p/commands' 'Accept:application/json' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/curl-request.adoc
new file mode 100644
index 0000000..46e2b3a
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/UhcXRbZmTu5YTElN9nUQ6sVLnBjo80cf/commands' -i -H 'Accept: */*'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/http-request.adoc
new file mode 100644
index 0000000..c324293
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/http-request.adoc
@@ -0,0 +1,7 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/accounts/UhcXRbZmTu5YTElN9nUQ6sVLnBjo80cf/commands HTTP/1.1
+Accept: */*
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/httpie-request.adoc
new file mode 100644
index 0000000..233d45c
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-return-only-available-commands/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/accounts/UhcXRbZmTu5YTElN9nUQ6sVLnBjo80cf/commands' 'Accept:*/*'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-unlock-account/curl-request.adoc b/service/src/doc/generated-snippets/test-account/should-unlock-account/curl-request.adoc
new file mode 100644
index 0000000..8a193f4
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-unlock-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/accounts/xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc/commands' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d 'xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-unlock-account/http-request.adoc b/service/src/doc/generated-snippets/test-account/should-unlock-account/http-request.adoc
new file mode 100644
index 0000000..49552e1
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-unlock-account/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+PUT /accounting/v1/accounts/xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc/commands HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-unlock-account/http-response.adoc b/service/src/doc/generated-snippets/test-account/should-unlock-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-unlock-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-account/should-unlock-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-account/should-unlock-account/httpie-request.adoc
new file mode 100644
index 0000000..19126a3
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-account/should-unlock-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc' | http PUT 'http://localhost:8080/accounting/v1/accounts/xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc/commands' 'Accept:application/json' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/curl-request.adoc b/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/curl-request.adoc
new file mode 100644
index 0000000..4346e0e
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/journal' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d 'GKImphLY'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/http-request.adoc b/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/http-request.adoc
new file mode 100644
index 0000000..3c37547
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+POST /accounting/v1/journal HTTP/1.1
+Content-Type: application/json
+Accept: application/json
+Host: localhost:8080
+Content-Length: 8
+
+GKImphLY
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/http-response.adoc b/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/httpie-request.adoc b/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/httpie-request.adoc
new file mode 100644
index 0000000..662ea75
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-create-journal-entry/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'GKImphLY' | http POST 'http://localhost:8080/accounting/v1/journal' 'Content-Type:application/json' 'Accept:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/curl-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/curl-request.adoc
new file mode 100644
index 0000000..4b8a086
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/journal' -i -H 'Accept: */*' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/http-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/http-request.adoc
new file mode 100644
index 0000000..99e782a
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/journal HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/http-response.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/httpie-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/httpie-request.adoc
new file mode 100644
index 0000000..c086125
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account-and-amount/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/journal' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/curl-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/curl-request.adoc
new file mode 100644
index 0000000..4b8a086
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/journal' -i -H 'Accept: */*' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/http-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/http-request.adoc
new file mode 100644
index 0000000..99e782a
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/journal HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/http-response.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/httpie-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/httpie-request.adoc
new file mode 100644
index 0000000..c086125
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-account/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/journal' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/curl-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/curl-request.adoc
new file mode 100644
index 0000000..4b8a086
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/journal' -i -H 'Accept: */*' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/http-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/http-request.adoc
new file mode 100644
index 0000000..99e782a
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/journal HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/http-response.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/httpie-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/httpie-request.adoc
new file mode 100644
index 0000000..c086125
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range-and-amount/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/journal' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/curl-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/curl-request.adoc
new file mode 100644
index 0000000..4b8a086
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/journal' -i -H 'Accept: */*' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/http-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/http-request.adoc
new file mode 100644
index 0000000..99e782a
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/journal HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/http-response.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/httpie-request.adoc b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/httpie-request.adoc
new file mode 100644
index 0000000..c086125
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-journal/should-fetch-journal-entries-with-date-range/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/journal' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/curl-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/curl-request.adoc
new file mode 100644
index 0000000..d27392e
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/ledgers/tQgYJsit' -i -X POST -H 'Accept: application/json' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/http-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/http-request.adoc
new file mode 100644
index 0000000..947c05c
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+POST /accounting/v1/ledgers/tQgYJsit HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/http-response.adoc b/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/httpie-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/httpie-request.adoc
new file mode 100644
index 0000000..82eebdd
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-add-sub-ledger/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http POST 'http://localhost:8080/accounting/v1/ledgers/tQgYJsit' 'Accept:application/json' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-create-ledger/curl-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-create-ledger/curl-request.adoc
new file mode 100644
index 0000000..bda1df7
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-create-ledger/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/ledgers' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '6NomITyb'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-create-ledger/http-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-create-ledger/http-request.adoc
new file mode 100644
index 0000000..f7bf79d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-create-ledger/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+POST /accounting/v1/ledgers HTTP/1.1
+Content-Type: application/json
+Accept: application/json
+Host: localhost:8080
+Content-Length: 8
+
+6NomITyb
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-create-ledger/http-response.adoc b/service/src/doc/generated-snippets/test-ledger/should-create-ledger/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-create-ledger/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-create-ledger/httpie-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-create-ledger/httpie-request.adoc
new file mode 100644
index 0000000..f64054e
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-create-ledger/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo '6NomITyb' | http POST 'http://localhost:8080/accounting/v1/ledgers' 'Content-Type:application/json' 'Accept:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/curl-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/curl-request.adoc
new file mode 100644
index 0000000..55a1f81
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/ledgers/vIYq1aU7' -i -X DELETE -H 'Accept: */*' -H 'Content-Type: application/json' -d 'vIYq1aU7'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/http-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/http-request.adoc
new file mode 100644
index 0000000..d8fda9e
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+DELETE /accounting/v1/ledgers/vIYq1aU7 HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 8
+
+vIYq1aU7
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/http-response.adoc b/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/httpie-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/httpie-request.adoc
new file mode 100644
index 0000000..96d2151
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-delete-ledger/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'vIYq1aU7' | http DELETE 'http://localhost:8080/accounting/v1/ledgers/vIYq1aU7' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/curl-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/curl-request.adoc
new file mode 100644
index 0000000..6fc1c88
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/ledgers/' -i -H 'Accept: */*' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/http-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/http-request.adoc
new file mode 100644
index 0000000..7d24c76
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/ledgers/ HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/http-response.adoc b/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/httpie-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/httpie-request.adoc
new file mode 100644
index 0000000..cebb6a5
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-fetch-ledgers/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/ledgers/' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/curl-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/curl-request.adoc
new file mode 100644
index 0000000..fe7930d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/ledgers/qq4iM1m2/' -i -H 'Accept: */*' -H 'Content-Type: application/json' -d '[org.apache.fineract.cn.accounting.api.v1.domain.Ledger@6d8d78a]'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/http-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/http-request.adoc
new file mode 100644
index 0000000..e99b752
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/ledgers/qq4iM1m2/ HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 64
+
+[org.apache.fineract.cn.accounting.api.v1.domain.Ledger@6d8d78a]
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/http-response.adoc b/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/httpie-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/httpie-request.adoc
new file mode 100644
index 0000000..9979305
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-fetch-sub-ledgers/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo '[org.apache.fineract.cn.accounting.api.v1.domain.Ledger@6d8d78a]' | http GET 'http://localhost:8080/accounting/v1/ledgers/qq4iM1m2/' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-find-ledger/curl-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-find-ledger/curl-request.adoc
new file mode 100644
index 0000000..5ecf8a6
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-find-ledger/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/ledgers/JMhJyw1e' -i -H 'Accept: */*' -H 'Content-Type: application/json' -d 'JMhJyw1e'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-find-ledger/http-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-find-ledger/http-request.adoc
new file mode 100644
index 0000000..b33d836
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-find-ledger/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/ledgers/JMhJyw1e HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 8
+
+JMhJyw1e
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-find-ledger/http-response.adoc b/service/src/doc/generated-snippets/test-ledger/should-find-ledger/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-find-ledger/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-find-ledger/httpie-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-find-ledger/httpie-request.adoc
new file mode 100644
index 0000000..4ce2499
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-find-ledger/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'JMhJyw1e' | http GET 'http://localhost:8080/accounting/v1/ledgers/JMhJyw1e' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/curl-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/curl-request.adoc
new file mode 100644
index 0000000..3fa9fce
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/ledgers/8kc9Qdr2' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/http-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/http-request.adoc
new file mode 100644
index 0000000..60b8f3d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+PUT /accounting/v1/ledgers/8kc9Qdr2 HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/http-response.adoc b/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/httpie-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/httpie-request.adoc
new file mode 100644
index 0000000..351cc77
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-modify-ledger/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http PUT 'http://localhost:8080/accounting/v1/ledgers/8kc9Qdr2' 'Accept:application/json' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/curl-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/curl-request.adoc
new file mode 100644
index 0000000..914ebe3
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/ledgers/GPOImtnt/accounts' -i -H 'Accept: */*' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/http-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/http-request.adoc
new file mode 100644
index 0000000..c5a499c
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/ledgers/GPOImtnt/accounts HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/http-response.adoc b/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/httpie-request.adoc b/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/httpie-request.adoc
new file mode 100644
index 0000000..cb5068e
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-ledger/should-stream-all-accounts-belonging-to-ledger/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/ledgers/GPOImtnt/accounts' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/curl-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/curl-request.adoc
new file mode 100644
index 0000000..d866218
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/transactiontypes/changeable' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/http-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/http-request.adoc
new file mode 100644
index 0000000..89df2bf
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+PUT /accounting/v1/transactiontypes/changeable HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/http-response.adoc b/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/httpie-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/httpie-request.adoc
new file mode 100644
index 0000000..0db9517
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-change-transaction-type/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http PUT 'http://localhost:8080/accounting/v1/transactiontypes/changeable' 'Accept:application/json' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/curl-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/curl-request.adoc
new file mode 100644
index 0000000..5635901
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/transactiontypes' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d 'olmC'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/http-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/http-request.adoc
new file mode 100644
index 0000000..8177768
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+POST /accounting/v1/transactiontypes HTTP/1.1
+Content-Type: application/json
+Accept: application/json
+Host: localhost:8080
+Content-Length: 4
+
+olmC
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/http-response.adoc b/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/httpie-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/httpie-request.adoc
new file mode 100644
index 0000000..bdb90ae
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-create-transaction-type/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'olmC' | http POST 'http://localhost:8080/accounting/v1/transactiontypes' 'Content-Type:application/json' 'Accept:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/curl-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/curl-request.adoc
new file mode 100644
index 0000000..3e1e339
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/transactiontypes/' -i -H 'Accept: */*' -H 'Content-Type: application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/http-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/http-request.adoc
new file mode 100644
index 0000000..38df4cb
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/http-request.adoc
@@ -0,0 +1,8 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/transactiontypes/ HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/http-response.adoc b/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/httpie-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/httpie-request.adoc
new file mode 100644
index 0000000..d908312
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-fetch-pre-configured-types/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ http GET 'http://localhost:8080/accounting/v1/transactiontypes/' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/curl-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/curl-request.adoc
new file mode 100644
index 0000000..2a068d4
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/curl-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ curl 'http://localhost:8080/accounting/v1/transactiontypes/bMpk' -i -H 'Accept: */*' -H 'Content-Type: application/json' -d 'bMpk'
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/http-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/http-request.adoc
new file mode 100644
index 0000000..2cdf3ab
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/http-request.adoc
@@ -0,0 +1,10 @@
+[source,http,options="nowrap"]
+----
+GET /accounting/v1/transactiontypes/bMpk HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 4
+
+bMpk
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/http-response.adoc b/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/http-response.adoc
new file mode 100644
index 0000000..f3b256d
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/http-response.adoc
@@ -0,0 +1,5 @@
+[source,http,options="nowrap"]
+----
+HTTP/1.1 404 Not Found
+
+----
\ No newline at end of file
diff --git a/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/httpie-request.adoc b/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/httpie-request.adoc
new file mode 100644
index 0000000..f9dcb26
--- /dev/null
+++ b/service/src/doc/generated-snippets/test-transaction/should-find-transaction-type/httpie-request.adoc
@@ -0,0 +1,4 @@
+[source,bash]
+----
+$ echo 'bMpk' | http GET 'http://localhost:8080/accounting/v1/transactiontypes/bMpk' 'Accept:*/*' 'Content-Type:application/json'
+----
\ No newline at end of file
diff --git a/service/src/doc/html5/html5/api-docs.html b/service/src/doc/html5/html5/api-docs.html
new file mode 100644
index 0000000..4b1cbe7
--- /dev/null
+++ b/service/src/doc/html5/html5/api-docs.html
@@ -0,0 +1,1344 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.3">
+<title>Apache Fineract CN Financial Accounting API Documentation</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
+/* Remove comment around @import statement below when using as a custom stylesheet */
+/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
+article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
+audio,canvas,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+[hidden],template{display:none}
+script{display:none!important}
+html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
+body{margin:0}
+a{background:transparent}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+abbr[title]{border-bottom:1px dotted}
+b,strong{font-weight:bold}
+dfn{font-style:italic}
+hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
+input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
+input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+body{-webkit-font-smoothing:antialiased}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.center{margin-left:auto;margin-right:auto}
+.spread{width:100%}
+p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:none}
+p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
+ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
+ul.square{list-style-type:square}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ul.no-bullet{list-style:none}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
+abbr{text-transform:none}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
+blockquote cite:before{content:"\2014 \0020"}
+blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
+table thead,table tfoot{background:#f7f8f7;font-weight:bold}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
+body{tab-size:4}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
+.clearfix:after,.float-group:after{clear:both}
+*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
+pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menu{color:rgba(0,0,0,.8)}
+b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
+b.button:before{content:"[";padding:0 3px 0 2px}
+b.button:after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
+#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
+#content{margin-top:1.25em}
+#content:before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
+#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span:before{content:"\00a0\2013\00a0"}
+#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark:before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber:after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
+@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
+.sect1{padding-bottom:.625em}
+@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
+.sect1+.sect1{border-top:1px solid #efefed}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
+.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
+table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
+.exampleblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child{margin-bottom:0}
+.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
+.sidebarblock>:first-child{margin-top:0}
+.sidebarblock>:last-child{margin-bottom:0}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
+.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
+.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
+.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
+@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
+@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
+.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
+.listingblock:hover code[data-lang]:before{display:block}
+.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
+.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
+table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
+table.pyhltable td.code{padding-left:.75em;padding-right:0}
+pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
+pre.pygments .lineno{display:inline-block;margin-right:.25em}
+table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
+.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
+.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
+.quoteblock .quoteblock blockquote:before{display:none}
+.verseblock{margin:0 1em 1.25em 1em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
+.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
+.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
+table.tableblock{max-width:100%;border-collapse:separate}
+table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
+table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
+table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
+table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
+table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
+table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
+table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
+table.frame-all{border-width:1px}
+table.frame-sides{border-width:0 1px}
+table.frame-topbot{border-width:1px 0}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+td>div.verse{white-space:pre}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
+ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
+ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
+ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
+ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
+ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
+ul.inline>li>*{display:block}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
+.colist>table tr>td:last-of-type{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
+.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
+.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
+.gist .file-data>table td.line-data{width:99%}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background-color:#00fafa}
+.black{color:#000}
+.black-background{background-color:#000}
+.blue{color:#0000bf}
+.blue-background{background-color:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background-color:#fa00fa}
+.gray{color:#606060}
+.gray-background{background-color:#7d7d7d}
+.green{color:#006000}
+.green-background{background-color:#007d00}
+.lime{color:#00bf00}
+.lime-background{background-color:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background-color:#7d0000}
+.navy{color:#000060}
+.navy-background{background-color:#00007d}
+.olive{color:#606000}
+.olive-background{background-color:#7d7d00}
+.purple{color:#600060}
+.purple-background{background-color:#7d007d}
+.red{color:#bf0000}
+.red-background{background-color:#fa0000}
+.silver{color:#909090}
+.silver-background{background-color:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background-color:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background-color:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background-color:#fafa00}
+span.icon>.fa{cursor:default}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]:after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@media print{@page{margin:1.25cm .75cm}
+*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]:after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
+.sect1{padding-bottom:0!important}
+.sect1+.sect1{border:0!important}
+#header>h1:first-child{margin-top:1.25rem}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span:before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]:before{display:block}
+#footer{background:none!important;padding:0 .9375em}
+#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+</style>
+</head>
+<body class="book">
+<div id="header">
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_apache_fineract_cn_financial_accounting_api_documentation">Apache Fineract CN Financial Accounting API Documentation</h2>
+<div class="sectionbody">
+
+</div>
+</div>
+<div class="sect1">
+<h2 id="_accounts">Accounts</h2>
+<div class="sectionbody">
+<div class="sect3">
+<h4 id="_create_an_account">Create An Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d 'spfPmPXlY1pR0kS9SCGyiyD3OhX8rDQW'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">POST /accounting/v1/accounts HTTP/1.1
+Content-Type: application/json
+Accept: application/json
+Host: localhost:8080
+Content-Length: 32
+
+spfPmPXlY1pR0kS9SCGyiyD3OhX8rDQW</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'spfPmPXlY1pR0kS9SCGyiyD3OhX8rDQW' | http POST 'http://localhost:8080/accounting/v1/accounts' 'Content-Type:application/json' 'Accept:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_an_account">Get An Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/Fhy4B9BTrW6TguvV70Z2CUlekfrqLcXp' -i -H 'Accept: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/accounts/Fhy4B9BTrW6TguvV70Z2CUlekfrqLcXp HTTP/1.1
+Accept: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/accounts/Fhy4B9BTrW6TguvV70Z2CUlekfrqLcXp' 'Accept:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_an_account_using_alternative_account_number">Get An Account Using Alternative Account Number</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/alt-account-10001' -i -H 'Accept: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/accounts/alt-account-10001 HTTP/1.1
+Accept: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/accounts/alt-account-10001' 'Accept:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_accounts">Get Accounts</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts' -i -H 'Accept: */*'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/accounts HTTP/1.1
+Accept: */*
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/accounts' 'Accept:*/*'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_account_entries">Get Account Entries</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/1sbEdwDe/entries' -i -H 'Accept: */*'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/accounts/1sbEdwDe/entries HTTP/1.1
+Accept: */*
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/accounts/1sbEdwDe/entries' 'Accept:*/*'</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_update_account_details">Update Account Details</h2>
+<div class="sectionbody">
+<div class="sect3">
+<h4 id="_update_an_account">Update An Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d 'PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">PUT /accounting/v1/accounts/PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo' | http PUT 'http://localhost:8080/accounting/v1/accounts/PDNPdqCIDqvmPRD71llpzKtVGvWh8RFo' 'Accept:application/json' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_delete_an_account">Delete An Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/UGf89ghtU7EaeEeepgvADsZARq0s0zEt' -i -X DELETE -H 'Accept: */*' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">DELETE /accounting/v1/accounts/UGf89ghtU7EaeEeepgvADsZARq0s0zEt HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http DELETE 'http://localhost:8080/accounting/v1/accounts/UGf89ghtU7EaeEeepgvADsZARq0s0zEt' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_command_an_account">Command An Account</h2>
+<div class="sectionbody">
+<div class="sect3">
+<h4 id="_list_an_account_s_commands">List An Account&#8217;s Commands</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/UhcXRbZmTu5YTElN9nUQ6sVLnBjo80cf/commands' -i -H 'Accept: */*'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/accounts/UhcXRbZmTu5YTElN9nUQ6sVLnBjo80cf/commands HTTP/1.1
+Accept: */*
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/accounts/UhcXRbZmTu5YTElN9nUQ6sVLnBjo80cf/commands' 'Accept:*/*'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_lock_an_account">Lock An Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL/commands' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d '7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">PUT /accounting/v1/accounts/7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL/commands HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo '7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL' | http PUT 'http://localhost:8080/accounting/v1/accounts/7iaCoXCmLrFGLRlgGH1dldeAPVOQVeHL/commands' 'Accept:application/json' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_unlock_an_account">Unlock An Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc/commands' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d 'xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">PUT /accounting/v1/accounts/xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc/commands HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc' | http PUT 'http://localhost:8080/accounting/v1/accounts/xXKY8U9VoGEaj1NggqBPT6fQvDAOUQSc/commands' 'Accept:application/json' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_close_an_account">Close An Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3/commands' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d 'BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">PUT /accounting/v1/accounts/BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3/commands HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3' | http PUT 'http://localhost:8080/accounting/v1/accounts/BgWRNAjVxv4UKE3WMggQwnQx3kdPyUK3/commands' 'Accept:application/json' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_reopen_an_account">Reopen An Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/accounts/LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p/commands' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d 'LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">PUT /accounting/v1/accounts/LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p/commands HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 32
+
+LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p' | http PUT 'http://localhost:8080/accounting/v1/accounts/LhKdYu0aYTAQmBLsNMww2ieYH8Y5rX1p/commands' 'Accept:application/json' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_ledgers">Ledgers</h2>
+<div class="sectionbody">
+<div class="sect3">
+<h4 id="_create_a_ledger">Create A Ledger</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/ledgers' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '6NomITyb'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">POST /accounting/v1/ledgers HTTP/1.1
+Content-Type: application/json
+Accept: application/json
+Host: localhost:8080
+Content-Length: 8
+
+6NomITyb</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo '6NomITyb' | http POST 'http://localhost:8080/accounting/v1/ledgers' 'Content-Type:application/json' 'Accept:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_a_ledger">Get A Ledger</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/ledgers/JMhJyw1e' -i -H 'Accept: */*' -H 'Content-Type: application/json' -d 'JMhJyw1e'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/ledgers/JMhJyw1e HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 8
+
+JMhJyw1e</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'JMhJyw1e' | http GET 'http://localhost:8080/accounting/v1/ledgers/JMhJyw1e' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_ledgers">Get Ledgers</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/ledgers/' -i -H 'Accept: */*' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/ledgers/ HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/ledgers/' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_a_ledger_s_sub_ledgers">Get A Ledger&#8217;s Sub Ledgers</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/ledgers/qq4iM1m2/' -i -H 'Accept: */*' -H 'Content-Type: application/json' -d '[org.apache.fineract.cn.accounting.api.v1.domain.Ledger@6d8d78a]'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/ledgers/qq4iM1m2/ HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 64
+
+[org.apache.fineract.cn.accounting.api.v1.domain.Ledger@6d8d78a]</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo '[org.apache.fineract.cn.accounting.api.v1.domain.Ledger@6d8d78a]' | http GET 'http://localhost:8080/accounting/v1/ledgers/qq4iM1m2/' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_a_ledger_s_accounts">Get A Ledger&#8217;s Accounts</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/ledgers/GPOImtnt/accounts' -i -H 'Accept: */*' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/ledgers/GPOImtnt/accounts HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/ledgers/GPOImtnt/accounts' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_update_a_ledger">Update A Ledger</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/ledgers/8kc9Qdr2' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">PUT /accounting/v1/ledgers/8kc9Qdr2 HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http PUT 'http://localhost:8080/accounting/v1/ledgers/8kc9Qdr2' 'Accept:application/json' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_add_a_sub_ledger">Add A Sub Ledger</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/ledgers/tQgYJsit' -i -X POST -H 'Accept: application/json' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">POST /accounting/v1/ledgers/tQgYJsit HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http POST 'http://localhost:8080/accounting/v1/ledgers/tQgYJsit' 'Accept:application/json' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_delete_a_ledger">Delete A Ledger</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/ledgers/vIYq1aU7' -i -X DELETE -H 'Accept: */*' -H 'Content-Type: application/json' -d 'vIYq1aU7'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">DELETE /accounting/v1/ledgers/vIYq1aU7 HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 8
+
+vIYq1aU7</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'vIYq1aU7' | http DELETE 'http://localhost:8080/accounting/v1/ledgers/vIYq1aU7' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_journals">Journals</h2>
+<div class="sectionbody">
+<div class="sect3">
+<h4 id="_create_a_journal_entry">Create A Journal Entry</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/journal' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d 'GKImphLY'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">POST /accounting/v1/journal HTTP/1.1
+Content-Type: application/json
+Accept: application/json
+Host: localhost:8080
+Content-Length: 8
+
+GKImphLY</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'GKImphLY' | http POST 'http://localhost:8080/accounting/v1/journal' 'Content-Type:application/json' 'Accept:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_journal_entries_within_date_range">Get Journal Entries Within Date Range</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/journal' -i -H 'Accept: */*' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/journal HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/journal' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_journal_entries_within_date_range_and_account">Get Journal Entries Within Date Range And Account</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/journal' -i -H 'Accept: */*' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/journal HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/journal' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_journal_entries_within_date_range_account_and_amount">Get Journal Entries Within Date Range, Account And Amount</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/journal' -i -H 'Accept: */*' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/journal HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/journal' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_transaction_types">Transaction Types</h2>
+<div class="sectionbody">
+<div class="sect3">
+<h4 id="_create_transaction_type">Create Transaction Type</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/transactiontypes' -i -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d 'olmC'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">POST /accounting/v1/transactiontypes HTTP/1.1
+Content-Type: application/json
+Accept: application/json
+Host: localhost:8080
+Content-Length: 4
+
+olmC</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'olmC' | http POST 'http://localhost:8080/accounting/v1/transactiontypes' 'Content-Type:application/json' 'Accept:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_a_transaction_type">Get A Transaction Type</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/transactiontypes/bMpk' -i -H 'Accept: */*' -H 'Content-Type: application/json' -d 'bMpk'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/transactiontypes/bMpk HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080
+Content-Length: 4
+
+bMpk</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ echo 'bMpk' | http GET 'http://localhost:8080/accounting/v1/transactiontypes/bMpk' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_get_transaction_types">Get Transaction Types</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/transactiontypes/' -i -H 'Accept: */*' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">GET /accounting/v1/transactiontypes/ HTTP/1.1
+Accept: */*
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http GET 'http://localhost:8080/accounting/v1/transactiontypes/' 'Accept:*/*' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_update_a_transaction_type">Update A Transaction Type</h4>
+<div class="listingblock">
+<div class="title">curl-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ curl 'http://localhost:8080/accounting/v1/transactiontypes/changeable' -i -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json'</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-request</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">PUT /accounting/v1/transactiontypes/changeable HTTP/1.1
+Accept: application/json
+Content-Type: application/json
+Host: localhost:8080</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">http-response</div>
+<div class="content">
+<pre class="highlightjs highlight nowrap"><code class="language-http" data-lang="http">HTTP/1.1 404 Not Found</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="title">httpie-request</div>
+<div class="content">
+<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">$ http PUT 'http://localhost:8080/accounting/v1/transactiontypes/changeable' 'Accept:application/json' 'Content-Type:application/json'</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2018-04-16 17:35:41 +01:00
+</div>
+</div>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/styles/github.min.css">
+<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/highlight.min.js"></script>
+<script>hljs.initHighlighting()</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/AbstractAccountingTest.java b/service/src/test/java/org/apache/fineract/cn/accounting/AbstractAccountingTest.java
new file mode 100644
index 0000000..22bf4e1
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/AbstractAccountingTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.accounting;
+
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.client.LedgerManager;
+import org.apache.fineract.cn.accounting.service.AccountingServiceConfiguration;
+import org.apache.fineract.cn.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
+import org.apache.fineract.cn.api.context.AutoUserContext;
+import org.apache.fineract.cn.test.fixture.TenantDataStoreContextTestRule;
+import org.apache.fineract.cn.test.listener.EnableEventRecording;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+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.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("SpringAutowiredFieldsWarningInspection")
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
+        classes = {AbstractAccountingTest.TestConfiguration.class})
+public class AbstractAccountingTest extends SuiteTestEnvironment{
+  protected static final String TEST_USER = "setna";
+  public static final String TEST_LOGGER = "test-logger";
+
+  @ClassRule
+  public final static TenantDataStoreContextTestRule tenantDataStoreContext = TenantDataStoreContextTestRule.forRandomTenantName(cassandraInitializer, mariaDBInitializer);
+
+  @Rule
+  public final TenantApplicationSecurityEnvironmentTestRule tenantApplicationSecurityEnvironment
+          = new TenantApplicationSecurityEnvironmentTestRule(testEnvironment, this::waitForInitialize);
+  @Autowired
+  protected LedgerManager testSubject;
+  @Autowired
+  @Qualifier(TEST_LOGGER)
+  protected Logger logger;
+  @Autowired
+  protected EventRecorder eventRecorder;
+
+  private AutoUserContext autoUserContext;
+
+  public AbstractAccountingTest() {
+    super();
+  }
+
+  @Before
+  public void prepTest() throws Exception {
+    this.autoUserContext = this.tenantApplicationSecurityEnvironment.createAutoUserContext(AbstractAccountingTest.TEST_USER);
+  }
+
+  @After
+  public void cleanTest() throws Exception {
+    this.autoUserContext.close();
+  }
+
+  public boolean waitForInitialize() {
+    try {
+      return this.eventRecorder.wait(EventConstants.INITIALIZE, "1");
+    } catch (final InterruptedException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  @Configuration
+  @EnableEventRecording
+  @EnableFeignClients(basePackages = {"org.apache.fineract.cn.accounting.api.v1"})
+  @RibbonClient(name = APP_NAME)
+  @Import({AccountingServiceConfiguration.class})
+  @ComponentScan("org.apache.fineract.cn.accounting.listener")
+  public static class TestConfiguration {
+    public TestConfiguration() {
+      super();
+    }
+
+    @Bean(name= TEST_LOGGER)
+    public Logger logger() {
+      return LoggerFactory.getLogger(TEST_LOGGER);
+    }
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/StressTestJournalEntry.java b/service/src/test/java/org/apache/fineract/cn/accounting/StressTestJournalEntry.java
new file mode 100644
index 0000000..1679072
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/StressTestJournalEntry.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.domain.Account;
+import org.apache.fineract.cn.accounting.api.v1.domain.JournalEntry;
+import org.apache.fineract.cn.accounting.api.v1.domain.Ledger;
+import org.apache.fineract.cn.accounting.util.AccountGenerator;
+import org.apache.fineract.cn.accounting.util.JournalEntryGenerator;
+import org.apache.fineract.cn.accounting.util.LedgerGenerator;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class StressTestJournalEntry extends AbstractAccountingTest {
+
+  @Test
+  public void runStresser() throws Exception {
+    final int numberOfLedgers = 32;
+    final int numberOfAccounts = 512;
+    final int numberOfJournalEntries = 1024;
+
+    final Account[] preparedAccountsAsArray = this.prepareData(numberOfLedgers, numberOfAccounts);
+
+    this.writeJournalEntries(4, numberOfJournalEntries, preparedAccountsAsArray);
+    this.writeJournalEntries(8, numberOfJournalEntries, preparedAccountsAsArray);
+    this.writeJournalEntries(16, numberOfJournalEntries, preparedAccountsAsArray);
+    this.writeJournalEntries(24, numberOfJournalEntries, preparedAccountsAsArray);
+    this.writeJournalEntries(32, numberOfJournalEntries, preparedAccountsAsArray);
+  }
+
+  private void writeJournalEntries(final int numberOfThreads, final int numberOfJournalEntries, final Account[] preparedAccountsAsArray) {
+    final List<Future<?>> futures = new ArrayList<>(numberOfThreads);
+    final ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
+    final AtomicLong totalExecutionTime = new AtomicLong(0L);
+
+    for (int t = 0; t < numberOfThreads; t++) {
+      final Future<?> future = executorService.submit(
+          () -> {
+            long executionTime = 0L;
+            int randomBound = preparedAccountsAsArray.length;
+            for (int i = 0; i < numberOfJournalEntries; i++) {
+              final Account debtorAccount = preparedAccountsAsArray[RandomUtils.nextInt(randomBound)];
+              final Account creditorAccount = preparedAccountsAsArray[RandomUtils.nextInt(randomBound)];
+
+              final JournalEntry randomJournalEntry =
+                  JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00", creditorAccount, "50.00");
+              final long start = System.currentTimeMillis();
+              this.testSubject.createJournalEntry(randomJournalEntry);
+              executionTime += (System.currentTimeMillis() - start);
+            }
+            totalExecutionTime.addAndGet(executionTime);
+          }
+      );
+      futures.add(future);
+    }
+
+    futures.forEach(future -> {
+      try {
+        future.get();
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+    });
+
+    final long numberOfProcessedJournalEntries = numberOfJournalEntries * numberOfThreads;
+    final long processingTime = totalExecutionTime.get();
+    this.logger.error("Added {} journal entries in {}s.", numberOfProcessedJournalEntries, (processingTime / 1000L));
+    this.logger.error("Average processing time for one journal entry: {}ms", processingTime / numberOfProcessedJournalEntries);
+  }
+
+  private Account[] prepareData(int numberOfLedgers, int numberOfAccounts) throws Exception {
+    final ArrayList<Account> createdAccounts = new ArrayList<>(numberOfLedgers * numberOfAccounts);
+    final AtomicLong preparationTime = new AtomicLong(0L);
+    for (int i = 0; i < numberOfLedgers; i++) {
+      final long start = System.currentTimeMillis();
+      final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+      this.testSubject.createLedger(randomLedger);
+      this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+      for (int j = 0; j < numberOfAccounts; j++) {
+        final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+        this.testSubject.createAccount(randomAccount);
+        this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+        createdAccounts.add(randomAccount);
+      }
+      final long processingTime = (System.currentTimeMillis() - start);
+      preparationTime.addAndGet(processingTime);
+    }
+    this.logger.error("Created {} ledgers and {} accounts in {}s.", numberOfLedgers, (numberOfAccounts * numberOfLedgers), (preparationTime.get() / 1000L));
+    this.logger.error("Average processing time for one account: {}ms.", preparationTime.get() / (numberOfAccounts * numberOfLedgers));
+    final Account[] toReturn = new Account[createdAccounts.size()];
+    createdAccounts.toArray(toReturn);
+    return toReturn;
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/SuiteTestEnvironment.java b/service/src/test/java/org/apache/fineract/cn/accounting/SuiteTestEnvironment.java
new file mode 100644
index 0000000..f78cfab
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/SuiteTestEnvironment.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting;
+
+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;
+
+/**
+ * @author Myrle Krantz
+ */
+public class SuiteTestEnvironment {
+  static final String APP_NAME = "accounting-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));
+}
\ No newline at end of file
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/TestAccount.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestAccount.java
new file mode 100644
index 0000000..c932fb2
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestAccount.java
@@ -0,0 +1,763 @@
+/*
+ * 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.accounting;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.client.AccountAlreadyExistsException;
+import org.apache.fineract.cn.accounting.api.v1.client.AccountNotFoundException;
+import org.apache.fineract.cn.accounting.api.v1.client.AccountReferenceException;
+import org.apache.fineract.cn.accounting.api.v1.domain.*;
+import org.apache.fineract.cn.accounting.util.AccountGenerator;
+import org.apache.fineract.cn.accounting.util.JournalEntryGenerator;
+import org.apache.fineract.cn.accounting.util.LedgerGenerator;
+import org.apache.fineract.cn.lang.DateRange;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.JUnitRestDocumentation;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.time.Clock;
+import java.time.LocalDate;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+public class TestAccount extends AbstractAccountingTest {
+
+  @Rule
+  public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("src/doc/generated-snippets/test-account");
+
+  @Autowired
+  private WebApplicationContext context;
+
+  private MockMvc mockMvc;
+
+  final String path = "/accounting/v1";
+
+  @Before
+  public void setUp(){
+
+    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
+            .apply(documentationConfiguration(this.restDocumentation))
+            .alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
+            .build();
+  }
+
+  @Test
+  public void shouldCreateAccount() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+
+    this.testSubject.createAccount(account);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account.getIdentifier());
+
+    final Account savedAccount = this.testSubject.findAccount(account.getIdentifier());
+    Assert.assertNotNull(savedAccount);
+
+    this.mockMvc.perform(post(path + "/accounts")
+            .contentType(MediaType.APPLICATION_JSON_VALUE).accept(MediaType.APPLICATION_JSON_VALUE)
+            .content(savedAccount.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldNotCreateAccountAlreadyExists() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+
+    this.testSubject.createAccount(account);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account.getIdentifier());
+
+    try {
+      this.testSubject.createAccount(account);
+      Assert.fail();
+    } catch (final AccountAlreadyExistsException ignored) {
+    }
+  }
+
+  @Test
+  public void shouldNotCreatedAccountUnknownReferenceAccount() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    account.setReferenceAccount(RandomStringUtils.randomAlphanumeric(8));
+
+    try {
+      this.testSubject.createAccount(account);
+      Assert.fail();
+    } catch (final IllegalArgumentException ex) {
+      Assert.assertTrue(ex.getMessage().contains(account.getReferenceAccount()));
+    }
+  }
+
+  @Test
+  public void shouldNotCreateAccountUnknownLedger() throws Exception {
+    final Account account = AccountGenerator.createRandomAccount(RandomStringUtils.randomAlphanumeric(8));
+
+    try {
+      this.testSubject.createAccount(account);
+      Assert.fail();
+    } catch (final IllegalArgumentException ex) {
+      Assert.assertTrue(ex.getMessage().contains(account.getLedger()));
+    }
+  }
+
+  @Test
+  public void shouldNotCreatedAccountTypeMismatch() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    account.setType(AccountType.LIABILITY.name());
+
+    try {
+      this.testSubject.createAccount(account);
+      Assert.fail();
+    } catch (final IllegalArgumentException ex) {
+      Assert.assertTrue(ex.getMessage().contains(account.getType()));
+    }
+  }
+
+  @Test
+  public void shouldFindAccount() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account referenceAccount = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+
+    this.testSubject.createAccount(referenceAccount);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, referenceAccount.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    account.setReferenceAccount(referenceAccount.getIdentifier());
+    this.testSubject.createAccount(account);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account.getIdentifier());
+
+    final Account savedAccount = this.testSubject.findAccount(account.getIdentifier());
+    Assert.assertNotNull(savedAccount);
+    Assert.assertEquals(account.getIdentifier(), savedAccount.getIdentifier());
+    Assert.assertEquals(account.getName(), savedAccount.getName());
+    Assert.assertEquals(account.getType(), savedAccount.getType());
+    Assert.assertEquals(account.getLedger(), savedAccount.getLedger());
+    Assert.assertEquals(account.getReferenceAccount(), savedAccount.getReferenceAccount());
+    Assert.assertTrue(account.getHolders().containsAll(savedAccount.getHolders()));
+    Assert.assertTrue(account.getSignatureAuthorities().containsAll(savedAccount.getSignatureAuthorities()));
+    Assert.assertEquals(account.getBalance(), savedAccount.getBalance());
+    Assert.assertNotNull(savedAccount.getCreatedBy());
+    Assert.assertNotNull(savedAccount.getCreatedOn());
+    Assert.assertNull(savedAccount.getLastModifiedBy());
+    Assert.assertNull(savedAccount.getLastModifiedOn());
+    Assert.assertEquals(Account.State.OPEN.name(), savedAccount.getState());
+
+    this.mockMvc.perform(get(path + "/accounts/" + savedAccount.getIdentifier())
+            .accept(MediaType.APPLICATION_JSON))
+            .andExpect(status().is4xxClientError());
+  }
+
+  @Test
+  public void shouldNotFindAccountUnknown() {
+    final String randomName = RandomStringUtils.randomAlphanumeric(8);
+    try {
+      this.testSubject.findAccount(randomName);
+      Assert.fail();
+    } catch (final AccountNotFoundException ignored) {
+    }
+  }
+
+  @Test
+  public void shouldFetchAccounts() throws Exception {
+    final AccountPage currentAccountPage =
+            this.testSubject.fetchAccounts(true, null, null, true, null, null, null, null);
+
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+
+    this.testSubject.createAccount(account);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account.getIdentifier());
+
+    final AccountPage accountPage =
+            this.testSubject.fetchAccounts(true, null, null, true, null, null, null, null);
+    Assert.assertEquals(currentAccountPage.getTotalElements() + 1L, accountPage.getTotalElements().longValue());
+
+    this.mockMvc.perform(get(path + "/accounts").accept(MediaType.ALL))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldFetchAccountForTerm() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account referenceAccount = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    referenceAccount.setIdentifier("001.1");
+
+    this.testSubject.createAccount(referenceAccount);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, referenceAccount.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    account.setIdentifier("001.2");
+    account.setReferenceAccount(referenceAccount.getIdentifier());
+
+    this.testSubject.createAccount(account);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account.getIdentifier());
+
+    final AccountPage accountPage = this.testSubject.fetchAccounts(
+            true, "001.", null, true, null, null, null, null);
+    Assert.assertEquals(Long.valueOf(2L), accountPage.getTotalElements());
+  }
+
+  @Test
+  public void shouldNotFetchAccountUnknownTerm() throws Exception {
+    final AccountPage accountPage =
+            this.testSubject.fetchAccounts(
+                    true, RandomStringUtils.randomAlphanumeric(8), null, true, null, null, null, null);
+    Assert.assertTrue(accountPage.getTotalElements() == 0);
+  }
+
+  @Test
+  public void shouldFindOnlyActiveAccounts() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account referenceAccount = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    this.testSubject.createAccount(referenceAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, referenceAccount.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    account.setReferenceAccount(referenceAccount.getIdentifier());
+    this.testSubject.createAccount(account);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account.getIdentifier());
+
+    final AccountCommand accountCommand = new AccountCommand();
+    accountCommand.setAction(AccountCommand.Action.CLOSE.name());
+    accountCommand.setComment("close reference!");
+    this.testSubject.accountCommand(referenceAccount.getIdentifier(), accountCommand);
+    Assert.assertTrue(this.eventRecorder.wait(EventConstants.CLOSE_ACCOUNT, referenceAccount.getIdentifier()));
+
+    final AccountPage accountPage = this.testSubject.fetchAccounts(
+            false, null, null, true, null, null, null, null);
+    Assert.assertEquals(Long.valueOf(1), accountPage.getTotalElements());
+  }
+
+  @Test
+  public void shouldModifyAccount() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account account = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    this.testSubject.createAccount(account);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account.getIdentifier());
+
+    final Account modifiedAccount = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    modifiedAccount.setIdentifier(account.getIdentifier());
+    modifiedAccount.setType(account.getType());
+
+    this.testSubject.modifyAccount(modifiedAccount.getIdentifier(), modifiedAccount);
+
+    this.eventRecorder.wait(EventConstants.PUT_ACCOUNT, modifiedAccount.getIdentifier());
+
+    final Account fetchedAccount = this.testSubject.findAccount(account.getIdentifier());
+    Assert.assertNotNull(fetchedAccount);
+    Assert.assertEquals(modifiedAccount.getIdentifier(), fetchedAccount.getIdentifier());
+    Assert.assertEquals(modifiedAccount.getType(), fetchedAccount.getType());
+    Assert.assertEquals(modifiedAccount.getLedger(), fetchedAccount.getLedger());
+    Assert.assertEquals(modifiedAccount.getReferenceAccount(), fetchedAccount.getReferenceAccount());
+    Assert.assertTrue(modifiedAccount.getHolders().containsAll(fetchedAccount.getHolders()));
+    Assert.assertTrue(modifiedAccount.getSignatureAuthorities().containsAll(fetchedAccount.getSignatureAuthorities()));
+    Assert.assertEquals(modifiedAccount.getBalance(), fetchedAccount.getBalance());
+    Assert.assertNotNull(fetchedAccount.getCreatedBy());
+    Assert.assertNotNull(fetchedAccount.getCreatedOn());
+    Assert.assertNotNull(fetchedAccount.getLastModifiedBy());
+    Assert.assertNotNull(fetchedAccount.getLastModifiedOn());
+    Assert.assertEquals(Account.State.OPEN.name(), fetchedAccount.getState());
+
+    this.mockMvc.perform(put(path + "/accounts/" + account.getIdentifier())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(modifiedAccount.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldListAccountEntries() throws InterruptedException {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    this.testSubject.createAccount(debtorAccount);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(ledger.getIdentifier());
+    this.testSubject.createAccount(creditorAccount);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final int journaEntryCount = 58;
+    final List<JournalEntry> randomJournalEntries = Stream.generate(() -> JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00", creditorAccount, "50.00"))
+            .limit(journaEntryCount)
+            .collect(Collectors.toList());
+
+    randomJournalEntries.stream()
+            .map(randomJournalEntry -> {
+              this.testSubject.createJournalEntry(randomJournalEntry);
+              return randomJournalEntry.getTransactionIdentifier();
+            })
+            .forEach(transactionIdentifier -> {
+              try {
+                this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, transactionIdentifier);
+                this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, transactionIdentifier);
+              }
+              catch (final InterruptedException e) {
+                throw new RuntimeException(e);
+              }
+            });
+
+    Thread.sleep(300L); // Short pause to make sure it really is last.
+    final JournalEntry lastRandomJournalEntry = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00", creditorAccount, "50.00");
+    this.testSubject.createJournalEntry(lastRandomJournalEntry);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, lastRandomJournalEntry.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, lastRandomJournalEntry.getTransactionIdentifier());
+
+    final Set<String> journalEntryMessages
+            = randomJournalEntries.stream().map(JournalEntry::getMessage).collect(Collectors.toSet());
+    journalEntryMessages.add(lastRandomJournalEntry.getMessage());
+
+    final LocalDate today = LocalDate.now(Clock.systemUTC());
+    final String todayDateRange = new DateRange(today, today).toString();
+    final List<AccountEntry> accountEntriesForward = this.testSubject.fetchAccountEntriesStream(creditorAccount.getIdentifier(),
+            todayDateRange, null, "ASC")
+            .collect(Collectors.toList());
+    final Set<String> accountEntryMessages = accountEntriesForward.stream()
+            .map(AccountEntry::getMessage)
+            .collect(Collectors.toSet());
+
+    Assert.assertEquals(journalEntryMessages, accountEntryMessages);
+    Assert.assertEquals(journaEntryCount + 1, accountEntryMessages.size());
+
+    final String oneMessage = accountEntryMessages.iterator().next();
+    final List<AccountEntry> oneAccountEntry = this.testSubject.fetchAccountEntriesStream(creditorAccount.getIdentifier(),
+            todayDateRange, oneMessage, "ASC").collect(Collectors.toList());
+    Assert.assertEquals(1, oneAccountEntry.size());
+    Assert.assertEquals(oneMessage, oneAccountEntry.get(0).getMessage());
+
+    final List<AccountEntry> accountEntriesBackward = this.testSubject
+            .fetchAccountEntriesStream(
+                    creditorAccount.getIdentifier(),
+                    todayDateRange,
+                    null, "DESC")
+            .collect(Collectors.toList());
+
+    final Optional<AccountEntry> lastAccountEntry = accountEntriesBackward.stream().findFirst();
+    Assert.assertTrue(lastAccountEntry.isPresent());
+    Assert.assertEquals(lastRandomJournalEntry.getMessage(), lastAccountEntry.get().getMessage());
+
+    Collections.reverse(accountEntriesBackward);
+    Assert.assertEquals(accountEntriesBackward, accountEntriesForward);
+
+    try {
+      this.mockMvc.perform(get(path + "/accounts/" + ledger.getIdentifier() + "/entries")
+              .accept(MediaType.ALL))
+              .andExpect(status().is4xxClientError());
+    } catch (Exception exception){ exception.printStackTrace(); }
+
+  }
+
+  @Test
+  public void shouldCloseAccount() throws Exception {
+    final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(randomLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+
+    final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    this.testSubject.createAccount(randomAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+
+    final AccountCommand accountCommand = new AccountCommand();
+    accountCommand.setAction(AccountCommand.Action.CLOSE.name());
+    accountCommand.setComment("close this!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), accountCommand);
+    Assert.assertTrue(this.eventRecorder.wait(EventConstants.CLOSE_ACCOUNT, randomAccount.getIdentifier()));
+
+    this.mockMvc.perform(put(path + "/accounts/" + randomAccount.getIdentifier() + "/commands")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(randomAccount.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldReopenAccount() throws Exception {
+    final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(randomLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+
+    final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    this.testSubject.createAccount(randomAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+
+    final AccountCommand closeAccountCommand = new AccountCommand();
+    closeAccountCommand.setAction(AccountCommand.Action.CLOSE.name());
+    closeAccountCommand.setComment("close this!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), closeAccountCommand);
+    this.eventRecorder.wait(EventConstants.CLOSE_ACCOUNT, randomAccount.getIdentifier());
+
+    final AccountCommand reopenAccountCommand = new AccountCommand();
+    reopenAccountCommand.setAction(AccountCommand.Action.REOPEN.name());
+    reopenAccountCommand.setComment("reopen it!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), reopenAccountCommand);
+    Assert.assertTrue(this.eventRecorder.wait(EventConstants.REOPEN_ACCOUNT, randomAccount.getIdentifier()));
+
+    this.mockMvc.perform(put(path + "/accounts/" + randomAccount.getIdentifier() + "/commands")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(randomAccount.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldLockAccount() throws Exception {
+    final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(randomLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+
+    final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    this.testSubject.createAccount(randomAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+
+    final AccountCommand accountCommand = new AccountCommand();
+    accountCommand.setAction(AccountCommand.Action.LOCK.name());
+    accountCommand.setComment("lock this!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), accountCommand);
+    Assert.assertTrue(this.eventRecorder.wait(EventConstants.LOCK_ACCOUNT, randomAccount.getIdentifier()));
+
+    this.mockMvc.perform(put(path + "/accounts/" + randomAccount.getIdentifier() + "/commands")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(randomAccount.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldUnlockAccount() throws Exception {
+    final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(randomLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+
+    final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    this.testSubject.createAccount(randomAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+
+    final AccountCommand lockAccountCommand = new AccountCommand();
+    lockAccountCommand.setAction(AccountCommand.Action.LOCK.name());
+    lockAccountCommand.setComment("lock this!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), lockAccountCommand);
+    this.eventRecorder.wait(EventConstants.LOCK_ACCOUNT, randomAccount.getIdentifier());
+
+    final AccountCommand unlockAccountCommand = new AccountCommand();
+    unlockAccountCommand.setAction(AccountCommand.Action.UNLOCK.name());
+    unlockAccountCommand.setComment("unlock it!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), unlockAccountCommand);
+    Assert.assertTrue(this.eventRecorder.wait(EventConstants.UNLOCK_ACCOUNT, randomAccount.getIdentifier()));
+
+    this.mockMvc.perform(put(path + "/accounts/" + randomAccount.getIdentifier() + "/commands")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(randomAccount.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldDeleteAccount() throws Exception {
+    final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(randomLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+
+    final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    this.testSubject.createAccount(randomAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+
+    final AccountCommand accountCommand = new AccountCommand();
+    accountCommand.setAction(AccountCommand.Action.CLOSE.name());
+    accountCommand.setComment("close this!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), accountCommand);
+    this.eventRecorder.wait(EventConstants.CLOSE_ACCOUNT, randomAccount.getIdentifier());
+
+    this.testSubject.deleteAccount(randomAccount.getIdentifier());
+    Assert.assertTrue(this.eventRecorder.wait(EventConstants.DELETE_ACCOUNT, randomAccount.getIdentifier()));
+
+    this.mockMvc.perform(delete(path + "/accounts/" + randomAccount.getIdentifier())
+            .accept(MediaType.ALL_VALUE)
+            .contentType(MediaType.APPLICATION_JSON))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldNotDeleteAccountStillOpen() throws Exception {
+    final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(randomLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+
+    final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    this.testSubject.createAccount(randomAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+
+    try {
+      this.testSubject.deleteAccount(randomAccount.getIdentifier());
+      Assert.fail();
+    } catch (final AccountReferenceException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldNotDeleteAccountEntriesExists() throws Exception {
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(assetLedger.getIdentifier());
+    debtorAccount.setType(AccountType.LIABILITY.name());
+    debtorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(debtorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(liabilityLedger.getIdentifier());
+    creditorAccount.setType(AccountType.LIABILITY.name());
+    creditorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(creditorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final JournalEntry journalEntry = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "100.00",
+            creditorAccount, "100.00");
+    this.testSubject.createJournalEntry(journalEntry);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntry.getTransactionIdentifier());
+
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntry.getTransactionIdentifier());
+
+    final AccountCommand closeAccountCommand = new AccountCommand();
+    closeAccountCommand.setAction(AccountCommand.Action.CLOSE.name());
+    closeAccountCommand.setComment("close this!");
+    this.testSubject.accountCommand(debtorAccount.getIdentifier(), closeAccountCommand);
+    this.eventRecorder.wait(EventConstants.CLOSE_ACCOUNT, debtorAccount.getIdentifier());
+
+    try {
+      this.testSubject.deleteAccount(debtorAccount.getIdentifier());
+      Assert.fail();
+    } catch (final AccountReferenceException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldNotDeleteAccountIsReferenced() throws Exception {
+    final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(randomLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+
+    final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    this.testSubject.createAccount(randomAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+
+    final Account referencingAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    referencingAccount.setReferenceAccount(randomAccount.getIdentifier());
+    this.testSubject.createAccount(referencingAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, referencingAccount.getIdentifier());
+
+    try {
+      this.testSubject.deleteAccount(randomAccount.getIdentifier());
+      Assert.fail();
+    } catch (final AccountReferenceException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldReturnOnlyAvailableCommands() throws Exception {
+    final Ledger randomLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(randomLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, randomLedger.getIdentifier());
+
+    final Account randomAccount = AccountGenerator.createRandomAccount(randomLedger.getIdentifier());
+    this.testSubject.createAccount(randomAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, randomAccount.getIdentifier());
+
+    final List<AccountCommand> openAccountCommands = super.testSubject.fetchActions(randomAccount.getIdentifier());
+    Assert.assertEquals(2, openAccountCommands.size());
+    Assert.assertEquals(AccountCommand.Action.LOCK.name(), openAccountCommands.get(0).getAction());
+    Assert.assertEquals(AccountCommand.Action.CLOSE.name(), openAccountCommands.get(1).getAction());
+
+    final AccountCommand lockAccountCommand = new AccountCommand();
+    lockAccountCommand.setAction(AccountCommand.Action.LOCK.name());
+    lockAccountCommand.setComment("lock this!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), lockAccountCommand);
+    this.eventRecorder.wait(EventConstants.LOCK_ACCOUNT, randomAccount.getIdentifier());
+
+    final List<AccountCommand> lockedAccountCommands = super.testSubject.fetchActions(randomAccount.getIdentifier());
+    Assert.assertEquals(2, lockedAccountCommands.size());
+    Assert.assertEquals(AccountCommand.Action.UNLOCK.name(), lockedAccountCommands.get(0).getAction());
+    Assert.assertEquals(AccountCommand.Action.CLOSE.name(), lockedAccountCommands.get(1).getAction());
+
+    final AccountCommand unlockAccountCommand = new AccountCommand();
+    unlockAccountCommand.setAction(AccountCommand.Action.UNLOCK.name());
+    unlockAccountCommand.setComment("unlock this!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), unlockAccountCommand);
+    this.eventRecorder.wait(EventConstants.UNLOCK_ACCOUNT, randomAccount.getIdentifier());
+
+    final List<AccountCommand> unlockedAccountCommands = super.testSubject.fetchActions(randomAccount.getIdentifier());
+    Assert.assertEquals(2, unlockedAccountCommands.size());
+    Assert.assertEquals(AccountCommand.Action.LOCK.name(), unlockedAccountCommands.get(0).getAction());
+    Assert.assertEquals(AccountCommand.Action.CLOSE.name(), unlockedAccountCommands.get(1).getAction());
+
+    final AccountCommand closeAccountCommand = new AccountCommand();
+    closeAccountCommand.setAction(AccountCommand.Action.CLOSE.name());
+    closeAccountCommand.setComment("unlock this!");
+    this.testSubject.accountCommand(randomAccount.getIdentifier(), closeAccountCommand);
+    this.eventRecorder.wait(EventConstants.CLOSE_ACCOUNT, randomAccount.getIdentifier());
+
+    final List<AccountCommand> closedAccountCommands = super.testSubject.fetchActions(randomAccount.getIdentifier());
+    Assert.assertEquals(1, closedAccountCommands.size());
+    Assert.assertEquals(AccountCommand.Action.REOPEN.name(), closedAccountCommands.get(0).getAction());
+
+    try
+    {
+      this.mockMvc.perform(get(path + "/accounts/" + randomAccount.getIdentifier() + "/commands" )
+              .accept(MediaType.ALL))
+              .andExpect(status().isNotFound());
+    } catch (Exception exception){ exception.printStackTrace(); }
+  }
+
+  @Test
+  public void shouldFetchAccountsWithEmptyHolder() throws Exception {
+    final Ledger ledger = LedgerGenerator.createLedger("noholder-10000", AccountType.EQUITY);
+
+    this.testSubject.createLedger(ledger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account account1 =
+            AccountGenerator.createAccount(ledger.getIdentifier(), "noholder-10001", AccountType.EQUITY);
+    account1.setHolders(null);
+    this.testSubject.createAccount(account1);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account1.getIdentifier());
+
+    final Account account2 =
+            AccountGenerator.createAccount(ledger.getIdentifier(), "noholder-10002", AccountType.EQUITY);
+    account2.setHolders(new HashSet<>());
+    this.testSubject.createAccount(account2);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account2.getIdentifier());
+
+    final AccountPage accountPage =
+            this.testSubject.fetchAccounts(false, "noholder", AccountType.EQUITY.name(), false, null, null, null, null);
+    Assert.assertEquals(2L, accountPage.getTotalElements().longValue());
+  }
+
+  @Test
+  public void shouldFindAccountWithAlternativeAccountNumber() throws Exception {
+    final Ledger ledger = LedgerGenerator.createLedger("alt-account-10000", AccountType.EQUITY);
+
+    this.testSubject.createLedger(ledger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Account altAccount =
+            AccountGenerator.createAccount(ledger.getIdentifier(), "alt-account-10001", AccountType.EQUITY);
+    altAccount.setAlternativeAccountNumber("08154711");
+    this.testSubject.createAccount(altAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, altAccount.getIdentifier());
+
+    final AccountPage accountPage = this.testSubject.fetchAccounts(true, "08154711", null, true,
+            0, 10, null, null);
+    Assert.assertEquals(Long.valueOf(1L), accountPage.getTotalElements());
+    final Account account = accountPage.getAccounts().get(0);
+    Assert.assertEquals("alt-account-10001", account.getIdentifier());
+    Assert.assertEquals("08154711", account.getAlternativeAccountNumber());
+
+    this.mockMvc.perform(get(path + "/accounts/" + altAccount.getIdentifier())
+            .accept(MediaType.APPLICATION_JSON))
+            .andExpect(status().is4xxClientError());
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/TestChartOfAccounts.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestChartOfAccounts.java
new file mode 100644
index 0000000..1de96c3
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestChartOfAccounts.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting;
+
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.domain.Account;
+import org.apache.fineract.cn.accounting.api.v1.domain.AccountType;
+import org.apache.fineract.cn.accounting.api.v1.domain.ChartOfAccountEntry;
+import org.apache.fineract.cn.accounting.api.v1.domain.Ledger;
+import org.apache.fineract.cn.accounting.util.AccountGenerator;
+import org.apache.fineract.cn.accounting.util.LedgerGenerator;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+public class TestChartOfAccounts extends AbstractAccountingTest {
+
+  @Test
+  public void shouldShowChartOfAccounts() throws Exception {
+    final Ledger parentRevenueLedger = LedgerGenerator.createLedger("10000", AccountType.REVENUE);
+    this.testSubject.createLedger(parentRevenueLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, parentRevenueLedger.getIdentifier());
+
+    final Ledger interestRevenueLedger = LedgerGenerator.createLedger("11000", AccountType.REVENUE);
+    this.testSubject.addSubLedger(parentRevenueLedger.getIdentifier(), interestRevenueLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, interestRevenueLedger.getIdentifier());
+
+    final Account consumerInterestRevenueAccount =
+        AccountGenerator.createAccount(interestRevenueLedger.getIdentifier(), "11100", AccountType.REVENUE);
+    this.testSubject.createAccount(consumerInterestRevenueAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, consumerInterestRevenueAccount.getIdentifier());
+
+    final Ledger feeRevenueLedger = LedgerGenerator.createLedger("12000", AccountType.REVENUE);
+    this.testSubject.addSubLedger(parentRevenueLedger.getIdentifier(), feeRevenueLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, feeRevenueLedger.getIdentifier());
+
+    final Ledger specialFeeRevenueLedger = LedgerGenerator.createLedger("12100", AccountType.REVENUE);
+    this.testSubject.addSubLedger(feeRevenueLedger.getIdentifier(), specialFeeRevenueLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, specialFeeRevenueLedger.getIdentifier());
+
+    final Ledger parentAssetLedger = LedgerGenerator.createLedger("70000", AccountType.ASSET);
+    this.testSubject.createLedger(parentAssetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, parentAssetLedger.getIdentifier());
+
+    final Ledger consumerLoanAssetLedger = LedgerGenerator.createLedger("73000", AccountType.ASSET);
+    consumerLoanAssetLedger.setShowAccountsInChart(Boolean.FALSE);
+    this.testSubject.addSubLedger(parentAssetLedger.getIdentifier(), consumerLoanAssetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, consumerLoanAssetLedger.getIdentifier());
+
+    for (int i = 1; i < 100; i++) {
+      final String identifier = Integer.valueOf(73000 + i).toString();
+      final Account consumerLoanAccount =
+          AccountGenerator.createAccount(consumerLoanAssetLedger.getIdentifier(), identifier, AccountType.ASSET);
+      this.testSubject.createAccount(consumerLoanAccount);
+      this.eventRecorder.wait(EventConstants.POST_ACCOUNT, identifier);
+    }
+
+    final List<ChartOfAccountEntry> chartOfAccounts = this.testSubject.getChartOfAccounts();
+    Assert.assertNotNull(chartOfAccounts);
+    Assert.assertEquals(7, chartOfAccounts.size());
+    Assert.assertEquals(Integer.valueOf(0), chartOfAccounts.get(0).getLevel());
+    Assert.assertEquals(Integer.valueOf(1), chartOfAccounts.get(1).getLevel());
+    Assert.assertEquals(Integer.valueOf(2), chartOfAccounts.get(2).getLevel());
+    Assert.assertEquals(Integer.valueOf(1), chartOfAccounts.get(3).getLevel());
+    Assert.assertEquals(Integer.valueOf(2), chartOfAccounts.get(4).getLevel());
+    Assert.assertEquals(Integer.valueOf(0), chartOfAccounts.get(5).getLevel());
+    Assert.assertEquals(Integer.valueOf(1), chartOfAccounts.get(6).getLevel());
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/TestFinancialCondition.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestFinancialCondition.java
new file mode 100644
index 0000000..8bfd7f2
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestFinancialCondition.java
@@ -0,0 +1,145 @@
+/*
+ * 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.accounting;
+
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.domain.Account;
+import org.apache.fineract.cn.accounting.api.v1.domain.AccountType;
+import org.apache.fineract.cn.accounting.api.v1.domain.JournalEntry;
+import org.apache.fineract.cn.accounting.api.v1.domain.Ledger;
+import org.apache.fineract.cn.accounting.api.v1.domain.financial.statement.FinancialCondition;
+import org.apache.fineract.cn.accounting.util.AccountGenerator;
+import org.apache.fineract.cn.accounting.util.JournalEntryGenerator;
+import org.apache.fineract.cn.accounting.util.LedgerGenerator;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+
+public class TestFinancialCondition extends AbstractAccountingTest {
+
+  public TestFinancialCondition() {
+    super();
+  }
+
+  @Test
+  public void shouldReturnFinancialCondition() throws Exception {
+    this.fixtures();
+    this.sampleJournalEntries();
+
+    final BigDecimal totalAssets = BigDecimal.valueOf(250.00D);
+    final BigDecimal expectedEquitiesAndLiabilities = BigDecimal.valueOf(250.00D);
+
+    final FinancialCondition financialCondition = super.testSubject.getFinancialCondition();
+    Assert.assertTrue(financialCondition.getTotalAssets().compareTo(totalAssets) == 0);
+    Assert.assertTrue(financialCondition.getTotalEquitiesAndLiabilities().compareTo(expectedEquitiesAndLiabilities) == 0);
+  }
+
+  private void fixtures() throws Exception {
+    final Ledger assetLedger = LedgerGenerator.createLedger("7000", AccountType.ASSET);
+    assetLedger.setName("Assets");
+    super.testSubject.createLedger(assetLedger);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier()));
+
+    final Ledger assetSubLedger7010 = LedgerGenerator.createLedger("7010", AccountType.ASSET);
+    assetSubLedger7010.setParentLedgerIdentifier(assetLedger.getParentLedgerIdentifier());
+    assetSubLedger7010.setName("Loans to Members");
+    super.testSubject.addSubLedger(assetLedger.getIdentifier(), assetSubLedger7010);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, assetSubLedger7010.getIdentifier()));
+
+    final Ledger assetSubLedger7020 = LedgerGenerator.createLedger("7020", AccountType.ASSET);
+    assetSubLedger7020.setParentLedgerIdentifier(assetLedger.getParentLedgerIdentifier());
+    assetSubLedger7020.setName("Lines of Credit to Members");
+    super.testSubject.addSubLedger(assetLedger.getIdentifier(), assetSubLedger7020);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, assetSubLedger7020.getIdentifier()));
+
+    final Account firstAssetAccount =
+        AccountGenerator.createAccount(assetSubLedger7010.getIdentifier(), "7011", AccountType.ASSET);
+    super.testSubject.createAccount(firstAssetAccount);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, firstAssetAccount.getIdentifier()));
+
+    final Account secondAssetAccount =
+        AccountGenerator.createAccount(assetSubLedger7020.getIdentifier(), "7021", AccountType.ASSET);
+    super.testSubject.createAccount(secondAssetAccount);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, secondAssetAccount.getIdentifier()));
+
+    final Ledger liabilityLedger = LedgerGenerator.createLedger("8000", AccountType.LIABILITY);
+    liabilityLedger.setName("Liabilities");
+    super.testSubject.createLedger(liabilityLedger);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier()));
+
+    final Ledger liabilitySubLedger8100 = LedgerGenerator.createLedger("8100", AccountType.LIABILITY);
+    liabilitySubLedger8100.setParentLedgerIdentifier(liabilityLedger.getParentLedgerIdentifier());
+    liabilitySubLedger8100.setName("Accounts Payable");
+    super.testSubject.addSubLedger(liabilityLedger.getIdentifier(), liabilitySubLedger8100);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, liabilitySubLedger8100.getIdentifier()));
+
+    final Ledger liabilitySubLedger8200 = LedgerGenerator.createLedger("8200", AccountType.LIABILITY);
+    liabilitySubLedger8200.setParentLedgerIdentifier(liabilityLedger.getParentLedgerIdentifier());
+    liabilitySubLedger8200.setName("Interest Payable");
+    super.testSubject.addSubLedger(liabilityLedger.getIdentifier(), liabilitySubLedger8200);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, liabilitySubLedger8200.getIdentifier()));
+
+    final Account firstLiabilityAccount =
+        AccountGenerator.createAccount(liabilitySubLedger8100.getIdentifier(), "8110", AccountType.LIABILITY);
+    super.testSubject.createAccount(firstLiabilityAccount);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, firstLiabilityAccount.getIdentifier()));
+
+    final Account secondLiabilityAccount =
+        AccountGenerator.createAccount(liabilitySubLedger8200.getIdentifier(), "8210", AccountType.LIABILITY);
+    super.testSubject.createAccount(secondLiabilityAccount);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, secondLiabilityAccount.getIdentifier()));
+
+    final Ledger equityLedger = LedgerGenerator.createLedger("9000", AccountType.EQUITY);
+    equityLedger.setName("Equities");
+    super.testSubject.createLedger(equityLedger);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, equityLedger.getIdentifier()));
+
+    final Ledger equitySubLedger9100 = LedgerGenerator.createLedger("9100", AccountType.EQUITY);
+    equitySubLedger9100.setParentLedgerIdentifier(equityLedger.getParentLedgerIdentifier());
+    equitySubLedger9100.setName("Member Savings");
+    super.testSubject.addSubLedger(equityLedger.getIdentifier(), equitySubLedger9100);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_LEDGER, equitySubLedger9100.getIdentifier()));
+
+    final Account firstEquityAccount =
+        AccountGenerator.createAccount(equitySubLedger9100.getIdentifier(), "9110", AccountType.EQUITY);
+    super.testSubject.createAccount(firstEquityAccount);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_ACCOUNT, firstEquityAccount.getIdentifier()));
+  }
+
+  private void sampleJournalEntries() throws Exception {
+    final JournalEntry firstTransaction =
+        JournalEntryGenerator
+            .createRandomJournalEntry("7011", "150.00", "8110", "150.00");
+    super.testSubject.createJournalEntry(firstTransaction);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, firstTransaction.getTransactionIdentifier()));
+
+    final JournalEntry secondTransaction =
+        JournalEntryGenerator
+            .createRandomJournalEntry("7021", "100.00", "8210", "100.00");
+    super.testSubject.createJournalEntry(secondTransaction);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, secondTransaction.getTransactionIdentifier()));
+
+    final JournalEntry thirdTransaction =
+        JournalEntryGenerator
+            .createRandomJournalEntry("8210", "50.00", "9110", "50.00");
+    super.testSubject.createJournalEntry(thirdTransaction);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, thirdTransaction.getTransactionIdentifier()));
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/TestIncomeStatement.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestIncomeStatement.java
new file mode 100644
index 0000000..f206e69
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestIncomeStatement.java
@@ -0,0 +1,155 @@
+/*
+ * 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.accounting;
+
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.domain.Account;
+import org.apache.fineract.cn.accounting.api.v1.domain.AccountType;
+import org.apache.fineract.cn.accounting.api.v1.domain.JournalEntry;
+import org.apache.fineract.cn.accounting.api.v1.domain.Ledger;
+import org.apache.fineract.cn.accounting.api.v1.domain.financial.statement.IncomeStatement;
+import org.apache.fineract.cn.accounting.util.AccountGenerator;
+import org.apache.fineract.cn.accounting.util.JournalEntryGenerator;
+import org.apache.fineract.cn.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/service/src/test/java/org/apache/fineract/cn/accounting/TestJournalEntry.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestJournalEntry.java
new file mode 100644
index 0000000..1e23ca0
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestJournalEntry.java
@@ -0,0 +1,505 @@
+/*
+ * 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.accounting;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.client.JournalEntryAlreadyExistsException;
+import org.apache.fineract.cn.accounting.api.v1.client.JournalEntryValidationException;
+import org.apache.fineract.cn.accounting.api.v1.domain.*;
+import org.apache.fineract.cn.accounting.util.AccountGenerator;
+import org.apache.fineract.cn.accounting.util.JournalEntryGenerator;
+import org.apache.fineract.cn.accounting.util.LedgerGenerator;
+import org.apache.fineract.cn.lang.DateConverter;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.JUnitRestDocumentation;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.math.BigDecimal;
+import java.text.MessageFormat;
+import java.time.LocalDate;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+public class TestJournalEntry extends AbstractAccountingTest {
+
+  @Rule
+  public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("src/doc/generated-snippets/test-journal");
+
+  @Autowired
+  private WebApplicationContext context;
+
+  private MockMvc mockMvc;
+
+  final String path = "/accounting/v1";
+
+  @Before
+  public void setUp(){
+
+    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
+            .apply(documentationConfiguration(this.restDocumentation))
+            .alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
+            .build();
+  }
+
+  @Test
+  public void shouldCreateJournalEntry() throws Exception {
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.ASSET.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(assetLedger.getIdentifier());
+    debtorAccount.setType(AccountType.ASSET.name());
+    debtorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(debtorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(liabilityLedger.getIdentifier());
+    creditorAccount.setType(AccountType.LIABILITY.name());
+    creditorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(creditorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final JournalEntry journalEntry = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    this.testSubject.createJournalEntry(journalEntry);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntry.getTransactionIdentifier());
+
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntry.getTransactionIdentifier());
+
+    final JournalEntry foundJournalEntry = this.testSubject.findJournalEntry(journalEntry.getTransactionIdentifier());
+    Assert.assertNotNull(foundJournalEntry);
+    Assert.assertEquals(JournalEntry.State.PROCESSED.name(), foundJournalEntry.getState());
+    Assert.assertEquals(journalEntry.getTransactionType(), foundJournalEntry.getTransactionType());
+
+    final Account modifiedDebtorAccount = this.testSubject.findAccount(debtorAccount.getIdentifier());
+    Assert.assertNotNull(modifiedDebtorAccount);
+    Assert.assertEquals(150.0D, modifiedDebtorAccount.getBalance(), 0.0D);
+
+    final Account modifiedCreditorAccount = this.testSubject.findAccount(creditorAccount.getIdentifier());
+    Assert.assertNotNull(modifiedCreditorAccount);
+    Assert.assertEquals(150.0d, modifiedCreditorAccount.getBalance(), 0.0D);
+
+    this.mockMvc.perform(post(path + "/journal")
+            .contentType(MediaType.APPLICATION_JSON_VALUE).accept(MediaType.APPLICATION_JSON_VALUE)
+            .content(foundJournalEntry.getTransactionIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldFetchJournalEntriesWithDateRange() throws Exception{
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.ASSET.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(assetLedger.getIdentifier());
+    debtorAccount.setType(AccountType.ASSET.name());
+    debtorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(debtorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(liabilityLedger.getIdentifier());
+    creditorAccount.setType(AccountType.LIABILITY.name());
+    creditorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(creditorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final JournalEntry journalEntryOne = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    final OffsetDateTime start = OffsetDateTime.of(1982, 6, 24, 1, 0, 0, 0, ZoneOffset.UTC);
+    journalEntryOne.setTransactionDate(start.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+
+    this.testSubject.createJournalEntry(journalEntryOne);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntryOne.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntryOne.getTransactionIdentifier());
+
+    final JournalEntry journalEntryTwo = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    final OffsetDateTime end = OffsetDateTime.of(1982, 6, 26, 1, 0, 0, 0, ZoneOffset.UTC);
+    journalEntryTwo.setTransactionDate(end.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+
+    this.testSubject.createJournalEntry(journalEntryTwo);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntryTwo.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntryTwo.getTransactionIdentifier());
+
+    final LocalDate beginDate = LocalDate.of(1982, 6, 24);
+    final LocalDate endDate = LocalDate.of(1982, 6, 26);
+    final String dateRange = MessageFormat.format("{0}..{1}",
+            DateConverter.toIsoString(beginDate),
+            DateConverter.toIsoString(endDate));
+
+    final List<JournalEntry> journalEntries = this.testSubject.fetchJournalEntries(dateRange, null, null);
+
+    Assert.assertTrue(journalEntries.size() >= 2);
+
+    checkAccountEntries(debtorAccount, creditorAccount, journalEntryOne, journalEntryTwo, dateRange);
+
+    this.mockMvc.perform(get(path + "/journal")
+            .accept(MediaType.ALL_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().is4xxClientError());
+  }
+
+  @Test
+  public void shouldFetchJournalEntriesWithDateRangeAndAccount() throws Exception{
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.ASSET.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(assetLedger.getIdentifier());
+    debtorAccount.setType(AccountType.ASSET.name());
+    debtorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(debtorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(liabilityLedger.getIdentifier());
+    creditorAccount.setType(AccountType.LIABILITY.name());
+    creditorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(creditorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final JournalEntry journalEntryOne = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    final OffsetDateTime start = OffsetDateTime.of(1982, 6, 24, 1, 0, 0, 0, ZoneOffset.UTC);
+    journalEntryOne.setTransactionDate(start.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+
+    this.testSubject.createJournalEntry(journalEntryOne);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntryOne.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntryOne.getTransactionIdentifier());
+
+    final JournalEntry journalEntryTwo = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    final OffsetDateTime end = OffsetDateTime.of(1982, 6, 26, 1, 0, 0, 0, ZoneOffset.UTC);
+    journalEntryTwo.setTransactionDate(end.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+
+    this.testSubject.createJournalEntry(journalEntryTwo);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntryTwo.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntryTwo.getTransactionIdentifier());
+
+    final LocalDate beginDate = LocalDate.of(1982, 6, 24);
+    final LocalDate endDate = LocalDate.of(1982, 6, 26);
+    final String dateRange = MessageFormat.format("{0}..{1}",
+            DateConverter.toIsoString(beginDate),
+            DateConverter.toIsoString(endDate));
+
+    final List<JournalEntry> journalEntries = this.testSubject.fetchJournalEntries(dateRange, debtorAccount.getIdentifier(), null);
+
+    Assert.assertEquals(2, journalEntries.size());
+
+    checkAccountEntries(debtorAccount, creditorAccount, journalEntryOne, journalEntryTwo, dateRange);
+
+    this.mockMvc.perform(get(path + "/journal")
+            .accept(MediaType.ALL_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().is4xxClientError());
+  }
+
+  @Test
+  public void shouldFetchJournalEntriesWithDateRangeAndAmount() throws Exception{
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.ASSET.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(assetLedger.getIdentifier());
+    debtorAccount.setType(AccountType.ASSET.name());
+    debtorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(debtorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(liabilityLedger.getIdentifier());
+    creditorAccount.setType(AccountType.LIABILITY.name());
+    creditorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(creditorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final JournalEntry journalEntryOne = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    final OffsetDateTime start = OffsetDateTime.of(1982, 6, 24, 1, 0, 0, 0, ZoneOffset.UTC);
+    journalEntryOne.setTransactionDate(start.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+
+    this.testSubject.createJournalEntry(journalEntryOne);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntryOne.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntryOne.getTransactionIdentifier());
+
+    final JournalEntry journalEntryTwo = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    final OffsetDateTime end = OffsetDateTime.of(1982, 6, 26, 1, 0, 0, 0, ZoneOffset.UTC);
+    journalEntryTwo.setTransactionDate(end.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+
+    this.testSubject.createJournalEntry(journalEntryTwo);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntryTwo.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntryTwo.getTransactionIdentifier());
+
+    final LocalDate beginDate = LocalDate.of(1982, 6, 24);
+    final LocalDate endDate = LocalDate.of(1982, 6, 26);
+    final String dateRange = MessageFormat.format("{0}..{1}",
+            DateConverter.toIsoString(beginDate),
+            DateConverter.toIsoString(endDate));
+
+    final List<JournalEntry> journalEntries = this.testSubject.fetchJournalEntries(dateRange, null, BigDecimal.valueOf(50.00D));
+
+    Assert.assertEquals(2, journalEntries.size());
+
+    checkAccountEntries(debtorAccount, creditorAccount, journalEntryOne, journalEntryTwo, dateRange);
+
+    this.mockMvc.perform(get(path + "/journal")
+            .accept(MediaType.ALL_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().is4xxClientError());
+  }
+
+  @Test
+  public void shouldFetchJournalEntriesWithDateRangeAndAccountAndAmount() throws Exception{
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.ASSET.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(assetLedger.getIdentifier());
+    debtorAccount.setType(AccountType.ASSET.name());
+    debtorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(debtorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(liabilityLedger.getIdentifier());
+    creditorAccount.setType(AccountType.LIABILITY.name());
+    creditorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(creditorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final JournalEntry journalEntryOne = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    final OffsetDateTime start = OffsetDateTime.of(1982, 6, 24, 1, 0, 0, 0, ZoneOffset.UTC);
+    journalEntryOne.setTransactionDate(start.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+
+    this.testSubject.createJournalEntry(journalEntryOne);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntryOne.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntryOne.getTransactionIdentifier());
+
+    final JournalEntry journalEntryTwo = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            creditorAccount, "50.00");
+    final OffsetDateTime end = OffsetDateTime.of(1982, 6, 26, 1, 0, 0, 0, ZoneOffset.UTC);
+    journalEntryTwo.setTransactionDate(end.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+
+    this.testSubject.createJournalEntry(journalEntryTwo);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntryTwo.getTransactionIdentifier());
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, journalEntryTwo.getTransactionIdentifier());
+
+    final LocalDate beginDate = LocalDate.of(1982, 6, 24);
+    final LocalDate endDate = LocalDate.of(1982, 6, 26);
+    final String dateRange = MessageFormat.format("{0}..{1}",
+            DateConverter.toIsoString(beginDate),
+            DateConverter.toIsoString(endDate));
+
+    final List<JournalEntry> journalEntries = this.testSubject.fetchJournalEntries(dateRange, creditorAccount.getIdentifier(), BigDecimal.valueOf(50.00D));
+
+    Assert.assertEquals(2, journalEntries.size());
+
+    checkAccountEntries(debtorAccount, creditorAccount, journalEntryOne, journalEntryTwo, dateRange);
+
+    this.mockMvc.perform(get(path + "/journal")
+            .accept(MediaType.ALL_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().is4xxClientError());
+  }
+
+  @Test(expected = JournalEntryValidationException.class)
+  public void shouldNotCreateJournalEntryMissingDebtors() throws Exception {
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(liabilityLedger.getIdentifier());
+    creditorAccount.setType(AccountType.LIABILITY.name());
+    creditorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(creditorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final JournalEntry journalEntry = JournalEntryGenerator.createRandomJournalEntry(null, null,
+            creditorAccount, "50.00");
+    this.testSubject.createJournalEntry(journalEntry);
+  }
+
+  @Test(expected = JournalEntryAlreadyExistsException.class)
+  public void shouldNotCreateJournalAlreadyExists() throws Exception {
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.ASSET.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(assetLedger.getIdentifier());
+    debtorAccount.setType(AccountType.ASSET.name());
+    debtorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(debtorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Account creditorAccount = AccountGenerator.createRandomAccount(liabilityLedger.getIdentifier());
+    creditorAccount.setType(AccountType.LIABILITY.name());
+    creditorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(creditorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, creditorAccount.getIdentifier());
+
+    final JournalEntry journalEntry = JournalEntryGenerator.createRandomJournalEntry(creditorAccount, "50.00",
+            creditorAccount, "50.00");
+    this.testSubject.createJournalEntry(journalEntry);
+    this.eventRecorder.wait(EventConstants.POST_JOURNAL_ENTRY, journalEntry.getTransactionIdentifier());
+
+    this.testSubject.createJournalEntry(journalEntry);
+  }
+
+  @Test(expected = JournalEntryValidationException.class)
+  public void shouldNotCreateJournalEntryMissingCreditors() throws Exception {
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.ASSET.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Account debtorAccount = AccountGenerator.createRandomAccount(assetLedger.getIdentifier());
+    debtorAccount.setType(AccountType.ASSET.name());
+    debtorAccount.setBalance(100.00D);
+    this.testSubject.createAccount(debtorAccount);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, debtorAccount.getIdentifier());
+
+    final JournalEntry journalEntry = JournalEntryGenerator.createRandomJournalEntry(debtorAccount, "50.00",
+            null, null);
+    this.testSubject.createJournalEntry(journalEntry);
+  }
+
+  private void checkAccountEntries(
+          final Account debtorAccount,
+          final Account creditorAccount,
+          final JournalEntry journalEntryOne,
+          final JournalEntry journalEntryTwo,
+          final String dateRange) {
+    final AccountEntryPage creditorAccountEntries = this.testSubject.fetchAccountEntries(
+            creditorAccount.getIdentifier(),
+            dateRange,
+            null,
+            null,
+            null,
+            null,
+            "ASC");
+    Assert.assertEquals(Long.valueOf(2L), creditorAccountEntries.getTotalElements());
+    Assert.assertEquals("Sort order check for ascending.",
+            journalEntryOne.getMessage(),
+            creditorAccountEntries.getAccountEntries().get(0).getMessage());
+
+    final AccountEntryPage creditorAccountEntriesWithMessage1 = this.testSubject.fetchAccountEntries(
+            creditorAccount.getIdentifier(),
+            dateRange,
+            journalEntryOne.getMessage(),
+            null,
+            null,
+            null,
+            null);
+    Assert.assertEquals(Long.valueOf(1L), creditorAccountEntriesWithMessage1.getTotalElements());
+    Assert.assertEquals("Correct entry returned.",
+            journalEntryOne.getMessage(),
+            creditorAccountEntriesWithMessage1.getAccountEntries().get(0).getMessage());
+
+    final AccountEntryPage debtorAccountEntries = this.testSubject.fetchAccountEntries(
+            debtorAccount.getIdentifier(),
+            dateRange,
+            null,
+            null,
+            null,
+            null,
+            "DESC");
+    Assert.assertEquals(Long.valueOf(2L), debtorAccountEntries.getTotalElements());
+    Assert.assertEquals("Sort order check for descending.",
+            journalEntryTwo.getMessage(),
+            debtorAccountEntries.getAccountEntries().get(0).getMessage());
+
+    final AccountEntryPage debtorAccountEntriesWithMessage2 = this.testSubject.fetchAccountEntries(
+            creditorAccount.getIdentifier(),
+            dateRange,
+            journalEntryTwo.getMessage(),
+            null,
+            null,
+            null,
+            null);
+    Assert.assertEquals(Long.valueOf(1L), debtorAccountEntriesWithMessage2.getTotalElements());
+    Assert.assertEquals("Correct entry returned.",
+            journalEntryTwo.getMessage(),
+            debtorAccountEntriesWithMessage2.getAccountEntries().get(0).getMessage());
+
+    final AccountEntryPage debtorAccountEntriesWithRandomMessage = this.testSubject.fetchAccountEntries(
+            creditorAccount.getIdentifier(),
+            dateRange,
+            RandomStringUtils.randomAlphanumeric(20),
+            null,
+            null,
+            null,
+            null);
+    Assert.assertEquals(Long.valueOf(0L), debtorAccountEntriesWithRandomMessage.getTotalElements());
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/TestLedger.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestLedger.java
new file mode 100644
index 0000000..200d0fd
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestLedger.java
@@ -0,0 +1,447 @@
+/*
+ * 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.accounting;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.client.LedgerAlreadyExistsException;
+import org.apache.fineract.cn.accounting.api.v1.client.LedgerNotFoundException;
+import org.apache.fineract.cn.accounting.api.v1.client.LedgerReferenceExistsException;
+import org.apache.fineract.cn.accounting.api.v1.domain.Account;
+import org.apache.fineract.cn.accounting.api.v1.domain.AccountType;
+import org.apache.fineract.cn.accounting.api.v1.domain.Ledger;
+import org.apache.fineract.cn.accounting.api.v1.domain.LedgerPage;
+import org.apache.fineract.cn.accounting.util.AccountGenerator;
+import org.apache.fineract.cn.accounting.util.LedgerGenerator;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.JUnitRestDocumentation;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+public class TestLedger extends AbstractAccountingTest {
+
+  @Rule
+  public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("src/doc/generated-snippets/test-ledger");
+
+  @Autowired
+  private WebApplicationContext context;
+
+  private MockMvc mockMvc;
+
+  final String path = "/accounting/v1";
+
+  @Before
+  public void setUp(){
+
+    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
+            .apply(documentationConfiguration(this.restDocumentation))
+            .alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
+            .build();
+  }
+
+  @Test
+  public void shouldCreateLedger() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    Assert.assertTrue(this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier()));
+
+    this.mockMvc.perform(post(path + "/ledgers")
+            .contentType(MediaType.APPLICATION_JSON_VALUE).accept(MediaType.APPLICATION_JSON_VALUE)
+            .content(ledger.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldNotCreateLedgerAlreadyExists() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    try {
+      this.testSubject.createLedger(ledger);
+      Assert.fail();
+    } catch (final LedgerAlreadyExistsException ex) {
+      // do nothing, expected
+    }
+
+  }
+
+  @Test
+  public void shouldFetchLedgers() throws Exception {
+    final LedgerPage currentLedgerPage = this.testSubject.fetchLedgers(false, null, null, null, null, null, null);
+
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final LedgerPage ledgerPage = this.testSubject.fetchLedgers(false, null, null, null, null, null, null);
+    Assert.assertEquals(currentLedgerPage.getTotalElements() + 1L, ledgerPage.getTotalElements().longValue());
+
+    this.mockMvc.perform(get(path + "/ledgers/")
+            .accept(MediaType.ALL_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().is4xxClientError());
+  }
+
+  @Test
+  public void shouldFetchSubLedgers() throws Exception {
+    final Ledger parent = LedgerGenerator.createRandomLedger();
+    final Ledger child = LedgerGenerator.createRandomLedger();
+    parent.setSubLedgers(Collections.singletonList(child));
+
+    final LedgerPage currentLedgerPage = this.testSubject.fetchLedgers(true, child.getIdentifier(), null, null, null, null, null);
+
+    this.testSubject.createLedger(parent);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, parent.getIdentifier());
+
+    final LedgerPage ledgerPage = this.testSubject.fetchLedgers(true, child.getIdentifier(), null, null, null, null, null);
+    Assert.assertEquals(currentLedgerPage.getTotalElements() + 1L, ledgerPage.getTotalElements().longValue());
+    final Ledger fetchedSubLedger = ledgerPage.getLedgers().get(0);
+    Assert.assertEquals(parent.getIdentifier(), fetchedSubLedger.getParentLedgerIdentifier());
+
+    this.mockMvc.perform(get(path + "/ledgers/" + parent.getIdentifier() + "/")
+            .accept(MediaType.ALL_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE).content(ledgerPage.getLedgers().toString()))
+            .andExpect(status().is4xxClientError());
+  }
+
+  @Test
+  public void shouldFindLedger() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final Ledger foundLedger = this.testSubject.findLedger(ledger.getIdentifier());
+
+    Assert.assertNotNull(foundLedger);
+    Assert.assertEquals(ledger.getIdentifier(), foundLedger.getIdentifier());
+    Assert.assertEquals(ledger.getType(), foundLedger.getType());
+    Assert.assertEquals(ledger.getName(), foundLedger.getName());
+    Assert.assertEquals(ledger.getDescription(), foundLedger.getDescription());
+    Assert.assertNull(ledger.getParentLedgerIdentifier());
+    Assert.assertTrue(foundLedger.getSubLedgers().size() == 0);
+    Assert.assertNotNull(foundLedger.getCreatedBy());
+    Assert.assertNotNull(foundLedger.getCreatedOn());
+    Assert.assertNull(foundLedger.getLastModifiedBy());
+    Assert.assertNull(foundLedger.getLastModifiedOn());
+    Assert.assertEquals(ledger.getShowAccountsInChart(), foundLedger.getShowAccountsInChart());
+
+    this.mockMvc.perform(get(path + "/ledgers/" + ledger.getIdentifier())
+            .accept(MediaType.ALL_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(ledger.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldNotFindLedgerUnknown() throws Exception {
+    try {
+      this.testSubject.findLedger(RandomStringUtils.randomAlphanumeric(8));
+      Assert.fail();
+    } catch (final LedgerNotFoundException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldAddSubLedger() throws Exception {
+    final Ledger parentLedger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(parentLedger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, parentLedger.getIdentifier());
+
+    final Ledger subLedger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.addSubLedger(parentLedger.getIdentifier(), subLedger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, subLedger.getIdentifier());
+
+    final Ledger foundParentLedger = this.testSubject.findLedger(parentLedger.getIdentifier());
+    Assert.assertTrue(foundParentLedger.getSubLedgers().size() == 1);
+    final Ledger foundSubLedger = foundParentLedger.getSubLedgers().get(0);
+    Assert.assertEquals(subLedger.getIdentifier(), foundSubLedger.getIdentifier());
+
+    this.mockMvc.perform(post(path + "/ledgers/" + parentLedger.getIdentifier())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldNotAddSubLedgerParentUnknown() throws Exception {
+    final Ledger subLedger = LedgerGenerator.createRandomLedger();
+
+    try {
+      this.testSubject.addSubLedger(RandomStringUtils.randomAlphanumeric(8), subLedger);
+      Assert.fail();
+    } catch (final LedgerNotFoundException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldNotAddSubLedgerAlreadyExists() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    try {
+      final Ledger subLedger = LedgerGenerator.createRandomLedger();
+      subLedger.setIdentifier(ledger.getIdentifier());
+      this.testSubject.addSubLedger(ledger.getIdentifier(), subLedger);
+      Assert.fail();
+    } catch (final LedgerAlreadyExistsException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldModifyLedger() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    ledger.setName(RandomStringUtils.randomAlphabetic(256));
+    ledger.setDescription(RandomStringUtils.randomAlphabetic(2048));
+    ledger.setShowAccountsInChart(Boolean.TRUE);
+
+    this.testSubject.modifyLedger(ledger.getIdentifier(), ledger);
+
+    this.eventRecorder.wait(EventConstants.PUT_LEDGER, ledger.getIdentifier());
+
+    final Ledger modifiedLedger = this.testSubject.findLedger(ledger.getIdentifier());
+    Assert.assertEquals(ledger.getName(), modifiedLedger.getName());
+    Assert.assertEquals(ledger.getDescription(), modifiedLedger.getDescription());
+    Assert.assertNotNull(modifiedLedger.getLastModifiedBy());
+    Assert.assertNotNull(modifiedLedger.getLastModifiedOn());
+    Assert.assertEquals(ledger.getShowAccountsInChart(), modifiedLedger.getShowAccountsInChart());
+
+    this.mockMvc.perform(put(path + "/ledgers/" + ledger.getIdentifier())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldNotModifyLedgerIdentifierMismatch() throws Exception {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier());
+
+    final String randomName = RandomStringUtils.randomAlphanumeric(8);
+    try {
+      this.testSubject.modifyLedger(randomName, ledger);
+      Assert.fail();
+    } catch (final IllegalArgumentException ex) {
+      Assert.assertTrue(ex.getMessage().contains(randomName));
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldNotModifyLedgerUnknown() {
+    final Ledger ledger = LedgerGenerator.createRandomLedger();
+
+    try {
+      this.testSubject.modifyLedger(ledger.getIdentifier(), ledger);
+      Assert.fail();
+    } catch (final LedgerNotFoundException ex) {
+      // do nothing , expected
+    }
+  }
+
+  @Test
+  public void shouldDeleteLedger() throws Exception {
+    final Ledger ledger2delete = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger2delete);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger2delete.getIdentifier());
+
+    this.testSubject.deleteLedger(ledger2delete.getIdentifier());
+
+    this.eventRecorder.wait(EventConstants.DELETE_LEDGER, ledger2delete.getIdentifier());
+
+    try {
+      this.testSubject.findLedger(ledger2delete.getIdentifier());
+      Assert.fail();
+    } catch (final LedgerNotFoundException ex) {
+      // do nothing, expected
+    }
+
+    this.mockMvc.perform(delete(path + "/ledgers/" + ledger2delete.getIdentifier())
+            .accept(MediaType.ALL_VALUE)
+            .contentType(MediaType.APPLICATION_JSON)
+            .content(ledger2delete.getIdentifier()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test
+  public void shouldNotDeleteLedgerUnknown() throws Exception {
+    try {
+      this.testSubject.deleteLedger(RandomStringUtils.randomAlphanumeric(8));
+      Assert.fail();
+    } catch (final LedgerNotFoundException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldNotDeleteLedgerHoldsSubLedger() throws Exception {
+    final Ledger ledger2delete = LedgerGenerator.createRandomLedger();
+    ledger2delete.setSubLedgers(Collections.singletonList(LedgerGenerator.createRandomLedger()));
+
+    this.testSubject.createLedger(ledger2delete);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger2delete.getIdentifier());
+
+    try {
+      this.testSubject.deleteLedger(ledger2delete.getIdentifier());
+      Assert.fail();
+    } catch (final LedgerReferenceExistsException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldNotDeleteLedgerHoldsAccount() throws Exception {
+    final Ledger ledger2delete = LedgerGenerator.createRandomLedger();
+
+    this.testSubject.createLedger(ledger2delete);
+
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger2delete.getIdentifier());
+
+    final Account ledgerAccount = AccountGenerator.createRandomAccount(ledger2delete.getIdentifier());
+
+    this.testSubject.createAccount(ledgerAccount);
+
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, ledgerAccount.getIdentifier());
+
+    try {
+      this.testSubject.deleteLedger(ledger2delete.getIdentifier());
+      Assert.fail();
+    } catch (final LedgerReferenceExistsException ex) {
+      // do nothing, expected
+    }
+  }
+
+  @Test
+  public void shouldFindLedgerWithSeparatorInIdentifier() throws Exception {
+    // RFC 3986 unreserved characters: ALPHA  DIGIT  "-", ".", "_", "~"
+    final String[] unreservedCharacters = new String[] {
+            "-",
+            ".",
+            "_"
+    };
+
+    this.logger.info("Creating {} ledgers with unreserved characters.", unreservedCharacters.length);
+    boolean failed = false;
+    for (String unreservedCharacter : unreservedCharacters) {
+      final Ledger ledger = LedgerGenerator.createRandomLedger();
+      final String identifier = RandomStringUtils.randomAlphanumeric(3) + unreservedCharacter + RandomStringUtils.randomAlphanumeric(2);
+      ledger.setIdentifier(identifier);
+
+      this.logger.info("Creating ledger '{}' with unreserved character '{}' in identifier.", identifier, unreservedCharacter);
+      this.testSubject.createLedger(ledger);
+
+      Assert.assertTrue(this.eventRecorder.wait(EventConstants.POST_LEDGER, ledger.getIdentifier()));
+
+      try {
+        this.testSubject.findLedger(ledger.getIdentifier());
+        this.logger.info("Ledger '{}' with unreserved character '{}' in identifier found.", identifier, unreservedCharacter);
+      } catch (final Exception ex) {
+        this.logger.error("Ledger '{}' with unreserved character '{}' in identifier not found.", identifier, unreservedCharacter);
+        failed = true;
+      }
+    }
+
+    Assert.assertFalse(failed);
+  }
+
+  @Test
+  public void shouldStreamAllAccountsBelongingToLedger() throws InterruptedException {
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    assetLedger.setType(AccountType.ASSET.name());
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final List<Account> createdAssetAccounts = Stream.generate(() -> AccountGenerator.createRandomAccount(assetLedger.getIdentifier())).limit(1)
+            .peek(account -> {
+              account.setType(AccountType.ASSET.name());
+              this.testSubject.createAccount(account);
+            })
+            .collect(Collectors.toList());
+
+    for (final Account account : createdAssetAccounts) {
+      this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account.getIdentifier());
+    }
+
+    final List<Account> foundAccounts = testSubject.streamAccountsOfLedger(assetLedger.getIdentifier(), "ASC")
+            .peek(account -> account.setState(null))
+            .collect(Collectors.toList());
+
+    Assert.assertEquals(createdAssetAccounts, foundAccounts);
+
+    try{
+
+      this.mockMvc.perform(get(path + "/ledgers/" + assetLedger.getIdentifier() + "/accounts" )
+              .accept(MediaType.ALL_VALUE)
+              .contentType(MediaType.APPLICATION_JSON_VALUE))
+              .andExpect(status().is4xxClientError());
+    } catch (Exception exception){ exception.printStackTrace(); }
+
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/TestSuite.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestSuite.java
new file mode 100644
index 0000000..9769e93
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestSuite.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.accounting;
+
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * @author Myrle Krantz
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    TestAccount.class,
+    TestChartOfAccounts.class,
+    TestFinancialCondition.class,
+    TestIncomeStatement.class,
+    TestJournalEntry.class,
+    TestLedger.class,
+    TestTransactionType.class,
+    TestTrialBalance.class,
+})
+public class TestSuite extends SuiteTestEnvironment {
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/TestTransactionType.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestTransactionType.java
new file mode 100644
index 0000000..071b348
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestTransactionType.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting;
+
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.client.TransactionTypeAlreadyExists;
+import org.apache.fineract.cn.accounting.api.v1.client.TransactionTypeNotFoundException;
+import org.apache.fineract.cn.accounting.api.v1.client.TransactionTypeValidationException;
+import org.apache.fineract.cn.accounting.api.v1.domain.TransactionType;
+import org.apache.fineract.cn.accounting.api.v1.domain.TransactionTypePage;
+import org.apache.fineract.cn.accounting.util.TransactionTypeGenerator;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.JUnitRestDocumentation;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+public class TestTransactionType extends AbstractAccountingTest {
+
+  public TestTransactionType() {
+    super();
+  }
+
+  @Rule
+  public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("src/doc/generated-snippets/test-transaction");
+
+  @Autowired
+  private WebApplicationContext context;
+
+  private MockMvc mockMvc;
+
+  final String path = "/accounting/v1";
+
+  @Before
+  public void setUp(){
+
+    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
+            .apply(documentationConfiguration(this.restDocumentation))
+            .alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
+            .build();
+  }
+
+  @Test
+  public void shouldFetchPreConfiguredTypes() {
+    final TransactionTypePage transactionTypePage =
+            super.testSubject.fetchTransactionTypes(null, 0, 100, "identifier", Sort.Direction.DESC.name());
+
+    Assert.assertTrue(transactionTypePage.getTotalElements() >= 54L);
+
+    try{
+      this.mockMvc.perform(get(path + "/transactiontypes/")
+              .accept(MediaType.ALL_VALUE)
+              .contentType(MediaType.APPLICATION_JSON_VALUE))
+              .andExpect(status().is4xxClientError());
+    } catch( Exception e ){ e.printStackTrace();}
+  }
+
+  @Test
+  public void shouldCreateTransactionType() throws Exception {
+    final TransactionType transactionType = TransactionTypeGenerator.createRandomTransactionType();
+
+    super.testSubject.createTransactionType(transactionType);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TX_TYPE, transactionType.getCode()));
+
+    this.mockMvc.perform(post(path + "/transactiontypes")
+            .contentType(MediaType.APPLICATION_JSON_VALUE).accept(MediaType.APPLICATION_JSON_VALUE)
+            .content(transactionType.getCode()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test(expected = TransactionTypeAlreadyExists.class)
+  public void shouldNotCreateTransactionTypeAlreadyExists() throws Exception {
+    final TransactionType transactionType = TransactionTypeGenerator.createRandomTransactionType();
+    transactionType.setCode("duplicate");
+
+    super.testSubject.createTransactionType(transactionType);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TX_TYPE, transactionType.getCode()));
+
+    super.testSubject.createTransactionType(transactionType);
+  }
+
+  @Test
+  public void shouldChangeTransactionType() throws Exception {
+    final String code = "changeable";
+
+    final TransactionType transactionType = TransactionTypeGenerator.createRandomTransactionType();
+    transactionType.setCode(code);
+
+    super.testSubject.createTransactionType(transactionType);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TX_TYPE, transactionType.getCode()));
+
+    final String changedName = "Changed name";
+    transactionType.setName(changedName);
+
+    super.testSubject.changeTransactionType(code, transactionType);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.PUT_TX_TYPE, transactionType.getCode()));
+
+    final TransactionTypePage transactionTypePage =
+            super.testSubject.fetchTransactionTypes(code, 0, 1, null, null);
+
+    Assert.assertTrue(transactionTypePage.getTotalElements() == 1L);
+    final TransactionType fetchedTransactionType = transactionTypePage.getTransactionTypes().get(0);
+    Assert.assertEquals(changedName, fetchedTransactionType.getName());
+
+    this.mockMvc.perform(put(path + "/transactiontypes/" + transactionType.getCode())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test(expected = TransactionTypeNotFoundException.class)
+  public void shouldNotChangeTransactionTypeNotFound() {
+    final String code = "unknown";
+
+    final TransactionType transactionType = TransactionTypeGenerator.createRandomTransactionType();
+    transactionType.setCode(code);
+
+    super.testSubject.changeTransactionType(code, transactionType);
+  }
+
+  @Test(expected = TransactionTypeValidationException.class)
+  public void shouldNotChangeTransactionTypeCodeMismatch() {
+    final String code = "mismatch";
+
+    final TransactionType transactionType = TransactionTypeGenerator.createRandomTransactionType();
+
+    super.testSubject.changeTransactionType(code, transactionType);
+  }
+
+  @Test
+  public void shouldFindTransactionType() throws Exception {
+    final TransactionType randomTransactionType = TransactionTypeGenerator.createRandomTransactionType();
+
+    super.testSubject.createTransactionType(randomTransactionType);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TX_TYPE, randomTransactionType.getCode()));
+
+    final TransactionType fetchedTransactionType = super.testSubject.findTransactionType(randomTransactionType.getCode());
+    Assert.assertNotNull(fetchedTransactionType);
+    Assert.assertEquals(randomTransactionType.getCode(), fetchedTransactionType.getCode());
+    Assert.assertEquals(randomTransactionType.getName(), fetchedTransactionType.getName());
+    Assert.assertEquals(randomTransactionType.getDescription(), fetchedTransactionType.getDescription());
+
+    this.mockMvc.perform(get(path + "/transactiontypes/" + fetchedTransactionType.getCode())
+            .accept(MediaType.ALL_VALUE).contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(fetchedTransactionType.getCode()))
+            .andExpect(status().isNotFound());
+  }
+
+  @Test(expected = TransactionTypeNotFoundException.class)
+  public void shouldNotFindTransactionTypeNotFound() {
+    super.testSubject.findTransactionType("unknown");
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/TestTrialBalance.java b/service/src/test/java/org/apache/fineract/cn/accounting/TestTrialBalance.java
new file mode 100644
index 0000000..a3c79b2
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/TestTrialBalance.java
@@ -0,0 +1,99 @@
+/*
+ * 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.accounting;
+
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.domain.Account;
+import org.apache.fineract.cn.accounting.api.v1.domain.AccountType;
+import org.apache.fineract.cn.accounting.api.v1.domain.JournalEntry;
+import org.apache.fineract.cn.accounting.api.v1.domain.Ledger;
+import org.apache.fineract.cn.accounting.api.v1.domain.financial.statement.TrialBalance;
+import org.apache.fineract.cn.accounting.util.AccountGenerator;
+import org.apache.fineract.cn.accounting.util.JournalEntryGenerator;
+import org.apache.fineract.cn.accounting.util.LedgerGenerator;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+
+public class TestTrialBalance extends AbstractAccountingTest {
+  @Test
+  public void shouldGenerateTrialBalance() throws Exception {
+    final Ledger assetLedger = LedgerGenerator.createRandomLedger();
+    this.testSubject.createLedger(assetLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier());
+
+    final Ledger assetSubLedgerOne = LedgerGenerator.createRandomLedger();
+    this.testSubject.addSubLedger(assetLedger.getIdentifier(), assetSubLedgerOne);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetSubLedgerOne.getIdentifier());
+
+    final Ledger assetSubLedgerTwo = LedgerGenerator.createRandomLedger();
+    this.testSubject.addSubLedger(assetLedger.getIdentifier(), assetSubLedgerTwo);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, assetSubLedgerTwo.getIdentifier());
+
+    final Ledger liabilityLedger = LedgerGenerator.createRandomLedger();
+    liabilityLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.createLedger(liabilityLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilityLedger.getIdentifier());
+
+    final Ledger liabilitySubLedger = LedgerGenerator.createRandomLedger();
+    liabilitySubLedger.setType(AccountType.LIABILITY.name());
+    this.testSubject.addSubLedger(liabilityLedger.getIdentifier(), liabilitySubLedger);
+    this.eventRecorder.wait(EventConstants.POST_LEDGER, liabilitySubLedger.getIdentifier());
+
+    final Account account4ledgerOne = AccountGenerator.createRandomAccount(assetSubLedgerOne.getIdentifier());
+    this.testSubject.createAccount(account4ledgerOne);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account4ledgerOne.getIdentifier());
+
+    final Account secondAccount4ledgerOne = AccountGenerator.createRandomAccount(assetSubLedgerOne.getIdentifier());
+    this.testSubject.createAccount(secondAccount4ledgerOne);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, secondAccount4ledgerOne.getIdentifier());
+
+    final Account account4subLedgerOne = AccountGenerator.createRandomAccount(assetSubLedgerTwo.getIdentifier());
+    this.testSubject.createAccount(account4subLedgerOne);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account4subLedgerOne.getIdentifier());
+
+    final Account account4ledgerTwo = AccountGenerator.createRandomAccount(liabilitySubLedger.getIdentifier());
+    account4ledgerTwo.setType(AccountType.LIABILITY.name());
+    this.testSubject.createAccount(account4ledgerTwo);
+    this.eventRecorder.wait(EventConstants.POST_ACCOUNT, account4ledgerTwo.getIdentifier());
+
+    final JournalEntry firstBooking =
+        JournalEntryGenerator.createRandomJournalEntry(secondAccount4ledgerOne, "50.00", account4ledgerTwo, "50.00");
+    this.testSubject.createJournalEntry(firstBooking);
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, firstBooking.getTransactionIdentifier());
+
+    final JournalEntry secondBooking =
+        JournalEntryGenerator.createRandomJournalEntry(secondAccount4ledgerOne, "50.00", account4ledgerOne, "50.00");
+    this.testSubject.createJournalEntry(secondBooking);
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, secondBooking.getTransactionIdentifier());
+
+    final JournalEntry thirdBooking =
+        JournalEntryGenerator.createRandomJournalEntry(account4subLedgerOne, "50.00", account4ledgerTwo, "50.00");
+    this.testSubject.createJournalEntry(thirdBooking);
+    this.eventRecorder.wait(EventConstants.RELEASE_JOURNAL_ENTRY, thirdBooking.getTransactionIdentifier());
+
+    final TrialBalance trialBalance = this.testSubject.getTrialBalance(true);
+    Assert.assertNotNull(trialBalance);
+    Assert.assertEquals(3, trialBalance.getTrialBalanceEntries().size());
+    final BigDecimal expectedValue = BigDecimal.valueOf(100.00D);
+    Assert.assertTrue(trialBalance.getDebitTotal().compareTo(expectedValue) == 0);
+    Assert.assertTrue(trialBalance.getCreditTotal().compareTo(expectedValue) == 0);
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/importer/TestImport.java b/service/src/test/java/org/apache/fineract/cn/accounting/importer/TestImport.java
new file mode 100644
index 0000000..0623e77
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/importer/TestImport.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting.importer;
+
+import org.apache.fineract.cn.accounting.AbstractAccountingTest;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.accounting.api.v1.domain.*;
+import org.apache.fineract.cn.accounting.importer.AccountImporter;
+import org.apache.fineract.cn.accounting.importer.LedgerImporter;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Myrle Krantz
+ */
+public class TestImport extends AbstractAccountingTest {
+  @Test
+  public void testAccountImportHappyCase() throws IOException, InterruptedException {
+    final Ledger assetLedger = new Ledger();
+    assetLedger.setType(AccountType.ASSET.name());
+    assetLedger.setIdentifier("assetLedger");
+    assetLedger.setName("asset Ledger");
+    assetLedger.setShowAccountsInChart(true);
+
+    testSubject.createLedger(assetLedger);
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, assetLedger.getIdentifier()));
+
+    final Ledger equityLedger = new Ledger();
+    equityLedger.setType(AccountType.EQUITY.name());
+    equityLedger.setIdentifier("equityLedger");
+    equityLedger.setName("equity Ledger");
+    equityLedger.setShowAccountsInChart(true);
+
+    testSubject.createLedger(equityLedger);
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, equityLedger.getIdentifier()));
+
+
+    final AccountImporter accountImporter = new AccountImporter(testSubject, logger);
+    final URL uri = ClassLoader.getSystemResource("importdata/account-happy-case.csv");
+    accountImporter.importCSV(uri);
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "abcd"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "xyz"));
+
+    //Import a second time.
+    accountImporter.importCSV(uri);
+
+    final AccountPage accountsOfAssetLedger
+            = testSubject.fetchAccountsOfLedger(assetLedger.getIdentifier(), 0, 10, null, null);
+    final Account firstAccount = accountsOfAssetLedger.getAccounts().get(0);
+    Assert.assertEquals("abcd", firstAccount.getIdentifier());
+    Assert.assertEquals(Double.valueOf(0.0), firstAccount.getBalance());
+    Assert.assertEquals(AbstractAccountingTest.TEST_USER, firstAccount.getCreatedBy());
+
+    final AccountPage accountsOfEquityLedger
+            = testSubject.fetchAccountsOfLedger(equityLedger.getIdentifier(), 0, 10, null, null);
+    final Account secondAccount = accountsOfEquityLedger.getAccounts().get(0);
+    Assert.assertEquals("xyz", secondAccount.getIdentifier());
+    Assert.assertEquals(Double.valueOf(20.0), secondAccount.getBalance());
+    Assert.assertEquals(AbstractAccountingTest.TEST_USER, secondAccount.getCreatedBy());
+  }
+
+  @Test
+  public void testAccountFromARealCase() throws IOException, InterruptedException {
+    final Ledger ledger1000 = new Ledger();
+    ledger1000.setType(AccountType.REVENUE.name());
+    ledger1000.setIdentifier("1000");
+    ledger1000.setName("Income");
+    ledger1000.setShowAccountsInChart(true);
+
+    testSubject.createLedger(ledger1000);
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, ledger1000.getIdentifier()));
+
+    final Ledger ledger1100 = new Ledger();
+    ledger1100.setType(AccountType.REVENUE.name());
+    ledger1100.setIdentifier("1100");
+    ledger1100.setName("Income from Loans");
+    ledger1100.setParentLedgerIdentifier("1000");
+    ledger1100.setShowAccountsInChart(true);
+
+    testSubject.createLedger(ledger1100);
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, ledger1100.getIdentifier()));
+
+
+    final AccountImporter accountImporter = new AccountImporter(testSubject, logger);
+    final URL uri = ClassLoader.getSystemResource("importdata/account-from-a-real-case.csv");
+    accountImporter.importCSV(uri);
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1101"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1102"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1103"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1104"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1105"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1120"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1121"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1140"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_ACCOUNT, "1190"));
+
+    //Import a second time.
+    accountImporter.importCSV(uri);
+
+    final AccountPage accountsOfAssetLedger
+            = testSubject.fetchAccountsOfLedger(ledger1100.getIdentifier(), 0, 10, null, null);
+    final Account firstAccount = accountsOfAssetLedger.getAccounts().get(0);
+    Assert.assertEquals("1101", firstAccount.getIdentifier());
+    Assert.assertEquals("Interest on Business Loans", firstAccount.getName());
+    Assert.assertEquals(Double.valueOf(0.0), firstAccount.getBalance());
+    Assert.assertEquals(AccountType.REVENUE, AccountType.valueOf(firstAccount.getType()));
+    Assert.assertEquals(AbstractAccountingTest.TEST_USER, firstAccount.getCreatedBy());
+
+    final AccountPage accountsOfEquityLedger
+            = testSubject.fetchAccountsOfLedger(ledger1100.getIdentifier(), 0, 10, null, null);
+    final Account secondAccount = accountsOfEquityLedger.getAccounts().get(1);
+    Assert.assertEquals("1102", secondAccount.getIdentifier());
+    Assert.assertEquals("Interest on Agriculture Loans", secondAccount.getName());
+    Assert.assertEquals(Double.valueOf(0.0), secondAccount.getBalance());
+    Assert.assertEquals(AccountType.REVENUE, AccountType.valueOf(secondAccount.getType()));
+    Assert.assertEquals(AbstractAccountingTest.TEST_USER, secondAccount.getCreatedBy());
+  }
+
+  @Test
+  public void testLedgerImportHappyCase() throws IOException, InterruptedException {
+    final LedgerImporter ledgerImporter = new LedgerImporter(testSubject, logger);
+    final URL uri = ClassLoader.getSystemResource("importdata/ledger-happy-case.csv");
+    ledgerImporter.importCSV(uri);
+
+    //Import a second time.
+    ledgerImporter.importCSV(uri);
+
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, "110"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, "111"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, "111.1"));
+
+    final LedgerPage ledgerPage = testSubject.fetchLedgers(true, "11", null, null, null, null, null);
+    final List<Ledger> ledgers = ledgerPage.getLedgers();
+    Assert.assertTrue(ledgers.size() >= 3); //3 from this test, but other tests may already have run.
+    final Optional<Ledger> ledger110 = ledgers.stream().filter(x -> x.getIdentifier().equals("110")).findAny();
+    Assert.assertTrue(ledger110.isPresent());
+    Assert.assertEquals("Loan Ledger", ledger110.get().getDescription());
+    Assert.assertEquals("ASSET", ledger110.get().getType());
+    Assert.assertEquals(true, ledger110.get().getShowAccountsInChart());
+    Assert.assertEquals(AbstractAccountingTest.TEST_USER, ledger110.get().getCreatedBy());
+
+    final Optional<Ledger> ledger111 = ledgers.stream().filter(x -> x.getIdentifier().equals("111")).findAny();
+    Assert.assertTrue(ledger111.isPresent());
+    Assert.assertEquals("Loan Ledger Interest", ledger111.get().getDescription());
+    Assert.assertEquals("ASSET", ledger111.get().getType());
+    Assert.assertEquals(false, ledger111.get().getShowAccountsInChart());
+    Assert.assertEquals(AbstractAccountingTest.TEST_USER, ledger111.get().getCreatedBy());
+
+    final Optional<Ledger> ledger111dot1 = ledgers.stream().filter(x -> x.getIdentifier().equals("111.1")).findAny();
+    Assert.assertTrue(ledger111dot1.isPresent());
+    Assert.assertEquals("blub blah", ledger111dot1.get().getDescription());
+    Assert.assertEquals("ASSET", ledger111dot1.get().getType());
+    Assert.assertEquals(true, ledger111dot1.get().getShowAccountsInChart());
+    Assert.assertEquals(AbstractAccountingTest.TEST_USER, ledger111dot1.get().getCreatedBy());
+  }
+
+  @Test
+  public void testLedgerImportMissingNameCase() throws IOException, InterruptedException {
+    final LedgerImporter ledgerImporter = new LedgerImporter(testSubject, logger);
+    final URL uri = ClassLoader.getSystemResource("importdata/ledger-missing-name-case.csv");
+    ledgerImporter.importCSV(uri);
+
+    //Import a second time.
+    ledgerImporter.importCSV(uri);
+
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, "210"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, "211"));
+    Assert.assertTrue(eventRecorder.wait(EventConstants.POST_LEDGER, "211.1"));
+
+    final LedgerPage ledgerPage = testSubject.fetchLedgers(true, "21", null, null, null, null, null);
+    final List<Ledger> ledgers = ledgerPage.getLedgers();
+    Assert.assertEquals(3,ledgers.size());
+
+    ledgers.forEach(x -> Assert.assertEquals(x.getIdentifier(), x.getName()));
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/listener/AccountEventListener.java b/service/src/test/java/org/apache/fineract/cn/accounting/listener/AccountEventListener.java
new file mode 100644
index 0000000..e30938f
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/listener/AccountEventListener.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting.listener;
+
+import org.apache.fineract.cn.accounting.AbstractAccountingTest;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+@SuppressWarnings("unused")
+@Component
+public class AccountEventListener {
+
+  private final Logger logger;
+  private final EventRecorder eventRecorder;
+
+  @SuppressWarnings("SpringJavaAutowiringInspection")
+  @Autowired
+  public AccountEventListener(final @Qualifier(AbstractAccountingTest.TEST_LOGGER) Logger logger, final EventRecorder eventRecorder) {
+    super();
+    this.logger = logger;
+    this.eventRecorder = eventRecorder;
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_POST_ACCOUNT,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onCreateAccount(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                           final String payload) {
+    this.logger.debug("Account created.");
+    this.eventRecorder.event(tenant, EventConstants.POST_ACCOUNT, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_PUT_ACCOUNT,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onChangeAccount(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                          final String payload) {
+    this.logger.debug("Account modified.");
+    this.eventRecorder.event(tenant, EventConstants.PUT_ACCOUNT, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_CLOSE_ACCOUNT,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onCloseAccount(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                            final String payload) {
+    this.logger.debug("Account closed.");
+    this.eventRecorder.event(tenant, EventConstants.CLOSE_ACCOUNT, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_LOCK_ACCOUNT,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onLockAccount(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                           final String payload) {
+    this.logger.debug("Account locked.");
+    this.eventRecorder.event(tenant, EventConstants.LOCK_ACCOUNT, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_UNLOCK_ACCOUNT,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onUnlockAccount(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                             final String payload) {
+    this.logger.debug("Account unlocked.");
+    this.eventRecorder.event(tenant, EventConstants.UNLOCK_ACCOUNT, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_REOPEN_ACCOUNT,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onReopenAccount(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                             final String payload) {
+    this.logger.debug("Account reopened.");
+    this.eventRecorder.event(tenant, EventConstants.REOPEN_ACCOUNT, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_DELETE_ACCOUNT,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onDeleteAccount(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                              final String payload) {
+    this.logger.debug("Account deleted.");
+    this.eventRecorder.event(tenant, EventConstants.DELETE_ACCOUNT, payload, String.class);
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/listener/JournalEntryEventListener.java b/service/src/test/java/org/apache/fineract/cn/accounting/listener/JournalEntryEventListener.java
new file mode 100644
index 0000000..6e66b7d
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/listener/JournalEntryEventListener.java
@@ -0,0 +1,68 @@
+/*
+ * 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.accounting.listener;
+
+import org.apache.fineract.cn.accounting.AbstractAccountingTest;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+@SuppressWarnings("unused")
+@Component
+public class JournalEntryEventListener {
+
+  private final Logger logger;
+  private final EventRecorder eventRecorder;
+
+  @SuppressWarnings("SpringJavaAutowiringInspection")
+  @Autowired
+  public JournalEntryEventListener(final @Qualifier(AbstractAccountingTest.TEST_LOGGER) Logger logger,
+                                   final EventRecorder eventRecorder) {
+    this.logger = logger;
+    this.eventRecorder = eventRecorder;
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_POST_JOURNAL_ENTRY,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onPostJournalEntry(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                                 final String transactionIdentifier) {
+    this.logger.debug("Journal entry created");
+    this.eventRecorder.event(tenant, EventConstants.POST_JOURNAL_ENTRY, transactionIdentifier, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_RELEASE_JOURNAL_ENTRY,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onJournalEntryProcessed(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                                      final String transactionIdentifier) {
+    this.logger.debug("Journal entry processed");
+    this.eventRecorder.event(tenant, EventConstants.RELEASE_JOURNAL_ENTRY, transactionIdentifier, String.class);
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/listener/LedgerEventListener.java b/service/src/test/java/org/apache/fineract/cn/accounting/listener/LedgerEventListener.java
new file mode 100644
index 0000000..ae99da9
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/listener/LedgerEventListener.java
@@ -0,0 +1,79 @@
+/*
+ * 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.accounting.listener;
+
+import org.apache.fineract.cn.accounting.AbstractAccountingTest;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+@SuppressWarnings("unused")
+@Component
+public class LedgerEventListener {
+
+  private final Logger logger;
+  private final EventRecorder eventRecorder;
+
+  @SuppressWarnings("SpringJavaAutowiringInspection")
+  @Autowired
+  public LedgerEventListener(final @Qualifier(AbstractAccountingTest.TEST_LOGGER) Logger logger, final EventRecorder eventRecorder) {
+    super();
+    this.logger = logger;
+    this.eventRecorder = eventRecorder;
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_POST_LEDGER,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onPostLedger(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                           final String payload) {
+    this.logger.debug("Ledger created.");
+    this.eventRecorder.event(tenant, EventConstants.POST_LEDGER, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_PUT_LEDGER,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onPutLedger(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                          final String payload) {
+    this.logger.debug("Ledger modified.");
+    this.eventRecorder.event(tenant, EventConstants.PUT_LEDGER, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_DELETE_LEDGER,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onDeleteLedger(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                             final String payload) {
+    this.logger.debug("Ledger deleted.");
+    this.eventRecorder.event(tenant, EventConstants.DELETE_LEDGER, payload, String.class);
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/listener/MigrationEventListener.java b/service/src/test/java/org/apache/fineract/cn/accounting/listener/MigrationEventListener.java
new file mode 100644
index 0000000..e5a86b3
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/listener/MigrationEventListener.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting.listener;
+
+import org.apache.fineract.cn.accounting.AbstractAccountingTest;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+@SuppressWarnings("unused")
+@Component
+public class MigrationEventListener {
+
+  private final Logger logger;
+  private final EventRecorder eventRecorder;
+
+  @SuppressWarnings("SpringJavaAutowiringInspection")
+  @Autowired
+  public MigrationEventListener(final @Qualifier(AbstractAccountingTest.TEST_LOGGER) Logger logger, final EventRecorder eventRecorder) {
+    super();
+    this.logger = logger;
+    this.eventRecorder = eventRecorder;
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_INITIALIZE,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onInitialization(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                               final String payload) {
+    this.logger.debug("Provisioning finished.");
+    this.eventRecorder.event(tenant, EventConstants.INITIALIZE, payload, String.class);
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/listener/TransactionTypeEventListener.java b/service/src/test/java/org/apache/fineract/cn/accounting/listener/TransactionTypeEventListener.java
new file mode 100644
index 0000000..591e9f3
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/listener/TransactionTypeEventListener.java
@@ -0,0 +1,68 @@
+/*
+ * 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.accounting.listener;
+
+import org.apache.fineract.cn.accounting.AbstractAccountingTest;
+import org.apache.fineract.cn.accounting.api.v1.EventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+@SuppressWarnings("unused")
+@Component
+public class TransactionTypeEventListener {
+
+  private final Logger logger;
+  private final EventRecorder eventRecorder;
+
+  @Autowired
+  public TransactionTypeEventListener(@Qualifier(AbstractAccountingTest.TEST_LOGGER) final Logger logger,
+                                      final EventRecorder eventRecorder) {
+    super();
+    this.logger = logger;
+    this.eventRecorder = eventRecorder;
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_POST_TX_TYPE,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onPostTransactionType(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                                    final String payload) {
+    this.logger.debug("Transaction type created.");
+    this.eventRecorder.event(tenant, EventConstants.POST_TX_TYPE, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_PUT_TX_TYPE,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onPutTransactionType(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                                   final String payload) {
+    this.logger.debug("Transaction type created.");
+    this.eventRecorder.event(tenant, EventConstants.PUT_TX_TYPE, payload, String.class);
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/util/AccountGenerator.java b/service/src/test/java/org/apache/fineract/cn/accounting/util/AccountGenerator.java
new file mode 100644
index 0000000..f83a0d7
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/util/AccountGenerator.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting.util;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.accounting.api.v1.domain.Account;
+import org.apache.fineract.cn.accounting.api.v1.domain.AccountType;
+
+import java.util.Collections;
+import java.util.HashSet;
+
+public class AccountGenerator {
+
+  private AccountGenerator() {
+    super();
+  }
+
+  public static Account createRandomAccount(final String ledgerIdentifier) {
+    final Account account = new Account();
+    account.setIdentifier(RandomStringUtils.randomAlphanumeric(32));
+    account.setName(RandomStringUtils.randomAlphanumeric(256));
+    account.setType(AccountType.ASSET.name());
+    account.setLedger(ledgerIdentifier);
+    account.setHolders(new HashSet<>(Collections.singletonList(RandomStringUtils.randomAlphanumeric(32))));
+    account.setSignatureAuthorities(new HashSet<>(Collections.singletonList(RandomStringUtils.randomAlphanumeric(32))));
+    account.setBalance(0.00D);
+    return account;
+  }
+
+  public static Account createAccount(final String ledgerIdentifier, final String accountIdentifier, final AccountType accountType) {
+    final Account account = new Account();
+    account.setIdentifier(accountIdentifier);
+    account.setName(RandomStringUtils.randomAlphanumeric(256));
+    account.setType(accountType.name());
+    account.setLedger(ledgerIdentifier);
+    account.setHolders(new HashSet<>(Collections.singletonList(RandomStringUtils.randomAlphanumeric(32))));
+    account.setSignatureAuthorities(new HashSet<>(Collections.singletonList(RandomStringUtils.randomAlphanumeric(32))));
+    account.setBalance(0.00D);
+    return account;
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/util/JournalEntryGenerator.java b/service/src/test/java/org/apache/fineract/cn/accounting/util/JournalEntryGenerator.java
new file mode 100644
index 0000000..631901f
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/util/JournalEntryGenerator.java
@@ -0,0 +1,81 @@
+/*
+ * 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.accounting.util;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.accounting.api.v1.domain.Account;
+import org.apache.fineract.cn.accounting.api.v1.domain.Creditor;
+import org.apache.fineract.cn.accounting.api.v1.domain.Debtor;
+import org.apache.fineract.cn.accounting.api.v1.domain.JournalEntry;
+
+import java.time.Clock;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Collections;
+import java.util.HashSet;
+
+public class JournalEntryGenerator {
+
+  private JournalEntryGenerator() {
+    super();
+  }
+
+  public static JournalEntry createRandomJournalEntry(final Account debtorAccount,
+                                                      final String debtorAmount,
+                                                      final Account creditorAccount,
+                                                      final String creditorAmount) {
+    return JournalEntryGenerator
+        .createRandomJournalEntry(
+            debtorAccount != null ? debtorAccount.getIdentifier() : "randomDebtor",
+            debtorAmount,
+            creditorAccount != null ? creditorAccount.getIdentifier() : "randomCreditor",
+            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));
+    journalEntry.setTransactionType(RandomStringUtils.randomAlphabetic(4));
+    journalEntry.setClerk("clark");
+    if (debtorAccount != null) {
+      final Debtor debtor = new Debtor();
+      debtor.setAccountNumber(debtorAccount);
+      debtor.setAmount(debtorAmount);
+      journalEntry.setDebtors(new HashSet<>(Collections.singletonList(debtor)));
+    } else {
+      journalEntry.setDebtors(Sets.newHashSet());
+    }
+    if (creditorAccount != null) {
+      final Creditor creditor = new Creditor();
+      creditor.setAccountNumber(creditorAccount);
+      creditor.setAmount(creditorAmount);
+      journalEntry.setCreditors(new HashSet<>(Collections.singletonList(creditor)));
+    } else {
+      journalEntry.setCreditors(Sets.newHashSet());
+    }
+    journalEntry.setNote(RandomStringUtils.randomAlphanumeric(512));
+    journalEntry.setMessage(RandomStringUtils.randomAlphanumeric(512));
+    return journalEntry;
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/util/LedgerGenerator.java b/service/src/test/java/org/apache/fineract/cn/accounting/util/LedgerGenerator.java
new file mode 100644
index 0000000..0f41589
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/util/LedgerGenerator.java
@@ -0,0 +1,50 @@
+/*
+ * 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.accounting.util;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.accounting.api.v1.domain.AccountType;
+import org.apache.fineract.cn.accounting.api.v1.domain.Ledger;
+
+public class LedgerGenerator {
+
+  private LedgerGenerator() {
+    super();
+  }
+
+  public static Ledger createRandomLedger() {
+    final Ledger ledger = new Ledger();
+    ledger.setType(AccountType.ASSET.name());
+    ledger.setIdentifier(RandomStringUtils.randomAlphanumeric(8));
+    ledger.setName(RandomStringUtils.randomAlphanumeric(256));
+    ledger.setDescription(RandomStringUtils.randomAlphanumeric(2048));
+    ledger.setShowAccountsInChart(Boolean.FALSE);
+    return ledger;
+  }
+
+  public static Ledger createLedger(final String identifier, final AccountType accountType) {
+    final Ledger ledger = new Ledger();
+    ledger.setType(accountType.name());
+    ledger.setIdentifier(identifier);
+    ledger.setName(RandomStringUtils.randomAlphanumeric(256));
+    ledger.setDescription(RandomStringUtils.randomAlphanumeric(2048));
+    ledger.setShowAccountsInChart(Boolean.TRUE);
+    return ledger;
+  }
+}
diff --git a/service/src/test/java/org/apache/fineract/cn/accounting/util/TransactionTypeGenerator.java b/service/src/test/java/org/apache/fineract/cn/accounting/util/TransactionTypeGenerator.java
new file mode 100644
index 0000000..1efe73f
--- /dev/null
+++ b/service/src/test/java/org/apache/fineract/cn/accounting/util/TransactionTypeGenerator.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.accounting.util;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.accounting.api.v1.domain.TransactionType;
+
+public class TransactionTypeGenerator {
+
+  private TransactionTypeGenerator() {
+    super();
+  }
+
+  public static TransactionType createRandomTransactionType() {
+    final TransactionType transactionType = new TransactionType();
+    transactionType.setCode(RandomStringUtils.randomAlphabetic(4));
+    transactionType.setName(RandomStringUtils.randomAlphanumeric(256));
+    transactionType.setDescription(RandomStringUtils.randomAlphanumeric(2048));
+
+    return transactionType;
+  }
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services