You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ra...@apache.org on 2021/06/01 15:43:14 UTC
[fineract-cn-mobile] branch development updated (592099e -> b7a5530)
This is an automated email from the ASF dual-hosted git repository.
rajanmaurya154 pushed a change to branch development
in repository https://gitbox.apache.org/repos/asf/fineract-cn-mobile.git.
from 592099e :
new 86c910a initialize couchbaseLite, implement group & customers and add UI tests
new b7a5530 Delete sync-gateway-config.json
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
app/build.gradle | 10 +-
.../creategroup/CreateGroupActivityAndroidTest.kt | 115 +++++++++++++++++
.../grouplist/GroupListFragmentAndroidTest.kt | 54 ++++++++
.../org/apache/fineract/FineractApplication.java | 2 +
.../apache/fineract/couchbase/CouchbaseDatabase.kt | 72 +++++++++++
.../org/apache/fineract/couchbase/DocumentType.kt | 10 ++
.../org/apache/fineract/couchbase/Replicate.java | 69 +++++++++++
.../fineract/couchbase/SynchronizationManager.kt | 112 +++++++++++++++++
.../java/org/apache/fineract/data/models/Group.kt | 6 +-
.../fineract/data/models/customer/Customer.kt | 46 +++----
.../org/apache/fineract/data/remote/BaseUrl.java | 1 +
.../apache/fineract/ui/adapters/GroupsAdapter.kt | 4 +-
.../customeractivity/CreateCustomerPresenter.java | 89 +++++---------
.../FormCustomerAddressFragment.java | 18 +--
.../customerdetails/CustomerDetailsFragment.java | 31 +++--
.../customerdetails/CustomerDetailsPresenter.java | 50 ++------
.../customers/customerlist/CustomersFragment.java | 35 +++---
.../customers/customerlist/CustomersPresenter.java | 136 +++++++++------------
.../CustomerTasksBottomSheetContract.java | 5 +-
.../CustomerTasksBottomSheetFragment.java | 20 ++-
.../CustomerTasksBottomSheetPresenter.java | 70 ++++++-----
.../groups/creategroup/CreateGroupActivity.kt | 6 +-
.../online/groups/grouplist/GroupListFragment.kt | 24 ++--
.../ui/online/groups/grouplist/GroupViewModel.kt | 64 +++++++---
.../groups/grouplist/GroupViewModelFactory.kt | 11 +-
.../grouptasks/GroupTasksBottomSheetFragment.kt | 4 +-
.../java/org/apache/fineract/utils/Constants.kt | 4 +
.../java/org/apache/fineract/utils/DateUtils.java | 3 +-
.../java/org/apache/fineract/utils/GsonUtils.kt | 31 +++++
app/src/main/resources/groups.json | 3 +-
.../fineract/online/CustomerPresenterTest.kt | 97 ---------------
build.gradle | 8 +-
32 files changed, 798 insertions(+), 412 deletions(-)
create mode 100644 app/src/androidTest/java/org/apache/fineract/ui/online/groups/creategroup/CreateGroupActivityAndroidTest.kt
create mode 100644 app/src/androidTest/java/org/apache/fineract/ui/online/groups/grouplist/GroupListFragmentAndroidTest.kt
create mode 100644 app/src/main/java/org/apache/fineract/couchbase/CouchbaseDatabase.kt
create mode 100644 app/src/main/java/org/apache/fineract/couchbase/DocumentType.kt
create mode 100644 app/src/main/java/org/apache/fineract/couchbase/Replicate.java
create mode 100644 app/src/main/java/org/apache/fineract/couchbase/SynchronizationManager.kt
create mode 100644 app/src/main/java/org/apache/fineract/utils/GsonUtils.kt
delete mode 100644 app/src/test/java/org/apache/fineract/online/CustomerPresenterTest.kt
[fineract-cn-mobile] 02/02: Delete sync-gateway-config.json
Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rajanmaurya154 pushed a commit to branch development
in repository https://gitbox.apache.org/repos/asf/fineract-cn-mobile.git
commit b7a55308f7e6525c82cf6f74c986dddd321dc4ae
Author: Ahmad Jawid Muhammadi <49...@users.noreply.github.com>
AuthorDate: Sun Sep 13 13:08:06 2020 +0530
Delete sync-gateway-config.json
---
app/sync-gateway-config.json | 19 -------------------
1 file changed, 19 deletions(-)
diff --git a/app/sync-gateway-config.json b/app/sync-gateway-config.json
deleted file mode 100644
index b3f7592..0000000
--- a/app/sync-gateway-config.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "interface":"0.0.0.0:4984",
- "log": ["*"],
- "databases": {
- "fineract-cn": {
- "server": "ws://localhost:8091/",
- "bucket": "fineract-cn-mobile",
- "username": "fineract-cn",
- "password": "password",
- "enable_shared_bucket_access": true,
- "import_docs": true,
- "num_index_replicas": 0,
- "users": {
- "GUEST": { "disabled": false, "admin_channels": ["*"] },
- "sync_gateway": {"password": "password"}
- }
- }
- }
-}
\ No newline at end of file
[fineract-cn-mobile] 01/02: initialize couchbaseLite,
implement group & customers and add UI tests
Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rajanmaurya154 pushed a commit to branch development
in repository https://gitbox.apache.org/repos/asf/fineract-cn-mobile.git
commit 86c910ab44f65ca8fed3e19689d4924334bd533b
Author: jawidMuhammadi <sp...@gmail.com>
AuthorDate: Fri Aug 7 14:49:14 2020 +0530
initialize couchbaseLite, implement group & customers and add UI tests
---
app/build.gradle | 10 +-
.../creategroup/CreateGroupActivityAndroidTest.kt | 115 +++++++++++++++++
.../grouplist/GroupListFragmentAndroidTest.kt | 54 ++++++++
.../org/apache/fineract/FineractApplication.java | 2 +
.../apache/fineract/couchbase/CouchbaseDatabase.kt | 72 +++++++++++
.../org/apache/fineract/couchbase/DocumentType.kt | 10 ++
.../org/apache/fineract/couchbase/Replicate.java | 69 +++++++++++
.../fineract/couchbase/SynchronizationManager.kt | 112 +++++++++++++++++
.../java/org/apache/fineract/data/models/Group.kt | 6 +-
.../fineract/data/models/customer/Customer.kt | 46 +++----
.../org/apache/fineract/data/remote/BaseUrl.java | 1 +
.../apache/fineract/ui/adapters/GroupsAdapter.kt | 4 +-
.../customeractivity/CreateCustomerPresenter.java | 89 +++++---------
.../FormCustomerAddressFragment.java | 18 +--
.../customerdetails/CustomerDetailsFragment.java | 31 +++--
.../customerdetails/CustomerDetailsPresenter.java | 50 ++------
.../customers/customerlist/CustomersFragment.java | 35 +++---
.../customers/customerlist/CustomersPresenter.java | 136 +++++++++------------
.../CustomerTasksBottomSheetContract.java | 5 +-
.../CustomerTasksBottomSheetFragment.java | 20 ++-
.../CustomerTasksBottomSheetPresenter.java | 70 ++++++-----
.../groups/creategroup/CreateGroupActivity.kt | 6 +-
.../online/groups/grouplist/GroupListFragment.kt | 24 ++--
.../ui/online/groups/grouplist/GroupViewModel.kt | 64 +++++++---
.../groups/grouplist/GroupViewModelFactory.kt | 11 +-
.../grouptasks/GroupTasksBottomSheetFragment.kt | 4 +-
.../java/org/apache/fineract/utils/Constants.kt | 4 +
.../java/org/apache/fineract/utils/DateUtils.java | 3 +-
.../java/org/apache/fineract/utils/GsonUtils.kt | 31 +++++
app/src/main/resources/groups.json | 3 +-
.../fineract/online/CustomerPresenterTest.kt | 97 ---------------
app/sync-gateway-config.json | 19 +++
build.gradle | 8 +-
33 files changed, 817 insertions(+), 412 deletions(-)
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 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
+ kotlinOptions {
+ jvmTarget = JavaVersion.VERSION_1_8
+ }
}
dependencies {
@@ -157,6 +160,9 @@ dependencies {
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 @@ dependencies {
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 @@ dependencies {
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/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 @@ package org.apache.fineract;
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 @@ public class FineractApplication extends Application {
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/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 @@ package org.apache.fineract.data.models
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 @@ data class Group(
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.annotation.*
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/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 class BaseUrl {
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/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 @@ class GroupsAdapter @Inject constructor(@ApplicationContext var context: Context
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/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 javax.inject.Inject;
+import java.util.Objects;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.CompositeDisposable;
-import io.reactivex.observers.DisposableCompletableObserver;
-import io.reactivex.schedulers.Schedulers;
+import javax.inject.Inject;
/**
* @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 class FormCustomerAddressFragment extends FineractBaseFragment implements
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 @@ package org.apache.fineract.ui.online.customers.customerdetails;
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.ImageView;
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 @@ import butterknife.OnClick;
/**
* @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 @@ public class CustomerDetailsFragment extends FineractBaseFragment
@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 @@ public class CustomerDetailsFragment extends FineractBaseFragment
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 @@ public class CustomerDetailsFragment extends FineractBaseFragment
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 @@ package org.apache.fineract.ui.online.customers.customerdetails;
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 javax.inject.Inject;
+import java.util.HashMap;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.CompositeDisposable;
-import io.reactivex.observers.DisposableObserver;
-import io.reactivex.schedulers.Schedulers;
+import javax.inject.Inject;
/**
* @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 @@ public class CustomerDetailsPresenter extends BasePresenter<CustomerDetailsContr
@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.LinearLayout;
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.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
+import static android.app.Activity.RESULT_OK;
+
/**
* @author Rajan Maurya
* On 20/06/17.
@@ -123,18 +124,19 @@ public class CustomersFragment extends FineractBaseFragment implements Customers
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 @@ public class CustomersFragment extends FineractBaseFragment implements Customers
@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 @@ package org.apache.fineract.ui.online.customers.customerlist;
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 @@ import io.reactivex.schedulers.Schedulers;
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 @@ public class CustomersPresenter extends BasePresenter<CustomersContract.View>
@Override
public void detachView() {
super.detachView();
- compositeDisposable.clear();
}
@Override
@@ -63,44 +59,34 @@ public class CustomersPresenter extends BasePresenter<CustomersContract.View>
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();
-
- 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());
- }
- }
-
- @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));
- }
- }
-
- @Override
- public void onComplete() {
- }
- })
- );
+ ArrayList<Customer> customerList = new ArrayList<>();
+
+ Expression expression = Expression.property("documentType")
+ .equalTo(Expression.string(DocumentType.CUSTOMER.getValue()));
+
+ List<HashMap<String, Object>> map = synchronizationManager.getDocuments(
+ expression,
+ size,
+ pageIndex);
+
+ 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 @@ public class CustomersPresenter extends BasePresenter<CustomersContract.View>
@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 @@ public interface CustomerTasksBottomSheetContract {
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 @@ package org.apache.fineract.ui.online.customers.customertasks;
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.LinearLayout;
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 @@ import butterknife.OnClick;
/**
* @author Rajan Maurya
- * On 27/07/17.
+ * On 27/07/17.
*/
public class CustomerTasksBottomSheetFragment extends FineractBaseBottomSheetDialogFragment
implements CustomerTasksBottomSheetContract.View {
@@ -71,6 +73,7 @@ public class CustomerTasksBottomSheetFragment extends FineractBaseBottomSheetDia
@Inject
CustomerTasksBottomSheetPresenter tasksBottomSheetPresenter;
+
View rootView;
private BottomSheetBehavior behavior;
@@ -78,6 +81,7 @@ public class CustomerTasksBottomSheetFragment extends FineractBaseBottomSheetDia
private Command command;
private String customerIdentifier;
private OnTasksChangeListener onTasksChangeListener;
+ private Customer customer;
@NonNull
@Override
@@ -188,11 +192,15 @@ public class CustomerTasksBottomSheetFragment extends FineractBaseBottomSheetDia
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 javax.inject.Inject;
+import java.util.Objects;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.CompositeDisposable;
-import io.reactivex.observers.DisposableCompletableObserver;
-import io.reactivex.schedulers.Schedulers;
+import javax.inject.Inject;
/**
* @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 @@ public class CustomerTasksBottomSheetPresenter
@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.data.models.customer.Address
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 @@ class CreateGroupActivity : FineractBaseActivity(), StepperLayout.StepperListene
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 @@ class CreateGroupActivity : FineractBaseActivity(), StepperLayout.StepperListene
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 @@ import javax.inject.Inject
* Created by saksham on 15/June/2019
*/
+
class GroupListFragment : FineractBaseFragment(), OnItemClickListener {
lateinit var rootView: View
@@ -42,6 +43,7 @@ class GroupListFragment : FineractBaseFragment(), OnItemClickListener {
@Inject
lateinit var groupViewModelFactory: GroupViewModelFactory
+
lateinit var groupList: ArrayList<Group>
val searchedGroup: (ArrayList<Group>) -> Unit = { groups ->
@@ -63,15 +65,11 @@ class GroupListFragment : FineractBaseFragment(), OnItemClickListener {
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 @@ class GroupListFragment : FineractBaseFragment(), OnItemClickListener {
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 android.annotation.SuppressLint
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 @@ class GroupViewModel constructor(val dataManagerGroups: DataManagerGroups, val d
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 @@ class GroupViewModel constructor(val dataManagerGroups: DataManagerGroups, val d
}
}
- 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 @@ class GroupViewModel constructor(val dataManagerGroups: DataManagerGroups, val d
}
}
- 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 @@ class GroupViewModel constructor(val dataManagerGroups: DataManagerGroups, val d
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 @@ class GroupViewModel constructor(val dataManagerGroups: DataManagerGroups, val d
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 @@ class GroupViewModel constructor(val dataManagerGroups: DataManagerGroups, val d
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 @@ package org.apache.fineract.ui.online.groups.grouplist
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 @@ import javax.inject.Inject
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 @@ class GroupTasksBottomSheetFragment(val group: Group) : FineractBaseBottomSheetD
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 @@ class GroupTasksBottomSheetFragment(val group: Group) : FineractBaseBottomSheetD
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/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 @@ package org.apache.fineract.utils
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 @@ public class DateUtils {
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/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/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/app/sync-gateway-config.json b/app/sync-gateway-config.json
new file mode 100644
index 0000000..b3f7592
--- /dev/null
+++ b/app/sync-gateway-config.json
@@ -0,0 +1,19 @@
+{
+ "interface":"0.0.0.0:4984",
+ "log": ["*"],
+ "databases": {
+ "fineract-cn": {
+ "server": "ws://localhost:8091/",
+ "bucket": "fineract-cn-mobile",
+ "username": "fineract-cn",
+ "password": "password",
+ "enable_shared_bucket_access": true,
+ "import_docs": true,
+ "num_index_replicas": 0,
+ "users": {
+ "GUEST": { "disabled": false, "admin_channels": ["*"] },
+ "sync_gateway": {"password": "password"}
+ }
+ }
+ }
+}
\ 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 @@ task clean(type: Delete) {
ext {
// Sdk and tools
- minSdkVersion = 16
+ minSdkVersion = 19
targetSdkVersion = 28
compileSdkVersion = 28
buildToolsVersion = '28.0.3'
@@ -61,7 +61,7 @@ ext {
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 @@ ext {
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"
}