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