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:15 UTC
[fineract-cn-mobile] 01/02: initialize couchbaseLite,
implement group & customers and add UI tests
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"
}