fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From my...@apache.org
Subject [fineract-cn-teller] 04/30: first iteration for teller management
Date Mon, 22 Jan 2018 15:32:02 GMT
This is an automated email from the ASF dual-hosted git repository.

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

commit 55ce69bf7b01e39635b1d4718f87220a2f9fd664
Author: mgeiss <mgeiss@mifos.org>
AuthorDate: Sun Jun 11 13:41:10 2017 +0200

    first iteration for teller management
---
 .../mifos/teller/{ => api/v1}/EventConstants.java  |   8 +-
 .../teller/{ => api/v1}/PermittableGroupIds.java   |   2 +-
 .../v1/client/TellerAlreadyExistsException.java    |   5 +-
 .../teller/{ => api/v1}/client/TellerManager.java  |  37 +-
 .../api/v1/client/TellerNotFoundException.java     |   5 +-
 .../TellerTransactionValidationException.java      |   5 +-
 .../api/v1/client/TellerValidationException.java   |   5 +-
 .../v1/domain/Charge.java}                         |  39 +-
 .../mifos/teller/{ => api/v1}/domain/Teller.java   |  42 +-
 .../v1/domain/TellerAuthentication.java}           |  30 +-
 .../teller/api/v1/domain/TellerBalanceSheet.java   |  53 +++
 .../teller/{ => api/v1}/domain/TellerEntry.java    |  26 +-
 .../v1}/domain/TellerManagementCommand.java        |  17 +-
 .../{ => api/v1}/domain/TellerTransaction.java     |  37 +-
 .../v1}/domain/TellerTransactionCosts.java         |  17 +-
 .../client/TellerAlreadyExistsException.java       |   4 -
 .../teller/client/TellerNotFoundException.java     |   4 -
 .../TellerTransactionValidationException.java      |   4 -
 .../teller/client/TellerValidationException.java   |   4 -
 .../main/java/io/mifos/teller/domain/Charge.java   |  36 --
 .../mifos/teller/domain/TellerAuthentication.java  |  27 --
 .../io/mifos/teller/domain/TellerBalanceSheet.java |  38 --
 .../java/io/mifos/teller/AbstractTellerTest.java   | 150 +++++++
 .../java/io/mifos/teller/TestTellerManagement.java | 481 +++++++++++++++++++++
 .../teller/listener/MigrationEventListener.java    |  53 +++
 .../mifos/teller/listener/TellerEventListener.java |  84 ++++
 .../java/io/mifos/teller/util/TellerGenerator.java |  37 ++
 component-test/src/main/resources/logback-test.xml |   4 +-
 service/build.gradle                               |   5 +
 .../java/io/mifos/teller/ServiceConstants.java     |   2 +
 .../java/io/mifos/teller/TellerConfiguration.java  |  15 +
 .../internal/command/ChangeTellerCommand.java      |  26 +-
 .../internal/command/CloseTellerCommand.java       |  38 ++
 .../internal/command/CreateTellerCommand.java      |  26 +-
 .../internal/command/MigrationCommand.java}        |   9 +-
 .../internal/command/OpenTellerCommand.java        |  38 ++
 .../command/handler/MigrationAggregate.java        |  63 +++
 .../internal/command/handler/TellerAggregate.java  | 278 ++++++++++++
 .../service/internal/mapper/TellerEntryMapper.java |  36 ++
 .../service/internal/mapper/TellerMapper.java      |  71 +++
 .../service/internal/repository/TellerEntity.java  | 181 ++++++++
 .../internal/repository/TellerRepository.java      |  18 +-
 .../internal/service/TellerManagementService.java  | 106 +++++
 .../internal/service/TellerOperationService.java}  |   8 +-
 .../internal/service/helper/AccountingService.java |  62 +++
 .../helper/DepositAccountManagementService.java    |  38 ++
 .../service/helper/OrganizationService.java        |  59 +++
 .../internal/service/helper/PortfolioService.java  |  40 ++
 .../rest/TellerManagementRestController.java       | 236 ++++++++++
 .../rest/TellerOperationRestController.java        | 143 ++++++
 .../teller/service/rest/TellerRestController.java  |  59 +++
 .../db/migrations/mariadb/V1__initial_setup.sql    |  20 +-
 shared.gradle                                      |   5 +
 53 files changed, 2618 insertions(+), 218 deletions(-)

diff --git a/api/src/main/java/io/mifos/teller/EventConstants.java b/api/src/main/java/io/mifos/teller/api/v1/EventConstants.java
similarity index 72%
copy from api/src/main/java/io/mifos/teller/EventConstants.java
copy to api/src/main/java/io/mifos/teller/api/v1/EventConstants.java
index f2a0d0b..34b1abb 100644
--- a/api/src/main/java/io/mifos/teller/EventConstants.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/EventConstants.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.api.v1;
 
 @SuppressWarnings("unused")
 public interface EventConstants {
@@ -27,4 +27,10 @@ public interface EventConstants {
 
   String POST_TELLER = "post-teller";
   String SELECTOR_POST_TELLER = SELECTOR_NAME + " = '" + POST_TELLER + "'";
+  String PUT_TELLER = "put-teller";
+  String SELECTOR_PUT_TELLER = SELECTOR_NAME + " = '" + PUT_TELLER + "'";
+  String OPEN_TELLER = "open-teller";
+  String SELECTOR_OPEN_TELLER = SELECTOR_NAME + " = '" + OPEN_TELLER + "'";
+  String CLOSE_TELLER = "close-teller";
+  String SELECTOR_CLOSE_TELLER = SELECTOR_NAME + " = '" + CLOSE_TELLER + "'";
 }
diff --git a/api/src/main/java/io/mifos/teller/PermittableGroupIds.java b/api/src/main/java/io/mifos/teller/api/v1/PermittableGroupIds.java
similarity index 96%
rename from api/src/main/java/io/mifos/teller/PermittableGroupIds.java
rename to api/src/main/java/io/mifos/teller/api/v1/PermittableGroupIds.java
index aff0c79..08fd7ea 100644
--- a/api/src/main/java/io/mifos/teller/PermittableGroupIds.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/PermittableGroupIds.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.api.v1;
 
 @SuppressWarnings("unused")
 public interface PermittableGroupIds {
diff --git a/service/src/main/java/io/mifos/teller/ServiceConstants.java b/api/src/main/java/io/mifos/teller/api/v1/client/TellerAlreadyExistsException.java
similarity index 84%
copy from service/src/main/java/io/mifos/teller/ServiceConstants.java
copy to api/src/main/java/io/mifos/teller/api/v1/client/TellerAlreadyExistsException.java
index 98de3be..3674d5f 100644
--- a/service/src/main/java/io/mifos/teller/ServiceConstants.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/client/TellerAlreadyExistsException.java
@@ -13,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.api.v1.client;
 
-public interface ServiceConstants {
-  String LOGGER_NAME = "teller-logger";
+public class TellerAlreadyExistsException extends RuntimeException {
 }
diff --git a/api/src/main/java/io/mifos/teller/client/TellerManager.java b/api/src/main/java/io/mifos/teller/api/v1/client/TellerManager.java
similarity index 84%
rename from api/src/main/java/io/mifos/teller/client/TellerManager.java
rename to api/src/main/java/io/mifos/teller/api/v1/client/TellerManager.java
index 2b9b0b4..0972873 100644
--- a/api/src/main/java/io/mifos/teller/client/TellerManager.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/client/TellerManager.java
@@ -1,14 +1,29 @@
-package io.mifos.teller.client;
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.api.v1.client;
 
 import io.mifos.core.api.annotation.ThrowsException;
 import io.mifos.core.api.annotation.ThrowsExceptions;
 import io.mifos.core.api.util.CustomFeignClientsConfiguration;
-import io.mifos.teller.domain.Teller;
-import io.mifos.teller.domain.TellerAuthentication;
-import io.mifos.teller.domain.TellerBalanceSheet;
-import io.mifos.teller.domain.TellerManagementCommand;
-import io.mifos.teller.domain.TellerTransaction;
-import io.mifos.teller.domain.TellerTransactionCosts;
+import io.mifos.teller.api.v1.domain.Teller;
+import io.mifos.teller.api.v1.domain.TellerAuthentication;
+import io.mifos.teller.api.v1.domain.TellerBalanceSheet;
+import io.mifos.teller.api.v1.domain.TellerManagementCommand;
+import io.mifos.teller.api.v1.domain.TellerTransaction;
+import io.mifos.teller.api.v1.domain.TellerTransactionCosts;
 import org.springframework.cloud.netflix.feign.FeignClient;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
@@ -25,7 +40,7 @@ import java.util.List;
 public interface TellerManager {
 
   @RequestMapping(
-      value = "/offices/{officeIdentifier}",
+      value = "/offices/{officeIdentifier}/teller",
       method = RequestMethod.POST,
       consumes = MediaType.APPLICATION_JSON_VALUE,
       produces = MediaType.APPLICATION_JSON_VALUE
@@ -44,7 +59,8 @@ public interface TellerManager {
       produces = MediaType.ALL_VALUE
   )
   @ThrowsExceptions({
-      @ThrowsException(status = HttpStatus.NOT_FOUND, exception = TellerNotFoundException.class)
+      @ThrowsException(status = HttpStatus.NOT_FOUND, exception = TellerNotFoundException.class),
+      @ThrowsException(status = HttpStatus.BAD_REQUEST, exception = TellerValidationException.class)
   })
   Teller find(@PathVariable("officeIdentifier") final String officeIdentifier,
               @PathVariable("tellerCode") final String tellerCode);
@@ -56,7 +72,8 @@ public interface TellerManager {
       produces = MediaType.ALL_VALUE
   )
   @ThrowsExceptions({
-      @ThrowsException(status = HttpStatus.NOT_FOUND, exception = TellerNotFoundException.class)
+      @ThrowsException(status = HttpStatus.NOT_FOUND, exception = TellerNotFoundException.class),
+      @ThrowsException(status = HttpStatus.BAD_REQUEST, exception = TellerValidationException.class)
   })
   List<Teller> fetch(@PathVariable("officeIdentifier") final String officeIdentifier);
 
diff --git a/service/src/main/java/io/mifos/teller/ServiceConstants.java b/api/src/main/java/io/mifos/teller/api/v1/client/TellerNotFoundException.java
similarity index 85%
copy from service/src/main/java/io/mifos/teller/ServiceConstants.java
copy to api/src/main/java/io/mifos/teller/api/v1/client/TellerNotFoundException.java
index 98de3be..335273f 100644
--- a/service/src/main/java/io/mifos/teller/ServiceConstants.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/client/TellerNotFoundException.java
@@ -13,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.api.v1.client;
 
-public interface ServiceConstants {
-  String LOGGER_NAME = "teller-logger";
+public class TellerNotFoundException extends RuntimeException {
 }
diff --git a/service/src/main/java/io/mifos/teller/ServiceConstants.java b/api/src/main/java/io/mifos/teller/api/v1/client/TellerTransactionValidationException.java
similarity index 83%
copy from service/src/main/java/io/mifos/teller/ServiceConstants.java
copy to api/src/main/java/io/mifos/teller/api/v1/client/TellerTransactionValidationException.java
index 98de3be..b46b30b 100644
--- a/service/src/main/java/io/mifos/teller/ServiceConstants.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/client/TellerTransactionValidationException.java
@@ -13,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.api.v1.client;
 
-public interface ServiceConstants {
-  String LOGGER_NAME = "teller-logger";
+public class TellerTransactionValidationException extends RuntimeException {
 }
diff --git a/service/src/main/java/io/mifos/teller/ServiceConstants.java b/api/src/main/java/io/mifos/teller/api/v1/client/TellerValidationException.java
similarity index 85%
copy from service/src/main/java/io/mifos/teller/ServiceConstants.java
copy to api/src/main/java/io/mifos/teller/api/v1/client/TellerValidationException.java
index 98de3be..e726612 100644
--- a/service/src/main/java/io/mifos/teller/ServiceConstants.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/client/TellerValidationException.java
@@ -13,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.api.v1.client;
 
-public interface ServiceConstants {
-  String LOGGER_NAME = "teller-logger";
+public class TellerValidationException extends RuntimeException {
 }
diff --git a/api/src/main/java/io/mifos/teller/EventConstants.java b/api/src/main/java/io/mifos/teller/api/v1/domain/Charge.java
similarity index 52%
copy from api/src/main/java/io/mifos/teller/EventConstants.java
copy to api/src/main/java/io/mifos/teller/api/v1/domain/Charge.java
index f2a0d0b..e576a09 100644
--- a/api/src/main/java/io/mifos/teller/EventConstants.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/domain/Charge.java
@@ -13,18 +13,39 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.api.v1.domain;
 
-@SuppressWarnings("unused")
-public interface EventConstants {
+public class Charge {
 
-  String DESTINATION = "teller-v1";
+  private String code;
+  private String name;
+  private Double amount;
 
-  String SELECTOR_NAME = "operation";
+  public Charge() {
+    super();
+  }
 
-  String INITIALIZE = "initialize";
-  String SELECTOR_INITIALIZE = SELECTOR_NAME + " = '" + INITIALIZE + "'";
+  public String getCode() {
+    return this.code;
+  }
 
-  String POST_TELLER = "post-teller";
-  String SELECTOR_POST_TELLER = SELECTOR_NAME + " = '" + POST_TELLER + "'";
+  public void setCode(final String code) {
+    this.code = code;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public Double getAmount() {
+    return this.amount;
+  }
+
+  public void setAmount(final Double amount) {
+    this.amount = amount;
+  }
 }
diff --git a/api/src/main/java/io/mifos/teller/domain/Teller.java b/api/src/main/java/io/mifos/teller/api/v1/domain/Teller.java
similarity index 67%
rename from api/src/main/java/io/mifos/teller/domain/Teller.java
rename to api/src/main/java/io/mifos/teller/api/v1/domain/Teller.java
index b1fa3b4..6d5f7b6 100644
--- a/api/src/main/java/io/mifos/teller/domain/Teller.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/domain/Teller.java
@@ -1,4 +1,19 @@
-package io.mifos.teller.domain;
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.api.v1.domain;
 
 import io.mifos.core.lang.validation.constraints.ValidIdentifier;
 import org.hibernate.validator.constraints.NotEmpty;
@@ -8,7 +23,7 @@ import javax.validation.constraints.NotNull;
 
 public class Teller {
 
-  public enum Status {
+  public enum State {
     ACTIVE,
     CLOSED,
     OPEN,
@@ -26,7 +41,8 @@ public class Teller {
   private String tellerAccountIdentifier;
   @ValidIdentifier
   private String vaultAccountIdentifier;
-  private Status status;
+  private String assignedEmployee;
+  private State state;
   private String createdBy;
   private String createdOn;
   private String lastModifiedBy;
@@ -76,12 +92,24 @@ public class Teller {
     this.vaultAccountIdentifier = vaultAccountIdentifier;
   }
 
-  public String getStatus() {
-    return this.status.name();
+  public String getAssignedEmployee() {
+    return this.assignedEmployee;
   }
 
-  public void setStatus(final String status) {
-    this.status = Status.valueOf(status);
+  public void setAssignedEmployee(final String assignedEmployee) {
+    this.assignedEmployee = assignedEmployee;
+  }
+
+  public String getState() {
+    if (this.state != null) {
+      return this.state.name();
+    } else {
+      return null;
+    }
+  }
+
+  public void setState(final String state) {
+    this.state = State.valueOf(state);
   }
 
   public String getCreatedBy() {
diff --git a/api/src/main/java/io/mifos/teller/EventConstants.java b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerAuthentication.java
similarity index 52%
copy from api/src/main/java/io/mifos/teller/EventConstants.java
copy to api/src/main/java/io/mifos/teller/api/v1/domain/TellerAuthentication.java
index f2a0d0b..dbd6bc4 100644
--- a/api/src/main/java/io/mifos/teller/EventConstants.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerAuthentication.java
@@ -13,18 +13,30 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.api.v1.domain;
 
-@SuppressWarnings("unused")
-public interface EventConstants {
+public class TellerAuthentication {
 
-  String DESTINATION = "teller-v1";
+  private String employeeIdentifier;
+  private byte[] password;
 
-  String SELECTOR_NAME = "operation";
+  public TellerAuthentication() {
+    super();
+  }
 
-  String INITIALIZE = "initialize";
-  String SELECTOR_INITIALIZE = SELECTOR_NAME + " = '" + INITIALIZE + "'";
+  public String getEmployeeIdentifier() {
+    return this.employeeIdentifier;
+  }
 
-  String POST_TELLER = "post-teller";
-  String SELECTOR_POST_TELLER = SELECTOR_NAME + " = '" + POST_TELLER + "'";
+  public void setEmployeeIdentifier(final String employeeIdentifier) {
+    this.employeeIdentifier = employeeIdentifier;
+  }
+
+  public byte[] getPassword() {
+    return this.password;
+  }
+
+  public void setPassword(final byte[] password) {
+    this.password = password;
+  }
 }
diff --git a/api/src/main/java/io/mifos/teller/api/v1/domain/TellerBalanceSheet.java b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerBalanceSheet.java
new file mode 100644
index 0000000..253354a
--- /dev/null
+++ b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerBalanceSheet.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.api.v1.domain;
+
+import java.util.List;
+
+public class TellerBalanceSheet {
+
+  private String day;
+  private Double balance;
+  private List<TellerEntry> entries;
+
+  public TellerBalanceSheet() {
+    super();
+  }
+
+  public String getDay() {
+    return this.day;
+  }
+
+  public void setDay(final String day) {
+    this.day = day;
+  }
+
+  public Double getBalance() {
+    return this.balance;
+  }
+
+  public void setBalance(final Double balance) {
+    this.balance = balance;
+  }
+
+  public List<TellerEntry> getEntries() {
+    return this.entries;
+  }
+
+  public void setEntries(final List<TellerEntry> entries) {
+    this.entries = entries;
+  }
+}
diff --git a/api/src/main/java/io/mifos/teller/domain/TellerEntry.java b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerEntry.java
similarity index 56%
rename from api/src/main/java/io/mifos/teller/domain/TellerEntry.java
rename to api/src/main/java/io/mifos/teller/api/v1/domain/TellerEntry.java
index 72535d3..b74e344 100644
--- a/api/src/main/java/io/mifos/teller/domain/TellerEntry.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerEntry.java
@@ -1,4 +1,19 @@
-package io.mifos.teller.domain;
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.api.v1.domain;
 
 public class TellerEntry {
 
@@ -11,7 +26,6 @@ public class TellerEntry {
   private String transactionDate;
   private String message;
   private Double amount;
-  private Double balance;
 
   public TellerEntry() {
     super();
@@ -48,12 +62,4 @@ public class TellerEntry {
   public void setAmount(final Double amount) {
     this.amount = amount;
   }
-
-  public Double getBalance() {
-    return this.balance;
-  }
-
-  public void setBalance(final Double balance) {
-    this.balance = balance;
-  }
 }
diff --git a/api/src/main/java/io/mifos/teller/domain/TellerManagementCommand.java b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerManagementCommand.java
similarity index 65%
rename from api/src/main/java/io/mifos/teller/domain/TellerManagementCommand.java
rename to api/src/main/java/io/mifos/teller/api/v1/domain/TellerManagementCommand.java
index c974451..01194eb 100644
--- a/api/src/main/java/io/mifos/teller/domain/TellerManagementCommand.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerManagementCommand.java
@@ -1,4 +1,19 @@
-package io.mifos.teller.domain;
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.api.v1.domain;
 
 import io.mifos.core.lang.validation.constraints.ValidIdentifier;
 
diff --git a/api/src/main/java/io/mifos/teller/domain/TellerTransaction.java b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerTransaction.java
similarity index 62%
rename from api/src/main/java/io/mifos/teller/domain/TellerTransaction.java
rename to api/src/main/java/io/mifos/teller/api/v1/domain/TellerTransaction.java
index e3d3a81..5dc8ffa 100644
--- a/api/src/main/java/io/mifos/teller/domain/TellerTransaction.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerTransaction.java
@@ -1,4 +1,19 @@
-package io.mifos.teller.domain;
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.api.v1.domain;
 
 import io.mifos.core.lang.validation.constraints.ValidIdentifier;
 
@@ -21,8 +36,12 @@ public class TellerTransaction {
   private String transactionDate;
   @ValidIdentifier
   private String productIdentifier;
+  @ValidIdentifier(optional = true)
+  private String productCaseIdentifier;
   @ValidIdentifier
   private String customerAccountIdentifier;
+  @ValidIdentifier(optional = true)
+  private String targetAccountIdentifier;
   @ValidIdentifier
   private String clerk;
   @NotNull
@@ -66,6 +85,14 @@ public class TellerTransaction {
     this.productIdentifier = productIdentifier;
   }
 
+  public String getProductCaseIdentifier() {
+    return this.productCaseIdentifier;
+  }
+
+  public void setProductCaseIdentifier(final String productCaseIdentifier) {
+    this.productCaseIdentifier = productCaseIdentifier;
+  }
+
   public String getCustomerAccountIdentifier() {
     return this.customerAccountIdentifier;
   }
@@ -74,6 +101,14 @@ public class TellerTransaction {
     this.customerAccountIdentifier = customerAccountIdentifier;
   }
 
+  public String getTargetAccountIdentifier() {
+    return this.targetAccountIdentifier;
+  }
+
+  public void setTargetAccountIdentifier(final String targetAccountIdentifier) {
+    this.targetAccountIdentifier = targetAccountIdentifier;
+  }
+
   public String getClerk() {
     return this.clerk;
   }
diff --git a/api/src/main/java/io/mifos/teller/domain/TellerTransactionCosts.java b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerTransactionCosts.java
similarity index 55%
rename from api/src/main/java/io/mifos/teller/domain/TellerTransactionCosts.java
rename to api/src/main/java/io/mifos/teller/api/v1/domain/TellerTransactionCosts.java
index ceb7348..2ba3cfa 100644
--- a/api/src/main/java/io/mifos/teller/domain/TellerTransactionCosts.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/domain/TellerTransactionCosts.java
@@ -1,4 +1,19 @@
-package io.mifos.teller.domain;
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.api.v1.domain;
 
 import java.util.List;
 
diff --git a/api/src/main/java/io/mifos/teller/client/TellerAlreadyExistsException.java b/api/src/main/java/io/mifos/teller/client/TellerAlreadyExistsException.java
deleted file mode 100644
index 28cf9aa..0000000
--- a/api/src/main/java/io/mifos/teller/client/TellerAlreadyExistsException.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package io.mifos.teller.client;
-
-public class TellerAlreadyExistsException extends RuntimeException {
-}
diff --git a/api/src/main/java/io/mifos/teller/client/TellerNotFoundException.java b/api/src/main/java/io/mifos/teller/client/TellerNotFoundException.java
deleted file mode 100644
index 4334646..0000000
--- a/api/src/main/java/io/mifos/teller/client/TellerNotFoundException.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package io.mifos.teller.client;
-
-public class TellerNotFoundException extends RuntimeException {
-}
diff --git a/api/src/main/java/io/mifos/teller/client/TellerTransactionValidationException.java b/api/src/main/java/io/mifos/teller/client/TellerTransactionValidationException.java
deleted file mode 100644
index 453b5d2..0000000
--- a/api/src/main/java/io/mifos/teller/client/TellerTransactionValidationException.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package io.mifos.teller.client;
-
-public class TellerTransactionValidationException extends RuntimeException {
-}
diff --git a/api/src/main/java/io/mifos/teller/client/TellerValidationException.java b/api/src/main/java/io/mifos/teller/client/TellerValidationException.java
deleted file mode 100644
index 07f0be8..0000000
--- a/api/src/main/java/io/mifos/teller/client/TellerValidationException.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package io.mifos.teller.client;
-
-public class TellerValidationException extends RuntimeException {
-}
diff --git a/api/src/main/java/io/mifos/teller/domain/Charge.java b/api/src/main/java/io/mifos/teller/domain/Charge.java
deleted file mode 100644
index 8f71964..0000000
--- a/api/src/main/java/io/mifos/teller/domain/Charge.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.mifos.teller.domain;
-
-public class Charge {
-
-  private String code;
-  private String name;
-  private Double amount;
-
-  public Charge() {
-    super();
-  }
-
-  public String getCode() {
-    return this.code;
-  }
-
-  public void setCode(final String code) {
-    this.code = code;
-  }
-
-  public String getName() {
-    return this.name;
-  }
-
-  public void setName(final String name) {
-    this.name = name;
-  }
-
-  public Double getAmount() {
-    return this.amount;
-  }
-
-  public void setAmount(final Double amount) {
-    this.amount = amount;
-  }
-}
diff --git a/api/src/main/java/io/mifos/teller/domain/TellerAuthentication.java b/api/src/main/java/io/mifos/teller/domain/TellerAuthentication.java
deleted file mode 100644
index e6578c8..0000000
--- a/api/src/main/java/io/mifos/teller/domain/TellerAuthentication.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.mifos.teller.domain;
-
-public class TellerAuthentication {
-
-  private String employeeIdentifier;
-  private byte[] password;
-
-  public TellerAuthentication() {
-    super();
-  }
-
-  public String getEmployeeIdentifier() {
-    return this.employeeIdentifier;
-  }
-
-  public void setEmployeeIdentifier(final String employeeIdentifier) {
-    this.employeeIdentifier = employeeIdentifier;
-  }
-
-  public byte[] getPassword() {
-    return this.password;
-  }
-
-  public void setPassword(final byte[] password) {
-    this.password = password;
-  }
-}
diff --git a/api/src/main/java/io/mifos/teller/domain/TellerBalanceSheet.java b/api/src/main/java/io/mifos/teller/domain/TellerBalanceSheet.java
deleted file mode 100644
index f46478c..0000000
--- a/api/src/main/java/io/mifos/teller/domain/TellerBalanceSheet.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.mifos.teller.domain;
-
-import java.util.List;
-
-public class TellerBalanceSheet {
-
-  private String day;
-  private Double balance;
-  private List<TellerEntry> entries;
-
-  public TellerBalanceSheet() {
-    super();
-  }
-
-  public String getDay() {
-    return this.day;
-  }
-
-  public void setDay(final String day) {
-    this.day = day;
-  }
-
-  public Double getBalance() {
-    return this.balance;
-  }
-
-  public void setBalance(final Double balance) {
-    this.balance = balance;
-  }
-
-  public List<TellerEntry> getEntries() {
-    return this.entries;
-  }
-
-  public void setEntries(final List<TellerEntry> entries) {
-    this.entries = entries;
-  }
-}
diff --git a/component-test/src/main/java/io/mifos/teller/AbstractTellerTest.java b/component-test/src/main/java/io/mifos/teller/AbstractTellerTest.java
new file mode 100644
index 0000000..4d60f41
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/teller/AbstractTellerTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller;
+
+import io.mifos.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
+import io.mifos.core.api.context.AutoUserContext;
+import io.mifos.core.lang.ApplicationName;
+import io.mifos.core.test.env.TestEnvironment;
+import io.mifos.core.test.fixture.TenantDataStoreContextTestRule;
+import io.mifos.core.test.fixture.cassandra.CassandraInitializer;
+import io.mifos.core.test.fixture.mariadb.MariaDBInitializer;
+import io.mifos.core.test.listener.EnableEventRecording;
+import io.mifos.core.test.listener.EventRecorder;
+import io.mifos.teller.api.v1.EventConstants;
+import io.mifos.teller.api.v1.client.TellerManager;
+import io.mifos.teller.service.internal.service.helper.AccountingService;
+import io.mifos.teller.service.internal.service.helper.DepositAccountManagementService;
+import io.mifos.teller.service.internal.service.helper.OrganizationService;
+import io.mifos.teller.service.internal.service.helper.PortfolioService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+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;
+
+import java.security.interfaces.RSAPrivateKey;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(
+    webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
+    classes = {AbstractTellerTest.TestConfiguration.class}
+)
+public class AbstractTellerTest {
+
+  private static final String APP_NAME = "teller-v1";
+  public static final String LOGGER_NAME = "test-logger";
+
+  @Configuration
+  @EnableEventRecording
+  @EnableFeignClients(basePackages = {"io.mifos.teller.api.v1.client"})
+  @RibbonClient(name = APP_NAME)
+  @Import({TellerConfiguration.class})
+  @ComponentScan("io.mifos.teller.listener")
+  public static class TestConfiguration {
+    public TestConfiguration() {
+      super();
+    }
+
+    @Bean(name = LOGGER_NAME)
+    public Logger logger() {
+      return LoggerFactory.getLogger(LOGGER_NAME);
+    }
+  }
+
+  private static final String TEST_USER = "homer";
+
+  private final static TestEnvironment testEnvironment = new TestEnvironment(APP_NAME);
+  private final static CassandraInitializer cassandraInitializer = new CassandraInitializer();
+  private final static MariaDBInitializer mariaDBInitializer = new MariaDBInitializer();
+  final static TenantDataStoreContextTestRule tenantDataStoreContext = TenantDataStoreContextTestRule.forRandomTenantName(cassandraInitializer, mariaDBInitializer);
+
+  @ClassRule
+  public static TestRule orderClassRules = RuleChain
+      .outerRule(testEnvironment)
+      .around(cassandraInitializer)
+      .around(mariaDBInitializer)
+      .around(tenantDataStoreContext);
+
+  @Rule
+  public final TenantApplicationSecurityEnvironmentTestRule tenantApplicationSecurityEnvironment
+      = new TenantApplicationSecurityEnvironmentTestRule(testEnvironment, this::waitForInitialize);
+
+  private AutoUserContext userContext;
+
+  @Autowired
+  TellerManager testSubject;
+
+  @Autowired
+  EventRecorder eventRecorder;
+
+  @MockBean
+  OrganizationService organizationServiceSpy;
+
+  @MockBean
+  AccountingService accountingServiceSpy;
+
+  @MockBean
+  DepositAccountManagementService depositAccountManagementServiceSpy;
+
+  @MockBean
+  PortfolioService portfolioServiceSpy;
+
+  @Autowired
+  private ApplicationName applicationName;
+
+  @Autowired
+  @Qualifier(LOGGER_NAME)
+  Logger logger;
+
+  @Before
+  public void prepTest() {
+    userContext = tenantApplicationSecurityEnvironment.createAutoUserContext(TEST_USER);
+    final RSAPrivateKey tenantPrivateKey = tenantApplicationSecurityEnvironment.getSystemSecurityEnvironment().tenantPrivateKey();
+    logger.info("tenantPrivateKey = {}", tenantPrivateKey);
+  }
+
+  @After
+  public void cleanTest() {
+    userContext.close();
+    eventRecorder.clear();
+  }
+
+  public boolean waitForInitialize() {
+    try {
+      final String version = this.applicationName.getVersionString();
+      this.logger.info("Waiting on initialize event for version: {}.", version);
+      return this.eventRecorder.wait(EventConstants.INITIALIZE, version);
+    } catch (final InterruptedException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+}
diff --git a/component-test/src/main/java/io/mifos/teller/TestTellerManagement.java b/component-test/src/main/java/io/mifos/teller/TestTellerManagement.java
new file mode 100644
index 0000000..b9f703d
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/teller/TestTellerManagement.java
@@ -0,0 +1,481 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller;
+
+import io.mifos.teller.api.v1.EventConstants;
+import io.mifos.teller.api.v1.client.TellerAlreadyExistsException;
+import io.mifos.teller.api.v1.client.TellerNotFoundException;
+import io.mifos.teller.api.v1.client.TellerValidationException;
+import io.mifos.teller.api.v1.domain.Teller;
+import io.mifos.teller.api.v1.domain.TellerManagementCommand;
+import io.mifos.teller.util.TellerGenerator;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class TestTellerManagement extends AbstractTellerTest {
+
+  public TestTellerManagement() {
+    super();
+  }
+
+  @Test
+  public void shouldCreateTeller() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode()));
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotCreateTellerUnknownOffice() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> false)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    super.testSubject.create(officeIdentifier, teller);
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotCreateTellerUnknownTellerAccount() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> false)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotCreateTellerUnknownVaultAccount() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> false)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+  }
+
+
+  @Test(expected = TellerAlreadyExistsException.class)
+  public void shouldCreateTellerAlreadyExists() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode()));
+
+    super.testSubject.create(officeIdentifier, teller);
+  }
+
+  @Test
+  public void shouldFindTeller() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode()));
+
+    final Teller foundTeller = super.testSubject.find(officeIdentifier, teller.getCode());
+    Assert.assertNotNull(foundTeller);
+
+    this.compareTeller(teller, foundTeller);
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotFindTellerUnknownOffice() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final String tellerCode = RandomStringUtils.randomAlphabetic(32);
+
+    Mockito.doAnswer(invocation -> false)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    super.testSubject.find(officeIdentifier, tellerCode);
+  }
+
+  @Test(expected = TellerNotFoundException.class)
+  public void shouldNotFindTellerUnknownTeller() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final String tellerCode = RandomStringUtils.randomAlphabetic(32);
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    super.testSubject.find(officeIdentifier, tellerCode);
+  }
+
+  @Test
+  public void shouldFetchTeller() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final List<Teller> tellerToCreate = Arrays.asList(
+        TellerGenerator.createRandomTeller(),
+        TellerGenerator.createRandomTeller(),
+        TellerGenerator.createRandomTeller(),
+        TellerGenerator.createRandomTeller(),
+        TellerGenerator.createRandomTeller()
+    );
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    tellerToCreate.forEach(teller -> {
+      Mockito.doAnswer(invocation -> true)
+          .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+      Mockito.doAnswer(invocation -> true)
+          .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+      super.testSubject.create(officeIdentifier, teller);
+
+      try {
+        Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode()));
+      } catch (final InterruptedException e) {
+        throw new IllegalStateException(e);
+      }
+    });
+
+    final List<Teller> fetchedTeller = super.testSubject.fetch(officeIdentifier);
+
+    Assert.assertTrue(fetchedTeller.size() >= tellerToCreate.size());
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotFetchTellerUnknownOffice() {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+
+    Mockito.doAnswer(invocation -> false)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    super.testSubject.fetch(officeIdentifier);
+  }
+
+  @Test
+  public void shouldUpdateTeller() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    teller.setCashdrawLimit(15000.00D);
+
+    super.testSubject.change(officeIdentifier, teller.getCode(), teller);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.PUT_TELLER, teller.getCode()));
+
+    final Teller changedTeller = super.testSubject.find(officeIdentifier, teller.getCode());
+    Assert.assertNotNull(changedTeller);
+
+    this.compareTeller(teller, changedTeller);
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotUpdateTellerUnknownOffice() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    Mockito.doAnswer(invocation -> false)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    super.testSubject.change(officeIdentifier, teller.getCode(), teller);
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotUpdateTellerUnknownTellerAccount() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    teller.setTellerAccountIdentifier(RandomStringUtils.randomAlphanumeric(32));
+
+    Mockito.doAnswer(invocation -> false)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    super.testSubject.change(officeIdentifier, teller.getCode(), teller);
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotUpdateTellerUnknownVaultAccount() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    teller.setVaultAccountIdentifier(RandomStringUtils.randomAlphanumeric(32));
+
+    Mockito.doAnswer(invocation -> false)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.change(officeIdentifier, teller.getCode(), teller);
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotUpdateTellerMismatch() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final String tellerCode = RandomStringUtils.randomAlphanumeric(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+    teller.setCode(tellerCode);
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    teller.setCode(RandomStringUtils.randomAlphanumeric(32));
+
+    super.testSubject.change(officeIdentifier, tellerCode, teller);
+  }
+
+  @Test(expected = TellerNotFoundException.class)
+  public void shouldNotUpdateTellerUnknownTeller() {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    super.testSubject.change(officeIdentifier, teller.getCode(), teller);
+  }
+
+  @Test
+  public void shouldOpenTeller() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    final TellerManagementCommand command = new TellerManagementCommand();
+    command.setAction(TellerManagementCommand.Action.OPEN.name());
+    command.setAssignedEmployeeIdentifier(RandomStringUtils.randomAlphanumeric(32));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).employeeExists(Matchers.eq(command.getAssignedEmployeeIdentifier()));
+
+    super.testSubject.post(officeIdentifier, teller.getCode(), command);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.OPEN_TELLER, teller.getCode()));
+
+    final Teller openedTeller = super.testSubject.find(officeIdentifier, teller.getCode());
+    Assert.assertEquals(Teller.State.OPEN.name(), openedTeller.getState());
+    Assert.assertEquals(command.getAssignedEmployeeIdentifier(), openedTeller.getAssignedEmployee());
+  }
+
+  @Test
+  public void shouldCloseTeller() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    final TellerManagementCommand command = new TellerManagementCommand();
+    command.setAction(TellerManagementCommand.Action.OPEN.name());
+    command.setAssignedEmployeeIdentifier(RandomStringUtils.randomAlphanumeric(32));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).employeeExists(Matchers.eq(command.getAssignedEmployeeIdentifier()));
+
+    super.testSubject.post(officeIdentifier, teller.getCode(), command);
+
+    super.eventRecorder.wait(EventConstants.OPEN_TELLER, teller.getCode());
+
+    command.setAction(TellerManagementCommand.Action.CLOSE.name());
+    command.setAssignedEmployeeIdentifier(null);
+    super.testSubject.post(officeIdentifier, teller.getCode(), command);
+
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.CLOSE_TELLER, teller.getCode()));
+
+    final Teller openedTeller = super.testSubject.find(officeIdentifier, teller.getCode());
+    Assert.assertEquals(Teller.State.CLOSED.name(), openedTeller.getState());
+    Assert.assertNull(openedTeller.getAssignedEmployee());
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotCloseTellerAlreadyClosed() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    final TellerManagementCommand command = new TellerManagementCommand();
+    command.setAction(TellerManagementCommand.Action.CLOSE.name());
+
+    super.testSubject.post(officeIdentifier, teller.getCode(), command);
+  }
+
+  @Test(expected = TellerValidationException.class)
+  public void shouldNotOpenTellerAlreadyOpen() throws Exception {
+    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
+    final Teller teller = TellerGenerator.createRandomTeller();
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getTellerAccountIdentifier()));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.accountingServiceSpy).accountExists(Matchers.eq(teller.getVaultAccountIdentifier()));
+
+    super.testSubject.create(officeIdentifier, teller);
+
+    super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode());
+
+    final TellerManagementCommand command = new TellerManagementCommand();
+    command.setAction(TellerManagementCommand.Action.OPEN.name());
+    command.setAssignedEmployeeIdentifier(RandomStringUtils.randomAlphanumeric(32));
+
+    Mockito.doAnswer(invocation -> true)
+        .when(super.organizationServiceSpy).employeeExists(Matchers.eq(command.getAssignedEmployeeIdentifier()));
+
+    super.testSubject.post(officeIdentifier, teller.getCode(), command);
+
+    super.eventRecorder.wait(EventConstants.OPEN_TELLER, teller.getCode());
+
+    // and again ...
+    super.testSubject.post(officeIdentifier, teller.getCode(), command);
+  }
+
+  private void compareTeller(final Teller expected, final Teller actual) {
+    Assert.assertEquals(expected.getCode(), actual.getCode());
+    Assert.assertEquals(expected.getTellerAccountIdentifier(), actual.getTellerAccountIdentifier());
+    Assert.assertEquals(expected.getVaultAccountIdentifier(), actual.getVaultAccountIdentifier());
+    Assert.assertEquals(expected.getCashdrawLimit(), actual.getCashdrawLimit());
+  }
+}
diff --git a/component-test/src/main/java/io/mifos/teller/listener/MigrationEventListener.java b/component-test/src/main/java/io/mifos/teller/listener/MigrationEventListener.java
new file mode 100644
index 0000000..30de7c1
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/teller/listener/MigrationEventListener.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.listener;
+
+import io.mifos.core.lang.config.TenantHeaderFilter;
+import io.mifos.core.test.listener.EventRecorder;
+import io.mifos.teller.AbstractTellerTest;
+import io.mifos.teller.api.v1.EventConstants;
+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;
+
+@Component
+public class MigrationEventListener {
+
+  private final Logger logger;
+  private final EventRecorder eventRecorder;
+
+  @Autowired
+  public MigrationEventListener(@Qualifier(AbstractTellerTest.LOGGER_NAME) final 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 onInitialize(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                           final String payload) {
+    this.logger.debug("Service initialized.");
+    this.eventRecorder.event(tenant, EventConstants.INITIALIZE, payload, String.class);
+  }
+}
diff --git a/component-test/src/main/java/io/mifos/teller/listener/TellerEventListener.java b/component-test/src/main/java/io/mifos/teller/listener/TellerEventListener.java
new file mode 100644
index 0000000..ee40f75
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/teller/listener/TellerEventListener.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.listener;
+
+import io.mifos.core.lang.config.TenantHeaderFilter;
+import io.mifos.core.test.listener.EventRecorder;
+import io.mifos.teller.AbstractTellerTest;
+import io.mifos.teller.api.v1.EventConstants;
+import org.slf4j.Logger;
+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;
+
+@Component
+public class TellerEventListener {
+
+  private final Logger logger;
+  private final EventRecorder eventRecorder;
+
+  public TellerEventListener(@Qualifier(AbstractTellerTest.LOGGER_NAME) final Logger logger,
+                             final EventRecorder eventRecorder) {
+    super();
+    this.logger = logger;
+    this.eventRecorder = eventRecorder;
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_POST_TELLER,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onCreate(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                           final String payload) {
+    this.logger.debug("Teller {} created.", payload);
+    this.eventRecorder.event(tenant, EventConstants.POST_TELLER, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_PUT_TELLER,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onChange(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                           final String payload) {
+    this.logger.debug("Teller {} created.", payload);
+    this.eventRecorder.event(tenant, EventConstants.PUT_TELLER, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_OPEN_TELLER,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onOpen(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                       final String payload) {
+    this.logger.debug("Teller {} created.", payload);
+    this.eventRecorder.event(tenant, EventConstants.OPEN_TELLER, payload, String.class);
+  }
+
+  @JmsListener(
+      destination = EventConstants.DESTINATION,
+      selector = EventConstants.SELECTOR_CLOSE_TELLER,
+      subscription = EventConstants.DESTINATION
+  )
+  public void onClose(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                     final String payload) {
+    this.logger.debug("Teller {} created.", payload);
+    this.eventRecorder.event(tenant, EventConstants.CLOSE_TELLER, payload, String.class);
+  }
+}
diff --git a/component-test/src/main/java/io/mifos/teller/util/TellerGenerator.java b/component-test/src/main/java/io/mifos/teller/util/TellerGenerator.java
new file mode 100644
index 0000000..baec507
--- /dev/null
+++ b/component-test/src/main/java/io/mifos/teller/util/TellerGenerator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.util;
+
+import io.mifos.teller.api.v1.domain.Teller;
+import org.apache.commons.lang3.RandomStringUtils;
+
+public class TellerGenerator {
+
+  public TellerGenerator() {
+    super();
+  }
+
+  public static Teller createRandomTeller() {
+    final Teller teller = new Teller();
+    teller.setCode(RandomStringUtils.randomAlphanumeric(32));
+    teller.setPassword(RandomStringUtils.randomAlphanumeric(12));
+    teller.setTellerAccountIdentifier(RandomStringUtils.randomAlphanumeric(32));
+    teller.setVaultAccountIdentifier(RandomStringUtils.randomAlphanumeric(32));
+    teller.setCashdrawLimit(10000.00D);
+
+    return teller;
+  }
+}
diff --git a/component-test/src/main/resources/logback-test.xml b/component-test/src/main/resources/logback-test.xml
index 1d5c4e7..57424f0 100644
--- a/component-test/src/main/resources/logback-test.xml
+++ b/component-test/src/main/resources/logback-test.xml
@@ -22,11 +22,11 @@
         </encoder>
     </appender>
 
-    <logger name="org" level="OFF"/>
+    <logger name="org" level="INFO"/>
     <logger name="com" level="OFF"/>
     <logger name="ch" level="OFF"/>
 
-    <root level="DEBUG">
+    <root level="INFO">
         <appender-ref ref="STDOUT"/>
     </root>
 </configuration>
\ No newline at end of file
diff --git a/service/build.gradle b/service/build.gradle
index a00147c..dad52d3 100644
--- a/service/build.gradle
+++ b/service/build.gradle
@@ -31,6 +31,10 @@ dependencies {
             [group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka'],
             [group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'],
             [group: 'io.mifos.teller', name: 'api', version: project.version],
+            [group: 'io.mifos.office', name: 'api', version: versions.frameworkoffice],
+            [group: 'io.mifos.accounting', name: 'api', version: versions.frameworkaccounting],
+            [group: 'io.mifos.deposit-account-management', name: 'api', version: versions.frameworkdeposit],
+            [group: 'io.mifos.portfolio', name: 'api', version: versions.frameworkportfolio],
             [group: 'io.mifos.anubis', name: 'library', version: versions.frameworkanubis],
             [group: 'com.google.code.gson', name: 'gson'],
             [group: 'io.mifos.core', name: 'lang', version: versions.frameworklang],
@@ -38,6 +42,7 @@ dependencies {
             [group: 'io.mifos.core', name: 'cassandra', version: versions.frameworkcassandra],
             [group: 'io.mifos.core', name: 'mariadb', version: versions.frameworkmariadb],
             [group: 'io.mifos.core', name: 'command', version: versions.frameworkcommand],
+            [group: 'io.mifos.tools', name: 'crypto', version: versions.frameworkcrypto],
             [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator]
     )
 }
diff --git a/service/src/main/java/io/mifos/teller/ServiceConstants.java b/service/src/main/java/io/mifos/teller/ServiceConstants.java
index 98de3be..adfef4e 100644
--- a/service/src/main/java/io/mifos/teller/ServiceConstants.java
+++ b/service/src/main/java/io/mifos/teller/ServiceConstants.java
@@ -17,4 +17,6 @@ package io.mifos.teller;
 
 public interface ServiceConstants {
   String LOGGER_NAME = "teller-logger";
+  int ITERATION_COUNT = 2048;
+  int LENGTH = 2048;
 }
diff --git a/service/src/main/java/io/mifos/teller/TellerConfiguration.java b/service/src/main/java/io/mifos/teller/TellerConfiguration.java
index 42b730a..5c60d5b 100644
--- a/service/src/main/java/io/mifos/teller/TellerConfiguration.java
+++ b/service/src/main/java/io/mifos/teller/TellerConfiguration.java
@@ -15,6 +15,7 @@
  */
 package io.mifos.teller;
 
+import io.mifos.accounting.api.v1.client.LedgerManager;
 import io.mifos.anubis.config.EnableAnubis;
 import io.mifos.core.async.config.EnableAsync;
 import io.mifos.core.cassandra.config.EnableCassandra;
@@ -22,10 +23,15 @@ import io.mifos.core.command.config.EnableCommandProcessing;
 import io.mifos.core.lang.config.EnableServiceException;
 import io.mifos.core.lang.config.EnableTenantContext;
 import io.mifos.core.mariadb.config.EnableMariaDB;
+import io.mifos.deposit.api.v1.client.DepositAccountManager;
+import io.mifos.office.api.v1.client.OrganizationManager;
+import io.mifos.portfolio.api.v1.client.PortfolioManager;
+import io.mifos.tool.crypto.config.EnableCrypto;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
@@ -44,6 +50,15 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
 @EnableCommandProcessing
 @EnableAnubis
 @EnableServiceException
+@EnableCrypto
+@EnableFeignClients(
+    clients = {
+        OrganizationManager.class,
+        LedgerManager.class,
+        DepositAccountManager.class,
+        PortfolioManager.class
+    }
+)
 @ComponentScan({
     "io.mifos.teller.service.rest",
     "io.mifos.teller.service.internal.service",
diff --git a/api/src/main/java/io/mifos/teller/EventConstants.java b/service/src/main/java/io/mifos/teller/service/internal/command/ChangeTellerCommand.java
similarity index 54%
copy from api/src/main/java/io/mifos/teller/EventConstants.java
copy to service/src/main/java/io/mifos/teller/service/internal/command/ChangeTellerCommand.java
index f2a0d0b..795bf2d 100644
--- a/api/src/main/java/io/mifos/teller/EventConstants.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/ChangeTellerCommand.java
@@ -13,18 +13,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.service.internal.command;
 
-@SuppressWarnings("unused")
-public interface EventConstants {
+import io.mifos.teller.api.v1.domain.Teller;
 
-  String DESTINATION = "teller-v1";
+public class ChangeTellerCommand {
 
-  String SELECTOR_NAME = "operation";
+  private final String officeIdentifier;
+  private final Teller teller;
 
-  String INITIALIZE = "initialize";
-  String SELECTOR_INITIALIZE = SELECTOR_NAME + " = '" + INITIALIZE + "'";
+  public ChangeTellerCommand(final String officeIdentifier, final Teller teller) {
+    super();
+    this.officeIdentifier = officeIdentifier;
+    this.teller = teller;
+  }
 
-  String POST_TELLER = "post-teller";
-  String SELECTOR_POST_TELLER = SELECTOR_NAME + " = '" + POST_TELLER + "'";
+  public String officeIdentifier() {
+    return this.officeIdentifier;
+  }
+
+  public Teller teller() {
+    return this.teller;
+  }
 }
diff --git a/service/src/main/java/io/mifos/teller/service/internal/command/CloseTellerCommand.java b/service/src/main/java/io/mifos/teller/service/internal/command/CloseTellerCommand.java
new file mode 100644
index 0000000..c3825e7
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/CloseTellerCommand.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.command;
+
+import io.mifos.teller.api.v1.domain.TellerManagementCommand;
+
+public class CloseTellerCommand {
+
+  private final String tellerCode;
+  private final TellerManagementCommand tellerManagementCommand;
+
+  public CloseTellerCommand(final String tellerCode, final TellerManagementCommand tellerManagementCommand) {
+    super();
+    this.tellerCode = tellerCode;
+    this.tellerManagementCommand = tellerManagementCommand;
+  }
+
+  public String tellerCode() {
+    return this.tellerCode;
+  }
+
+  public TellerManagementCommand tellerManagementCommand() {
+    return this.tellerManagementCommand;
+  }
+}
diff --git a/api/src/main/java/io/mifos/teller/EventConstants.java b/service/src/main/java/io/mifos/teller/service/internal/command/CreateTellerCommand.java
similarity index 54%
copy from api/src/main/java/io/mifos/teller/EventConstants.java
copy to service/src/main/java/io/mifos/teller/service/internal/command/CreateTellerCommand.java
index f2a0d0b..dd2f12e 100644
--- a/api/src/main/java/io/mifos/teller/EventConstants.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/CreateTellerCommand.java
@@ -13,18 +13,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.service.internal.command;
 
-@SuppressWarnings("unused")
-public interface EventConstants {
+import io.mifos.teller.api.v1.domain.Teller;
 
-  String DESTINATION = "teller-v1";
+public class CreateTellerCommand {
 
-  String SELECTOR_NAME = "operation";
+  private final String officeIdentifier;
+  private final Teller teller;
 
-  String INITIALIZE = "initialize";
-  String SELECTOR_INITIALIZE = SELECTOR_NAME + " = '" + INITIALIZE + "'";
+  public CreateTellerCommand(final String officeIdentifier, final Teller teller) {
+    super();
+    this.officeIdentifier = officeIdentifier;
+    this.teller = teller;
+  }
 
-  String POST_TELLER = "post-teller";
-  String SELECTOR_POST_TELLER = SELECTOR_NAME + " = '" + POST_TELLER + "'";
+  public String officeIdentifier() {
+    return this.officeIdentifier;
+  }
+
+  public Teller teller() {
+    return this.teller;
+  }
 }
diff --git a/service/src/main/java/io/mifos/teller/ServiceConstants.java b/service/src/main/java/io/mifos/teller/service/internal/command/MigrationCommand.java
similarity index 82%
copy from service/src/main/java/io/mifos/teller/ServiceConstants.java
copy to service/src/main/java/io/mifos/teller/service/internal/command/MigrationCommand.java
index 98de3be..6729c89 100644
--- a/service/src/main/java/io/mifos/teller/ServiceConstants.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/MigrationCommand.java
@@ -13,8 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.service.internal.command;
 
-public interface ServiceConstants {
-  String LOGGER_NAME = "teller-logger";
+public class MigrationCommand {
+
+  public MigrationCommand() {
+    super();
+  }
 }
diff --git a/service/src/main/java/io/mifos/teller/service/internal/command/OpenTellerCommand.java b/service/src/main/java/io/mifos/teller/service/internal/command/OpenTellerCommand.java
new file mode 100644
index 0000000..f28d09e
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/OpenTellerCommand.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.command;
+
+import io.mifos.teller.api.v1.domain.TellerManagementCommand;
+
+public class OpenTellerCommand {
+
+  private final String tellerCode;
+  private final TellerManagementCommand tellerManagementCommand;
+
+  public OpenTellerCommand(final String tellerCode, final TellerManagementCommand tellerManagementCommand) {
+    super();
+    this.tellerCode = tellerCode;
+    this.tellerManagementCommand = tellerManagementCommand;
+  }
+
+  public String tellerCode() {
+    return this.tellerCode;
+  }
+
+  public TellerManagementCommand tellerManagementCommand() {
+    return this.tellerManagementCommand;
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/command/handler/MigrationAggregate.java b/service/src/main/java/io/mifos/teller/service/internal/command/handler/MigrationAggregate.java
new file mode 100644
index 0000000..a48c686
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/handler/MigrationAggregate.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.command.handler;
+
+import io.mifos.core.command.annotation.Aggregate;
+import io.mifos.core.command.annotation.CommandHandler;
+import io.mifos.core.command.annotation.EventEmitter;
+import io.mifos.core.lang.ApplicationName;
+import io.mifos.core.mariadb.domain.FlywayFactoryBean;
+import io.mifos.teller.ServiceConstants;
+import io.mifos.teller.api.v1.EventConstants;
+import io.mifos.teller.service.internal.command.MigrationCommand;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.sql.DataSource;
+
+@Aggregate
+public class MigrationAggregate {
+
+  private final Logger logger;
+  private final DataSource dataSource;
+  private final FlywayFactoryBean flywayFactoryBean;
+  private final ApplicationName applicationName;
+
+  @Autowired
+  public MigrationAggregate(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                            final DataSource dataSource,
+                            final FlywayFactoryBean flywayFactoryBean,
+                            final ApplicationName applicationName) {
+    super();
+    this.logger = logger;
+    this.dataSource = dataSource;
+    this.flywayFactoryBean = flywayFactoryBean;
+    this.applicationName = applicationName;
+  }
+
+  @CommandHandler
+  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = EventConstants.INITIALIZE)
+  @Transactional
+  public String process(final MigrationCommand migrationCommand) {
+    this.logger.info("Starting migration for teller version: {}.", applicationName.getVersionString());
+    this.flywayFactoryBean.create(this.dataSource).migrate();
+
+    this.logger.info("Migration finished.");
+    return this.applicationName.getVersionString();
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/command/handler/TellerAggregate.java b/service/src/main/java/io/mifos/teller/service/internal/command/handler/TellerAggregate.java
new file mode 100644
index 0000000..9fb534f
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/handler/TellerAggregate.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.command.handler;
+
+import com.google.common.collect.Sets;
+import io.mifos.accounting.api.v1.domain.Creditor;
+import io.mifos.accounting.api.v1.domain.Debtor;
+import io.mifos.accounting.api.v1.domain.JournalEntry;
+import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.command.annotation.Aggregate;
+import io.mifos.core.command.annotation.CommandHandler;
+import io.mifos.core.command.annotation.EventEmitter;
+import io.mifos.core.lang.DateConverter;
+import io.mifos.teller.ServiceConstants;
+import io.mifos.teller.api.v1.EventConstants;
+import io.mifos.teller.api.v1.domain.Teller;
+import io.mifos.teller.api.v1.domain.TellerManagementCommand;
+import io.mifos.teller.service.internal.command.ChangeTellerCommand;
+import io.mifos.teller.service.internal.command.CloseTellerCommand;
+import io.mifos.teller.service.internal.command.CreateTellerCommand;
+import io.mifos.teller.service.internal.command.OpenTellerCommand;
+import io.mifos.teller.service.internal.mapper.TellerMapper;
+import io.mifos.teller.service.internal.repository.TellerEntity;
+import io.mifos.teller.service.internal.repository.TellerRepository;
+import io.mifos.teller.service.internal.service.helper.AccountingService;
+import io.mifos.teller.service.internal.service.helper.OrganizationService;
+import io.mifos.tool.crypto.HashGenerator;
+import io.mifos.tool.crypto.SaltGenerator;
+import org.apache.commons.lang.RandomStringUtils;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Base64Utils;
+
+import java.time.Clock;
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+@Aggregate
+public class TellerAggregate {
+
+  private final Logger logger;
+  private final TellerRepository tellerRepository;
+  private final OrganizationService organizationService;
+  private final AccountingService accountingService;
+  private final HashGenerator hashGenerator;
+  private final SaltGenerator saltGenerator;
+
+  @Autowired
+  public TellerAggregate(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                         final TellerRepository tellerRepository,
+                         final OrganizationService organizationService,
+                         final AccountingService accountingService,
+                         final HashGenerator hashGenerator,
+                         final SaltGenerator saltGenerator) {
+    super();
+    this.logger = logger;
+    this.tellerRepository = tellerRepository;
+    this.organizationService = organizationService;
+    this.accountingService = accountingService;
+    this.hashGenerator = hashGenerator;
+    this.saltGenerator = saltGenerator;
+  }
+
+  @Transactional
+  @CommandHandler
+  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = EventConstants.POST_TELLER)
+  public String process(final CreateTellerCommand createTellerCommand) {
+    final String officeIdentifier = createTellerCommand.officeIdentifier();
+    final Teller teller = createTellerCommand.teller();
+
+    if (this.checkPreconditions(officeIdentifier, teller)) {
+
+      final TellerEntity tellerEntity = TellerMapper.map(officeIdentifier, teller);
+
+      this.encryptPassword(teller, tellerEntity);
+
+      tellerEntity.setState(Teller.State.CLOSED.name());
+      tellerEntity.setCreatedBy(UserContextHolder.checkedGetUser());
+      tellerEntity.setCreatedOn(LocalDateTime.now(Clock.systemUTC()));
+
+      this.tellerRepository.save(tellerEntity);
+
+      return teller.getCode();
+    } else {
+      throw new IllegalStateException("Preconditions not met, see log file for further information.");
+    }
+  }
+
+  @Transactional
+  @CommandHandler
+  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = EventConstants.PUT_TELLER)
+  public String process(final ChangeTellerCommand changeTellerCommand) {
+    final String officeIdentifier = changeTellerCommand.officeIdentifier();
+    final Teller teller = changeTellerCommand.teller();
+
+    if (this.checkPreconditions(officeIdentifier, teller)) {
+      final Optional<TellerEntity> optionalTellerEntity = this.tellerRepository.findByIdentifier(teller.getCode());
+      if (optionalTellerEntity.isPresent()) {
+        final TellerEntity tellerEntity = optionalTellerEntity.get();
+
+        this.encryptPassword(teller, tellerEntity);
+
+        tellerEntity.setTellerAccountIdentifier(teller.getTellerAccountIdentifier());
+        tellerEntity.setVaultAccountIdentifier(teller.getVaultAccountIdentifier());
+        tellerEntity.setCashdrawLimit(teller.getCashdrawLimit());
+        tellerEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
+        tellerEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
+
+        this.tellerRepository.save(tellerEntity);
+
+        return teller.getCode();
+      } else {
+        throw new IllegalStateException("Teller " + teller.getCode() + " not found.");
+      }
+    } else {
+      throw new IllegalStateException("Preconditions not met, see log file for further information.");
+    }
+  }
+
+  @Transactional
+  @CommandHandler
+  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = EventConstants.OPEN_TELLER)
+  public String process(final OpenTellerCommand openTellerCommand) {
+    final String tellerCode = openTellerCommand.tellerCode();
+    final TellerManagementCommand tellerManagementCommand = openTellerCommand.tellerManagementCommand();
+
+    final Optional<TellerEntity> optionalTellerEntity = this.tellerRepository.findByIdentifier(tellerCode);
+    if (optionalTellerEntity.isPresent()) {
+      final TellerEntity tellerEntity = optionalTellerEntity.get();
+
+      if (this.checkPreconditions(tellerEntity.getOfficeIdentifier(), TellerMapper.map(tellerEntity))) {
+
+        if (tellerManagementCommand.getAmount() != null && tellerManagementCommand.getAmount() > 0.00D) {
+          this.accountingService.postJournalEntry(this.createJournalEntry(tellerEntity, tellerManagementCommand));
+        }
+
+        tellerEntity.setAssignedEmployeeIdentifier(tellerManagementCommand.getAssignedEmployeeIdentifier());
+        tellerEntity.setState(Teller.State.OPEN.name());
+        tellerEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
+        tellerEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
+
+        this.tellerRepository.save(tellerEntity);
+        return tellerCode;
+      } else {
+        throw new IllegalStateException("Preconditions not met, see log file for further information.");
+      }
+    } else {
+      throw new IllegalStateException("Teller " + tellerCode + " not found.");
+    }
+  }
+
+  @Transactional
+  @CommandHandler
+  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = EventConstants.CLOSE_TELLER)
+  public String process(final CloseTellerCommand closeTellerCommand) {
+    final String tellerCode = closeTellerCommand.tellerCode();
+    final TellerManagementCommand tellerManagementCommand = closeTellerCommand.tellerManagementCommand();
+
+    final Optional<TellerEntity> optionalTellerEntity = this.tellerRepository.findByIdentifier(tellerCode);
+    if (optionalTellerEntity.isPresent()) {
+      final TellerEntity tellerEntity = optionalTellerEntity.get();
+
+      if (this.checkPreconditions(tellerEntity.getOfficeIdentifier(), TellerMapper.map(tellerEntity))) {
+
+        if (tellerManagementCommand.getAmount() != null && tellerManagementCommand.getAmount() > 0.00D) {
+          this.accountingService.postJournalEntry(this.createJournalEntry(tellerEntity, tellerManagementCommand));
+        }
+        tellerEntity.setAssignedEmployeeIdentifier(null);
+        tellerEntity.setState(Teller.State.CLOSED.name());
+        tellerEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
+        tellerEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
+
+        this.tellerRepository.save(tellerEntity);
+        return tellerCode;
+      } else {
+        throw new IllegalStateException("Preconditions not met, see log file for further information.");
+      }
+    } else {
+      throw new IllegalStateException("Teller " + tellerCode + " not found.");
+    }
+  }
+
+  private boolean checkPreconditions(final String officeIdentifier, final Teller teller) {
+    boolean pass = true;
+
+    if (!this.organizationService.officeExists(officeIdentifier)) {
+      this.logger.warn("Office {} not found.", officeIdentifier);
+      pass = false;
+    }
+
+    if (!this.accountingService.accountExists(teller.getTellerAccountIdentifier())) {
+      this.logger.warn("Teller account {} not found.", teller.getTellerAccountIdentifier());
+      pass = false;
+    }
+
+    if (!this.accountingService.accountExists(teller.getVaultAccountIdentifier())) {
+      this.logger.warn("Vault account {} not found.", teller.getVaultAccountIdentifier());
+      pass = false;
+    }
+
+    return pass;
+  }
+
+  private void encryptPassword(final Teller teller, final TellerEntity tellerEntity) {
+    final byte[] salt = this.saltGenerator.createRandomSalt();
+    final byte[] newPassword = this.hashGenerator.hash(teller.getPassword(), salt, ServiceConstants.ITERATION_COUNT,
+        ServiceConstants.LENGTH);
+    tellerEntity.setSalt(Base64Utils.encodeToString(salt));
+    tellerEntity.setPassword(Base64Utils.encodeToString(newPassword));
+  }
+
+  private JournalEntry createJournalEntry(final TellerEntity tellerEntity, final TellerManagementCommand tellerManagementCommand) {
+
+    if (tellerManagementCommand.getAmount() > tellerEntity.getCashdrawLimit()) {
+      this.logger.warn("Adjustment {} exceeds cashdraw limit {}.", tellerManagementCommand.getAmount(),
+          tellerEntity.getCashdrawLimit());
+      throw new IllegalArgumentException("Adjustment exceeds cashdraw limit.");
+    }
+
+    final JournalEntry journalEntry = new JournalEntry();
+    journalEntry.setTransactionIdentifier(RandomStringUtils.randomNumeric(32));
+    journalEntry.setTransactionDate(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
+    journalEntry.setClerk(UserContextHolder.checkedGetUser());
+    journalEntry.setMessage("Teller adjustment.");
+
+    final TellerManagementCommand.Adjustment adjustment =
+        TellerManagementCommand.Adjustment.valueOf(tellerManagementCommand.getAdjustment());
+
+    final Debtor debtor = new Debtor();
+    final Creditor creditor = new Creditor();
+    switch (adjustment) {
+      case DEBIT:
+        journalEntry.setTransactionType("DAJT");
+
+        debtor.setAccountNumber(tellerEntity.getTellerAccountIdentifier());
+        debtor.setAmount(tellerManagementCommand.getAmount().toString());
+        journalEntry.setDebtors(Sets.newHashSet(debtor));
+
+        creditor.setAccountNumber(tellerEntity.getVaultAccountIdentifier());
+        creditor.setAmount(tellerManagementCommand.getAmount().toString());
+        journalEntry.setCreditors(Sets.newHashSet(creditor));
+
+        break;
+      case CREDIT:
+        journalEntry.setTransactionType("CAJT");
+
+        debtor.setAccountNumber(tellerEntity.getVaultAccountIdentifier());
+        debtor.setAmount(tellerManagementCommand.getAmount().toString());
+        journalEntry.setDebtors(Sets.newHashSet(debtor));
+
+        creditor.setAccountNumber(tellerEntity.getTellerAccountIdentifier());
+        creditor.setAmount(tellerManagementCommand.getAmount().toString());
+        journalEntry.setCreditors(Sets.newHashSet(creditor));
+
+        break;
+      default:
+        this.logger.warn("Unsupported adjustment type {}.", tellerManagementCommand.getAdjustment());
+    }
+
+    return journalEntry;
+  }
+}
+
diff --git a/service/src/main/java/io/mifos/teller/service/internal/mapper/TellerEntryMapper.java b/service/src/main/java/io/mifos/teller/service/internal/mapper/TellerEntryMapper.java
new file mode 100644
index 0000000..eef8674
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/mapper/TellerEntryMapper.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.mapper;
+
+import io.mifos.accounting.api.v1.domain.AccountEntry;
+import io.mifos.teller.api.v1.domain.TellerEntry;
+
+public class TellerEntryMapper {
+
+  private TellerEntryMapper() {
+    super();
+  }
+
+  public static TellerEntry map(final AccountEntry accountEntry) {
+    final TellerEntry tellerEntry = new TellerEntry();
+    tellerEntry.setType(accountEntry.getType());
+    tellerEntry.setTransactionDate(accountEntry.getTransactionDate());
+    tellerEntry.setMessage(accountEntry.getMessage());
+    tellerEntry.setAmount(accountEntry.getAmount());
+
+    return tellerEntry;
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/mapper/TellerMapper.java b/service/src/main/java/io/mifos/teller/service/internal/mapper/TellerMapper.java
new file mode 100644
index 0000000..bfb83af
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/mapper/TellerMapper.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.mapper;
+
+import io.mifos.core.lang.DateConverter;
+import io.mifos.teller.api.v1.domain.Teller;
+import io.mifos.teller.service.internal.repository.TellerEntity;
+
+public class TellerMapper {
+
+  private TellerMapper() {
+    super();
+  }
+
+  public static Teller map(final TellerEntity tellerEntity) {
+    final Teller teller = new Teller();
+    teller.setCode(tellerEntity.getIdentifier());
+    teller.setPassword(tellerEntity.getPassword());
+    teller.setTellerAccountIdentifier(tellerEntity.getTellerAccountIdentifier());
+    teller.setVaultAccountIdentifier(tellerEntity.getVaultAccountIdentifier());
+    teller.setCashdrawLimit(tellerEntity.getCashdrawLimit());
+    teller.setAssignedEmployee(tellerEntity.getAssignedEmployeeIdentifier());
+    teller.setState(tellerEntity.getState());
+    if (tellerEntity.getCreatedBy() != null) {
+      teller.setCreatedBy(tellerEntity.getCreatedBy());
+      teller.setCreatedOn(DateConverter.toIsoString(tellerEntity.getCreatedOn()));
+    }
+    if (tellerEntity.getLastModifiedBy() != null) {
+      teller.setLastModifiedBy(tellerEntity.getLastModifiedBy());
+      teller.setLastModifiedOn(DateConverter.toIsoString(tellerEntity.getLastModifiedOn()));
+    }
+
+    return teller;
+  }
+
+  public static TellerEntity map(final String officeIdentifier, final Teller teller) {
+    final TellerEntity tellerEntity = new TellerEntity();
+    tellerEntity.setIdentifier(teller.getCode());
+    tellerEntity.setPassword(teller.getPassword());
+    tellerEntity.setOfficeIdentifier(officeIdentifier);
+    tellerEntity.setTellerAccountIdentifier(teller.getTellerAccountIdentifier());
+    tellerEntity.setVaultAccountIdentifier(teller.getVaultAccountIdentifier());
+    tellerEntity.setCashdrawLimit(teller.getCashdrawLimit());
+    tellerEntity.setAssignedEmployeeIdentifier(teller.getAssignedEmployee());
+    if (teller.getState() != null) {
+      tellerEntity.setState(teller.getState());
+    }
+    if (teller.getCreatedBy() != null) {
+      tellerEntity.setCreatedBy(teller.getCreatedBy());
+      tellerEntity.setCreatedOn(DateConverter.fromIsoString(teller.getCreatedOn()));
+    }
+    if (teller.getLastModifiedBy() != null) {
+      tellerEntity.setLastModifiedBy(teller.getLastModifiedBy());
+      tellerEntity.setLastModifiedOn(DateConverter.fromIsoString(teller.getLastModifiedOn()));
+    }
+    return tellerEntity;
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/repository/TellerEntity.java b/service/src/main/java/io/mifos/teller/service/internal/repository/TellerEntity.java
new file mode 100644
index 0000000..00abbe2
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/repository/TellerEntity.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.repository;
+
+import io.mifos.core.mariadb.util.LocalDateTimeConverter;
+
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "tajet_teller")
+public class TellerEntity {
+
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  @Column(name = "id", nullable = false)
+  private Long id;
+  @Column(name = "identifier", nullable = false, length = 32)
+  private String identifier;
+  @Column(name = "a_password", nullable = false, length = 4096)
+  private String password;
+  @Column(name = "a_salt", nullable = false, length = 4096)
+  private String salt;
+  @Column(name = "office_identifier", nullable = false, length = 32)
+  private String officeIdentifier;
+  @Column(name = "cashdraw_limit", nullable = false)
+  private Double cashdrawLimit;
+  @Column(name = "teller_account_identifier", nullable = false, length = 32)
+  private String tellerAccountIdentifier;
+  @Column(name = "vault_account_identifier", nullable = false, length = 32)
+  private String vaultAccountIdentifier;
+  @Column(name = "assigned_employee_identifier", nullable = true, length = 32)
+  private String assignedEmployeeIdentifier;
+  @Column(name = "a_state", nullable = false, length = 256)
+  private String state;
+  @Column(name = "created_by", nullable = false, length = 32)
+  private String createdBy;
+  @Column(name = "created_on", nullable = false)
+  @Convert(converter = LocalDateTimeConverter.class)
+  private LocalDateTime createdOn;
+  @Column(name = "last_modified_by", nullable = true, length = 32)
+  private String lastModifiedBy;
+  @Column(name = "last_modified_on", nullable = true)
+  @Convert(converter = LocalDateTimeConverter.class)
+  private LocalDateTime lastModifiedOn;
+
+  public TellerEntity() {
+    super();
+  }
+
+  public Long getId() {
+    return this.id;
+  }
+
+  public void setId(final Long id) {
+    this.id = id;
+  }
+
+  public String getIdentifier() {
+    return this.identifier;
+  }
+
+  public void setIdentifier(final String identifier) {
+    this.identifier = identifier;
+  }
+
+  public String getPassword() {
+    return this.password;
+  }
+
+  public void setPassword(final String password) {
+    this.password = password;
+  }
+
+  public String getSalt() {
+    return this.salt;
+  }
+
+  public void setSalt(final String salt) {
+    this.salt = salt;
+  }
+
+  public String getOfficeIdentifier() {
+    return this.officeIdentifier;
+  }
+
+  public void setOfficeIdentifier(final String officeIdentifier) {
+    this.officeIdentifier = officeIdentifier;
+  }
+
+  public Double getCashdrawLimit() {
+    return this.cashdrawLimit;
+  }
+
+  public void setCashdrawLimit(final Double cashdrawLimit) {
+    this.cashdrawLimit = cashdrawLimit;
+  }
+
+  public String getTellerAccountIdentifier() {
+    return this.tellerAccountIdentifier;
+  }
+
+  public void setTellerAccountIdentifier(final String tellerAccountIdentifier) {
+    this.tellerAccountIdentifier = tellerAccountIdentifier;
+  }
+
+  public String getVaultAccountIdentifier() {
+    return this.vaultAccountIdentifier;
+  }
+
+  public void setVaultAccountIdentifier(final String vaultAccountIdentifier) {
+    this.vaultAccountIdentifier = vaultAccountIdentifier;
+  }
+
+  public String getAssignedEmployeeIdentifier() {
+    return this.assignedEmployeeIdentifier;
+  }
+
+  public void setAssignedEmployeeIdentifier(final String assignedEmployeeIdentifier) {
+    this.assignedEmployeeIdentifier = assignedEmployeeIdentifier;
+  }
+
+  public String getState() {
+    return this.state;
+  }
+
+  public void setState(final String state) {
+    this.state = state;
+  }
+
+  public String getCreatedBy() {
+    return this.createdBy;
+  }
+
+  public void setCreatedBy(final String createdBy) {
+    this.createdBy = createdBy;
+  }
+
+  public LocalDateTime getCreatedOn() {
+    return this.createdOn;
+  }
+
+  public void setCreatedOn(final LocalDateTime createdOn) {
+    this.createdOn = createdOn;
+  }
+
+  public String getLastModifiedBy() {
+    return this.lastModifiedBy;
+  }
+
+  public void setLastModifiedBy(final String lastModifiedBy) {
+    this.lastModifiedBy = lastModifiedBy;
+  }
+
+  public LocalDateTime getLastModifiedOn() {
+    return this.lastModifiedOn;
+  }
+
+  public void setLastModifiedOn(final LocalDateTime lastModifiedOn) {
+    this.lastModifiedOn = lastModifiedOn;
+  }
+}
diff --git a/api/src/main/java/io/mifos/teller/EventConstants.java b/service/src/main/java/io/mifos/teller/service/internal/repository/TellerRepository.java
similarity index 57%
rename from api/src/main/java/io/mifos/teller/EventConstants.java
rename to service/src/main/java/io/mifos/teller/service/internal/repository/TellerRepository.java
index f2a0d0b..530cb19 100644
--- a/api/src/main/java/io/mifos/teller/EventConstants.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/repository/TellerRepository.java
@@ -13,18 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.service.internal.repository;
 
-@SuppressWarnings("unused")
-public interface EventConstants {
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
 
-  String DESTINATION = "teller-v1";
+import java.util.List;
+import java.util.Optional;
 
-  String SELECTOR_NAME = "operation";
+@Repository
+public interface TellerRepository extends JpaRepository<TellerEntity, Long> {
 
-  String INITIALIZE = "initialize";
-  String SELECTOR_INITIALIZE = SELECTOR_NAME + " = '" + INITIALIZE + "'";
+  Optional<TellerEntity> findByIdentifier(final String identifier);
 
-  String POST_TELLER = "post-teller";
-  String SELECTOR_POST_TELLER = SELECTOR_NAME + " = '" + POST_TELLER + "'";
+  List<TellerEntity> findByOfficeIdentifier(final String officeIdentifier);
 }
diff --git a/service/src/main/java/io/mifos/teller/service/internal/service/TellerManagementService.java b/service/src/main/java/io/mifos/teller/service/internal/service/TellerManagementService.java
new file mode 100644
index 0000000..e2b4ac3
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/service/TellerManagementService.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.service;
+
+import io.mifos.accounting.api.v1.domain.AccountEntryPage;
+import io.mifos.teller.ServiceConstants;
+import io.mifos.teller.api.v1.domain.Teller;
+import io.mifos.teller.api.v1.domain.TellerBalanceSheet;
+import io.mifos.teller.api.v1.domain.TellerEntry;
+import io.mifos.teller.service.internal.mapper.TellerEntryMapper;
+import io.mifos.teller.service.internal.mapper.TellerMapper;
+import io.mifos.teller.service.internal.repository.TellerEntity;
+import io.mifos.teller.service.internal.repository.TellerRepository;
+import io.mifos.teller.service.internal.service.helper.AccountingService;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Service
+public class TellerManagementService {
+
+  private final Logger logger;
+  private final TellerRepository tellerRepository;
+  private final AccountingService accountingService;
+
+  @Autowired
+  public TellerManagementService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                 final TellerRepository tellerRepository,
+                                 final AccountingService accountingService) {
+    super();
+    this.logger = logger;
+    this.tellerRepository = tellerRepository;
+    this.accountingService = accountingService;
+  }
+
+  public Optional<Teller> findByIdentifier(final String code) {
+    return this.tellerRepository.findByIdentifier(code).map(TellerMapper::map);
+  }
+
+  public List<Teller> findByOfficeIdentifier(final String officeIdentifier) {
+    return this.tellerRepository.findByOfficeIdentifier(officeIdentifier)
+        .stream()
+        .map(TellerMapper::map)
+        .collect(Collectors.toList());
+  }
+
+  public TellerBalanceSheet getBalance(final String tellerCode) {
+    final TellerBalanceSheet tellerBalanceSheet = new TellerBalanceSheet();
+
+    final Optional<TellerEntity> optionalTellerEntity = this.tellerRepository.findByIdentifier(tellerCode);
+    optionalTellerEntity.ifPresent(tellerEntity -> {
+
+      final String accountIdentifier = tellerEntity.getTellerAccountIdentifier();
+      final LocalDateTime lastModifiedOn = tellerEntity.getLastModifiedOn();
+      final LocalDateTime startDate = lastModifiedOn.withHour(0).withMinute(0).withSecond(0).withNano(0);
+      final LocalDateTime endDate = lastModifiedOn.withHour(23).withMinute(59).withSecond(59).withNano(999);
+      final String dateRange =
+          startDate.format(DateTimeFormatter.BASIC_ISO_DATE) + ".." + endDate.format(DateTimeFormatter.BASIC_ISO_DATE);
+
+      final List<TellerEntry> tellerEntries = this.fetchTellerEntries(accountIdentifier, dateRange, 0);
+
+      tellerBalanceSheet.setDay(startDate.format(DateTimeFormatter.BASIC_ISO_DATE));
+      tellerBalanceSheet.setBalance(tellerEntries.stream().mapToDouble(TellerEntry::getAmount).sum());
+      tellerBalanceSheet.setEntries(tellerEntries);
+    });
+    return tellerBalanceSheet;
+  }
+
+  private List<TellerEntry> fetchTellerEntries(final String accountIdentifier, final String dateRange, final Integer pageIndex) {
+    final ArrayList<TellerEntry> tellerEntries = new ArrayList<>();
+
+    final AccountEntryPage accountEntryPage =
+        this.accountingService.fetchAccountEntries(accountIdentifier, dateRange, pageIndex, 250);
+    tellerEntries.addAll(
+        accountEntryPage.getAccountEntries().stream().map(TellerEntryMapper::map).collect(Collectors.toList())
+    );
+
+    final Integer nextPage = pageIndex + 1;
+    if (nextPage < accountEntryPage.getTotalPages()) {
+      tellerEntries.addAll(this.fetchTellerEntries(accountIdentifier, dateRange, nextPage));
+    }
+
+    return tellerEntries;
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/ServiceConstants.java b/service/src/main/java/io/mifos/teller/service/internal/service/TellerOperationService.java
similarity index 80%
copy from service/src/main/java/io/mifos/teller/ServiceConstants.java
copy to service/src/main/java/io/mifos/teller/service/internal/service/TellerOperationService.java
index 98de3be..220abb6 100644
--- a/service/src/main/java/io/mifos/teller/ServiceConstants.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/service/TellerOperationService.java
@@ -13,8 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.teller;
+package io.mifos.teller.service.internal.service;
 
-public interface ServiceConstants {
-  String LOGGER_NAME = "teller-logger";
+import org.springframework.stereotype.Service;
+
+@Service
+public class TellerOperationService {
 }
diff --git a/service/src/main/java/io/mifos/teller/service/internal/service/helper/AccountingService.java b/service/src/main/java/io/mifos/teller/service/internal/service/helper/AccountingService.java
new file mode 100644
index 0000000..d64decb
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/service/helper/AccountingService.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.service.helper;
+
+import io.mifos.accounting.api.v1.client.AccountNotFoundException;
+import io.mifos.accounting.api.v1.client.LedgerManager;
+import io.mifos.accounting.api.v1.domain.AccountEntryPage;
+import io.mifos.accounting.api.v1.domain.JournalEntry;
+import io.mifos.teller.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AccountingService {
+
+  private final Logger logger;
+  private final LedgerManager ledgerManager;
+
+  @Autowired
+  public AccountingService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                           final LedgerManager ledgerManager) {
+    super();
+    this.logger = logger;
+    this.ledgerManager = ledgerManager;
+  }
+
+  public boolean accountExists(final String accountIdentifier) {
+    try {
+      this.ledgerManager.findAccount(accountIdentifier);
+      return true;
+    } catch (final AccountNotFoundException anfex) {
+      this.logger.warn("Account {} not found.", accountIdentifier);
+      return false;
+    }
+  }
+
+  public AccountEntryPage fetchAccountEntries(final String accountIdentifier, final String dateRange, final Integer pageIndex,
+                                              final Integer pageSize) {
+    return this.ledgerManager.fetchAccountEntries(accountIdentifier, dateRange, pageIndex, pageSize, "identifier",
+        Sort.Direction.DESC.name());
+  }
+
+  public void postJournalEntry(final JournalEntry journalEntry) {
+    this.ledgerManager.createJournalEntry(journalEntry);
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/service/helper/DepositAccountManagementService.java b/service/src/main/java/io/mifos/teller/service/internal/service/helper/DepositAccountManagementService.java
new file mode 100644
index 0000000..4d0a458
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/service/helper/DepositAccountManagementService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.service.helper;
+
+import io.mifos.deposit.api.v1.client.DepositAccountManager;
+import io.mifos.teller.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DepositAccountManagementService {
+
+  private final Logger logger;
+  private final DepositAccountManager depositAccountManager;
+
+  @Autowired
+  public DepositAccountManagementService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                         final DepositAccountManager depositAccountManager) {
+    super();
+    this.logger = logger;
+    this.depositAccountManager = depositAccountManager;
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/service/helper/OrganizationService.java b/service/src/main/java/io/mifos/teller/service/internal/service/helper/OrganizationService.java
new file mode 100644
index 0000000..cb68e22
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/service/helper/OrganizationService.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.service.helper;
+
+import io.mifos.office.api.v1.client.NotFoundException;
+import io.mifos.office.api.v1.client.OrganizationManager;
+import io.mifos.teller.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OrganizationService {
+
+  private final Logger logger;
+  private final OrganizationManager organizationManager;
+
+  @Autowired
+  public OrganizationService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                             final OrganizationManager organizationManager) {
+    super();
+    this.logger = logger;
+    this.organizationManager = organizationManager;
+  }
+
+  public boolean officeExists(final String officeIdentifier) {
+    try {
+      this.organizationManager.findOfficeByIdentifier(officeIdentifier);
+      return true;
+    } catch (final NotFoundException nfex) {
+      this.logger.warn("Office {} not found.", officeIdentifier);
+      return false;
+    }
+  }
+
+  public boolean employeeExists(final String employeeIdentifier) {
+    try {
+      this.organizationManager.findEmployee(employeeIdentifier);
+      return true;
+    } catch (final NotFoundException nfex) {
+      this.logger.warn("Employee {} not found.", employeeIdentifier);
+      return false;
+    }
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/service/helper/PortfolioService.java b/service/src/main/java/io/mifos/teller/service/internal/service/helper/PortfolioService.java
new file mode 100644
index 0000000..6076c58
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/internal/service/helper/PortfolioService.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.internal.service.helper;
+
+import io.mifos.portfolio.api.v1.client.PortfolioManager;
+import io.mifos.teller.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class PortfolioService {
+
+  private final Logger logger;
+  private final PortfolioManager portfolioManager;
+
+  @Autowired
+  public PortfolioService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                          final PortfolioManager portfolioManager) {
+    super();
+    this.logger = logger;
+    this.portfolioManager = portfolioManager;
+  }
+
+
+}
diff --git a/service/src/main/java/io/mifos/teller/service/rest/TellerManagementRestController.java b/service/src/main/java/io/mifos/teller/service/rest/TellerManagementRestController.java
new file mode 100644
index 0000000..feef72a
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/rest/TellerManagementRestController.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.rest;
+
+import io.mifos.anubis.annotation.AcceptedTokenType;
+import io.mifos.anubis.annotation.Permittable;
+import io.mifos.core.command.gateway.CommandGateway;
+import io.mifos.core.lang.ServiceException;
+import io.mifos.teller.ServiceConstants;
+import io.mifos.teller.api.v1.PermittableGroupIds;
+import io.mifos.teller.api.v1.domain.Teller;
+import io.mifos.teller.api.v1.domain.TellerBalanceSheet;
+import io.mifos.teller.api.v1.domain.TellerManagementCommand;
+import io.mifos.teller.service.internal.command.ChangeTellerCommand;
+import io.mifos.teller.service.internal.command.CloseTellerCommand;
+import io.mifos.teller.service.internal.command.CreateTellerCommand;
+import io.mifos.teller.service.internal.command.OpenTellerCommand;
+import io.mifos.teller.service.internal.service.TellerManagementService;
+import io.mifos.teller.service.internal.service.helper.AccountingService;
+import io.mifos.teller.service.internal.service.helper.OrganizationService;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/offices/{officeIdentifier}/teller")
+public class TellerManagementRestController {
+
+  private final Logger logger;
+  private final CommandGateway commandGateway;
+  private final TellerManagementService tellerManagementService;
+  private final OrganizationService organizationService;
+  private final AccountingService accountingService;
+
+  @Autowired
+  public TellerManagementRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                        final CommandGateway commandGateway,
+                                        final TellerManagementService tellerManagementService,
+                                        final OrganizationService organizationService,
+                                        final AccountingService accountingService) {
+    super();
+    this.logger = logger;
+    this.commandGateway = commandGateway;
+    this.tellerManagementService = tellerManagementService;
+    this.organizationService = organizationService;
+    this.accountingService = accountingService;
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_MANAGEMENT)
+  @RequestMapping(
+      value = "",
+      method = RequestMethod.POST,
+      consumes = MediaType.APPLICATION_JSON_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<Void> create(@PathVariable("officeIdentifier") final String officeIdentifier,
+                              @RequestBody @Valid final Teller teller) {
+    if (this.tellerManagementService.findByIdentifier(teller.getCode()).isPresent()) {
+      throw ServiceException.conflict("Teller {0} already exists.", teller.getCode());
+    }
+
+    this.verifyOffice(officeIdentifier);
+    this.verifyAccount(teller.getTellerAccountIdentifier());
+    this.verifyAccount(teller.getVaultAccountIdentifier());
+
+    this.commandGateway.process(new CreateTellerCommand(officeIdentifier, teller));
+
+    return ResponseEntity.accepted().build();
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_MANAGEMENT)
+  @RequestMapping(
+      value = "/{tellerCode}",
+      method = RequestMethod.GET,
+      consumes = MediaType.ALL_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<Teller> find(@PathVariable("officeIdentifier") final String officeIdentifier,
+                              @PathVariable("tellerCode") final String tellerCode) {
+    this.verifyOffice(officeIdentifier);
+
+    return ResponseEntity.ok(
+        this.tellerManagementService.findByIdentifier(tellerCode)
+            .orElseThrow(() -> ServiceException.notFound("Teller {0} not found.", tellerCode))
+    );
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_MANAGEMENT)
+  @RequestMapping(
+      value = "",
+      method = RequestMethod.GET,
+      consumes = MediaType.ALL_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<List<Teller>> fetch(@PathVariable("officeIdentifier") final String officeIdentifier) {
+    this.verifyOffice(officeIdentifier);
+
+    return ResponseEntity.ok(
+        this.tellerManagementService.findByOfficeIdentifier(officeIdentifier)
+    );
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_MANAGEMENT)
+  @RequestMapping(
+      value = "/{tellerCode}",
+      method = RequestMethod.PUT,
+      consumes = MediaType.APPLICATION_JSON_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<Void> change(@PathVariable("officeIdentifier") final String officeIdentifier,
+                              @PathVariable("tellerCode") final String tellerCode,
+                              @RequestBody @Valid final Teller teller) {
+    if (!tellerCode.equals(teller.getCode())) {
+      throw ServiceException.badRequest("Teller code {0} must much given teller.", tellerCode);
+    }
+
+    this.verifyTeller(tellerCode);
+    this.verifyOffice(officeIdentifier);
+    this.verifyAccount(teller.getTellerAccountIdentifier());
+    this.verifyAccount(teller.getVaultAccountIdentifier());
+
+    this.commandGateway.process(new ChangeTellerCommand(officeIdentifier, teller));
+
+    return ResponseEntity.accepted().build();
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_MANAGEMENT)
+  @RequestMapping(
+      value = "/{tellerCode}/commands",
+      method = RequestMethod.POST,
+      consumes = MediaType.APPLICATION_JSON_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<Void> post(@PathVariable("officeIdentifier") final String officeIdentifier,
+                            @PathVariable("tellerCode") final String tellerCode,
+                            @RequestBody @Valid final TellerManagementCommand tellerManagementCommand) {
+    final Teller teller = this.verifyTeller(tellerCode);
+
+    if (tellerManagementCommand.getAmount() != null && tellerManagementCommand.getAmount() > teller.getCashdrawLimit()) {
+      throw ServiceException.badRequest("Adjustment exceeds cashdraw limit.");
+    }
+
+    final TellerManagementCommand.Action action = TellerManagementCommand.Action.valueOf(tellerManagementCommand.getAction());
+    switch (action) {
+      case OPEN:
+        if (!teller.getState().equals(Teller.State.CLOSED.name())) {
+          throw ServiceException.badRequest("Teller {0} is already active.", tellerCode);
+        }
+        this.verifyEmployee(tellerManagementCommand.getAssignedEmployeeIdentifier());
+        this.commandGateway.process(new OpenTellerCommand(tellerCode, tellerManagementCommand));
+        break;
+      case CLOSE:
+        if (teller.getState().equals(Teller.State.CLOSED.name())) {
+          throw ServiceException.badRequest("Teller {0} is already closed.", tellerCode);
+        }
+        this.commandGateway.process(new CloseTellerCommand(tellerCode, tellerManagementCommand));
+        break;
+      default:
+        throw ServiceException.badRequest("Unsupported teller command {0}.", action.name());
+    }
+
+    return ResponseEntity.accepted().build();
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_MANAGEMENT)
+  @RequestMapping(
+      value = "/{tellerCode}/balance",
+      method = RequestMethod.GET,
+      consumes = MediaType.ALL_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<TellerBalanceSheet> getBalance(@PathVariable("officeIdentifier") final String officeIdentifier,
+                                                @PathVariable("tellerCode") final String tellerCode) {
+    this.verifyOffice(officeIdentifier);
+    this.verifyTeller(tellerCode);
+
+    return ResponseEntity.ok(this.tellerManagementService.getBalance(tellerCode));
+  }
+
+  private void verifyAccount(final String accountIdentifier) {
+    if (!this.accountingService.accountExists(accountIdentifier)) {
+      throw ServiceException.badRequest("Account {0} not found.", accountIdentifier);
+    }
+  }
+
+  private void verifyEmployee(final String employeeIdentifier) {
+    if (!this.organizationService.employeeExists(employeeIdentifier)) {
+      throw ServiceException.badRequest("Employee {0} not found.", employeeIdentifier);
+    }
+  }
+
+  private void verifyOffice(final String officeIdentifier) {
+    if (!this.organizationService.officeExists(officeIdentifier)) {
+      throw ServiceException.badRequest("Office {0} not found.", officeIdentifier);
+    }
+  }
+
+  private Teller verifyTeller(final String tellerCode) {
+    final Optional<Teller> optionalTeller = this.tellerManagementService.findByIdentifier(tellerCode);
+    if (!optionalTeller.isPresent()) {
+      throw ServiceException.notFound("Teller {0} not found.", tellerCode);
+    }
+    return optionalTeller.get();
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/rest/TellerOperationRestController.java b/service/src/main/java/io/mifos/teller/service/rest/TellerOperationRestController.java
new file mode 100644
index 0000000..303428d
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/rest/TellerOperationRestController.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.rest;
+
+import io.mifos.accounting.api.v1.client.LedgerManager;
+import io.mifos.anubis.annotation.AcceptedTokenType;
+import io.mifos.anubis.annotation.Permittable;
+import io.mifos.core.command.gateway.CommandGateway;
+import io.mifos.core.lang.ServiceException;
+import io.mifos.deposit.api.v1.client.DepositAccountManager;
+import io.mifos.portfolio.api.v1.client.PortfolioManager;
+import io.mifos.teller.ServiceConstants;
+import io.mifos.teller.api.v1.PermittableGroupIds;
+import io.mifos.teller.api.v1.domain.TellerAuthentication;
+import io.mifos.teller.api.v1.domain.TellerTransaction;
+import io.mifos.teller.api.v1.domain.TellerTransactionCosts;
+import io.mifos.teller.service.internal.service.TellerManagementService;
+import io.mifos.teller.service.internal.service.TellerOperationService;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.util.Collections;
+import java.util.List;
+
+@RestController
+@RequestMapping("/teller/{tellerCode}")
+public class TellerOperationRestController {
+
+  private final Logger logger;
+  private final CommandGateway commandGateway;
+  private final TellerOperationService tellerOperationService;
+  private final TellerManagementService tellerManagementService;
+  private final LedgerManager ledgerManager;
+  private final DepositAccountManager depositAccountManager;
+  private final PortfolioManager portfolioManager;
+
+  @Autowired
+  public TellerOperationRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                                       final CommandGateway commandGateway,
+                                       final TellerOperationService tellerOperationService,
+                                       final TellerManagementService tellerManagementService,
+                                       final LedgerManager ledgerManager,
+                                       final DepositAccountManager depositAccountManager,
+                                       final PortfolioManager portfolioManager) {
+    this.logger = logger;
+    this.commandGateway = commandGateway;
+    this.tellerOperationService = tellerOperationService;
+    this.tellerManagementService = tellerManagementService;
+    this.ledgerManager = ledgerManager;
+    this.depositAccountManager = depositAccountManager;
+    this.portfolioManager = portfolioManager;
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_OPERATION)
+  @RequestMapping(
+      value = "/auth",
+      method = RequestMethod.POST,
+      consumes = MediaType.APPLICATION_JSON_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<Void> auth(@PathVariable("tellerCode") final String tellerCode,
+                            @RequestBody @Valid final TellerAuthentication tellerAuthentication) {
+    return ResponseEntity.accepted().build();
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_OPERATION)
+  @RequestMapping(
+      value = "",
+      method = RequestMethod.POST,
+      consumes = MediaType.APPLICATION_JSON_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<Void> post(@PathVariable("tellerCode") final String tellerCode,
+                            @RequestParam(value = "command", required = true) final String command) {
+    return ResponseEntity.accepted().build();
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_OPERATION)
+  @RequestMapping(
+      value = "/transactions",
+      method = RequestMethod.POST,
+      consumes = MediaType.APPLICATION_JSON_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<TellerTransactionCosts> post(@PathVariable("tellerCode") final String tellerCode,
+                                              @RequestBody @Valid final TellerTransaction tellerTransaction) {
+    throw ServiceException.notFound("Teller {0} not found.", tellerCode);
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_OPERATION)
+  @RequestMapping(
+      value = "/transactions/{identifier}",
+      method = RequestMethod.POST,
+      consumes = MediaType.APPLICATION_JSON_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<Void> confirm(@PathVariable("tellerCode") final String tellerCode,
+                               @PathVariable("identifier") final String tellerTransactionIdentifier,
+                               @RequestParam(value = "command", required = true) final String command) {
+    return ResponseEntity.accepted().build();
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_OPERATION)
+  @RequestMapping(
+      value = "/transactions",
+      method = RequestMethod.GET,
+      consumes = MediaType.ALL_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  @ResponseBody
+  ResponseEntity<List<TellerTransaction>> fetch(@PathVariable("tellerCode") final String tellerCode,
+                                                @RequestParam(value = "status", required = false) final String status) {
+    return ResponseEntity.ok(Collections.emptyList());
+  }
+}
diff --git a/service/src/main/java/io/mifos/teller/service/rest/TellerRestController.java b/service/src/main/java/io/mifos/teller/service/rest/TellerRestController.java
new file mode 100644
index 0000000..5518d93
--- /dev/null
+++ b/service/src/main/java/io/mifos/teller/service/rest/TellerRestController.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mifos.teller.service.rest;
+
+import io.mifos.anubis.annotation.AcceptedTokenType;
+import io.mifos.anubis.annotation.Permittable;
+import io.mifos.core.command.gateway.CommandGateway;
+import io.mifos.teller.ServiceConstants;
+import io.mifos.teller.service.internal.command.MigrationCommand;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/")
+public class TellerRestController {
+
+  private final Logger logger;
+  private final CommandGateway commandGateway;
+
+  public TellerRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+                              final CommandGateway commandGateway) {
+    super();
+    this.logger = logger;
+    this.commandGateway = commandGateway;
+  }
+
+  @Permittable(value = AcceptedTokenType.SYSTEM)
+  @RequestMapping(
+      value = "/initialize",
+      method = RequestMethod.POST,
+      consumes = MediaType.ALL_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE
+  )
+  public
+  @ResponseBody
+  ResponseEntity<Void> initialize() {
+    this.commandGateway.process(new MigrationCommand());
+    return ResponseEntity.accepted().build();
+  }
+}
diff --git a/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql b/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
index fb1b54e..717b5da 100644
--- a/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
+++ b/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
@@ -14,9 +14,21 @@
 -- limitations under the License.
 --
 
-CREATE TABLE template_samples (
+CREATE TABLE tajet_teller (
   id BIGINT NOT NULL AUTO_INCREMENT,
-  identifier VARCHAR(8) NOT NULL,
-  payload VARCHAR(512) NULL,
-  CONSTRAINT template_samples_pk PRIMARY KEY (id)
+  identifier                   VARCHAR(32)     NOT NULL,
+  a_password                   VARCHAR(4096)  NOT NULL,
+  a_salt                       VARCHAR(4069)  NOT NULL,
+  office_identifier            VARCHAR(32)    NOT NULL,
+  cashdraw_limit               NUMERIC(15, 5) NOT NULL,
+  teller_account_identifier    VARCHAR(32)    NOT NULL,
+  vault_account_identifier     VARCHAR(32)    NOT NULL,
+  assigned_employee_identifier VARCHAR(32)    NULL,
+  a_state                      VARCHAR(256)   NOT NULL,
+  created_on                   TIMESTAMP(3)   NOT NULL,
+  created_by                   VARCHAR(32)    NOT NULL,
+  last_modified_on             TIMESTAMP(3)   NULL,
+  last_modified_by             VARCHAR(32)    NULL,
+  CONSTRAINT tajet_teller_pk PRIMARY KEY (id),
+  CONSTRAINT tajet_teller_identifier_uq UNIQUE (identifier)
 );
diff --git a/shared.gradle b/shared.gradle
index 81135ee..4006bc4 100644
--- a/shared.gradle
+++ b/shared.gradle
@@ -9,7 +9,12 @@ ext.versions = [
         frameworkmariadb : '0.1.0-BUILD-SNAPSHOT',
         frameworkcommand : '0.1.0-BUILD-SNAPSHOT',
         frameworktest: '0.1.0-BUILD-SNAPSHOT',
+        frameworkcrypto: '0.1.0-BUILD-SNAPSHOT',
         frameworkanubis: '0.1.0-BUILD-SNAPSHOT',
+        frameworkoffice: '0.1.0-BUILD-SNAPSHOT',
+        frameworkaccounting: '0.1.0-BUILD-SNAPSHOT',
+        frameworkdeposit: '0.1.0-BUILD-SNAPSHOT',
+        frameworkportfolio: '0.1.0-BUILD-SNAPSHOT',
         validator : '5.3.0.Final'
 ]
 

-- 
To stop receiving notification emails like this one, please contact
myrle@apache.org.

Mime
View raw message