Setting start and end of term and payment size correctly for imported loans.
diff --git a/api/src/main/java/io/mifos/portfolio/api/v1/PermittableGroupIds.java b/api/src/main/java/io/mifos/portfolio/api/v1/PermittableGroupIds.java
index 05d282b..fbe7949 100644
--- a/api/src/main/java/io/mifos/portfolio/api/v1/PermittableGroupIds.java
+++ b/api/src/main/java/io/mifos/portfolio/api/v1/PermittableGroupIds.java
@@ -25,5 +25,5 @@
   String PRODUCT_MANAGEMENT = "portfolio__v1__products";
   String CASE_MANAGEMENT = "portfolio__v1__case";
   String CASE_DOCUMENT_MANAGEMENT = "portfolio__v1__case_documents";
-  String CASE_IMPORT = "portfolio__v1__case_import";
+  String CASE_STATUS = "portfolio__v1__case_status";
 }
diff --git a/api/src/main/java/io/mifos/portfolio/api/v1/client/PortfolioManager.java b/api/src/main/java/io/mifos/portfolio/api/v1/client/PortfolioManager.java
index a5da9a3..ab593a7 100644
--- a/api/src/main/java/io/mifos/portfolio/api/v1/client/PortfolioManager.java
+++ b/api/src/main/java/io/mifos/portfolio/api/v1/client/PortfolioManager.java
@@ -308,6 +308,15 @@
       @PathVariable("caseidentifier") final String caseIdentifier);
 
   @RequestMapping(
+      value = "/products/{productidentifier}/cases/{caseidentifier}/status",
+      method = RequestMethod.GET,
+      produces = MediaType.ALL_VALUE,
+      consumes = MediaType.APPLICATION_JSON_VALUE)
+  CaseStatus getCaseStatus(
+      @PathVariable("productidentifier") final String productIdentifier,
+      @PathVariable("caseidentifier") final String caseIdentifier);
+
+  @RequestMapping(
       value = "/products/{productidentifier}/cases/{caseidentifier}",
       method = RequestMethod.PUT,
       produces = MediaType.APPLICATION_JSON_VALUE,
diff --git a/api/src/main/java/io/mifos/portfolio/api/v1/domain/CaseStatus.java b/api/src/main/java/io/mifos/portfolio/api/v1/domain/CaseStatus.java
new file mode 100644
index 0000000..3aa0e48
--- /dev/null
+++ b/api/src/main/java/io/mifos/portfolio/api/v1/domain/CaseStatus.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017 Kuelap, Inc.
+ *
+ * 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.portfolio.api.v1.domain;
+
+import java.util.Objects;
+
+/**
+ * @author Myrle Krantz
+ */
+public class CaseStatus {
+  private String startOfTerm;
+  private String endOfTerm;
+  private Case.State currentState; //The same as Case.currentState.
+
+  public CaseStatus() {
+  }
+
+  public String getStartOfTerm() {
+    return startOfTerm;
+  }
+
+  public void setStartOfTerm(String startOfTerm) {
+    this.startOfTerm = startOfTerm;
+  }
+
+  public String getEndOfTerm() {
+    return endOfTerm;
+  }
+
+  public void setEndOfTerm(String endOfTerm) {
+    this.endOfTerm = endOfTerm;
+  }
+
+  public String getCurrentState() {
+    return currentState == null ? null : currentState.name();
+  }
+
+  public void setCurrentState(String currentState) {
+    this.currentState = Case.State.valueOf(currentState);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    CaseStatus that = (CaseStatus) o;
+    return Objects.equals(startOfTerm, that.startOfTerm) &&
+        Objects.equals(endOfTerm, that.endOfTerm) &&
+        currentState == that.currentState;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(startOfTerm, endOfTerm, currentState);
+  }
+
+  @Override
+  public String toString() {
+    return "CaseStatus{" +
+        "startOfTerm='" + startOfTerm + '\'' +
+        ", endOfTerm='" + endOfTerm + '\'' +
+        ", currentState=" + currentState +
+        '}';
+  }
+}
diff --git a/api/src/main/java/io/mifos/portfolio/api/v1/domain/ImportParameters.java b/api/src/main/java/io/mifos/portfolio/api/v1/domain/ImportParameters.java
index a301d8e..1a80bdf 100644
--- a/api/src/main/java/io/mifos/portfolio/api/v1/domain/ImportParameters.java
+++ b/api/src/main/java/io/mifos/portfolio/api/v1/domain/ImportParameters.java
@@ -22,6 +22,7 @@
 import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -37,8 +38,7 @@
   private BigDecimal paymentSize;
 
   @Valid
-  @NotNull
-  private BigDecimal currentBalance;
+  private Map<String, BigDecimal> currentBalances;
 
   @ValidLocalDateTimeString
   @NotNull
@@ -70,13 +70,12 @@
     this.paymentSize = paymentSize;
   }
 
-  @Nullable
-  public BigDecimal getCurrentBalance() {
-    return currentBalance;
+  public Map<String, BigDecimal> getCurrentBalances() {
+    return currentBalances;
   }
 
-  public void setCurrentBalance(@Nullable BigDecimal currentBalance) {
-    this.currentBalance = currentBalance;
+  public void setCurrentBalances(Map<String, BigDecimal> currentBalances) {
+    this.currentBalances = currentBalances;
   }
 
   public String getStartOfTerm() {
@@ -110,13 +109,13 @@
     ImportParameters that = (ImportParameters) o;
     return Objects.equals(caseAccountAssignments, that.caseAccountAssignments) &&
         Objects.equals(paymentSize, that.paymentSize) &&
-        Objects.equals(currentBalance, that.currentBalance) &&
+        Objects.equals(currentBalances, that.currentBalances) &&
         Objects.equals(startOfTerm, that.startOfTerm);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(caseAccountAssignments, paymentSize, currentBalance, startOfTerm);
+    return Objects.hash(caseAccountAssignments, paymentSize, currentBalances, startOfTerm);
   }
 
   @Override
@@ -124,7 +123,7 @@
     return "ImportParameters{" +
         "caseAccountAssignments=" + caseAccountAssignments +
         ", paymentSize=" + paymentSize +
-        ", currentBalance=" + currentBalance +
+        ", currentBalances=" + currentBalances +
         ", startOfTerm='" + startOfTerm + '\'' +
         ", createdOn='" + createdOn + '\'' +
         ", createdBy='" + createdBy + '\'' +
diff --git a/api/src/test/java/io/mifos/portfolio/api/v1/domain/ImportParametersTest.java b/api/src/test/java/io/mifos/portfolio/api/v1/domain/ImportParametersTest.java
index 81ebf11..408ba16 100644
--- a/api/src/test/java/io/mifos/portfolio/api/v1/domain/ImportParametersTest.java
+++ b/api/src/test/java/io/mifos/portfolio/api/v1/domain/ImportParametersTest.java
@@ -18,6 +18,7 @@
 import io.mifos.core.lang.DateConverter;
 import io.mifos.core.test.domain.ValidationTest;
 import io.mifos.core.test.domain.ValidationTestCase;
+import io.mifos.individuallending.api.v1.domain.product.AccountDesignators;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
@@ -44,7 +45,7 @@
     final ImportParameters ret = new ImportParameters();
     ret.setCaseAccountAssignments(Collections.emptyList());
     ret.setPaymentSize(BigDecimal.TEN);
-    ret.setCurrentBalance(BigDecimal.TEN.multiply(BigDecimal.TEN));
+    ret.setCurrentBalances(Collections.singletonMap(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, BigDecimal.TEN.multiply(BigDecimal.TEN)));
     ret.setStartOfTerm(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
     ret.setCreatedOn(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
     return ret;
@@ -61,8 +62,8 @@
         .adjustment(x -> x.setPaymentSize(null))
         .valid(false));
     ret.add(new ValidationTestCase<ImportParameters>("nullCurrentBalance")
-        .adjustment(x -> x.setCurrentBalance(null))
-        .valid(false));
+        .adjustment(x -> x.setCurrentBalances(null))
+        .valid(true));
     return ret;
   }
 
diff --git a/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java b/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
index 4665c8b..16f932a 100644
--- a/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
+++ b/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
@@ -307,15 +307,18 @@
     private final String ledgerIdentifer;
     private final String accountDesignator;
     private final AccountType type;
+    private final BigDecimal balance;
     private Account matchedArgument;
 
     private AccountMatcher(
         final String ledgerIdentifier,
         final String accountDesignator,
-        final AccountType type) {
+        final AccountType type,
+        final BigDecimal balance) {
       this.ledgerIdentifer = ledgerIdentifier;
       this.accountDesignator = accountDesignator;
       this.type = type;
+      this.balance = balance;
       this.matchedArgument = null; //Set when matches called and returns true.
     }
 
@@ -331,7 +334,7 @@
       final boolean ret = checkedArgument.getLedger().equals(ledgerIdentifer) &&
           checkedArgument.getIdentifier().contains(accountDesignator) &&
           checkedArgument.getType().equals(type.name()) &&
-          checkedArgument.getBalance() == 0.0;
+          checkedArgument.getBalance().compareTo(balance.doubleValue()) == 0;
 
       if (ret)
         matchedArgument = checkedArgument;
@@ -354,6 +357,7 @@
           "ledgerIdentifer='" + ledgerIdentifer + '\'' +
           ", accountDesignator='" + accountDesignator + '\'' +
           ", type=" + type +
+          ", balance=" + balance +
           '}';
     }
   }
@@ -590,8 +594,9 @@
       final LedgerManager ledgerManager,
       final String ledgerIdentifier,
       final String accountDesignator,
-      final AccountType type) {
-    final AccountMatcher specifiesCorrectAccount = new AccountMatcher(ledgerIdentifier, accountDesignator, type);
+      final AccountType type,
+      final BigDecimal balance) {
+    final AccountMatcher specifiesCorrectAccount = new AccountMatcher(ledgerIdentifier, accountDesignator, type, balance);
     Mockito.verify(ledgerManager).createAccount(AdditionalMatchers.and(argThat(isValid()), argThat(specifiesCorrectAccount)));
     return specifiesCorrectAccount.getMatchedArgument().getIdentifier();
   }
diff --git a/component-test/src/main/java/io/mifos/portfolio/TestAccountingInteractionInLoanWorkflow.java b/component-test/src/main/java/io/mifos/portfolio/TestAccountingInteractionInLoanWorkflow.java
index 15ab9f4..e4489ff 100644
--- a/component-test/src/main/java/io/mifos/portfolio/TestAccountingInteractionInLoanWorkflow.java
+++ b/component-test/src/main/java/io/mifos/portfolio/TestAccountingInteractionInLoanWorkflow.java
@@ -96,10 +96,9 @@
 
   @Test
   public void workflowImportingLoanFromExternalSystem() throws InterruptedException {
-    final LocalDateTime today = midnightToday();
     step1CreateProduct();
     step2CreateCase();
-    step3IImportCase(today);
+    step3IImportCase(LocalDateTime.of(2017,11,8,0,0));
   }
 
   @Test
@@ -474,22 +473,46 @@
   private void step3IImportCase(final LocalDateTime forDateTime) throws InterruptedException {
     logger.info("step3IImportCase");
 
+    final BigDecimal expectedNextRepaymentAmount = BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS);
+    final BigDecimal currentPrincipal = BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS);
+
     final ImportParameters importParameters = new ImportParameters();
     importParameters.setCaseAccountAssignments(Collections.singletonList(assignEntryToTeller()));
-    importParameters.setPaymentSize(BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));
+    importParameters.setPaymentSize(expectedNextRepaymentAmount);
     importParameters.setCreatedOn(DateConverter.toIsoString(forDateTime));
-    importParameters.setCurrentBalance(BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS));
+    importParameters.setCurrentBalances(Collections.singletonMap(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, currentPrincipal));
     importParameters.setStartOfTerm(DateConverter.toIsoString(forDateTime));
     portfolioManager.executeImportCommand(product.getIdentifier(), customerCase.getIdentifier(), importParameters);
 
     Assert.assertTrue(eventRecorder.wait(IndividualLoanEventConstants.IMPORT_INDIVIDUALLOAN_CASE, new IndividualLoanCommandEvent(product.getIdentifier(), customerCase.getIdentifier(), DateConverter.toIsoString(forDateTime))));
 
-    //TODO: check payment size, start of term, and end of term and account assignments.
+    final String customerLoanLedgerIdentifier = AccountingFixture.verifyLedgerCreation(
+        ledgerManager,
+        AccountingFixture.CUSTOMER_LOAN_LEDGER_IDENTIFIER,
+        AccountType.ASSET);
 
-    final Case changedCase = portfolioManager.getCase(product.getIdentifier(), customerCase.getIdentifier());
-    Assert.assertEquals(Case.State.ACTIVE.name(), changedCase.getCurrentState());
+    customerLoanPrincipalIdentifier =
+        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, AccountType.ASSET, currentPrincipal);
+    customerLoanInterestIdentifier =
+        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_INTEREST, AccountType.ASSET, BigDecimal.ZERO);
+    customerLoanFeeIdentifier =
+        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_FEES, AccountType.ASSET, BigDecimal.ZERO);
+
+    final CaseStatus changedCaseStatus = portfolioManager.getCaseStatus(product.getIdentifier(), customerCase.getIdentifier());
+    Assert.assertEquals(Case.State.ACTIVE.name(), changedCaseStatus.getCurrentState());
+    Assert.assertEquals(DateConverter.toIsoString(forDateTime), changedCaseStatus.getStartOfTerm());
+    Assert.assertEquals("2018-02-08T00:00:00Z", changedCaseStatus.getEndOfTerm());
     checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier(),
         Action.APPLY_INTEREST, Action.MARK_LATE, Action.ACCEPT_PAYMENT, Action.DISBURSE, Action.MARK_IN_ARREARS, Action.WRITE_OFF, Action.CLOSE);
+
+    expectedCurrentPrincipal = currentPrincipal;
+    updateBalanceMock();
+
+    final BigDecimal nextRepaymentAmount = findNextRepaymentAmount(forDateTime);
+    Assert.assertEquals(expectedNextRepaymentAmount, nextRepaymentAmount);
+
+
+    //TODO: check account assignments.
   }
 
 
@@ -547,11 +570,11 @@
         AccountType.ASSET);
 
     customerLoanPrincipalIdentifier =
-        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, AccountType.ASSET);
+        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, AccountType.ASSET, BigDecimal.ZERO);
     customerLoanInterestIdentifier =
-        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_INTEREST, AccountType.ASSET);
+        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_INTEREST, AccountType.ASSET, BigDecimal.ZERO);
     customerLoanFeeIdentifier =
-        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_FEES, AccountType.ASSET);
+        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_FEES, AccountType.ASSET, BigDecimal.ZERO);
 
     expectedCurrentPrincipal = BigDecimal.ZERO;
     interestAccrued = BigDecimal.ZERO;
diff --git a/service/src/main/java/io/mifos/individuallending/internal/command/handler/IndividualLoanCommandHandler.java b/service/src/main/java/io/mifos/individuallending/internal/command/handler/IndividualLoanCommandHandler.java
index 3e1216f..e9db1cf 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/command/handler/IndividualLoanCommandHandler.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/command/handler/IndividualLoanCommandHandler.java
@@ -49,6 +49,7 @@
 
 import javax.annotation.Nullable;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.util.Collections;
@@ -174,15 +175,19 @@
   @EventEmitter(
       selectorName = IndividualLoanEventConstants.SELECTOR_NAME,
       selectorValue = IndividualLoanEventConstants.IMPORT_INDIVIDUALLOAN_CASE)
-  public IndividualLoanCommandEvent process(final ImportCommand command) {
+  public IndividualLoanCommandEvent process(final ImportCommand command) throws InterruptedException {
     final String productIdentifier = command.getProductIdentifier();
     final String caseIdentifier = command.getCaseIdentifier();
     final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
         productIdentifier, caseIdentifier, command.getImportParameters().getCaseAccountAssignments());
-    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.OPEN);
+    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.IMPORT);
 
     checkIfTasksAreOutstanding(dataContextOfAction, Action.IMPORT);
 
+    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
+        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+    createAccounts(dataContextOfAction, designatorToAccountIdentifierMapper, command.getImportParameters().getCurrentBalances());
+
     final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();
 
     recordCommand(
@@ -191,14 +196,19 @@
         Action.IMPORT,
         Optional.empty());
 
+
+    final LocalDate startOfTerm = DateConverter.fromIsoString(command.getImportParameters().getStartOfTerm()).toLocalDate();
+    final LocalDateTime endOfTerm = ScheduledActionHelpers.getRoughEndDate(startOfTerm, dataContextOfAction.getCaseParameters())
+        .atTime(LocalTime.MIDNIGHT);
+    customerCase.setStartOfTerm(startOfTerm.atTime(LocalTime.MIDNIGHT));
+    customerCase.setEndOfTerm(endOfTerm);
     customerCase.setCurrentState(Case.State.ACTIVE.name());
     caseRepository.save(customerCase);
 
     final CaseParametersEntity caseParameters = dataContextOfAction.getCaseParametersEntity();
     caseParameters.setPaymentSize(command.getImportParameters().getPaymentSize());
     caseParametersRepository.save(caseParameters);
-    //TODO: find end of term.
-    //TODO: persist start of term.
+
     //TODO: create/connect to accounts in account assignments.
 
     return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, command.getImportParameters().getCreatedOn());
@@ -279,40 +289,8 @@
 
     final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
             = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+    createAccounts(dataContextOfAction, designatorToAccountIdentifierMapper, Collections.emptyMap());
 
-    //Create the needed account assignments for groups and persist them for the case.
-    try {
-      designatorToAccountIdentifierMapper.getGroupsNeedingLedgers()
-          .map(groupNeedingLedger -> {
-            try {
-              final String createdLedgerIdentifier = accountingAdapter.createLedger(
-                  dataContextOfAction.getCaseParametersEntity().getCustomerIdentifier(),
-                  groupNeedingLedger.getGroupName(),
-                  groupNeedingLedger.getParentLedger());
-              return new AccountAssignment(groupNeedingLedger.getGroupName(), createdLedgerIdentifier);
-            } catch (InterruptedException e) {
-              throw new InterruptedInALambdaException(e);
-            }
-          })
-          .map(accountAssignment -> CaseMapper.map(accountAssignment, dataContextOfAction.getCustomerCaseEntity()))
-          .forEach(caseAccountAssignmentEntity -> dataContextOfAction.getCustomerCaseEntity().getAccountAssignments().add(caseAccountAssignmentEntity));
-    }
-    catch (final InterruptedInALambdaException e) {
-      e.throwWrappedException();
-    }
-
-    //Create the needed account assignments and persist them for the case.
-    designatorToAccountIdentifierMapper.getLedgersNeedingAccounts()
-        .map(ledger ->
-            new AccountAssignment(ledger.getDesignator(),
-                accountingAdapter.createCaseAccountForLedgerAssignment(
-                    dataContextOfAction.getCaseParametersEntity().getCustomerIdentifier(),
-                    ledger)))
-        .map(accountAssignment -> CaseMapper.map(accountAssignment, dataContextOfAction.getCustomerCaseEntity()))
-        .forEach(caseAccountAssignmentEntity ->
-            dataContextOfAction.getCustomerCaseEntity().getAccountAssignments().add(caseAccountAssignmentEntity)
-        );
-    caseRepository.save(dataContextOfAction.getCustomerCaseEntity());
 
     final RealRunningBalances runningBalances = new RealRunningBalances(
         accountingAdapter,
@@ -381,11 +359,12 @@
         Action.DISBURSE,
         transactionUniqueifier);
 
-    //Only move to new state if book charges command was accepted.
+    //TODO: Only move to new state if book charges command was accepted.
     if (Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()) != Case.State.ACTIVE) {
-      final LocalDateTime endOfTerm
-          = ScheduledActionHelpers.getRoughEndDate(DateConverter.fromIsoString(command.getCommand().getCreatedOn()).toLocalDate(), dataContextOfAction.getCaseParameters())
+      final LocalDate startOfTerm = DateConverter.fromIsoString(command.getCommand().getCreatedOn()).toLocalDate();
+      final LocalDateTime endOfTerm = ScheduledActionHelpers.getRoughEndDate(startOfTerm, dataContextOfAction.getCaseParameters())
           .atTime(LocalTime.MIDNIGHT);
+      customerCase.setStartOfTerm(startOfTerm.atTime(LocalTime.MIDNIGHT));
       customerCase.setEndOfTerm(endOfTerm);
       customerCase.setCurrentState(Case.State.ACTIVE.name());
       caseRepository.save(customerCase);
@@ -715,6 +694,48 @@
     return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, command.getCommand().getCreatedOn());
   }
 
+  private void createAccounts(
+      final DataContextOfAction dataContextOfAction,
+      final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper,
+      final Map<String, BigDecimal> currentBalances) throws InterruptedException
+  {
+    //Create the needed account assignments for groups and persist them for the case.
+    try {
+      designatorToAccountIdentifierMapper.getGroupsNeedingLedgers()
+          .map(groupNeedingLedger -> {
+            try {
+              final String createdLedgerIdentifier = accountingAdapter.createLedger(
+                  dataContextOfAction.getCaseParametersEntity().getCustomerIdentifier(),
+                  groupNeedingLedger.getGroupName(),
+                  groupNeedingLedger.getParentLedger());
+              return new AccountAssignment(groupNeedingLedger.getGroupName(), createdLedgerIdentifier);
+            } catch (InterruptedException e) {
+              throw new InterruptedInALambdaException(e);
+            }
+          })
+          .map(accountAssignment -> CaseMapper.map(accountAssignment, dataContextOfAction.getCustomerCaseEntity()))
+          .forEach(caseAccountAssignmentEntity -> dataContextOfAction.getCustomerCaseEntity().getAccountAssignments().add(caseAccountAssignmentEntity));
+    }
+    catch (final InterruptedInALambdaException e) {
+      e.throwWrappedException();
+    }
+
+    //Create the needed account assignments and persist them for the case.
+    designatorToAccountIdentifierMapper.getLedgersNeedingAccounts()
+        .map(ledger -> {
+          final BigDecimal currentBalance = currentBalances.getOrDefault(ledger.getDesignator(), BigDecimal.ZERO);
+          return new AccountAssignment(ledger.getDesignator(),
+              accountingAdapter.createCaseAccountForLedgerAssignment(
+                  dataContextOfAction.getCaseParametersEntity().getCustomerIdentifier(),
+                  ledger,
+                  currentBalance));})
+        .map(accountAssignment -> CaseMapper.map(accountAssignment, dataContextOfAction.getCustomerCaseEntity()))
+        .forEach(caseAccountAssignmentEntity ->
+            dataContextOfAction.getCustomerCaseEntity().getAccountAssignments().add(caseAccountAssignmentEntity)
+        );
+    caseRepository.save(dataContextOfAction.getCustomerCaseEntity());
+  }
+
   private Map<String, BigDecimal> getRequestedChargeAmounts(final @Nullable List<CostComponent> costComponents) {
     if (costComponents == null)
       return Collections.emptyMap();
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AvailableRunningBalancesWithLimits.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AvailableRunningBalancesWithLimits.java
index 3f8a072..046106a 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AvailableRunningBalancesWithLimits.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AvailableRunningBalancesWithLimits.java
@@ -15,7 +15,6 @@
  */
 package io.mifos.individuallending.internal.service.costcomponent;
 
-import io.mifos.individuallending.internal.service.DataContextOfAction;
 import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
 
 import java.math.BigDecimal;
@@ -61,7 +60,7 @@
   }
 
   @Override
-  public Optional<LocalDateTime> getStartOfTerm(final DataContextOfAction dataContextOfAction) {
-    return decoratedRunningBalances.getStartOfTerm(dataContextOfAction);
+  public Optional<LocalDateTime> getStartOfTerm() {
+    return decoratedRunningBalances.getStartOfTerm();
   }
 }
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RealRunningBalances.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RealRunningBalances.java
index 30b05be..a394f2c 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RealRunningBalances.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RealRunningBalances.java
@@ -89,13 +89,22 @@
   }
 
   @Override
-  public Optional<LocalDateTime> getStartOfTerm(final DataContextOfAction dataContextOfAction) {
+  public Optional<LocalDateTime> getStartOfTerm() {
     if (!startOfTerm.isPresent()) {
+      final LocalDateTime persistedStartOfTerm = dataContextOfAction.getCustomerCaseEntity().getStartOfTerm();
+      if (persistedStartOfTerm != null) {
+        this.startOfTerm = Optional.of(persistedStartOfTerm);
+        return this.startOfTerm;
+      }
       final String customerLoanPrincipalAccountIdentifier = designatorToAccountIdentifierMapper.mapOrThrow(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL);
 
       this.startOfTerm = accountingAdapter.getDateOfOldestEntryContainingMessage(
           customerLoanPrincipalAccountIdentifier,
           dataContextOfAction.getMessageForCharge(Action.DISBURSE));
+
+      //Moving start of term persistence from accounting to the portfolio db.  Opportunistic migration only right now.
+      startOfTerm.ifPresent(startOfTermPersistedInAccounting ->
+          dataContextOfAction.getCustomerCaseEntity().setStartOfTerm(startOfTermPersistedInAccounting));
     }
 
     return this.startOfTerm;
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RunningBalances.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RunningBalances.java
index affd152..b18edaf 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RunningBalances.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RunningBalances.java
@@ -60,10 +60,10 @@
   BigDecimal getAccruedBalanceForCharge(
       final ChargeDefinition chargeDefinition);
 
-  Optional<LocalDateTime> getStartOfTerm(final DataContextOfAction dataContextOfAction);
+  Optional<LocalDateTime> getStartOfTerm();
 
   default LocalDateTime getStartOfTermOrThrow(final DataContextOfAction dataContextOfAction) {
-    return this.getStartOfTerm(dataContextOfAction)
+    return this.getStartOfTerm()
         .orElseThrow(() -> ServiceException.internalError(
             "Start of term for loan ''{0}'' could not be acquired from accounting.",
             dataContextOfAction.getCompoundIdentifer()));
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/SimulatedRunningBalances.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/SimulatedRunningBalances.java
index cf7d47c..05505fa 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/SimulatedRunningBalances.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/SimulatedRunningBalances.java
@@ -16,7 +16,6 @@
 
 package io.mifos.individuallending.internal.service.costcomponent;
 
-import io.mifos.individuallending.internal.service.DataContextOfAction;
 import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
 
 import java.math.BigDecimal;
@@ -54,7 +53,7 @@
   }
 
   @Override
-  public Optional<LocalDateTime> getStartOfTerm(final DataContextOfAction dataContextOfAction) {
+  public Optional<LocalDateTime> getStartOfTerm() {
     return Optional.ofNullable(startOfTerm);
   }
 
diff --git a/service/src/main/java/io/mifos/portfolio/service/internal/mapper/CaseMapper.java b/service/src/main/java/io/mifos/portfolio/service/internal/mapper/CaseMapper.java
index 2ffcbe8..e742ce3 100644
--- a/service/src/main/java/io/mifos/portfolio/service/internal/mapper/CaseMapper.java
+++ b/service/src/main/java/io/mifos/portfolio/service/internal/mapper/CaseMapper.java
@@ -19,6 +19,7 @@
 import io.mifos.core.lang.DateConverter;
 import io.mifos.portfolio.api.v1.domain.AccountAssignment;
 import io.mifos.portfolio.api.v1.domain.Case;
+import io.mifos.portfolio.api.v1.domain.CaseStatus;
 import io.mifos.portfolio.service.internal.repository.CaseAccountAssignmentEntity;
 import io.mifos.portfolio.service.internal.repository.CaseEntity;
 
@@ -49,6 +50,18 @@
     return ret;
   }
 
+  public static CaseStatus mapToStatus(final CaseEntity caseEntity) {
+    final CaseStatus ret = new CaseStatus();
+
+    ret.setCurrentState(caseEntity.getCurrentState());
+    if (caseEntity.getStartOfTerm() != null)
+      ret.setStartOfTerm(DateConverter.toIsoString(caseEntity.getStartOfTerm()));
+    if (caseEntity.getEndOfTerm() != null)
+      ret.setEndOfTerm(DateConverter.toIsoString(caseEntity.getEndOfTerm()));
+
+    return ret;
+  }
+
   public static AccountAssignment mapAccountAssignmentEntity(final CaseAccountAssignmentEntity instance) {
     final AccountAssignment ret = new AccountAssignment();
 
diff --git a/service/src/main/java/io/mifos/portfolio/service/internal/repository/CaseEntity.java b/service/src/main/java/io/mifos/portfolio/service/internal/repository/CaseEntity.java
index 39a4ee7..56d62bc 100644
--- a/service/src/main/java/io/mifos/portfolio/service/internal/repository/CaseEntity.java
+++ b/service/src/main/java/io/mifos/portfolio/service/internal/repository/CaseEntity.java
@@ -54,6 +54,10 @@
   @Column(name = "current_state", nullable = false)
   private String currentState;
 
+  @Column(name = "start_of_term")
+  @Convert(converter = LocalDateTimeConverter.class)
+  @Nullable private LocalDateTime startOfTerm;
+
   @Column(name = "end_of_term")
   @Convert(converter = LocalDateTimeConverter.class)
   @Nullable private LocalDateTime endOfTerm;
@@ -131,6 +135,15 @@
     this.currentState = currentState;
   }
 
+  @Nullable
+  public LocalDateTime getStartOfTerm() {
+    return startOfTerm;
+  }
+
+  public void setStartOfTerm(@Nullable LocalDateTime startOfTerm) {
+    this.startOfTerm = startOfTerm;
+  }
+
   public LocalDateTime getEndOfTerm() {
     return endOfTerm;
   }
diff --git a/service/src/main/java/io/mifos/portfolio/service/internal/service/CaseService.java b/service/src/main/java/io/mifos/portfolio/service/internal/service/CaseService.java
index 414d38e..48db85c 100644
--- a/service/src/main/java/io/mifos/portfolio/service/internal/service/CaseService.java
+++ b/service/src/main/java/io/mifos/portfolio/service/internal/service/CaseService.java
@@ -18,6 +18,7 @@
 import io.mifos.core.lang.ServiceException;
 import io.mifos.portfolio.api.v1.domain.Case;
 import io.mifos.portfolio.api.v1.domain.CasePage;
+import io.mifos.portfolio.api.v1.domain.CaseStatus;
 import io.mifos.portfolio.api.v1.domain.Payment;
 import io.mifos.portfolio.service.internal.mapper.CaseMapper;
 import io.mifos.portfolio.service.internal.pattern.PatternFactoryRegistry;
@@ -95,6 +96,12 @@
             .flatMap(caseEntity -> map(caseEntity, minorCurrencyUnitDigits));
   }
 
+  public Optional<CaseStatus> findStatusByIdentifier(final String productIdentifier, final String caseIdentifier)
+  {
+    return caseRepository.findByProductIdentifierAndIdentifier(productIdentifier, caseIdentifier)
+        .map(CaseMapper::mapToStatus);
+  }
+
   public Set<String> getNextActionsForCase(final String productIdentifier, final String caseIdentifier) {
     final PatternFactory pattern = getPatternFactoryOrThrow(productIdentifier);
 
@@ -109,8 +116,8 @@
 
   private Optional<Case> map(final CaseEntity caseEntity, final int minorCurrencyUnitDigits) {
     return getPatternFactory(caseEntity.getProductIdentifier())
-            .flatMap(x -> x.getParameters(caseEntity.getId(), minorCurrencyUnitDigits))
-            .map(x -> CaseMapper.map(caseEntity, x));
+        .flatMap(x -> x.getParameters(caseEntity.getId(), minorCurrencyUnitDigits))
+        .map(x -> CaseMapper.map(caseEntity, x));
   }
 
   private PatternFactory getPatternFactoryOrThrow(final String productIdentifier) {
diff --git a/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java b/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
index 158ec90..651497b 100644
--- a/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
+++ b/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
@@ -272,12 +272,15 @@
             productIdentifier, accountDesignator, ledgerIdentifier));
   }
 
-  public String createCaseAccountForLedgerAssignment(final String customerIdentifier, final AccountAssignment ledgerAssignment) {
+  public String createCaseAccountForLedgerAssignment(
+      final String customerIdentifier,
+      final AccountAssignment ledgerAssignment,
+      final BigDecimal currentBalance) {
     final Ledger ledger = ledgerManager.findLedger(ledgerAssignment.getLedgerIdentifier());
     final AccountPage accountsOfLedger = ledgerManager.fetchAccountsOfLedger(ledger.getIdentifier(), null, null, null, null);
 
     final Account generatedAccount = new Account();
-    generatedAccount.setBalance(0.0);
+    generatedAccount.setBalance(currentBalance.doubleValue());
     generatedAccount.setType(ledger.getType());
     generatedAccount.setState(Account.State.OPEN.name());
     long guestimatedAccountIndex = accountsOfLedger.getTotalElements() + 1;
diff --git a/service/src/main/java/io/mifos/portfolio/service/rest/CaseRestController.java b/service/src/main/java/io/mifos/portfolio/service/rest/CaseRestController.java
index 52da934..7a6b72b 100644
--- a/service/src/main/java/io/mifos/portfolio/service/rest/CaseRestController.java
+++ b/service/src/main/java/io/mifos/portfolio/service/rest/CaseRestController.java
@@ -132,12 +132,27 @@
           consumes = MediaType.ALL_VALUE,
           produces = MediaType.APPLICATION_JSON_VALUE)
   public @ResponseBody Case getCase(
-          @PathVariable("productidentifier") final String productIdentifier,
-          @PathVariable("caseidentifier") final String caseIdentifier)
+      @PathVariable("productidentifier") final String productIdentifier,
+      @PathVariable("caseidentifier") final String caseIdentifier)
   {
     return caseService.findByIdentifier(productIdentifier, caseIdentifier)
-            .orElseThrow(() -> ServiceException.notFound(
-                    "Instance with identifier " + productIdentifier + "." + caseIdentifier + " doesn't exist."));
+        .orElseThrow(() -> ServiceException.notFound(
+            "Instance with identifier ''{0}.{1}'' doesn''t exist.", productIdentifier, caseIdentifier));
+  }
+
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.CASE_STATUS)
+  @RequestMapping(
+      value = "{caseidentifier}/status",
+      method = RequestMethod.GET,
+      consumes = MediaType.ALL_VALUE,
+      produces = MediaType.APPLICATION_JSON_VALUE)
+  public @ResponseBody CaseStatus getCaseStatus(
+      @PathVariable("productidentifier") final String productIdentifier,
+      @PathVariable("caseidentifier") final String caseIdentifier)
+  {
+    return caseService.findStatusByIdentifier(productIdentifier, caseIdentifier)
+        .orElseThrow(() -> ServiceException.notFound(
+            "Instance with identifier ''{0}.{1}'' doesn''t exist.", productIdentifier, caseIdentifier));
   }
 
   @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.CASE_MANAGEMENT)
@@ -235,7 +250,7 @@
     return new ResponseEntity<>(HttpStatus.ACCEPTED);
   }
 
-  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.CASE_IMPORT)
+  @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.CASE_STATUS)
   @RequestMapping(
       value = "{caseidentifier}/commands/IMPORT",
       method = RequestMethod.POST,
diff --git a/service/src/main/resources/db/migrations/mariadb/V12__persist_start_of_term_locally.sql b/service/src/main/resources/db/migrations/mariadb/V12__persist_start_of_term_locally.sql
new file mode 100644
index 0000000..e254487
--- /dev/null
+++ b/service/src/main/resources/db/migrations/mariadb/V12__persist_start_of_term_locally.sql
@@ -0,0 +1,17 @@
+--
+-- Copyright 2017 Kuelap, Inc.
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--    http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+
+ALTER TABLE bastet_cases ADD COLUMN start_of_term TIMESTAMP(3) NULL DEFAULT NULL;
\ No newline at end of file