Merge pull request #114 from Cadreia/patch-1

FINCN-60: Update Readme
diff --git a/app/build.gradle b/app/build.gradle
index 0c7f303..5dbcc83 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -71,6 +71,9 @@
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
     }
+    kotlinOptions {
+        jvmTarget = JavaVersion.VERSION_1_8
+    }
 }
 
 dependencies {
@@ -157,6 +160,9 @@
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version_kotlin_coroutines"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version_kotlin_coroutines"
 
+    //couchbase
+    implementation "com.couchbase.lite:couchbase-lite-android:$couchbase"
+
 
     // Instrumentation test dependencies
     androidTestImplementation jUnit
@@ -173,6 +179,9 @@
     androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
     androidTestImplementation "androidx.test:runner:$runnerVersion"
     androidTestImplementation "androidx.test:rules:$rulesVersion"
+    androidTestImplementation "androidx.test.ext:junit:$extJunit"
+    androidTestImplementation "androidx.test.espresso:espresso-core:$espressoCore"
+    androidTestImplementation "androidx.test.espresso:espresso-contrib: $espressonContribute"
 
     // Unit tests dependencies
     testImplementation jUnit
@@ -182,7 +191,6 @@
     testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion"
     testImplementation "org.hamcrest:hamcrest-integration:$hamcrestVersion"
     testImplementation "org.robolectric:robolectric:$roboElectricVersion"
-
 }
 
 // Log out test results to console
diff --git a/app/src/androidTest/java/org/apache/fineract/ui/online/groups/creategroup/CreateGroupActivityAndroidTest.kt b/app/src/androidTest/java/org/apache/fineract/ui/online/groups/creategroup/CreateGroupActivityAndroidTest.kt
new file mode 100644
index 0000000..83441ad
--- /dev/null
+++ b/app/src/androidTest/java/org/apache/fineract/ui/online/groups/creategroup/CreateGroupActivityAndroidTest.kt
@@ -0,0 +1,115 @@
+package org.apache.fineract.ui.online.groups.creategroup
+
+import android.content.Intent
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.action.ViewActions.click
+import androidx.test.espresso.action.ViewActions.typeText
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.rule.ActivityTestRule
+import org.apache.fineract.R
+import org.apache.fineract.couchbase.SynchronizationManager
+import org.apache.fineract.data.models.Group
+import org.apache.fineract.ui.online.groups.GroupAction
+import org.apache.fineract.utils.Constants
+import org.apache.fineract.utils.toDataClass
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Created by Ahmad Jawid Muhammadi on 24/8/20.
+ */
+
+@RunWith(AndroidJUnit4::class)
+class CreateGroupActivityAndroidTest {
+
+    @get:Rule
+    var activityTestRule =
+            ActivityTestRule<CreateGroupActivity>(CreateGroupActivity::class.java, false, false)
+
+    lateinit var synchronizationManager: SynchronizationManager
+
+    @Before
+    fun before() {
+        //Open CreateGroupActivity with an intent by putting  create group action as an extra
+        val intent = Intent().apply {
+            putExtra(Constants.GROUP_ACTION, GroupAction.CREATE)
+        }
+        activityTestRule.launchActivity(intent)
+        synchronizationManager = SynchronizationManager(
+                InstrumentationRegistry.getInstrumentation().context
+        )
+    }
+
+    @Test
+    fun createGroupItem() {
+        onView(withId(R.id.etIdentifier))
+                .perform(typeText("testIdentifier"))
+        onView(withId(R.id.etGroupDefinitionIdentifier))
+                .perform(typeText("group definition"))
+        onView(withId(R.id.etName))
+                .perform(typeText("group name"))
+        onView(withId(R.id.etOffice))
+                .perform(typeText("office name"))
+        onView(withId(R.id.etAssignedEmployee))
+                .perform(typeText("assignedEmployee"))
+
+        //go to next fragment
+        onView(withText("NEXT")).perform(click())
+
+        //Add a member
+        onView(withId(R.id.ibAddMember))
+                .perform(click())
+        onView(withId(R.id.etNewMember))
+                .perform(typeText("Ahmad"))
+        onView(withId((R.id.btnAddMember)))
+                .perform(click())
+        onView(withText("NEXT")).perform(click())
+
+        //Add leader name
+        onView(withId(R.id.ibAddLeader))
+                .perform(click())
+        onView(withId(R.id.etNewLeader))
+                .perform(typeText("Jawid"))
+        onView(withId((R.id.btnAddLeader)))
+                .perform(click())
+        onView(withText("NEXT")).perform(click())
+
+        //fill address details
+        onView(withId(R.id.etStreet))
+                .perform(typeText("Street"))
+        onView(withId(R.id.etCity))
+                .perform(typeText("Pune"))
+        onView(withId(R.id.etRegion))
+                .perform(typeText("Region"))
+        onView(withId(R.id.etPostalCode))
+                .perform(typeText("411048"))
+        onView(withId(R.id.etCountry))
+                .perform(typeText("India"))
+        onView(withText("NEXT")).perform(click())
+        onView(withText("COMPLETE")).perform(click())
+
+        //Then assert if group item has been created
+        val mapItem = synchronizationManager.getDocumentForTest(
+                "testIdentifier",
+                InstrumentationRegistry.getInstrumentation().context
+        )
+        val groupItem = mapItem.toDataClass<Group>()
+        assertEquals(groupItem.identifier, "testIdentifier")
+        assertEquals(groupItem.name, "group name")
+    }
+
+    @After
+    fun after() {
+        //delete the created document in test
+        synchronizationManager.deleteDocument(
+                "testIdentifier"
+        )
+    }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/java/org/apache/fineract/ui/online/groups/grouplist/GroupListFragmentAndroidTest.kt b/app/src/androidTest/java/org/apache/fineract/ui/online/groups/grouplist/GroupListFragmentAndroidTest.kt
new file mode 100644
index 0000000..88cc97b
--- /dev/null
+++ b/app/src/androidTest/java/org/apache/fineract/ui/online/groups/grouplist/GroupListFragmentAndroidTest.kt
@@ -0,0 +1,54 @@
+package org.apache.fineract.ui.online.groups.grouplist
+
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.action.ViewActions.click
+import androidx.test.espresso.assertion.ViewAssertions.matches
+import androidx.test.espresso.contrib.DrawerActions
+import androidx.test.espresso.contrib.NavigationViewActions
+import androidx.test.espresso.contrib.RecyclerViewActions
+import androidx.test.espresso.matcher.ViewMatchers.*
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.rule.ActivityTestRule
+import org.apache.fineract.R
+import org.apache.fineract.ui.adapters.GroupsAdapter
+import org.apache.fineract.ui.online.DashboardActivity
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Created by Ahmad Jawid Muhammadi on 24/8/20.
+ */
+
+@RunWith(AndroidJUnit4::class)
+class GroupListFragmentAndroidTest {
+
+    @get:Rule
+    val activityRule =
+            ActivityTestRule<DashboardActivity>(DashboardActivity::class.java)
+
+    @Test
+    fun openDrawer_OpenGroupList_ClickOnRecyclerViewItem() {
+
+        //Open drawer
+        onView(withId(R.id.drawer_layout))
+                .perform(DrawerActions.open())
+
+        //From NavigationView navigate to Group list screen
+        onView(withId(R.id.nav_view))
+                .perform(NavigationViewActions.navigateTo(R.id.item_groups))
+
+        //Click on group item
+        onView(withId(R.id.rvGroups)).perform(
+                RecyclerViewActions.actionOnItem<GroupsAdapter.ViewHolder>(
+                        hasDescendant(withText("group")),
+                        click()
+                )
+        )
+
+        //Assert if thw item has been displayed correctly
+        onView(withId(R.id.tvIdentifier))
+                .check(matches(withText("group")))
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 08702c3..bad499e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -35,7 +35,7 @@
         </provider>
 
         <activity
-            android:name=".ui.online.SplashActivity"
+            android:name=".ui.online.launcher.LauncherActivity"
             android:theme="@style/SplashTheme">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -43,15 +43,14 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".ui.online.launcher.LauncherActivity" />
-
         <activity android:name=".ui.online.PassCodeActivity" />
 
         <activity
             android:name=".ui.online.login.LoginActivity"
             android:windowSoftInputMode="adjustResize" />
 
-        <activity android:name=".ui.online.DashboardActivity" />
+        <activity android:name=".ui.online.DashboardActivity"
+            android:theme="@style/AppTheme.TransparentStatusBar" />
 
         <activity android:name=".ui.online.customers.customerdetails.CustomerDetailsActivity" />
 
diff --git a/app/src/main/java/org/apache/fineract/FineractApplication.java b/app/src/main/java/org/apache/fineract/FineractApplication.java
index de32205..8144d4f 100644
--- a/app/src/main/java/org/apache/fineract/FineractApplication.java
+++ b/app/src/main/java/org/apache/fineract/FineractApplication.java
@@ -3,6 +3,7 @@
 import android.app.Application;
 import android.content.Context;
 
+import com.couchbase.lite.CouchbaseLite;
 import com.crashlytics.android.Crashlytics;
 import com.evernote.android.job.JobManager;
 import com.mifos.mobile.passcode.utils.ForegroundChecker;
@@ -37,6 +38,7 @@
         Fabric.with(this, new Crashlytics());
         FlowManager.init(this);
         ForegroundChecker.init(this);
+        CouchbaseLite.init(this);
     }
 
     public static Context getContext() {
diff --git a/app/src/main/java/org/apache/fineract/couchbase/CouchbaseDatabase.kt b/app/src/main/java/org/apache/fineract/couchbase/CouchbaseDatabase.kt
new file mode 100644
index 0000000..5cfac7b
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/couchbase/CouchbaseDatabase.kt
@@ -0,0 +1,72 @@
+package org.apache.fineract.couchbase
+
+import android.content.Context
+import com.couchbase.lite.CouchbaseLiteException
+import com.couchbase.lite.Database
+import com.couchbase.lite.DatabaseConfiguration
+import com.couchbase.lite.ListenerToken
+import org.apache.fineract.data.local.PreferencesHelper
+import org.apache.fineract.injection.ApplicationContext
+import org.apache.fineract.utils.Constants.DATABASE_NAME
+import javax.inject.Inject
+
+/**
+ * Created by Ahmad Jawid Muhammadi on 7/8/20.
+ */
+
+class CouchbaseDatabase @Inject constructor(
+        @ApplicationContext val context: Context?) {
+
+    @Volatile
+    private var database: Database? = null
+
+    @Inject
+    lateinit var preferencesHelper: PreferencesHelper
+
+    private var listener: ListenerToken? = null
+
+    fun getDatabase(): Database {
+        // we need this check only when we use database for UI/Integration testing
+        if (!::preferencesHelper.isInitialized) {
+            preferencesHelper = PreferencesHelper(context)
+            preferencesHelper.putUserName("ahmad")
+        }
+        return database
+                ?: createDatabase(context, preferencesHelper.userName, DATABASE_NAME).also {
+                    database = it
+                    Replicate.startReplicating(it)
+                }
+    }
+
+    fun deleteDatabase() {
+        database?.close()
+        database?.delete()
+        database = null
+    }
+
+    private fun createDatabase(
+            context: Context?,
+            userName: String,
+            databaseName: String
+    ): Database {
+        val configuration = DatabaseConfiguration()
+//        configuration.directory = String.format(
+//                "%s/%s",
+//                context?.filesDir,
+//                userName
+       // )
+
+        return Database(databaseName, configuration)
+    }
+
+    fun closeDatabaseForUser() {
+        try {
+            database?.let {
+                database?.close()
+                database = null
+            }
+        } catch (e: CouchbaseLiteException) {
+            e.printStackTrace()
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/couchbase/DocumentType.kt b/app/src/main/java/org/apache/fineract/couchbase/DocumentType.kt
new file mode 100644
index 0000000..9e32fd4
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/couchbase/DocumentType.kt
@@ -0,0 +1,10 @@
+package org.apache.fineract.couchbase
+
+/**
+ * Created by Ahmad Jawid Muhammadi on 14/8/20.
+ */
+
+enum class DocumentType(val value: String) {
+    GROUP("Group"),
+    CUSTOMER("customer")
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/couchbase/Replicate.java b/app/src/main/java/org/apache/fineract/couchbase/Replicate.java
new file mode 100644
index 0000000..ab61639
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/couchbase/Replicate.java
@@ -0,0 +1,69 @@
+package org.apache.fineract.couchbase;
+
+import android.util.Log;
+
+import com.couchbase.lite.BasicAuthenticator;
+import com.couchbase.lite.Database;
+import com.couchbase.lite.Endpoint;
+import com.couchbase.lite.Replicator;
+import com.couchbase.lite.ReplicatorConfiguration;
+import com.couchbase.lite.URLEndpoint;
+import com.google.gson.Gson;
+
+import org.apache.fineract.data.local.PreferencesHelper;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import static com.couchbase.lite.ReplicatorConfiguration.ReplicatorType;
+import static org.apache.fineract.data.remote.BaseUrl.LOCALHOST_URL;
+import static org.apache.fineract.utils.Constants.BASIC_AUTH_KEY;
+
+/**
+ * Created by Ahmad Jawid Muhammadi on 12/8/20.
+ */
+
+public class Replicate {
+
+    public static final String TAG = Replicate.class.getSimpleName();
+
+    public static void startReplicating(Database database) throws URISyntaxException {
+
+        Endpoint targetEndpoint = new URLEndpoint(URI.create(LOCALHOST_URL));
+        ReplicatorConfiguration config = new ReplicatorConfiguration(database, targetEndpoint);
+        config.setReplicatorType(ReplicatorType.PUSH_AND_PULL);
+
+       // config.setAuthenticator(new BasicAuthenticator(GATEWAY_USER_NAME, GATEWAY_PASSWORD));
+
+        Replicator replicator = new Replicator(config);
+
+        replicator.addChangeListener(change -> {
+            if (change.getStatus().getError() != null) {
+                Log.e(TAG, "Error status:  " + change.getStatus());
+                Log.e(TAG, "Error message:  " + change.getStatus().getProgress());
+            }
+        });
+
+        replicator.start();
+    }
+
+    /**
+     * Saves the Basic Authentication in SharedPreference
+     */
+    public void saveBasicAuthentication(
+            String username, String password,
+            PreferencesHelper preferencesHelper) {
+        preferencesHelper.putString(
+                BASIC_AUTH_KEY,
+                new Gson().toJson(new BasicAuthenticator(username, password))
+        );
+    }
+
+    public BasicAuthenticator getBasicAuthentication(
+            PreferencesHelper preferencesHelper) {
+        return new Gson().fromJson(
+                preferencesHelper.getString(BASIC_AUTH_KEY, null),
+                BasicAuthenticator.class
+        );
+    }
+}
diff --git a/app/src/main/java/org/apache/fineract/couchbase/SynchronizationManager.kt b/app/src/main/java/org/apache/fineract/couchbase/SynchronizationManager.kt
new file mode 100644
index 0000000..35f0382
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/couchbase/SynchronizationManager.kt
@@ -0,0 +1,112 @@
+package org.apache.fineract.couchbase
+
+import android.content.Context
+import android.util.Log.e
+import com.couchbase.lite.*
+import org.apache.fineract.injection.ApplicationContext
+import org.apache.fineract.utils.Constants.DATABASE_NAME
+import javax.inject.Inject
+
+
+/**
+ * Created by Ahmad Jawid Muhammadi on 6/8/20.
+ */
+
+class SynchronizationManager @Inject constructor(
+        @ApplicationContext val context: Context
+) {
+
+    private val TAG = SynchronizationManager::class.java.simpleName
+
+    @Inject
+    lateinit var database: CouchbaseDatabase
+
+    fun closeDatabase() {
+        database.closeDatabaseForUser()
+    }
+
+
+    @Throws(CouchbaseLiteException::class)
+    fun <T> saveDocument(identifier: String, properties: Map<String, T>) {
+        val document = MutableDocument(identifier, properties)
+        try {
+            e(TAG, "Document: $document")
+            database.getDatabase().save(document)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    fun deleteDocument(identifier: String) {
+        try {
+            database.getDatabase().purge(identifier)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    fun <T> updateDocument(identifier: String, properties: Map<String, T>) {
+        val document = MutableDocument(identifier, properties)
+        try {
+            database.getDatabase().save(document)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    fun getDocuments(expression: Expression, limit: Int = 50, offset: Int = 0): List<HashMap<String, Any>>? {
+        val list = arrayListOf<HashMap<String, Any>>()
+        val query = QueryBuilder
+                .select(SelectResult.all())
+                .from(DataSource.database(database.getDatabase()))
+                .where(expression)
+                .orderBy(Ordering.expression(Meta.id))
+                .limit(Expression.intValue(limit),
+                        Expression.intValue(offset)
+                )
+
+        val resultSet = query.execute()
+        var result: Result? = resultSet.next()
+        while (result != null) {
+            val valueMap = result.getDictionary(DATABASE_NAME)
+            val item = valueMap?.toMap()
+            list.add(item as HashMap<String, Any>)
+            result = resultSet.next()
+        }
+
+        return list
+    }
+
+
+    fun getDocumentForTest(identifier: String, context: Context): HashMap<String, Any> {
+        database = CouchbaseDatabase(context)
+        return getDocumentById(identifier)
+    }
+
+    fun getDocumentById(identifier: String): HashMap<String, Any> {
+        val query = QueryBuilder
+                .select(SelectResult.all())
+                .from(DataSource.database(database.getDatabase()))
+                .where(Meta.id.equalTo(Expression.string(identifier))
+                )
+                .limit(Expression.intValue(1))
+
+        val resultSet = query.execute().next()
+        return resultSet.getDictionary(DATABASE_NAME)?.toMap() as HashMap<String, Any>
+    }
+
+
+    fun clearDatabase() {
+        val query = QueryBuilder
+                .select(SelectResult.all())
+                .from(DataSource.database(database.getDatabase()))
+
+        val resultSet = query.execute()
+        var result: Result? = resultSet.next()
+        while (result != null) {
+            val valueMap = result.getDictionary(DATABASE_NAME)
+            TODO("implement code here to delete item")
+            result = resultSet.next()
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/data/datamanager/api/DataManagerLoans.java b/app/src/main/java/org/apache/fineract/data/datamanager/api/DataManagerLoans.java
index e641d7f..4efdfa2 100644
--- a/app/src/main/java/org/apache/fineract/data/datamanager/api/DataManagerLoans.java
+++ b/app/src/main/java/org/apache/fineract/data/datamanager/api/DataManagerLoans.java
@@ -17,7 +17,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 07/07/17.
+ * On 07/07/17.
  */
 @Singleton
 public class DataManagerLoans extends FineractBaseDataManager {
@@ -27,7 +27,7 @@
 
     @Inject
     public DataManagerLoans(BaseApiManager baseApiManager, PreferencesHelper preferencesHelper,
-            DataManagerAuth dataManagerAuth) {
+                            DataManagerAuth dataManagerAuth) {
         super(dataManagerAuth, preferencesHelper);
         this.baseApiManager = baseApiManager;
         this.preferencesHelper = preferencesHelper;
@@ -78,4 +78,13 @@
         return authenticatedCompletableApi(baseApiManager.getLoanApi()
                 .createLoan(productIdentifier, loanAccount));
     }
+
+    public Completable updateLoan(
+            String productIdentifier,
+            LoanAccount loanAccount,
+            String caseIdentifier) {
+        return authenticatedCompletableApi(
+                baseApiManager.getLoanApi().
+                        updateLoan(productIdentifier, caseIdentifier, loanAccount));
+    }
 }
diff --git a/app/src/main/java/org/apache/fineract/data/models/Group.kt b/app/src/main/java/org/apache/fineract/data/models/Group.kt
index 9f8a35f..781b6c0 100644
--- a/app/src/main/java/org/apache/fineract/data/models/Group.kt
+++ b/app/src/main/java/org/apache/fineract/data/models/Group.kt
@@ -2,6 +2,7 @@
 
 import android.os.Parcelable
 import kotlinx.android.parcel.Parcelize
+import org.apache.fineract.couchbase.DocumentType
 import org.apache.fineract.data.models.customer.Address
 
 /*
@@ -18,12 +19,13 @@
         var office: String? = null,
         var assignedEmployee: String? = null,
         var weekday: Int? = null,
-        var status: Status? = null,
+        var status: Status? = Status.PENDING,
         var address: Address? = null,
         var createdOn: String? = null,
         var createdBy: String? = null,
         var lastModifiedBy: String? = null,
-        var lastModifiedOn: String? = null) : Parcelable {
+        var lastModifiedOn: String? = null,
+        var documentType: String = DocumentType.GROUP.value) : Parcelable {
 
     enum class Status {
         PENDING,
diff --git a/app/src/main/java/org/apache/fineract/data/models/customer/Customer.kt b/app/src/main/java/org/apache/fineract/data/models/customer/Customer.kt
index 8fe5dd3..7471ec6 100644
--- a/app/src/main/java/org/apache/fineract/data/models/customer/Customer.kt
+++ b/app/src/main/java/org/apache/fineract/data/models/customer/Customer.kt
@@ -7,38 +7,40 @@
 import com.raizlabs.android.dbflow.sql.language.SQLite.select
 import com.raizlabs.android.dbflow.structure.BaseModel
 import kotlinx.android.parcel.Parcelize
+import org.apache.fineract.couchbase.DocumentType
 import org.apache.fineract.data.local.database.AppDatabase
 
 @Parcelize
 @Table(database = AppDatabase::class, useBooleanGetterSetters = false)
 data class Customer(
-    @PrimaryKey
-    @Column var identifier: String? = null,
-    @Column var type: String? = null,
-    @Column var givenName: String? = null,
-    @Column var middleName: String? = null,
-    @Column var surname: String? = null,
-    @ForeignKey(saveForeignKeyModel = true)
-    @Column var dateOfBirth: DateOfBirth? = null,
-    @Column var member: Boolean? = null,
-    @Column var accountBeneficiary: String? = null,
-    @Column var referenceCustomer: String? = null,
-    @Column var assignedOffice: String? = null,
-    @Column var assignedEmployee: String? = null,
-    @ForeignKey(saveForeignKeyModel = true)
-    @Column var address: Address? = null,
-    var contactDetails: List<ContactDetail>? = null,
-    @Column var currentState: State? = null,
-    @Column var createdBy: String? = null,
-    @Column var createdOn: String? = null,
-    @Column var lastModifiedBy: String? = null,
-    @Column var lastModifiedOn: String? = null
+        @PrimaryKey
+        @Column var identifier: String? = null,
+        @Column var type: String? = null,
+        @Column var givenName: String? = null,
+        @Column var middleName: String? = null,
+        @Column var surname: String? = null,
+        @ForeignKey(saveForeignKeyModel = true)
+        @Column var dateOfBirth: DateOfBirth? = null,
+        @Column var member: Boolean? = null,
+        @Column var accountBeneficiary: String? = null,
+        @Column var referenceCustomer: String? = null,
+        @Column var assignedOffice: String? = null,
+        @Column var assignedEmployee: String? = null,
+        @ForeignKey(saveForeignKeyModel = true)
+        @Column var address: Address? = null,
+        var contactDetails: List<ContactDetail>? = null,
+        @Column var currentState: State? = State.PENDING,
+        @Column var createdBy: String? = null,
+        @Column var createdOn: String? = null,
+        @Column var lastModifiedBy: String? = null,
+        @Column var lastModifiedOn: String? = null,
+        @Column var documentType: String = DocumentType.CUSTOMER.value
 ) : BaseModel(), Parcelable {
 
     var isUpdate: Boolean? = null
 
     @OneToMany(methods = arrayOf(OneToMany.Method.ALL), variableName = "contactDetails")
-    fun getContactDetail() : List<ContactDetail>? {
+    fun getContactDetail(): List<ContactDetail>? {
         contactDetails = select()
                 .from(ContactDetail::class.java)
                 .where(ContactDetail_Table.customer_identifier.eq(identifier))
diff --git a/app/src/main/java/org/apache/fineract/data/models/loan/AccountAssignment.kt b/app/src/main/java/org/apache/fineract/data/models/loan/AccountAssignment.kt
index 4a9e876..043d882 100644
--- a/app/src/main/java/org/apache/fineract/data/models/loan/AccountAssignment.kt
+++ b/app/src/main/java/org/apache/fineract/data/models/loan/AccountAssignment.kt
@@ -1,13 +1,16 @@
 package org.apache.fineract.data.models.loan
 
+import android.os.Parcelable
 import com.google.gson.annotations.SerializedName
+import kotlinx.android.parcel.Parcelize
 
 /**
  * @author Rajan Maurya
  * On 09/07/17.
  */
+@Parcelize
 data class AccountAssignment (
     @SerializedName("designator") var designator: String? = null,
     @SerializedName("accountIdentifier") var accountIdentifier: String? = null,
     @SerializedName("ledgerIdentifier") var ledgerIdentifier: String? = null
-)
\ No newline at end of file
+):Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/data/models/loan/LoanAccount.kt b/app/src/main/java/org/apache/fineract/data/models/loan/LoanAccount.kt
index b1daa84..c7dd13f 100644
--- a/app/src/main/java/org/apache/fineract/data/models/loan/LoanAccount.kt
+++ b/app/src/main/java/org/apache/fineract/data/models/loan/LoanAccount.kt
@@ -1,14 +1,16 @@
 package org.apache.fineract.data.models.loan
 
+import android.os.Parcelable
 import com.google.gson.Gson
 import com.google.gson.annotations.SerializedName
-
-import java.util.ArrayList
+import kotlinx.android.parcel.Parcelize
+import java.util.*
 
 /**
  * @author Rajan Maurya
  * On 09/07/17.
  */
+@Parcelize
 data class LoanAccount(
     @SerializedName("identifier") var identifier: String? = null,
     @SerializedName("productIdentifier")  var productIdentifier: String? = null,
@@ -20,7 +22,7 @@
     @SerializedName("createdBy") var createdBy: String? = null,
     @SerializedName("lastModifiedOn") var lastModifiedOn: String? = null,
     @SerializedName("lastModifiedBy") var lastModifiedBy: String? = null
-) {
+):Parcelable {
 
     private val loanParameters: LoanParameters? = null
 
diff --git a/app/src/main/java/org/apache/fineract/data/models/loan/LoanParameters.kt b/app/src/main/java/org/apache/fineract/data/models/loan/LoanParameters.kt
index 08e9b08..cbd83d4 100644
--- a/app/src/main/java/org/apache/fineract/data/models/loan/LoanParameters.kt
+++ b/app/src/main/java/org/apache/fineract/data/models/loan/LoanParameters.kt
@@ -1,17 +1,21 @@
 package org.apache.fineract.data.models.loan
 
+import android.os.Parcelable
 import com.google.gson.annotations.SerializedName
+import kotlinx.android.parcel.Parcelize
+import kotlinx.android.parcel.RawValue
 
 /**
  * @author Rajan Maurya
  * On 12/07/17.
  */
 
+@Parcelize
 data class LoanParameters(
-    @SerializedName("customerIdentifier") var customerIdentifier: String? = null,
-    @SerializedName("creditWorthinessSnapshots") var creditWorthinessSnapshots:
-    List<CreditWorthinessSnapshot>? = null,
-    @SerializedName("maximumBalance") var maximumBalance: Double? = null,
-    @SerializedName("termRange") var termRange: TermRange? = null,
-    @SerializedName("paymentCycle") var paymentCycle: PaymentCycle? = null
-)
\ No newline at end of file
+        @SerializedName("customerIdentifier") var customerIdentifier: String? = null,
+        @SerializedName("creditWorthinessSnapshots") var creditWorthinessSnapshots:
+        List<CreditWorthinessSnapshot>? = null,
+        @SerializedName("maximumBalance") var maximumBalance: Double? = null,
+        @SerializedName("termRange") var termRange: @RawValue TermRange? = null,
+        @SerializedName("paymentCycle") var paymentCycle: @RawValue PaymentCycle? = null
+) : Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/data/remote/BaseUrl.java b/app/src/main/java/org/apache/fineract/data/remote/BaseUrl.java
index 95fee4b..445bed3 100755
--- a/app/src/main/java/org/apache/fineract/data/remote/BaseUrl.java
+++ b/app/src/main/java/org/apache/fineract/data/remote/BaseUrl.java
@@ -14,6 +14,7 @@
     public static final String API_ENDPOINT = "pilot.kuelap.io";
     public static final String PORT = "80";
     // "/" in the last of the base url always
+    public static final String LOCALHOST_URL = "ws://10.0.2.2:4984/fineract-cn/";
 
     public String getName() {
         return "fineract";
diff --git a/app/src/main/java/org/apache/fineract/data/services/LoanService.java b/app/src/main/java/org/apache/fineract/data/services/LoanService.java
index f547c9f..b419331 100644
--- a/app/src/main/java/org/apache/fineract/data/services/LoanService.java
+++ b/app/src/main/java/org/apache/fineract/data/services/LoanService.java
@@ -10,12 +10,13 @@
 import retrofit2.http.Body;
 import retrofit2.http.GET;
 import retrofit2.http.POST;
+import retrofit2.http.PUT;
 import retrofit2.http.Path;
 import retrofit2.http.Query;
 
 /**
  * @author Rajan Maurya
- *         On 07/07/17.
+ * On 07/07/17.
  */
 public interface LoanService {
 
@@ -40,4 +41,10 @@
     Completable createLoan(
             @Path("productidentifier") String productidentifier,
             @Body LoanAccount loanAccount);
+
+    @PUT(EndPoints.API_PORTFOLIO_PATH + "/products/{productidentifier}/cases/{caseidentifier}")
+    Completable updateLoan(
+            @Path("productidentifier") String productIdentifier,
+            @Path("caseidentifier") String caseIdentifier,
+            @Body LoanAccount loanAccount);
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/adapters/GroupsAdapter.kt b/app/src/main/java/org/apache/fineract/ui/adapters/GroupsAdapter.kt
index 75e6ece..0324bf2 100644
--- a/app/src/main/java/org/apache/fineract/ui/adapters/GroupsAdapter.kt
+++ b/app/src/main/java/org/apache/fineract/ui/adapters/GroupsAdapter.kt
@@ -37,7 +37,9 @@
     override fun onBindViewHolder(holder: ViewHolder, position: Int) {
         var group: Group = groups[position]
 
-        StatusUtils.setGroupsStatusIcon(group.status, holder.ivTypeIndicator, context)
+        group.status?.let {
+            StatusUtils.setGroupsStatusIcon(group.status, holder.ivTypeIndicator, context)
+        }
 
         holder.tvGroupIdentifier.text = group.identifier
 
diff --git a/app/src/main/java/org/apache/fineract/ui/adapters/LoanApplicationStepAdapter.java b/app/src/main/java/org/apache/fineract/ui/adapters/LoanApplicationStepAdapter.java
index 924ed33..8566f04 100644
--- a/app/src/main/java/org/apache/fineract/ui/adapters/LoanApplicationStepAdapter.java
+++ b/app/src/main/java/org/apache/fineract/ui/adapters/LoanApplicationStepAdapter.java
@@ -1,6 +1,7 @@
 package org.apache.fineract.ui.adapters;
 
 import android.content.Context;
+
 import androidx.annotation.IntRange;
 import androidx.annotation.NonNull;
 import androidx.fragment.app.FragmentManager;
@@ -10,6 +11,8 @@
 import com.stepstone.stepper.viewmodel.StepViewModel;
 
 import org.apache.fineract.R;
+import org.apache.fineract.data.models.loan.LoanAccount;
+import org.apache.fineract.ui.online.loanaccounts.loanapplication.LoanApplicationAction;
 import org.apache.fineract.ui.online.loanaccounts.loanapplication.LoanDebtIncomeFragment;
 import org.apache.fineract.ui.online.loanaccounts.loanapplication.loancosigner.LoanCoSignerFragment;
 import org.apache.fineract.ui.online.loanaccounts.loanapplication.loandetails.LoanDetailsFragment;
@@ -17,16 +20,23 @@
 
 /**
  * @author Rajan Maurya
- *         On 17/07/17.
+ * On 17/07/17.
  */
 public class LoanApplicationStepAdapter extends AbstractFragmentStepAdapter {
 
     private String[] loanApplicationSteps;
+    private LoanAccount loanAccount;
+    private LoanApplicationAction loanApplicationAction;
 
-    public LoanApplicationStepAdapter(@NonNull FragmentManager fm, @NonNull Context context) {
+    public LoanApplicationStepAdapter(@NonNull FragmentManager fm,
+                                      @NonNull Context context,
+                                      @NonNull LoanAccount loanAccount,
+                                      @NonNull LoanApplicationAction loanApplicationAction) {
         super(fm, context);
         loanApplicationSteps = context.getResources().getStringArray(
                 R.array.loan_application_steps);
+        this.loanAccount = loanAccount;
+        this.loanApplicationAction = loanApplicationAction;
     }
 
     @NonNull
@@ -41,11 +51,11 @@
     public Step createStep(@IntRange(from = 0L) int position) {
         switch (position) {
             case 0:
-                return LoanDetailsFragment.newInstance();
+                return LoanDetailsFragment.newInstance(loanAccount, loanApplicationAction);
             case 1:
-                return LoanDebtIncomeFragment.newInstance();
+                return LoanDebtIncomeFragment.newInstance(loanAccount, loanApplicationAction);
             case 2:
-                return LoanCoSignerFragment.newInstance();
+                return LoanCoSignerFragment.newInstance(loanAccount, loanApplicationAction);
             case 3:
                 return AddLoanReviewFragment.Companion.newInstance();
         }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/SplashActivity.kt b/app/src/main/java/org/apache/fineract/ui/online/SplashActivity.kt
deleted file mode 100644
index b85c9df..0000000
--- a/app/src/main/java/org/apache/fineract/ui/online/SplashActivity.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.apache.fineract.ui.online
-
-import android.content.Intent
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import org.apache.fineract.ui.online.launcher.LauncherActivity
-
-/*
- * Created by saksham on 09/June/2019
-*/
-
-class SplashActivity : AppCompatActivity() {
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        startActivity(Intent(this, LauncherActivity::class.java))
-        finish()
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/createcustomer/customeractivity/CreateCustomerPresenter.java b/app/src/main/java/org/apache/fineract/ui/online/customers/createcustomer/customeractivity/CreateCustomerPresenter.java
index 251a6e1..a09bad3 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/createcustomer/customeractivity/CreateCustomerPresenter.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/createcustomer/customeractivity/CreateCustomerPresenter.java
@@ -1,87 +1,64 @@
 package org.apache.fineract.ui.online.customers.createcustomer.customeractivity;
 
 import android.content.Context;
+import android.util.Log;
 
-import org.apache.fineract.R;
-import org.apache.fineract.data.datamanager.contracts.ManagerCustomer;
-import org.apache.fineract.data.datamanager.database.DbManagerCustomer;
+import com.couchbase.lite.CouchbaseLiteException;
+
+import org.apache.fineract.couchbase.SynchronizationManager;
+import org.apache.fineract.data.local.PreferencesHelper;
 import org.apache.fineract.data.models.customer.Customer;
 import org.apache.fineract.injection.ApplicationContext;
 import org.apache.fineract.injection.ConfigPersistent;
 import org.apache.fineract.ui.base.BasePresenter;
+import org.apache.fineract.utils.DateUtils;
+import org.apache.fineract.utils.GsonUtilsKt;
+
+import java.util.Objects;
 
 import javax.inject.Inject;
 
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.CompositeDisposable;
-import io.reactivex.observers.DisposableCompletableObserver;
-import io.reactivex.schedulers.Schedulers;
-
 /**
  * @author Rajan Maurya
- *         On 27/07/17.
+ * On 27/07/17.
  */
 @ConfigPersistent
 public class CreateCustomerPresenter extends BasePresenter<CreateCustomerContract.View>
         implements CreateCustomerContract.Presenter {
 
-    private ManagerCustomer dbManagerCustomer;
-    private final CompositeDisposable compositeDisposable;
+    private SynchronizationManager synchronizationManager;
+    private PreferencesHelper preferencesHelper;
 
     @Inject
     public CreateCustomerPresenter(@ApplicationContext Context context,
-            DbManagerCustomer dataManagerCustomer) {
+                                   SynchronizationManager synchronizationManager,
+                                   PreferencesHelper preferencesHelper) {
         super(context);
-        this.dbManagerCustomer = dataManagerCustomer;
-        compositeDisposable = new CompositeDisposable();
+        this.synchronizationManager = synchronizationManager;
+        this.preferencesHelper = preferencesHelper;
     }
 
     @Override
-    public void createCustomer(final Customer customer) {
-        checkViewAttached();
-        getMvpView().showProgressbar();
-        compositeDisposable.add(dbManagerCustomer.createCustomer(customer)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribeWith(new DisposableCompletableObserver() {
-                    @Override
-                    public void onComplete() {
-                        getMvpView().hideProgressbar();
-                        getMvpView().customerCreatedSuccessfully();
-                    }
-
-                    @Override
-                    public void onError(Throwable throwable) {
-                        getMvpView().hideProgressbar();
-                        showExceptionError(throwable,
-                                context.getString(R.string.error_creating_customer));
-                    }
-                })
-
-        );
+    public void createCustomer(Customer customer) {
+        try {
+            customer.setCreatedBy(preferencesHelper.getUserName());
+            customer.setCreatedOn(DateUtils.getCurrentDate());
+            customer.setLastModifiedBy(preferencesHelper.getUserName());
+            customer.setLastModifiedOn(DateUtils.getCurrentDate());
+            synchronizationManager.saveDocument(Objects.requireNonNull(customer.getIdentifier()),
+                    GsonUtilsKt.serializeToMap(customer));
+        } catch (CouchbaseLiteException e) {
+            Log.e("CreateCustomerPresenter", e.toString());
+        }
+        getMvpView().customerCreatedSuccessfully();
     }
 
     @Override
     public void updateCustomer(String customerIdentifier, Customer customer) {
-        checkViewAttached();
-        getMvpView().showProgressbar();
-        compositeDisposable.add(dbManagerCustomer.updateCustomer(customerIdentifier, customer)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribeWith(new DisposableCompletableObserver() {
-                    @Override
-                    public void onComplete() {
-                        getMvpView().hideProgressbar();
-                        getMvpView().customerUpdatedSuccessfully();
-                    }
-
-                    @Override
-                    public void onError(Throwable throwable) {
-                        getMvpView().hideProgressbar();
-                        showExceptionError(throwable,
-                                context.getString(R.string.error_updating_customer));
-                    }
-                })
-        );
+        customer.setLastModifiedBy(preferencesHelper.getUserName());
+        customer.setLastModifiedOn(DateUtils.getCurrentDate());
+        synchronizationManager.updateDocument(Objects.requireNonNull(customer.getIdentifier()),
+                GsonUtilsKt.serializeToMap(customer));
+        getMvpView().customerUpdatedSuccessfully();
     }
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/createcustomer/formcustomeraddress/FormCustomerAddressFragment.java b/app/src/main/java/org/apache/fineract/ui/online/customers/createcustomer/formcustomeraddress/FormCustomerAddressFragment.java
index f3ba64c..b4c446f 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/createcustomer/formcustomeraddress/FormCustomerAddressFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/createcustomer/formcustomeraddress/FormCustomerAddressFragment.java
@@ -134,16 +134,18 @@
 
     public void showPreviousAddress() {
         Address address = customer.getAddress();
-        etStreet.setText(address.getStreet());
-        etCity.setText(address.getCity());
-        if (address.getPostalCode() != null) {
-            etPostalCode.setText(address.getPostalCode());
+        if (address != null) {
+            etStreet.setText(address.getStreet());
+            etCity.setText(address.getCity());
+            if (address.getPostalCode() != null) {
+                etPostalCode.setText(address.getPostalCode());
+            }
+            etCountry.setText(address.getCountry());
+            if (address.getRegion() != null) {
+                etRegion.setText(address.getRegion());
+            }
         }
-        etCountry.setText(address.getCountry());
         showTextInputLayoutError(tilCountry, null);
-        if (address.getRegion() != null) {
-            etRegion.setText(address.getRegion());
-        }
     }
 
     @Override
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/customerdetails/CustomerDetailsFragment.java b/app/src/main/java/org/apache/fineract/ui/online/customers/customerdetails/CustomerDetailsFragment.java
index b34f58e..64cdfe0 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/customerdetails/CustomerDetailsFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/customerdetails/CustomerDetailsFragment.java
@@ -2,12 +2,6 @@
 
 import android.content.Intent;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
-import com.google.android.material.appbar.AppBarLayout;
-import com.google.android.material.appbar.CollapsingToolbarLayout;
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -15,6 +9,14 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+
+import com.google.android.material.appbar.AppBarLayout;
+import com.google.android.material.appbar.CollapsingToolbarLayout;
+
 import org.apache.fineract.R;
 import org.apache.fineract.data.models.customer.Address;
 import org.apache.fineract.data.models.customer.ContactDetail;
@@ -44,7 +46,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 26/06/17.
+ * On 26/06/17.
  */
 public class CustomerDetailsFragment extends FineractBaseFragment
         implements AppBarLayout.OnOffsetChangedListener, CustomerDetailsContract.View,
@@ -133,7 +135,7 @@
 
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
+                             @Nullable Bundle savedInstanceState) {
         rootView = inflater.inflate(R.layout.fragment_customer_details, container, false);
         ((FineractBaseActivity) getActivity()).getActivityComponent().inject(this);
         ButterKnife.bind(this, rootView);
@@ -181,6 +183,7 @@
         tasksBottomSheet.setCustomerIdentifier(customerIdentifier);
         tasksBottomSheet.setCustomerTasksChangeListener(this);
         tasksBottomSheet.show(getChildFragmentManager(), getString(R.string.tasks));
+        tasksBottomSheet.setCustomer(customer);
     }
 
     @OnClick(R.id.ll_identifier_cards)
@@ -246,14 +249,16 @@
 
         Address address = customer.getAddress();
         StringBuilder addressBuilder = new StringBuilder();
-        addressBuilder
-                .append(address.getStreet()).append(", ")
-                .append(address.getCity()).append(", ");
-        if (address.getPostalCode() != null) {
+        if (address != null) {
+            addressBuilder.append(address.getStreet()).append(", ")
+                    .append(address.getCity()).append(", ");
+
             addressBuilder.append(address.getPostalCode());
             addressBuilder.append(", ");
+
+            addressBuilder.append(address.getCountry());
         }
-        addressBuilder.append(address.getCountry());
+
         tvAddress.setText(addressBuilder);
 
         if (customer.getContactDetails().size() == 0) {
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/customerdetails/CustomerDetailsPresenter.java b/app/src/main/java/org/apache/fineract/ui/online/customers/customerdetails/CustomerDetailsPresenter.java
index 97072ae..6047187 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/customerdetails/CustomerDetailsPresenter.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/customerdetails/CustomerDetailsPresenter.java
@@ -2,38 +2,32 @@
 
 import android.content.Context;
 
-import org.apache.fineract.R;
-import org.apache.fineract.data.datamanager.contracts.ManagerCustomer;
-import org.apache.fineract.data.datamanager.database.DbManagerCustomer;
+import org.apache.fineract.couchbase.SynchronizationManager;
 import org.apache.fineract.data.models.customer.Customer;
 import org.apache.fineract.injection.ApplicationContext;
 import org.apache.fineract.injection.ConfigPersistent;
 import org.apache.fineract.ui.base.BasePresenter;
+import org.apache.fineract.utils.GsonUtilsKt;
+
+import java.util.HashMap;
 
 import javax.inject.Inject;
 
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.CompositeDisposable;
-import io.reactivex.observers.DisposableObserver;
-import io.reactivex.schedulers.Schedulers;
-
 /**
  * @author Rajan Maurya
- *         On 26/06/17.
+ * On 26/06/17.
  */
 @ConfigPersistent
 public class CustomerDetailsPresenter extends BasePresenter<CustomerDetailsContract.View>
         implements CustomerDetailsContract.Presenter {
 
-    private ManagerCustomer dataManagerCustomer;
-    private final CompositeDisposable compositeDisposable;
+    private SynchronizationManager synchronizationManager;
 
     @Inject
     public CustomerDetailsPresenter(@ApplicationContext Context context,
-            DbManagerCustomer dataManager) {
+                                    SynchronizationManager synchronizationManager) {
         super(context);
-        dataManagerCustomer = dataManager;
-        compositeDisposable = new CompositeDisposable();
+        this.synchronizationManager = synchronizationManager;
     }
 
     @Override
@@ -44,35 +38,15 @@
     @Override
     public void detachView() {
         super.detachView();
-        compositeDisposable.clear();
     }
 
     @Override
     public void loanCustomerDetails(String identifier) {
         checkViewAttached();
         getMvpView().showProgressbar();
-        compositeDisposable.add(dataManagerCustomer.fetchCustomer(identifier)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribeWith(new DisposableObserver<Customer>() {
-                    @Override
-                    public void onNext(Customer customer) {
-                        getMvpView().hideProgressbar();
-                        getMvpView().showCustomerDetails(customer);
-                    }
-
-                    @Override
-                    public void onError(Throwable throwable) {
-                        getMvpView().hideProgressbar();
-                        showExceptionError(throwable,
-                                context.getString(R.string.error_fetching_customer_details));
-                    }
-
-                    @Override
-                    public void onComplete() {
-
-                    }
-                })
-        );
+        HashMap<String, Object> item = synchronizationManager.getDocumentById(identifier);
+        Customer customer = GsonUtilsKt.convertToData(item, Customer.class);
+        getMvpView().showCustomerDetails(customer);
+        getMvpView().hideProgressbar();
     }
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/customerlist/CustomersFragment.java b/app/src/main/java/org/apache/fineract/ui/online/customers/customerlist/CustomersFragment.java
index b4d80d1..32a9938 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/customerlist/CustomersFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/customerlist/CustomersFragment.java
@@ -1,18 +1,9 @@
 package org.apache.fineract.ui.online.customers.customerlist;
 
-import static android.app.Activity.RESULT_OK;
-
 import android.app.SearchManager;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
-import androidx.transition.TransitionManager;
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.appcompat.widget.SearchView;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -23,6 +14,14 @@
 import android.widget.RadioButton;
 import android.widget.RadioGroup;
 
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.SearchView;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+import androidx.transition.TransitionManager;
+
 import com.github.therajanmaurya.sweeterror.SweetUIErrorHandler;
 
 import org.apache.fineract.R;
@@ -48,6 +47,8 @@
 import butterknife.ButterKnife;
 import butterknife.OnClick;
 
+import static android.app.Activity.RESULT_OK;
+
 /**
  * @author Rajan Maurya
  * On 20/06/17.
@@ -123,18 +124,19 @@
 
         showUserInterface();
         sweetUIErrorHandler = new SweetUIErrorHandler(getActivity(), rootView);
-        if (preferencesHelper.isFetching()) {
-            sweetUIErrorHandler.showSweetCustomErrorUI(getString(R.string.syncing_please_wait),
-                    R.drawable.ic_error_black_24dp, swipeRefreshLayout, layoutError);
-        } else {
-            customerPresenter.fetchCustomers(0, false);
-        }
+
         return rootView;
     }
 
     @Override
     public void onResume() {
         super.onResume();
+        if (preferencesHelper.isFetching()) {
+            sweetUIErrorHandler.showSweetCustomErrorUI(getString(R.string.syncing_please_wait),
+                    R.drawable.ic_error_black_24dp, swipeRefreshLayout, layoutError);
+        } else {
+            customerPresenter.fetchCustomers(0, false);
+        }
         if (isNewCustomer) {
             isNewCustomer = false;
             customerPresenter.fetchCustomers(0, false);
@@ -192,8 +194,7 @@
     @Override
     public void showEmptyCustomers(String message) {
         showRecyclerView(false);
-        sweetUIErrorHandler.showSweetCustomErrorUI(getString(R.string.customer),
-                getString(Integer.parseInt(message)),
+        sweetUIErrorHandler.showSweetCustomErrorUI(message,
                 R.drawable.ic_customer_black_24dp, rvCustomers, layoutError);
     }
 
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/customerlist/CustomersPresenter.java b/app/src/main/java/org/apache/fineract/ui/online/customers/customerlist/CustomersPresenter.java
index 398b615..afdf1b1 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/customerlist/CustomersPresenter.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/customerlist/CustomersPresenter.java
@@ -2,24 +2,23 @@
 
 import android.content.Context;
 
+import com.couchbase.lite.Expression;
+
 import org.apache.fineract.R;
-import org.apache.fineract.data.datamanager.contracts.ManagerCustomer;
-import org.apache.fineract.data.datamanager.database.DbManagerCustomer;
+import org.apache.fineract.couchbase.DocumentType;
+import org.apache.fineract.couchbase.SynchronizationManager;
 import org.apache.fineract.data.models.customer.Customer;
-import org.apache.fineract.data.models.customer.CustomerPage;
 import org.apache.fineract.injection.ApplicationContext;
 import org.apache.fineract.injection.ConfigPersistent;
 import org.apache.fineract.ui.base.BasePresenter;
+import org.apache.fineract.utils.GsonUtilsKt;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 import javax.inject.Inject;
 
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.CompositeDisposable;
-import io.reactivex.observers.DisposableObserver;
-import io.reactivex.schedulers.Schedulers;
-
 /**
  * @author Rajan Maurya
  * On 20/06/17.
@@ -28,18 +27,16 @@
 public class CustomersPresenter extends BasePresenter<CustomersContract.View>
         implements CustomersContract.Presenter {
 
-    private final ManagerCustomer dataManagerCustomer;
-    private CompositeDisposable compositeDisposable;
-
     private int customerListSize = 50;
     private boolean loadmore = false;
 
+    private SynchronizationManager synchronizationManager;
+
     @Inject
     public CustomersPresenter(@ApplicationContext Context context,
-                              DbManagerCustomer dataManager) {
+                              SynchronizationManager synchronizationManager) {
         super(context);
-        dataManagerCustomer = dataManager;
-        compositeDisposable = new CompositeDisposable();
+        this.synchronizationManager = synchronizationManager;
     }
 
     @Override
@@ -50,7 +47,6 @@
     @Override
     public void detachView() {
         super.detachView();
-        compositeDisposable.clear();
     }
 
     @Override
@@ -63,44 +59,34 @@
     public void fetchCustomers(Integer pageIndex, Integer size) {
         checkViewAttached();
         getMvpView().showProgressbar();
-        compositeDisposable.add(dataManagerCustomer.fetchCustomers(pageIndex, size)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribeWith(new DisposableObserver<CustomerPage>() {
-                    @Override
-                    public void onNext(CustomerPage customerPage) {
-                        getMvpView().hideProgressbar();
+        ArrayList<Customer> customerList = new ArrayList<>();
 
-                        if (!loadmore && customerPage.getTotalPages() == 0) {
-                            getMvpView().showEmptyCustomers(
-                                    context.getString(R.string.empty_customer_list));
-                        } else if (loadmore && customerPage.getCustomers().size() == 0) {
-                            getMvpView().showMessage(
-                                    context.getString(R.string.no_more_customer_available));
-                        } else {
-                            showCustomers(customerPage.getCustomers());
-                        }
-                    }
+        Expression expression = Expression.property("documentType")
+                .equalTo(Expression.string(DocumentType.CUSTOMER.getValue()));
 
-                    @Override
-                    public void onError(Throwable throwable) {
-                        getMvpView().hideProgressbar();
-                        if (loadmore) {
-                            getMvpView().showMessage(
-                                    context.getString(R.string.error_loading_customers));
-                        } else {
-                            showExceptionError(throwable,
-                                    context.getString(R.string.error_loading_customers));
-                        }
-                    }
+        List<HashMap<String, Object>> map = synchronizationManager.getDocuments(
+                expression,
+                size,
+                pageIndex);
 
-                    @Override
-                    public void onComplete() {
-                    }
-                })
-        );
+        for (HashMap<String, Object> item : map) {
+            Customer customer = GsonUtilsKt.convertToData(item, Customer.class);
+            customerList.add(customer);
+        }
+
+        if (!loadmore && customerList.size() == 0) {
+            getMvpView().showEmptyCustomers(
+                    context.getString(R.string.empty_customer_list));
+        } else if (loadmore && customerList.size() == 0) {
+            getMvpView().showMessage(
+                    context.getString(R.string.no_more_customer_available));
+        } else {
+            showCustomers(customerList);
+        }
+        getMvpView().hideProgressbar();
     }
 
+
     @Override
     public void showCustomers(List<Customer> customers) {
         if (loadmore) {
@@ -112,29 +98,29 @@
 
     @Override
     public void searchCustomerOnline(String query) {
-        checkViewAttached();
-        getMvpView().showProgressbar();
-        compositeDisposable.add(
-                dataManagerCustomer.fetchCustomer(query)
-                        .subscribeOn(Schedulers.io())
-                        .observeOn(AndroidSchedulers.mainThread())
-                        .subscribeWith(new DisposableObserver<Customer>() {
-                            @Override
-                            public void onNext(Customer value) {
-                                getMvpView().hideProgressbar();
-                                getMvpView().searchCustomerList(value);
-                            }
-
-                            @Override
-                            public void onError(Throwable e) {
-                                showExceptionError(e,
-                                        context.getString(R.string.error_finding_customer));
-                            }
-
-                            @Override
-                            public void onComplete() {
-
-                            }
-                        }));
+//        checkViewAttached();
+//        getMvpView().showProgressbar();
+//        compositeDisposable.add(
+//                dataManagerCustomer.fetchCustomer(query)
+//                        .subscribeOn(Schedulers.io())
+//                        .observeOn(AndroidSchedulers.mainThread())
+//                        .subscribeWith(new DisposableObserver<Customer>() {
+//                            @Override
+//                            public void onNext(Customer value) {
+//                                getMvpView().hideProgressbar();
+//                                getMvpView().searchCustomerList(value);
+//                            }
+//
+//                            @Override
+//                            public void onError(Throwable e) {
+//                                showExceptionError(e,
+//                                        context.getString(R.string.error_finding_customer));
+//                            }
+//
+//                            @Override
+//                            public void onComplete() {
+//
+//                            }
+//                        }));
     }
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetContract.java b/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetContract.java
index 9d52907..7e79fe6 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetContract.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetContract.java
@@ -1,11 +1,12 @@
 package org.apache.fineract.ui.online.customers.customertasks;
 
 import org.apache.fineract.data.models.customer.Command;
+import org.apache.fineract.data.models.customer.Customer;
 import org.apache.fineract.ui.base.MvpView;
 
 /**
  * @author Rajan Maurya
- *         On 27/07/17.
+ * On 27/07/17.
  */
 
 public interface CustomerTasksBottomSheetContract {
@@ -21,6 +22,6 @@
 
     interface Presenter {
 
-        void changeCustomerStatus(String identifier, Command command);
+        void changeCustomerStatus(String identifier, Customer customer, Command command);
     }
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetFragment.java b/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetFragment.java
index 65e99d7..c09ca25 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetFragment.java
@@ -3,10 +3,6 @@
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import androidx.annotation.NonNull;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
-import com.google.android.material.bottomsheet.BottomSheetDialog;
-import androidx.core.content.ContextCompat;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
@@ -15,6 +11,12 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialog;
+
 import org.apache.fineract.R;
 import org.apache.fineract.data.models.customer.Command;
 import org.apache.fineract.data.models.customer.Customer;
@@ -30,7 +32,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 27/07/17.
+ * On 27/07/17.
  */
 public class CustomerTasksBottomSheetFragment extends FineractBaseBottomSheetDialogFragment
         implements CustomerTasksBottomSheetContract.View {
@@ -71,6 +73,7 @@
     @Inject
     CustomerTasksBottomSheetPresenter tasksBottomSheetPresenter;
 
+
     View rootView;
 
     private BottomSheetBehavior behavior;
@@ -78,6 +81,7 @@
     private Command command;
     private String customerIdentifier;
     private OnTasksChangeListener onTasksChangeListener;
+    private Customer customer;
 
     @NonNull
     @Override
@@ -188,11 +192,15 @@
         customerIdentifier = identifier;
     }
 
+    public void setCustomer(Customer customer) {
+        this.customer = customer;
+    }
+
     @OnClick(R.id.btn_submit_task)
     void submitTask() {
         command.setComment(etComment.getText().toString().trim());
         etComment.setEnabled(false);
-        tasksBottomSheetPresenter.changeCustomerStatus(customerIdentifier, command);
+        tasksBottomSheetPresenter.changeCustomerStatus(customerIdentifier, customer, command);
     }
 
     @OnClick(R.id.btn_cancel)
diff --git a/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetPresenter.java b/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetPresenter.java
index 5d3f6a7..e8cdece 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetPresenter.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/customers/customertasks/CustomerTasksBottomSheetPresenter.java
@@ -1,39 +1,38 @@
 package org.apache.fineract.ui.online.customers.customertasks;
 
 import android.content.Context;
+import android.util.Log;
 
 import org.apache.fineract.R;
-import org.apache.fineract.data.datamanager.api.DataManagerCustomer;
+import org.apache.fineract.couchbase.SynchronizationManager;
 import org.apache.fineract.data.models.customer.Command;
+import org.apache.fineract.data.models.customer.Customer;
 import org.apache.fineract.injection.ApplicationContext;
 import org.apache.fineract.injection.ConfigPersistent;
 import org.apache.fineract.ui.base.BasePresenter;
+import org.apache.fineract.utils.GsonUtilsKt;
+
+import java.util.Objects;
 
 import javax.inject.Inject;
 
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.CompositeDisposable;
-import io.reactivex.observers.DisposableCompletableObserver;
-import io.reactivex.schedulers.Schedulers;
-
 /**
  * @author Rajan Maurya
- *         On 28/07/17.
+ * On 28/07/17.
  */
 @ConfigPersistent
 public class CustomerTasksBottomSheetPresenter
         extends BasePresenter<CustomerTasksBottomSheetContract.View>
         implements CustomerTasksBottomSheetContract.Presenter {
 
-    private DataManagerCustomer dataManagerCustomer;
-    private final CompositeDisposable compositeDisposable;
+    private SynchronizationManager synchronizationManager;
 
     @Inject
     public CustomerTasksBottomSheetPresenter(@ApplicationContext Context context,
-            DataManagerCustomer dataManagerCustomer) {
+                                             SynchronizationManager synchronizationManager) {
         super(context);
-        this.dataManagerCustomer = dataManagerCustomer;
-        compositeDisposable = new CompositeDisposable();
+
+        this.synchronizationManager = synchronizationManager;
     }
 
     @Override
@@ -44,30 +43,37 @@
     @Override
     public void detachView() {
         super.detachView();
-        compositeDisposable.clear();
+        synchronizationManager.closeDatabase();
     }
 
     @Override
-    public void changeCustomerStatus(String identifier, Command command) {
+    public void changeCustomerStatus(String identifier, Customer customer, Command command) {
         checkViewAttached();
         getMvpView().showProgressbar();
-        compositeDisposable.add(dataManagerCustomer.customerCommand(identifier, command)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribeWith(new DisposableCompletableObserver() {
-                    @Override
-                    public void onComplete() {
-                        getMvpView().hideProgressbar();
-                        getMvpView().statusChangedSuccessfully();
-                    }
-
-                    @Override
-                    public void onError(Throwable throwable) {
-                        getMvpView().hideProgressbar();
-                        showExceptionError(throwable,
-                                context.getString(R.string.error_updating_status));
-                    }
-                })
-        );
+        try {
+            switch (Objects.requireNonNull(command.getAction())) {
+                case LOCK:
+                    customer.setCurrentState(Customer.State.LOCKED);
+                    break;
+                case REOPEN:
+                    customer.setCurrentState(Customer.State.PENDING);
+                    break;
+                case ACTIVATE:
+                case UNLOCK:
+                    customer.setCurrentState(Customer.State.ACTIVE);
+                    break;
+                case CLOSE:
+                    customer.setCurrentState(Customer.State.CLOSED);
+                    break;
+            }
+            synchronizationManager.updateDocument(identifier, GsonUtilsKt.serializeToMap(customer));
+            getMvpView().hideProgressbar();
+            getMvpView().statusChangedSuccessfully();
+        } catch (Exception e) {
+            getMvpView().hideProgressbar();
+            showExceptionError(e,
+                    context.getString(R.string.error_updating_status));
+            Log.e("CustomerTasks", e.toString());
+        }
     }
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/groups/creategroup/CreateGroupActivity.kt b/app/src/main/java/org/apache/fineract/ui/online/groups/creategroup/CreateGroupActivity.kt
index 00e5a8a..871f53f 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/groups/creategroup/CreateGroupActivity.kt
+++ b/app/src/main/java/org/apache/fineract/ui/online/groups/creategroup/CreateGroupActivity.kt
@@ -15,8 +15,8 @@
 import org.apache.fineract.ui.base.FineractBaseActivity
 import org.apache.fineract.ui.base.Toaster
 import org.apache.fineract.ui.online.groups.GroupAction
-import org.apache.fineract.ui.online.groups.grouplist.GroupViewModelFactory
 import org.apache.fineract.ui.online.groups.grouplist.GroupViewModel
+import org.apache.fineract.ui.online.groups.grouplist.GroupViewModelFactory
 import org.apache.fineract.utils.Constants
 import org.apache.fineract.utils.DateUtils
 import javax.inject.Inject
@@ -85,7 +85,7 @@
                 Status.DONE -> {
                     hideMifosProgressDialog()
                     if (groupAction == GroupAction.CREATE) {
-                        Toast.makeText(this, getString(R.string.group_identifier_updated_successfully, group.identifier), Toast.LENGTH_SHORT).show()
+                        Toast.makeText(this, getString(R.string.group_identifier_created_successfully, group.identifier), Toast.LENGTH_SHORT).show()
                     } else {
                         Toast.makeText(this, getString(R.string.group_identifier_updated_successfully, group.identifier), Toast.LENGTH_SHORT).show()
                     }
@@ -98,7 +98,7 @@
     override fun onCompleted(completeButton: View?) {
         when (groupAction) {
             GroupAction.EDIT -> group.identifier?.let {
-                viewModel.updateGroup(it, group)
+                viewModel.updateGroup(group)
             }
             GroupAction.CREATE -> viewModel.createGroup(group)
         }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupListFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupListFragment.kt
index 448554b..fad1dfd 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupListFragment.kt
+++ b/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupListFragment.kt
@@ -30,6 +30,7 @@
  * Created by saksham on 15/June/2019
 */
 
+
 class GroupListFragment : FineractBaseFragment(), OnItemClickListener {
 
     lateinit var rootView: View
@@ -42,6 +43,7 @@
     @Inject
     lateinit var groupViewModelFactory: GroupViewModelFactory
 
+
     lateinit var groupList: ArrayList<Group>
 
     val searchedGroup: (ArrayList<Group>) -> Unit = { groups ->
@@ -63,15 +65,11 @@
                               savedInstanceState: Bundle?): View? {
         rootView = inflater.inflate(R.layout.fragment_group_list, container, false)
         (activity as FineractBaseActivity).activityComponent.inject(this)
-        viewModel = ViewModelProviders.of(this,
-                groupViewModelFactory).get(GroupViewModel::class.java)
+        viewModel = ViewModelProviders.of(this, groupViewModelFactory)
+                .get(GroupViewModel::class.java)
         return rootView
     }
 
-    override fun onActivityCreated(savedInstanceState: Bundle?) {
-        super.onActivityCreated(savedInstanceState)
-    }
-
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
         ButterKnife.bind(this, rootView)
@@ -79,12 +77,16 @@
 
         rvGroups.adapter = adapter
         rvGroups.layoutManager = LinearLayoutManager(context)
-        viewModel.getGroups().observe(this,
+    }
 
-                Observer {
-                    groupList = it
-                    adapter.setGroupList(it)
-                })
+    override fun onStart() {
+        super.onStart()
+        viewModel.getGroups()?.observe(this, Observer {
+            it?.let {
+                groupList = it
+                adapter.setGroupList(it)
+            }
+        })
     }
 
     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
diff --git a/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupViewModel.kt b/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupViewModel.kt
index 6f9f159..8618704 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupViewModel.kt
+++ b/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupViewModel.kt
@@ -4,43 +4,58 @@
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import com.couchbase.lite.Expression
 import io.reactivex.Observable
 import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.functions.Predicate
 import io.reactivex.schedulers.Schedulers
 import kotlinx.coroutines.*
+import org.apache.fineract.couchbase.DocumentType
+import org.apache.fineract.couchbase.SynchronizationManager
 import org.apache.fineract.data.Status
 import org.apache.fineract.data.datamanager.api.DataManagerAnonymous
-import org.apache.fineract.data.datamanager.api.DataManagerGroups
+import org.apache.fineract.data.local.PreferencesHelper
 import org.apache.fineract.data.models.Group
 import org.apache.fineract.data.models.customer.Command
 import org.apache.fineract.data.models.customer.Country
+import org.apache.fineract.utils.DateUtils
+import org.apache.fineract.utils.serializeToMap
+import org.apache.fineract.utils.toDataClass
 
 /*
  * Created by saksham on 15/June/2019
 */
 
-class GroupViewModel constructor(val dataManagerGroups: DataManagerGroups, val dataManagerAnonymous: DataManagerAnonymous) : ViewModel() {
+class GroupViewModel constructor(private val synchronizationManager: SynchronizationManager,
+                                 private val dataManagerAnonymous: DataManagerAnonymous,
+                                 private val preferencesHelper: PreferencesHelper) : ViewModel() {
 
-    lateinit var groupsList: MutableLiveData<ArrayList<Group>>
+    var groupsList = MutableLiveData<ArrayList<Group>>()
     private var viewModelJob = Job()
+
     // Create a Coroutine scope using a job to be able to cancel when needed
     private val uiScope = CoroutineScope(viewModelJob + Dispatchers.IO)
     private var _status = MutableLiveData<Status>()
     val status: LiveData<Status>
         get() = _status
 
-    fun getGroups(): MutableLiveData<ArrayList<Group>> {
-        groupsList = dataManagerGroups.getGroups()
+    fun getGroups(): MutableLiveData<ArrayList<Group>>? {
+        val expression = Expression.property("documentType")
+                .equalTo(Expression.string(DocumentType.GROUP.value))
+                .and(Expression.property("status").notEqualTo(Expression.string("null")))
+        val hashMapList = synchronizationManager.getDocuments(expression)
+        if (hashMapList?.isEmpty() == null) {
+            return null
+        }
+        val list = arrayListOf<Group>()
+        for (map in hashMapList) {
+            list.add(map.toDataClass())
+        }
+        groupsList.value = list
         return groupsList
     }
 
     fun searchGroup(groups: ArrayList<Group>, query: String, searchedGroup: (ArrayList<Group>) -> Unit) {
-        searchedGroup(ArrayList(Observable.fromIterable(groups).filter(object : Predicate<Group> {
-            override fun test(group: Group): Boolean {
-                return group.identifier?.toLowerCase()?.contains(query.toLowerCase()).toString().toBoolean()
-            }
-        }).toList().blockingGet()))
+        searchedGroup(ArrayList(Observable.fromIterable(groups).filter { group -> group.identifier?.toLowerCase()?.contains(query.toLowerCase()).toString().toBoolean() }.toList().blockingGet()))
     }
 
     @SuppressLint("CheckResult")
@@ -59,7 +74,11 @@
             withContext(Dispatchers.Main) {
                 try {
                     _status.value = Status.LOADING
-                    dataManagerGroups.createGroup(group).await()
+                    group.createdBy = preferencesHelper.userName
+                    group.createdOn = DateUtils.getCurrentDate()
+                    group.lastModifiedBy = preferencesHelper.userName
+                    group.lastModifiedOn = DateUtils.getCurrentDate()
+                    synchronizationManager.saveDocument(group.identifier!!, group.serializeToMap())
                     _status.value = Status.DONE
                 } catch (e: Exception) {
                     _status.value = Status.ERROR
@@ -68,12 +87,12 @@
         }
     }
 
-    fun updateGroup(identifier: String, group: Group) {
+    fun updateGroup(group: Group) {
         uiScope.launch {
             withContext(Dispatchers.Main) {
                 try {
                     _status.value = Status.LOADING
-                    dataManagerGroups.updateGroup(identifier, group).await()
+                    synchronizationManager.updateDocument(group.identifier!!, group.serializeToMap())
                     _status.value = Status.DONE
                 } catch (e: Exception) {
                     _status.value = Status.ERROR
@@ -82,12 +101,20 @@
         }
     }
 
-    fun changeGroupStatus(identifier: String, command: Command) {
+    fun changeGroupStatus(identifier: String, group: Group, command: Command) {
         uiScope.launch {
             withContext(Dispatchers.Main) {
                 try {
                     _status.value = Status.LOADING
-                    dataManagerGroups.changeGroupStatus(identifier, command).await()
+                    when (command.action) {
+                        Command.Action.ACTIVATE -> group.status = Group.Status.ACTIVE
+                        Command.Action.REOPEN -> group.status = Group.Status.PENDING
+                        Command.Action.CLOSE -> group.status = Group.Status.CLOSED
+                        Command.Action.LOCK -> group.status = Group.Status.ACTIVE
+                        else -> group.status = Group.Status.PENDING
+                    }
+                    synchronizationManager.updateDocument(identifier, group.serializeToMap())
+                    //   dataManagerGroups.changeGroupStatus(identifier, command).await()
                     _status.value = Status.DONE
                 } catch (e: Exception) {
                     _status.value = Status.ERROR
@@ -102,7 +129,7 @@
 
     fun getCountryCode(countries: List<Country>, countryName: String): String? {
         for (country in countries) {
-            if (country.name.equals(countryName)) {
+            if (country.name == countryName) {
                 return country.alphaCode
             }
         }
@@ -111,7 +138,7 @@
 
     fun isCountryValid(countries: List<Country>, countryName: String): Boolean {
         for (country in countries) {
-            if (country.name.equals(countryName)) {
+            if (country.name == countryName) {
                 return true
             }
         }
@@ -125,6 +152,7 @@
     override fun onCleared() {
         super.onCleared()
         viewModelJob.cancel()
+        synchronizationManager.closeDatabase()
     }
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupViewModelFactory.kt b/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupViewModelFactory.kt
index f541a37..0d713f9 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupViewModelFactory.kt
+++ b/app/src/main/java/org/apache/fineract/ui/online/groups/grouplist/GroupViewModelFactory.kt
@@ -3,8 +3,9 @@
 import android.content.Context
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
+import org.apache.fineract.couchbase.SynchronizationManager
 import org.apache.fineract.data.datamanager.api.DataManagerAnonymous
-import org.apache.fineract.data.datamanager.api.DataManagerGroups
+import org.apache.fineract.data.local.PreferencesHelper
 import org.apache.fineract.injection.ApplicationContext
 import javax.inject.Inject
 
@@ -15,11 +16,13 @@
 
 
 class GroupViewModelFactory @Inject constructor(@ApplicationContext var context: Context,
-                                                private val dataManagerGroups: DataManagerGroups,
-                                                private val dataManagerAnonymous: DataManagerAnonymous)
+                                                private val synchronizationManager: SynchronizationManager,
+                                                private val dataManagerAnonymous: DataManagerAnonymous,
+                                                private val preferencesHelper: PreferencesHelper)
     : ViewModelProvider.NewInstanceFactory() {
 
+    @Suppress("UNCHECKED_CAST")
     override fun <T : ViewModel?> create(modelClass: Class<T>): T {
-        return GroupViewModel(dataManagerGroups, dataManagerAnonymous) as T
+        return GroupViewModel(synchronizationManager, dataManagerAnonymous, preferencesHelper) as T
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/groups/grouptasks/GroupTasksBottomSheetFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/groups/grouptasks/GroupTasksBottomSheetFragment.kt
index 76c601d..06893f4 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/groups/grouptasks/GroupTasksBottomSheetFragment.kt
+++ b/app/src/main/java/org/apache/fineract/ui/online/groups/grouptasks/GroupTasksBottomSheetFragment.kt
@@ -123,7 +123,7 @@
         command.comment = rootView.et_comment.text.toString().trim { it <= ' ' }
         rootView.et_comment.isEnabled = false
         group.identifier?.let {
-            viewModel.changeGroupStatus(it, command)
+            viewModel.changeGroupStatus(it, group, command)
         }
     }
 
@@ -134,7 +134,7 @@
 
     override fun onStart() {
         super.onStart()
-        behavior?.state = BottomSheetBehavior.STATE_EXPANDED
+        behavior.state = BottomSheetBehavior.STATE_EXPANDED
     }
 
     override fun onDestroy() {
diff --git a/app/src/main/java/org/apache/fineract/ui/online/launcher/LauncherActivity.java b/app/src/main/java/org/apache/fineract/ui/online/launcher/LauncherActivity.java
index 07a4403..3f034c8 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/launcher/LauncherActivity.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/launcher/LauncherActivity.java
@@ -18,7 +18,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 18/06/17.
+ * On 18/06/17.
  */
 public class LauncherActivity extends FineractBaseActivity implements LauncherContract.View {
 
@@ -33,6 +33,7 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        setTheme(R.style.AppTheme);
         setContentView(R.layout.activity_launcher);
         getActivityComponent().inject(this);
         launcherPresenter.attachView(this);
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanaccountlist/LoanAccountsFragment.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanaccountlist/LoanAccountsFragment.java
index 7862fca..a0ea70e 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanaccountlist/LoanAccountsFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanaccountlist/LoanAccountsFragment.java
@@ -24,6 +24,7 @@
 import org.apache.fineract.ui.base.FineractBaseFragment;
 import org.apache.fineract.ui.base.OnItemClickListener;
 import org.apache.fineract.ui.base.Toaster;
+import org.apache.fineract.ui.online.loanaccounts.loanapplication.LoanApplicationAction;
 import org.apache.fineract.ui.online.loanaccounts.loanapplication.loanactivity.LoanApplicationActivity;
 import org.apache.fineract.ui.online.loanaccounts.loandetails.CustomerLoanDetailsFragment;
 import org.apache.fineract.utils.ConstantKeys;
@@ -39,7 +40,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 07/07/17.
+ * On 07/07/17.
  */
 public class LoanAccountsFragment extends FineractBaseFragment implements LoanAccountsContract.View,
         SwipeRefreshLayout.OnRefreshListener, OnItemClickListener {
@@ -83,7 +84,7 @@
 
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
+                             @Nullable Bundle savedInstanceState) {
         rootView = inflater.inflate(R.layout.fragment_customer_loans, container, false);
         ((FineractBaseActivity) getActivity()).getActivityComponent().inject(this);
         ButterKnife.bind(this, rootView);
@@ -119,6 +120,7 @@
     void createNewLoan() {
         Intent intent = new Intent(getActivity(), LoanApplicationActivity.class);
         intent.putExtra(ConstantKeys.CUSTOMER_IDENTIFIER, customerIdentifier);
+        intent.putExtra(ConstantKeys.LOAN_APPLICATION_ACTION, LoanApplicationAction.CREATE);
         startActivity(intent);
     }
 
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/BaseFragmentDebtIncome.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/BaseFragmentDebtIncome.java
index 91d12fc..e70e63c 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/BaseFragmentDebtIncome.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/BaseFragmentDebtIncome.java
@@ -69,8 +69,8 @@
     private Double totalIncome = 0.0;
     private Double ratio = 00.00;
 
-    private List<CreditWorthinessFactor> debtCreditWorthinessFactors;
-    private List<CreditWorthinessFactor> incomeCreditWorthinessFactors;
+    protected List<CreditWorthinessFactor> debtCreditWorthinessFactors;
+    protected List<CreditWorthinessFactor> incomeCreditWorthinessFactors;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/LoanApplicationAction.kt b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/LoanApplicationAction.kt
new file mode 100644
index 0000000..c9f745c
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/LoanApplicationAction.kt
@@ -0,0 +1,6 @@
+package org.apache.fineract.ui.online.loanaccounts.loanapplication
+
+enum class LoanApplicationAction {
+    CREATE,
+    EDIT
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/LoanDebtIncomeFragment.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/LoanDebtIncomeFragment.java
index 173a9e4..31a1fdc 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/LoanDebtIncomeFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/LoanDebtIncomeFragment.java
@@ -3,29 +3,72 @@
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.NonNull;
+import android.view.View;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.gson.Gson;
 import com.stepstone.stepper.Step;
 import com.stepstone.stepper.VerificationError;
 
 import org.apache.fineract.R;
+import org.apache.fineract.data.models.loan.CreditWorthinessFactor;
+import org.apache.fineract.data.models.loan.CreditWorthinessSnapshot;
+import org.apache.fineract.data.models.loan.LoanAccount;
+import org.apache.fineract.data.models.loan.LoanParameters;
+import org.apache.fineract.utils.ConstantKeys;
+
+import java.util.Objects;
 
 /**
  * @author Rajan Maurya
- *         On 24/07/17.
+ * On 24/07/17.
  */
 public class LoanDebtIncomeFragment extends BaseFragmentDebtIncome implements Step {
 
     private OnNavigationBarListener.LoanDebtIncomeData onNavigationBarListener;
+    private LoanApplicationAction loanApplicationAction;
+    private LoanAccount loanAccount;
+    private LoanParameters loanParameters;
 
-    public static LoanDebtIncomeFragment newInstance() {
+    public static LoanDebtIncomeFragment newInstance(
+            LoanAccount loanAccount,
+            LoanApplicationAction loanApplicationAction) {
         LoanDebtIncomeFragment fragment = new LoanDebtIncomeFragment();
         Bundle args = new Bundle();
+        args.putSerializable(ConstantKeys.LOAN_APPLICATION_ACTION, loanApplicationAction);
+        args.putParcelable(ConstantKeys.LOAN_ACCOUNT, loanAccount);
         fragment.setArguments(args);
         return fragment;
     }
 
     @Override
+    public void onViewCreated(@NonNull View view,
+                              @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        loanApplicationAction = (LoanApplicationAction) getArguments()
+                .getSerializable(ConstantKeys.LOAN_APPLICATION_ACTION);
+
+        if (loanApplicationAction == LoanApplicationAction.EDIT) {
+            loanAccount = getArguments().getParcelable(ConstantKeys.LOAN_ACCOUNT);
+            loanParameters = new Gson().fromJson(loanAccount.getParameters(), LoanParameters.class);
+            for (CreditWorthinessSnapshot snapshot
+                    : Objects.requireNonNull(loanParameters.getCreditWorthinessSnapshots())) {
+                for (CreditWorthinessFactor debt : snapshot.getDebts()) {
+                    addDebt(debt);
+                }
+
+                for (CreditWorthinessFactor income : snapshot.getIncomeSources()) {
+                    addDebt(income);
+                }
+            }
+
+        }
+
+    }
+
+    @Override
     protected int getFragmentLayout() {
         return R.layout.fragment_loan_debt_income_ratio;
     }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationActivity.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationActivity.java
index 4dd4e51..578a915 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationActivity.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationActivity.java
@@ -17,6 +17,7 @@
 import org.apache.fineract.ui.adapters.LoanApplicationStepAdapter;
 import org.apache.fineract.ui.base.FineractBaseActivity;
 import org.apache.fineract.ui.base.Toaster;
+import org.apache.fineract.ui.online.loanaccounts.loanapplication.LoanApplicationAction;
 import org.apache.fineract.ui.online.loanaccounts.loanapplication.OnNavigationBarListener;
 import org.apache.fineract.utils.ConstantKeys;
 
@@ -30,7 +31,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 17/07/17.
+ * On 17/07/17.
  */
 public class LoanApplicationActivity extends FineractBaseActivity
         implements StepperLayout.StepperListener, OnNavigationBarListener.LoanDetailsData,
@@ -53,6 +54,8 @@
     private String customerIdentifier;
     private LoanParameters loanParameters;
     private String selectedProduct;
+    private LoanApplicationAction loanApplicationAction;
+    private String caseIdentifier;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -64,18 +67,31 @@
         creditWorthinessSnapshots = new ArrayList<>();
         loanAccount = new LoanAccount();
         loanParameters = new LoanParameters();
-
+        loanApplicationAction = (LoanApplicationAction) getIntent()
+                .getSerializableExtra(ConstantKeys.LOAN_APPLICATION_ACTION);
         customerIdentifier = getIntent().getExtras().getString(ConstantKeys.CUSTOMER_IDENTIFIER);
+        switch (loanApplicationAction) {
+            case CREATE:
+                setToolbarTitle(getString(R.string.create_new_loan));
+                break;
+            case EDIT:
+                setToolbarTitle(getString(R.string.edit_loan));
+                caseIdentifier = getIntent().getExtras().getString(ConstantKeys.CASE_IDENTIFIER);
+                loanAccount = getIntent().getExtras().getParcelable(ConstantKeys.LOAN_ACCOUNT);
+                if (loanAccount != null) {
+                    loanParameters = loanAccount.getLoanParameters();
+                }
+        }
 
         if (savedInstanceState != null) {
             currentPosition = savedInstanceState.getInt(CURRENT_STEP_POSITION);
         }
         LoanApplicationStepAdapter stepAdapter = new LoanApplicationStepAdapter(
-                getSupportFragmentManager(), this);
+                getSupportFragmentManager(), this, loanAccount, loanApplicationAction);
         stepperLayout.setAdapter(stepAdapter, currentPosition);
         stepperLayout.setListener(this);
         stepperLayout.setOffscreenPageLimit(stepAdapter.getCount());
-        setToolbarTitle(getString(R.string.create_new_loan));
+
         showBackButton();
     }
 
@@ -94,7 +110,18 @@
     @Override
     public void onCompleted(View completeButton) {
         loanParameters.setCreditWorthinessSnapshots(creditWorthinessSnapshots);
-        loanApplicationPresenter.createLoan(loanAccount.getProductIdentifier(), loanAccount);
+        switch (loanApplicationAction) {
+            case CREATE:
+                loanApplicationPresenter.createLoan(
+                        loanAccount.getProductIdentifier(),
+                        loanAccount);
+            case EDIT:
+                loanApplicationPresenter.updateLoan(
+                        loanAccount.getProductIdentifier(),
+                        loanAccount,
+                        caseIdentifier);
+        }
+
     }
 
     @Override
@@ -120,6 +147,11 @@
     }
 
     @Override
+    public void applicationUpdatedSuccessfully() {
+        finish();
+    }
+
+    @Override
     public void showProgressbar(String message) {
         stepperLayout.showProgress(message);
     }
@@ -140,9 +172,12 @@
     }
 
     @Override
-    public void setLoanDetails(LoanAccount.State currentState, String identifier,
-            String productIdentifier, Double maximumBalance, PaymentCycle paymentCycle,
-            TermRange termRange, String selectedProduct) {
+    public void setLoanDetails(LoanAccount.State currentState,
+                               String identifier,
+                               String productIdentifier,
+                               Double maximumBalance,
+                               PaymentCycle paymentCycle,
+                               TermRange termRange, String selectedProduct) {
         this.selectedProduct = selectedProduct;
 
         loanAccount.setCurrentState(currentState);
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationContract.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationContract.java
index 753d63e..4722418 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationContract.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationContract.java
@@ -13,6 +13,8 @@
 
         void applicationCreatedSuccessfully();
 
+        void applicationUpdatedSuccessfully();
+
         void showProgressbar(String message);
 
         void hideProgressbar();
@@ -23,5 +25,7 @@
     interface Presenter {
 
         void createLoan(String productIdentifier, LoanAccount loanAccount);
+
+        void updateLoan(String productIdentifier, LoanAccount loanAccount, String caseIdentifier);
     }
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationPresenter.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationPresenter.java
index 8bcf87b..a53b716 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationPresenter.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loanactivity/LoanApplicationPresenter.java
@@ -18,7 +18,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 24/07/17.
+ * On 24/07/17.
  */
 @ConfigPersistent
 public class LoanApplicationPresenter extends BasePresenter<LoanApplicationContract.View>
@@ -29,7 +29,7 @@
 
     @Inject
     public LoanApplicationPresenter(@ApplicationContext Context context,
-            DataManagerLoans dataManagerLoans) {
+                                    DataManagerLoans dataManagerLoans) {
         super(context);
         this.dataManagerLoans = dataManagerLoans;
         compositeDisposable = new CompositeDisposable();
@@ -69,4 +69,34 @@
                 })
         );
     }
+
+    @Override
+    public void updateLoan(String productIdentifier,
+                           LoanAccount loanAccount,
+                           String caseIdentifier) {
+        checkViewAttached();
+        getMvpView().showProgressbar(context.getString(R.string.updating_loan_please_wait));
+        compositeDisposable.add(dataManagerLoans.updateLoan(
+                productIdentifier,
+                loanAccount,
+                caseIdentifier
+                ).subscribeOn(Schedulers.io())
+                        .observeOn(AndroidSchedulers.mainThread())
+                        .subscribeWith(new DisposableCompletableObserver() {
+                            @Override
+                            public void onComplete() {
+                                getMvpView().hideProgressbar();
+                                getMvpView().applicationUpdatedSuccessfully();
+                            }
+
+                            @Override
+                            public void onError(Throwable throwable) {
+                                getMvpView().hideProgressbar();
+                                showExceptionError(throwable,
+                                        context.getString(R.string.error_while_updating_loan));
+                            }
+                        })
+        );
+    }
+
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loancosigner/LoanCoSignerFragment.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loancosigner/LoanCoSignerFragment.java
index 21f82fc..4851655 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loancosigner/LoanCoSignerFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loancosigner/LoanCoSignerFragment.java
@@ -3,23 +3,29 @@
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.ArrayAdapter;
 import android.widget.AutoCompleteTextView;
 import android.widget.ImageView;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.gson.Gson;
 import com.stepstone.stepper.Step;
 import com.stepstone.stepper.VerificationError;
 
 import org.apache.fineract.R;
 import org.apache.fineract.data.models.loan.CreditWorthinessSnapshot;
+import org.apache.fineract.data.models.loan.LoanAccount;
+import org.apache.fineract.data.models.loan.LoanParameters;
 import org.apache.fineract.ui.base.FineractBaseActivity;
 import org.apache.fineract.ui.base.Toaster;
 import org.apache.fineract.ui.online.loanaccounts.loanapplication.BaseFragmentDebtIncome;
+import org.apache.fineract.ui.online.loanaccounts.loanapplication.LoanApplicationAction;
 import org.apache.fineract.ui.online.loanaccounts.loanapplication.OnNavigationBarListener;
+import org.apache.fineract.utils.ConstantKeys;
 
 import java.util.List;
 
@@ -30,7 +36,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 19/07/17.
+ * On 19/07/17.
  */
 public class LoanCoSignerFragment extends BaseFragmentDebtIncome implements Step,
         LoanCoSignerContract.View {
@@ -49,10 +55,17 @@
     String[] customers;
 
     private OnNavigationBarListener.LoanCoSignerData onNavigationBarListener;
+    private LoanAccount loanAccount;
+    private LoanApplicationAction loanApplicationAction;
+    private LoanParameters loanParameters;
 
-    public static LoanCoSignerFragment newInstance() {
+    public static LoanCoSignerFragment newInstance(
+            LoanAccount loanAccount,
+            LoanApplicationAction loanApplicationAction) {
         LoanCoSignerFragment fragment = new LoanCoSignerFragment();
         Bundle args = new Bundle();
+        args.putSerializable(ConstantKeys.LOAN_APPLICATION_ACTION, loanApplicationAction);
+        args.putParcelable(ConstantKeys.LOAN_ACCOUNT, loanAccount);
         fragment.setArguments(args);
         return fragment;
     }
@@ -62,13 +75,23 @@
         super.onViewCreated(view, savedInstanceState);
         ((FineractBaseActivity) getActivity()).getActivityComponent().inject(this);
         loanCoSignerPresenter.attachView(this);
+        loanApplicationAction = (LoanApplicationAction) getArguments()
+                .getSerializable(ConstantKeys.LOAN_APPLICATION_ACTION);
+        if (loanApplicationAction == LoanApplicationAction.EDIT) {
+            loanAccount = getArguments().getParcelable(ConstantKeys.LOAN_ACCOUNT);
+            loanParameters = new Gson().fromJson(loanAccount.getParameters(), LoanParameters.class);
+            etCustomer.setText(
+                    loanParameters.getCreditWorthinessSnapshots().get(0).getForCustomer()
+            );
+        }
         rootView = view;
     }
 
     @OnClick(R.id.iv_search_customer)
     void searchCustomer() {
         if (TextUtils.isEmpty(etCustomer.getText().toString())) {
-            Toaster.show(rootView, getString(R.string.customer_name_should_not_be_empty));
+            Toaster.show(rootView,
+                    getString(R.string.customer_name_should_not_be_empty));
         } else {
             loanCoSignerPresenter.searchCustomer(etCustomer.getText().toString().trim());
         }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loancosigner/LoanCoSignerPresenter.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loancosigner/LoanCoSignerPresenter.java
index ee34cd2..a26d4e3 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loancosigner/LoanCoSignerPresenter.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loancosigner/LoanCoSignerPresenter.java
@@ -23,7 +23,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 24/07/17.
+ * On 24/07/17.
  */
 @ConfigPersistent
 public class LoanCoSignerPresenter extends BasePresenter<LoanCoSignerContract.View>
@@ -37,7 +37,7 @@
 
     @Inject
     public LoanCoSignerPresenter(@ApplicationContext Context context,
-            DataManagerCustomer dataManagerCustomer) {
+                                 DataManagerCustomer dataManagerCustomer) {
         super(context);
         this.dataManagerCustomer = dataManagerCustomer;
         compositeDisposable = new CompositeDisposable();
@@ -96,6 +96,7 @@
     @Override
     public Boolean findCustomer(final String customer, String[] customers) {
         boolean isCustomerPresent = false;
+        if (customers == null) return false;
         for (String s : customers) {
             if (s.equals(customer)) {
                 isCustomerPresent = true;
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsContract.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsContract.java
index f591509..c13ae62 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsContract.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsContract.java
@@ -7,7 +7,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 20/07/17.
+ * On 20/07/17.
  */
 
 public class LoanDetailsContract {
@@ -46,5 +46,7 @@
         void setProductPositionAndValidateViews(Integer position);
 
         List<String> getCurrentTermUnitType(List<String> unitTypes, String unitType);
+
+        int getItemIndexFromList(List<String> list, String item);
     }
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsFragment.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsFragment.java
index 54e208b..1acf683 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsFragment.java
@@ -3,11 +3,6 @@
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import com.google.android.material.textfield.TextInputLayout;
-import androidx.core.widget.NestedScrollView;
-import androidx.appcompat.widget.AppCompatSpinner;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.view.LayoutInflater;
@@ -19,18 +14,28 @@
 import android.widget.LinearLayout;
 import android.widget.RadioButton;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatSpinner;
+import androidx.core.widget.NestedScrollView;
+
+import com.google.android.material.textfield.TextInputLayout;
+import com.google.gson.Gson;
 import com.stepstone.stepper.Step;
 import com.stepstone.stepper.VerificationError;
 
 import org.apache.fineract.R;
 import org.apache.fineract.data.models.loan.LoanAccount;
+import org.apache.fineract.data.models.loan.LoanParameters;
 import org.apache.fineract.data.models.loan.PaymentCycle;
 import org.apache.fineract.data.models.loan.TermRange;
 import org.apache.fineract.data.models.product.Product;
 import org.apache.fineract.ui.base.FineractBaseActivity;
 import org.apache.fineract.ui.base.FineractBaseFragment;
 import org.apache.fineract.ui.base.Toaster;
+import org.apache.fineract.ui.online.loanaccounts.loanapplication.LoanApplicationAction;
 import org.apache.fineract.ui.online.loanaccounts.loanapplication.OnNavigationBarListener;
+import org.apache.fineract.utils.ConstantKeys;
 import org.apache.fineract.utils.Utils;
 import org.apache.fineract.utils.ValidateIdentifierUtil;
 import org.apache.fineract.utils.ValidationUtil;
@@ -47,7 +52,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 17/07/17.
+ * On 17/07/17.
  */
 public class LoanDetailsFragment extends FineractBaseFragment implements Step,
         LoanDetailsContract.View, AdapterView.OnItemSelectedListener, TextWatcher {
@@ -141,10 +146,17 @@
 
     private ArrayAdapter<String> productsAdapter;
     private ArrayAdapter<String> termUnitTypeAdapter;
+    private LoanAccount loanAccount;
+    private LoanParameters loanParameters;
+    private LoanApplicationAction loanApplicationAction;
 
-    public static LoanDetailsFragment newInstance() {
+    public static LoanDetailsFragment newInstance(
+            LoanAccount loanAccount,
+            LoanApplicationAction loanApplicationAction) {
         LoanDetailsFragment fragment = new LoanDetailsFragment();
         Bundle args = new Bundle();
+        args.putParcelable(ConstantKeys.LOAN_ACCOUNT, loanAccount);
+        args.putSerializable(ConstantKeys.LOAN_APPLICATION_ACTION, loanApplicationAction);
         fragment.setArguments(args);
         return fragment;
     }
@@ -170,12 +182,23 @@
 
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
+                             @Nullable Bundle savedInstanceState) {
         rootView = inflater.inflate(R.layout.fragment_loan_details, container, false);
         ButterKnife.bind(this, rootView);
         initializeFineractUIErrorHandler(getActivity(), rootView);
         loanDetailsPresenter.attachView(this);
 
+        if (getArguments() != null) {
+            loanApplicationAction = (LoanApplicationAction) getArguments().getSerializable(
+                    ConstantKeys.LOAN_APPLICATION_ACTION);
+        }
+
+        if (loanApplicationAction == LoanApplicationAction.EDIT) {
+            loanAccount = getArguments().getParcelable(ConstantKeys.LOAN_ACCOUNT);
+            loanParameters = new Gson().fromJson(loanAccount.getParameters(), LoanParameters.class);
+        }
+
+
         showUserInterface();
 
         loanDetailsPresenter.fetchProducts();
@@ -190,6 +213,65 @@
         loanDetailsPresenter.fetchProducts();
     }
 
+    public void showPreviousLoanDetails() {
+        spProducts.setSelection(loanDetailsPresenter.getItemIndexFromList(
+                products,
+                loanAccount.getProductIdentifier()
+        ));
+        etRepay.setText(String.valueOf(
+                loanParameters.getPaymentCycle().getPeriod()
+        ));
+        spTermUnitType.setSelection(
+                loanDetailsPresenter.getItemIndexFromList(
+                        repayUnitType,
+                        String.valueOf(loanParameters.getPaymentCycle().getTemporalUnit()))
+        );
+
+
+        int unitType = loanDetailsPresenter.getItemIndexFromList(
+                repayUnitType,
+                String.valueOf(loanParameters.getPaymentCycle().getTemporalUnit()));
+        switch (unitType) {
+            case 0:
+                spRepayUnitType.setSelection(0);
+                spRepayWeekDays.setSelection(loanParameters.getPaymentCycle().getAlignmentDay());
+                break;
+            case 1:
+                spRepayUnitType.setSelection(1);
+                if (loanParameters.getPaymentCycle().getAlignmentMonth() == null) {
+                    spRepayWeekDays.setSelection(
+                            loanParameters.getPaymentCycle().getAlignmentDay());
+                    rbRepayOnSpecificDay.setChecked(true);
+                    spRepayTimeSlots.setSelection(
+                            loanParameters.getPaymentCycle().getAlignmentWeek());
+                } else {
+                    rbRepayOnDay.setChecked(true);
+                    spRepayMonthDayInNumber.setSelection(
+                            loanParameters.getPaymentCycle().getAlignmentDay());
+                }
+                break;
+            case 2:
+                spRepayUnitType.setSelection(2);
+                if (loanParameters.getPaymentCycle().getAlignmentMonth() == null) {
+                    rbRepayOnSpecificDay.setChecked(true);
+                    spRepayWeekDays.setSelection(
+                            loanParameters.getPaymentCycle().getAlignmentDay());
+                    spRepayTimeSlots.setSelection(
+                            loanParameters.getPaymentCycle().getAlignmentWeek());
+                } else {
+                    spRepayMonthDayInNumber.setSelection(
+                            loanParameters.getPaymentCycle().getAlignmentDay());
+                    spRepayYearMonth.setSelection(
+                            loanParameters.getPaymentCycle().getAlignmentMonth());
+                }
+                break;
+        }
+
+        etShortName.setText(loanAccount.getIdentifier());
+        etPrincipalAmount.setText(String.valueOf(loanParameters.getMaximumBalance()));
+        etTerm.setText(String.valueOf(loanParameters.getTermRange().getMaximum()));
+    }
+
     @Override
     public VerificationError verifyStep() {
         if (!validateShortName() || !validateTerm() || !validateRepay()
@@ -233,11 +315,12 @@
                             Double.parseDouble(etTerm.getText().toString().trim()))
                     , spProducts.getSelectedItem().toString());
 
-
             return null;
         }
+
     }
 
+
     @Override
     public void onSelected() {
         // when every condition will fine in verifyStep();
@@ -343,14 +426,19 @@
     @Override
     public void setComponentsValidations(Product product) {
         this.product = product;
-        etPrincipalAmount.setText(String.valueOf(product.getBalanceRange().getMinimum()));
         ternUnitType.clear();
         ternUnitType.addAll(loanDetailsPresenter.getCurrentTermUnitType(
                 repayUnitType, product.getTermRange().getTemporalUnit()));
         termUnitTypeAdapter.notifyDataSetChanged();
         spTermUnitType.setEnabled(false);
-        etTerm.setText("1");
-        etRepay.setText("1");
+
+        if (loanApplicationAction == LoanApplicationAction.CREATE) {
+            etPrincipalAmount.setText(String.valueOf(product.getBalanceRange().getMinimum()));
+            etTerm.setText("1");
+            etRepay.setText("1");
+        } else {
+            showPreviousLoanDetails();
+        }
     }
 
     @Override
@@ -538,4 +626,6 @@
         outState.putStringArrayList("products", (ArrayList<String>) products);
         super.onSaveInstanceState(outState);
     }
+
+
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsPresenter.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsPresenter.java
index 67fc9ea..210c0b4 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsPresenter.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loanapplication/loandetails/LoanDetailsPresenter.java
@@ -25,7 +25,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 20/07/17.
+ * On 20/07/17.
  */
 @ConfigPersistent
 public class LoanDetailsPresenter extends BasePresenter<LoanDetailsContract.View>
@@ -41,7 +41,7 @@
 
     @Inject
     public LoanDetailsPresenter(@ApplicationContext Context context,
-            DataManagerLoans dataManagerLoans) {
+                                DataManagerLoans dataManagerLoans) {
         super(context);
         this.dataManagerLoans = dataManagerLoans;
         compositeDisposable = new CompositeDisposable();
@@ -117,4 +117,16 @@
             }
         }).toList().blockingGet();
     }
+
+    @Override
+    public int getItemIndexFromList(List<String> list, String item) {
+        int index = 0;
+        for (int i = 0; i < list.size(); i++) {
+            if (list.get(i).equals(item)) {
+                index = i;
+                break;
+            }
+        }
+        return index;
+    }
 }
diff --git a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loandetails/CustomerLoanDetailsFragment.java b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loandetails/CustomerLoanDetailsFragment.java
index 51cbc3b..2128429 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loandetails/CustomerLoanDetailsFragment.java
+++ b/app/src/main/java/org/apache/fineract/ui/online/loanaccounts/loandetails/CustomerLoanDetailsFragment.java
@@ -2,9 +2,6 @@
 
 import android.content.Intent;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
-import androidx.core.widget.NestedScrollView;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -15,6 +12,11 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.widget.NestedScrollView;
+
 import com.google.gson.Gson;
 
 import org.apache.fineract.R;
@@ -22,8 +24,9 @@
 import org.apache.fineract.data.models.loan.PaymentCycle;
 import org.apache.fineract.ui.base.FineractBaseActivity;
 import org.apache.fineract.ui.base.FineractBaseFragment;
-import org.apache.fineract.ui.base.Toaster;
 import org.apache.fineract.ui.online.loanaccounts.debtincomereport.DebtIncomeReportActivity;
+import org.apache.fineract.ui.online.loanaccounts.loanapplication.LoanApplicationAction;
+import org.apache.fineract.ui.online.loanaccounts.loanapplication.loanactivity.LoanApplicationActivity;
 import org.apache.fineract.ui.online.loanaccounts.plannedpayment.PlannedPaymentActivity;
 import org.apache.fineract.utils.ConstantKeys;
 import org.apache.fineract.utils.DateUtils;
@@ -38,7 +41,7 @@
 
 /**
  * @author Rajan Maurya
- *         On 11/07/17.
+ * On 11/07/17.
  */
 public class CustomerLoanDetailsFragment extends FineractBaseFragment implements
         CustomerLoanDetailsContract.View {
@@ -94,9 +97,10 @@
     private String caseIdentifier;
     private LoanAccount loanAccount;
     private String[] weeksName, repayOnMonths, timeSlots, monthsName;
+    private Menu menu;
 
     public static CustomerLoanDetailsFragment newInstance(String productIdentifier,
-            String caseIdentifier) {
+                                                          String caseIdentifier) {
         CustomerLoanDetailsFragment fragment = new CustomerLoanDetailsFragment();
         Bundle args = new Bundle();
         args.putString(ConstantKeys.PRODUCT_IDENTIFIER, productIdentifier);
@@ -121,7 +125,7 @@
 
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
+                             @Nullable Bundle savedInstanceState) {
         rootView = inflater.inflate(R.layout.fragment_customer_loan_details, container, false);
         ((FineractBaseActivity) getActivity()).getActivityComponent().inject(this);
         ButterKnife.bind(this, rootView);
@@ -235,6 +239,11 @@
         tvLastModifiedBy.setText(getString(R.string.loan_last_modified_by,
                 loanAccount.getLastModifiedBy(),
                 DateUtils.getDateTime(loanAccount.getLastModifiedOn())));
+
+        if (loanAccount.getCurrentState() == LoanAccount.State.APPROVED ||
+                loanAccount.getCurrentState() == LoanAccount.State.CLOSED) {
+            hideEditMenu(menu);
+        }
     }
 
     @Override
@@ -265,14 +274,23 @@
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         inflater.inflate(R.menu.menu_loan_account_details, menu);
         Utils.setToolbarIconColor(getActivity(), menu, R.color.white);
+        this.menu = menu;
         super.onCreateOptionsMenu(menu, inflater);
     }
 
+    private void hideEditMenu(@NonNull Menu menu) {
+        menu.findItem(R.id.menu_loan_account_edit).setVisible(false);
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case R.id.menu_loan_account_edit:
-                Toaster.show(rootView, R.string.Under_construction);
+                Intent intent = new Intent(getActivity(), LoanApplicationActivity.class)
+                        .putExtra(ConstantKeys.CASE_IDENTIFIER, caseIdentifier)
+                        .putExtra(ConstantKeys.LOAN_APPLICATION_ACTION, LoanApplicationAction.EDIT)
+                        .putExtra(ConstantKeys.LOAN_ACCOUNT, loanAccount);
+                startActivity(intent);
                 return true;
             default:
                 return super.onOptionsItemSelected(item);
diff --git a/app/src/main/java/org/apache/fineract/ui/online/review/AddLoanReviewFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/review/AddLoanReviewFragment.kt
index 6115765..88f7dd0 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/review/AddLoanReviewFragment.kt
+++ b/app/src/main/java/org/apache/fineract/ui/online/review/AddLoanReviewFragment.kt
@@ -2,10 +2,10 @@
 
 import android.content.Context
 import android.os.Bundle
-import androidx.recyclerview.widget.LinearLayoutManager
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import butterknife.ButterKnife
 import com.stepstone.stepper.Step
@@ -240,7 +240,6 @@
 
     }
 
-
     private fun showTotalIncome(pos: Int): Double {
 
         var totalIncome = 0.0
diff --git a/app/src/main/java/org/apache/fineract/utils/ConstantKeys.java b/app/src/main/java/org/apache/fineract/utils/ConstantKeys.java
index 028076b..76c9d99 100644
--- a/app/src/main/java/org/apache/fineract/utils/ConstantKeys.java
+++ b/app/src/main/java/org/apache/fineract/utils/ConstantKeys.java
@@ -2,11 +2,11 @@
 
 /**
  * @author Rajan Maurya
- *         On 27/06/17.
+ * On 27/06/17.
  */
 public class ConstantKeys {
 
-    public static final String CUSTOMER_IDENTIFIER  = "customer_identifier";
+    public static final String CUSTOMER_IDENTIFIER = "customer_identifier";
     public static final String CUSTOMER_STATUS = "customer_status";
     public static final String IS_NEW_CUSTOMER = "is_new_customer";
     public static final String CUSTOMER_ACTION = "customer_action";
@@ -25,6 +25,9 @@
     public static final String DEPOSIT_ACTION = "deposit_action";
     public static final String DEPOSIT_ACCOUNT = "deposit";
     public static final String COUNTRIES = "countries";
+    public static final String LOAN_ACCOUNT = "loan_account";
+    public static final String LOAN_APPLICATION_ACTION = "loan_application_action";
+
 
     public static final String PAYROLL_CONFIG = "payrollConfiguration";
 
diff --git a/app/src/main/java/org/apache/fineract/utils/Constants.kt b/app/src/main/java/org/apache/fineract/utils/Constants.kt
index 6d9dca5..072c90f 100644
--- a/app/src/main/java/org/apache/fineract/utils/Constants.kt
+++ b/app/src/main/java/org/apache/fineract/utils/Constants.kt
@@ -8,4 +8,8 @@
 object Constants {
     const val GROUP = "group"
     const val GROUP_ACTION = "group_action"
+    const val DATABASE_NAME = "fineract-cn-mobile"
+    const val BASIC_AUTH_KEY = "basic_auth_key"
+    const val GATEWAY_USER_NAME = "fineract-cn"
+    const val GATEWAY_PASSWORD = "password"
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/utils/DateUtils.java b/app/src/main/java/org/apache/fineract/utils/DateUtils.java
index a582653..d9f8c25 100644
--- a/app/src/main/java/org/apache/fineract/utils/DateUtils.java
+++ b/app/src/main/java/org/apache/fineract/utils/DateUtils.java
@@ -61,7 +61,8 @@
         SimpleDateFormat dateFormat = new SimpleDateFormat(inputFormat, Locale.ENGLISH);
         Date date = new Date();
         try {
-            date = dateFormat.parse(dateString);
+            if (dateString != null)
+                date = dateFormat.parse(dateString);
         } catch (ParseException e) {
             Log.d(LOG_TAG, e.getLocalizedMessage());
         }
diff --git a/app/src/main/java/org/apache/fineract/utils/GsonUtils.kt b/app/src/main/java/org/apache/fineract/utils/GsonUtils.kt
new file mode 100644
index 0000000..449ae0e
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/utils/GsonUtils.kt
@@ -0,0 +1,31 @@
+package org.apache.fineract.utils
+
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+
+/**
+ * Created by Ahmad Jawid Muhammadi on 7/8/20.
+ */
+
+//convert a data class to a map
+
+fun <T> T.serializeToMap(): Map<String, Any> {
+    return convert()
+}
+
+//convert a map to a data class
+inline fun <reified T> Map<String, Any>.toDataClass(): T {
+    return convert()
+}
+
+//convert an object of type I to type O
+inline fun <I, reified O> I.convert(): O {
+    val json = Gson().toJson(this)
+    return Gson().fromJson(json, object : TypeToken<O>() {}.type)
+}
+
+fun <O> Map<String, Any>.convertToData(type: Class<O>): O {
+    val json = Gson().toJson(this)
+    return Gson().fromJson(json, TypeToken.getParameterized(type).type)
+}
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index af22aaa..b25c3ac 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -112,6 +112,7 @@
     <string name="browse">Browse…</string>
     <string name="fetching_customer_please_wait">Fetching customer please wait…</string>
     <string name="creating_loan_please_wait">Creating loan please wait…</string>
+    <string name="updating_loan_please_wait">Updating loan please wait…</string>
     <string name="updating_customer_please_wait">Updating customer please wait…</string>
     <string name="creating_customer_please_wait">Creating customer please wait…</string>
     <string name="creating_identification_card_please_wait">Creating identification card please wait…</string>
@@ -293,6 +294,7 @@
     <string name="error_should_contain_only">should contain only</string>
     <string name="error_loading_products">Error while fetching products</string>
     <string name="error_while_creating_loan">Error while creating loan</string>
+    <string name="error_while_updating_loan">Error while updating loan</string>
     <string name="error_loading_countries">Error while fetching countries</string>
     <string name="error_creating_customer">Error while creating customer</string>
     <string name="error_updating_customer">Error while updating customer</string>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 9f078be..60e4631 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,4 +1,4 @@
-<resources>
+<resources xmlns:tools="http://schemas.android.com/tools">
 
     <!-- Base application theme. -->
     <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
@@ -13,6 +13,11 @@
         <item name="android:fontFamily">@font/roboto</item>
     </style>
 
+    <style name="AppTheme.TransparentStatusBar">
+        <item name="android:statusBarColor" tools:targetApi="lollipop">
+            @android:color/transparent
+        </item>
+    </style>
 
     <style name="AppTheme.Black" parent="Theme.AppCompat.Light.NoActionBar">
         <!-- Customize your theme here. -->
diff --git a/app/src/main/resources/groups.json b/app/src/main/resources/groups.json
index 086d27f..85a7b12 100644
--- a/app/src/main/resources/groups.json
+++ b/app/src/main/resources/groups.json
@@ -27,7 +27,8 @@
     "createdOn": "2018-06-26T15:09:36.672Z",
     "createdBy": "ranefer",
     "lastModifiedOn": "lastModifiedOn",
-    "lastModifiedBy": "lastModifiedBy"
+    "lastModifiedBy": "lastModifiedBy",
+    "type": "group"
   },
   {
     "identifier": "group002",
diff --git a/app/src/main/resources/loanAccount.json b/app/src/main/resources/loanAccount.json
index c619478..032d15e 100644
--- a/app/src/main/resources/loanAccount.json
+++ b/app/src/main/resources/loanAccount.json
@@ -1,7 +1,7 @@
 {
   "identifier": "identifier",
   "productIdentifier": "productIdentifier",
-  "parameters": "{\"customerIdentifier\":\"customerIdentifier\",\"maximumBalance\": 343.45,\"termRange\": {\"temporalUnit\": \"WEEKS\", \"maximum\": 45.45 }, \"paymentCycle\": {\"temporalUnit\": \"WEEKS\",\"period\": 1,\"alignmentDay\": 1,\"alignmentWeek\": 1,\"alignmentMonth\": 1},\"creditWorthinessSnapshots\":[{\"forCustomer\":\"forCustomer\"}]}",
+  "parameters": "{\"customerIdentifier\":\"customerIdentifier\",\"maximumBalance\": 343.45,\"termRange\": {\"temporalUnit\": \"WEEKS\", \"maximum\": 45.00 }, \"paymentCycle\": {\"temporalUnit\": \"WEEKS\",\"period\": 1,\"alignmentDay\": 1,\"alignmentWeek\": 1,\"alignmentMonth\": 1},\"creditWorthinessSnapshots\":[{\"forCustomer\":\"forCustomer\"}]}",
   "accountAssignments": [
     {
       "designator": "designator",
@@ -22,19 +22,19 @@
         "incomeSources": [
           {
             "description": "description",
-            "amount": 45.45
+            "amount": 45.00
           }
         ],
         "assets": [
           {
             "description": "description",
-            "amount": 45.45
+            "amount": 45.00
           }
         ],
         "debts": [
           {
             "description": "description",
-            "amount": 45.45
+            "amount": 45.00
           }
         ]
       }
diff --git a/app/src/test/java/org/apache/fineract/online/CustomerPresenterTest.kt b/app/src/test/java/org/apache/fineract/online/CustomerPresenterTest.kt
deleted file mode 100644
index 031a215..0000000
--- a/app/src/test/java/org/apache/fineract/online/CustomerPresenterTest.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.apache.fineract.online
-
-import android.content.Context
-import io.reactivex.Observable
-import org.apache.fineract.FakeRemoteDataSource
-import org.apache.fineract.R
-import org.apache.fineract.data.datamanager.contracts.ManagerCustomer
-import org.apache.fineract.data.datamanager.database.DbManagerCustomer
-import org.apache.fineract.data.models.customer.CustomerPage
-import org.apache.fineract.exceptions.NoConnectivityException
-import org.apache.fineract.ui.online.customers.customerlist.CustomersContract
-import org.apache.fineract.ui.online.customers.customerlist.CustomersPresenter
-import org.apache.fineract.util.RxSchedulersOverrideRule
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.verify
-import org.mockito.junit.MockitoJUnitRunner
-
-@RunWith(MockitoJUnitRunner::class)
-class CustomerPresenterTest {
-
-    @Rule
-    @JvmField
-    val overrideSchedulersRule = RxSchedulersOverrideRule()
-
-    @Mock
-    lateinit var mockedView: CustomersContract.View
-
-    @Mock
-    lateinit var mockedCustomerDataManager: DbManagerCustomer
-
-    lateinit var mockedManagerCustomer: ManagerCustomer
-
-    @Mock
-    lateinit var mockedContext: Context
-
-    lateinit var customerPresenter: CustomersPresenter
-
-    lateinit var customerPage: CustomerPage
-
-    val size = 10
-
-    val pageIndex: Int = 1
-
-    @Before
-    fun setup() {
-        customerPresenter = CustomersPresenter(mockedContext, mockedCustomerDataManager)
-        customerPresenter.attachView(mockedView)
-        customerPage = FakeRemoteDataSource.getCustomerPage()
-        mockedManagerCustomer = mockedCustomerDataManager
-    }
-
-    @Test
-    fun testGetCustomerPage() {
-        `when`(mockedManagerCustomer.fetchCustomers(pageIndex, size))
-                .thenReturn(Observable.just(customerPage))
-        customerPresenter.fetchCustomers(pageIndex, size)
-        verify(mockedView).showProgressbar()
-        verify(mockedView).hideProgressbar()
-        verify(mockedView).showCustomers(customerPage.customers)
-    }
-
-    @Test
-    fun testGetAccountsPageEmpty() {
-        `when`(mockedManagerCustomer.fetchCustomers(pageIndex, size))
-                .thenReturn(Observable.just(CustomerPage(totalPages = 0)))
-        `when`(mockedContext.getString(R.string.empty_customer_list))
-                .thenReturn("Empty customer list")
-        customerPresenter.fetchCustomers(pageIndex, size)
-        verify(mockedView).showProgressbar()
-        verify(mockedView).hideProgressbar()
-        verify(mockedView).showEmptyCustomers("Empty customer list")
-    }
-
-
-    @Test
-    fun testGetAccountsPageFail() {
-        val exception = NoConnectivityException()
-        `when`(mockedCustomerDataManager.fetchCustomers(pageIndex, size))
-                .thenReturn(Observable.error(exception))
-        customerPresenter.fetchCustomers(pageIndex, size)
-        verify(mockedView).showProgressbar()
-        verify(mockedView).hideProgressbar()
-        verify(mockedView).showNoInternetConnection()
-    }
-
-    @After
-    fun tearDown() {
-        customerPresenter.detachView()
-    }
-
-}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index e663451..b9a7f79 100644
--- a/build.gradle
+++ b/build.gradle
@@ -31,7 +31,7 @@
 
 ext {
     // Sdk and tools
-    minSdkVersion = 16
+    minSdkVersion = 19
     targetSdkVersion = 28
     compileSdkVersion = 28
     buildToolsVersion = '28.0.3'
@@ -61,7 +61,7 @@
     hamcrestVersion = '1.3'
     runnerVersion = '1.1.0'
     rulesVersion = '1.1.0'
-    espressoVersion = '3.1.0'
+    espressoVersion = '3.2.0'
     sweetErrorVersion = '1.0.0'
     glideVersion = '3.7.0'
     materialStepperVersion = '3.3.0'
@@ -72,4 +72,8 @@
     mifosPasscodeVersion = '1.0.0'
     easyValidationVersion = '1.0.1'
     version_kotlin_coroutines = '1.3.4'
+    couchbase = '2.7.1'
+    extJunit = "1.1.1"
+    espressoCore = "3.2.0"
+    espressonContribute = "3.2.0"
 }