diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bad499ef..feb947f2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -90,6 +90,12 @@
+
+
+
+
diff --git a/app/src/main/java/org/apache/fineract/couchbase/DocumentType.kt b/app/src/main/java/org/apache/fineract/couchbase/DocumentType.kt
index 9e32fd45..1dae00f1 100644
--- a/app/src/main/java/org/apache/fineract/couchbase/DocumentType.kt
+++ b/app/src/main/java/org/apache/fineract/couchbase/DocumentType.kt
@@ -6,5 +6,6 @@ package org.apache.fineract.couchbase
enum class DocumentType(val value: String) {
GROUP("Group"),
- CUSTOMER("customer")
+ CUSTOMER("customer"),
+ ACCOUNT("Account")
}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/data/datamanager/DataManagerAccounting.kt b/app/src/main/java/org/apache/fineract/data/datamanager/DataManagerAccounting.kt
index ed1304d2..6ce793b2 100644
--- a/app/src/main/java/org/apache/fineract/data/datamanager/DataManagerAccounting.kt
+++ b/app/src/main/java/org/apache/fineract/data/datamanager/DataManagerAccounting.kt
@@ -1,5 +1,6 @@
package org.apache.fineract.data.datamanager
+import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.functions.Function
@@ -36,6 +37,11 @@ class DataManagerAccounting @Inject constructor(val baseManagerApi: BaseApiManag
.onErrorResumeNext(Function>
{ Observable.just(FakeRemoteDataSource.getAccountPage()) })
+ fun createAccount(account: Account) : Completable =
+ baseManagerApi.accountingService.createAccount(account)
+
+ fun updateAccount(identifier: String, account: Account) : Completable =
+ baseManagerApi.accountingService.updateAccount(identifier, account)
fun findAccount(identifier: String): Observable =
baseManagerApi.accountingService.findAccount(identifier)
diff --git a/app/src/main/java/org/apache/fineract/data/models/accounts/Account.kt b/app/src/main/java/org/apache/fineract/data/models/accounts/Account.kt
index 52761c4a..6d51d3c5 100644
--- a/app/src/main/java/org/apache/fineract/data/models/accounts/Account.kt
+++ b/app/src/main/java/org/apache/fineract/data/models/accounts/Account.kt
@@ -3,25 +3,26 @@ package org.apache.fineract.data.models.accounts
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize
+import org.apache.fineract.couchbase.DocumentType
@Parcelize
data class Account(
- @SerializedName("type") val type: AccountType? = null,
- @SerializedName("identifier") val identifier: String? = null,
- @SerializedName("name") val name: String? = null,
- @SerializedName("holders") val holders: Set? = null,
- @SerializedName("signatureAuthorities") val signatureAuthorities: Set? = null,
- @SerializedName("balance") val balance: Double? = null,
- @SerializedName("referenceAccount") val referenceAccount: String? = null,
- @SerializedName("ledger") val ledger: String? = null,
- @SerializedName("state") val state: State? = null,
- @SerializedName("alternativeAccountNumber") val alternativeAccountNumber: String? = null,
- @SerializedName("createdOn") val createdOn: String? = null,
- @SerializedName("createdBy") val createdBy: String? = null,
- @SerializedName("lastModifiedOn") val lastModifiedOn: String? = null,
- @SerializedName("lastModifiedBy") val lastModifiedBy: String? = null
-
+ var type: AccountType? = null,
+ var identifier: String? = null,
+ var name: String? = null,
+ var holders: List? = null,
+ var signatureAuthorities: List? = null,
+ var balance: Double? = null,
+ var referenceAccount: String? = null,
+ var ledger: String? = null,
+ var state: State? = null,
+ var alternativeAccountNumber: String? = null,
+ var createdOn: String? = null,
+ var createdBy: String? = null,
+ var lastModifiedOn: String? = null,
+ var lastModifiedBy: String? = null,
+ var documentType: String = DocumentType.ACCOUNT.value
) : Parcelable {
enum class State {
diff --git a/app/src/main/java/org/apache/fineract/data/services/AccountingService.kt b/app/src/main/java/org/apache/fineract/data/services/AccountingService.kt
index 491e11e1..fb52ba44 100644
--- a/app/src/main/java/org/apache/fineract/data/services/AccountingService.kt
+++ b/app/src/main/java/org/apache/fineract/data/services/AccountingService.kt
@@ -1,13 +1,13 @@
package org.apache.fineract.data.services
+import io.reactivex.Completable
import io.reactivex.Observable
import org.apache.fineract.data.models.accounts.Account
import org.apache.fineract.data.models.accounts.AccountPage
import org.apache.fineract.data.models.accounts.Ledger
import org.apache.fineract.data.models.accounts.LedgerPage
import org.apache.fineract.data.remote.EndPoints
-import retrofit2.http.GET
-import retrofit2.http.Path
+import retrofit2.http.*
interface AccountingService {
@@ -24,4 +24,11 @@ interface AccountingService {
@GET(EndPoints.API_ACCOUNTING_PATH + "/accounts/{identifier}")
fun findAccount(@Path("identifier") identifier: String): Observable
+ @POST(EndPoints.API_ACCOUNTING_PATH + "/accounts")
+ fun createAccount(@Body account: Account) : Completable
+
+ @PUT(EndPoints.API_ACCOUNTING_PATH + "/accounts/{identifier}")
+ fun updateAccount(@Path("identifier") identifier: String,
+ @Body account: Account) : Completable
+
}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/injection/component/ActivityComponent.java b/app/src/main/java/org/apache/fineract/injection/component/ActivityComponent.java
index 7e8d2ec0..1a4fb00a 100644
--- a/app/src/main/java/org/apache/fineract/injection/component/ActivityComponent.java
+++ b/app/src/main/java/org/apache/fineract/injection/component/ActivityComponent.java
@@ -4,7 +4,15 @@
import org.apache.fineract.injection.module.ActivityModule;
import org.apache.fineract.ui.offline.CustomerPayloadFragment;
import org.apache.fineract.ui.online.DashboardActivity;
+import org.apache.fineract.ui.online.accounting.accounts.accountDetails.AccountDetailsActivity;
+import org.apache.fineract.ui.online.accounting.accounts.accountDetails.AccountDetailsFragment;
import org.apache.fineract.ui.online.accounting.accounts.AccountsFragment;
+import org.apache.fineract.ui.online.accounting.accounts.accounttasks.AccountTaskBottomSheetFragment;
+import org.apache.fineract.ui.online.accounting.accounts.createaccount.AccountDetailsStepFragment;
+import org.apache.fineract.ui.online.accounting.accounts.createaccount.AccountReviewStepFragment;
+import org.apache.fineract.ui.online.accounting.accounts.createaccount.AddAccountHoldersStepFragment;
+import org.apache.fineract.ui.online.accounting.accounts.createaccount.AddAccountSignAuthoritiesFragment;
+import org.apache.fineract.ui.online.accounting.accounts.createaccount.CreateAccountActivity;
import org.apache.fineract.ui.online.accounting.ledgers.LedgerFragment;
import org.apache.fineract.ui.online.customers.createcustomer.customeractivity
.CreateCustomerActivity;
@@ -159,5 +167,21 @@ public interface ActivityComponent {
void inject(GroupDetailsFragment groupDetailsFragment);
void inject(GroupTasksBottomSheetFragment groupTasksBottomSheetFragment);
+
+ void inject(AccountDetailsActivity accountDetailsActivity);
+
+ void inject(AccountDetailsFragment accountDetailsFragment);
+
+ void inject(CreateAccountActivity createAccountActivity);
+
+ void inject(AccountDetailsStepFragment accountDetailsStepFragment);
+
+ void inject(AccountReviewStepFragment accountReviewStepFragment);
+
+ void inject(AddAccountSignAuthoritiesFragment addAccountSignAuthoritiesFragment);
+
+ void inject(AddAccountHoldersStepFragment addAccountHoldersStepFragment);
+
+ void inject(AccountTaskBottomSheetFragment accountTaskBottomSheetFragment);
}
diff --git a/app/src/main/java/org/apache/fineract/ui/adapters/AccountsAdapter.kt b/app/src/main/java/org/apache/fineract/ui/adapters/AccountsAdapter.kt
index 6205ad7f..7b6d97d9 100644
--- a/app/src/main/java/org/apache/fineract/ui/adapters/AccountsAdapter.kt
+++ b/app/src/main/java/org/apache/fineract/ui/adapters/AccountsAdapter.kt
@@ -6,11 +6,13 @@ import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.LinearLayout
import android.widget.TextView
import kotlinx.android.synthetic.main.item_account.view.*
import org.apache.fineract.R
import org.apache.fineract.data.models.accounts.Account
import org.apache.fineract.injection.ApplicationContext
+import org.apache.fineract.ui.base.OnItemClickListener
import org.apache.fineract.utils.DateUtils
import org.apache.fineract.utils.StatusUtils
import javax.inject.Inject
@@ -20,6 +22,8 @@ class AccountsAdapter @Inject constructor(@ApplicationContext val context: Conte
var accounts: List = ArrayList()
+ lateinit var onItemClickListener: OnItemClickListener
+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_account, parent, false)
@@ -55,12 +59,27 @@ class AccountsAdapter @Inject constructor(@ApplicationContext val context: Conte
notifyDataSetChanged()
}
- class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ fun setItemClickListener(onItemClickListener: OnItemClickListener) {
+ this.onItemClickListener = onItemClickListener
+ }
+
+ inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
val tvIdentifier: TextView = itemView.tv_account_identifier
val tvModifiedBy: TextView = itemView.tv_modified_by
val tvModifiedOn: TextView = itemView.tv_modified_on
val tvName: TextView = itemView.tv_name
val ivAccountTypeIndicator: AppCompatImageView = itemView.iv_type_indicator
+ val llAccount: LinearLayout = itemView.ll_account
+
+ init {
+ llAccount.setOnClickListener(this)
+ }
+
+ override fun onClick(v: View?) {
+ if (onItemClickListener != null) {
+ onItemClickListener.onItemClick(v, adapterPosition)
+ }
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/AccountAction.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/AccountAction.kt
new file mode 100644
index 00000000..e9c212e7
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/AccountAction.kt
@@ -0,0 +1,10 @@
+package org.apache.fineract.ui.online.accounting.accounts
+
+/**
+ * Created by Varun Jain on 23/July/2021
+ */
+
+enum class AccountAction {
+ EDIT,
+ CREATE
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/AccountsFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/AccountsFragment.kt
index 67c27d8a..1b15eeed 100644
--- a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/AccountsFragment.kt
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/AccountsFragment.kt
@@ -2,34 +2,53 @@ package org.apache.fineract.ui.online.accounting.accounts
import android.app.SearchManager
import android.content.Context
+import android.content.Intent
import android.os.Bundle
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.appcompat.widget.SearchView
import android.text.TextUtils
import android.view.*
+import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.RecyclerView
+import butterknife.ButterKnife
import kotlinx.android.synthetic.main.fragment_accounts.*
import kotlinx.android.synthetic.main.layout_exception_handler.*
import org.apache.fineract.R
+import androidx.lifecycle.Observer
+import butterknife.OnClick
import org.apache.fineract.data.models.accounts.Account
import org.apache.fineract.ui.adapters.AccountsAdapter
import org.apache.fineract.ui.base.FineractBaseActivity
import org.apache.fineract.ui.base.FineractBaseFragment
-import java.util.*
+import org.apache.fineract.ui.base.OnItemClickListener
+import org.apache.fineract.ui.online.accounting.accounts.accountDetails.AccountDetailsActivity
+import org.apache.fineract.ui.online.accounting.accounts.createaccount.CreateAccountActivity
+import org.apache.fineract.ui.online.accounting.accounts.viewmodel.AccountsViewModel
+import org.apache.fineract.ui.online.accounting.accounts.viewmodel.AccountsViewModelFactory
+import org.apache.fineract.utils.Constants
import javax.inject.Inject
+import kotlin.collections.ArrayList
-class AccountsFragment : FineractBaseFragment(), AccountContract.View, SwipeRefreshLayout.OnRefreshListener {
+class AccountsFragment : FineractBaseFragment(), OnItemClickListener, SwipeRefreshLayout.OnRefreshListener {
+
+ lateinit var rootView: View
+
+ lateinit var accountsViewModel: AccountsViewModel
@Inject
- lateinit var accountsPresenter: AccountsPresenter
+ lateinit var accountsViewModelFactory: AccountsViewModelFactory
@Inject
lateinit var accountsAdapter: AccountsAdapter
lateinit var accountList : List
+ val searchedAccount: (ArrayList) -> Unit = { accounts ->
+ accountsAdapter.setAccountsList(accounts)
+ }
+
companion object {
fun newInstance() = AccountsFragment()
}
@@ -45,25 +64,36 @@ class AccountsFragment : FineractBaseFragment(), AccountContract.View, SwipeRefr
val rootView = inflater.inflate(R.layout.fragment_accounts, container, false)
(activity as FineractBaseActivity).activityComponent.inject(this)
- accountsPresenter.attachView(this)
- initializeFineractUIErrorHandler(activity, rootView)
-
+ accountsViewModel = ViewModelProviders.of(this, accountsViewModelFactory).get(AccountsViewModel::class.java)
+ ButterKnife.bind(this, rootView)
return rootView
}
+
+ override fun onStart() {
+ super.onStart()
+ accountsViewModel.getAccounts()?.observe(this, Observer {
+ it?.let {
+ accountList = it
+ accountsAdapter.setAccountsList(it)
+ }
+ })
+ }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ accountsAdapter.setItemClickListener(this)
showUserInterface()
btn_try_again.setOnClickListener {
+ showProgressbar()
layoutError.visibility = View.GONE
- accountsPresenter.getAccountsPage()
+ accountsViewModel.getAccounts()
+ hideProgressbar()
}
-
- accountsPresenter.getAccountsPage()
}
- override fun showUserInterface() {
+ fun showUserInterface() {
setToolbarTitle(getString(R.string.accounts))
val layoutManager = LinearLayoutManager(activity)
layoutManager.orientation = RecyclerView.VERTICAL
@@ -93,7 +123,7 @@ class AccountsFragment : FineractBaseFragment(), AccountContract.View, SwipeRefr
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
- accountsPresenter.searchAccount(accountList, query)
+ accountsViewModel.searchAccount(accountList as ArrayList, query, searchedAccount)
return false
}
@@ -102,36 +132,43 @@ class AccountsFragment : FineractBaseFragment(), AccountContract.View, SwipeRefr
showRecyclerView(true)
accountsAdapter.setAccountsList(accountList)
}
- accountsPresenter.searchAccount(accountList, newText)
+ accountsViewModel.searchAccount(accountList as ArrayList, newText, searchedAccount)
return false
}
})
}
- override fun searchedAccount(accounts: List) {
+ fun searchedAccount(accounts: List) {
showRecyclerView(true)
accountsAdapter.setAccountsList(accounts)
}
override fun onRefresh() {
- accountsPresenter.getAccountsPage()
+ showProgressbar()
+ accountsViewModel.getAccounts()?.observe(this, Observer {
+ it?.let {
+ accountList = it
+ accountsAdapter.setAccountsList(it)
+ }
+ })
+ hideProgressbar()
}
- override fun showAccounts(accounts: List) {
+ fun showAccounts(accounts: List) {
showRecyclerView(true)
accountList = accounts
accountsAdapter.setAccountsList(accountList)
}
- override fun showEmptyAccounts() {
+ fun showEmptyAccounts() {
showRecyclerView(false)
- showFineractEmptyUI(getString(R.string.accounts), getString(R.string.accounts),
- R.drawable.ic_person_outline_black_24dp)
+ showFineractEmptyUI(getString(R.string.account), getString(R.string.account),
+ R.drawable.ic_person_outline_black_24dp)
}
- override fun showRecyclerView(status: Boolean) {
+ fun showRecyclerView(status: Boolean) {
if (status) {
rvAccount.visibility = View.VISIBLE
layoutError.visibility = View.GONE
@@ -141,27 +178,38 @@ class AccountsFragment : FineractBaseFragment(), AccountContract.View, SwipeRefr
}
}
- override fun showProgressbar() {
+ fun showProgressbar() {
swipeContainer.isRefreshing = true
}
- override fun hideProgressbar() {
+ fun hideProgressbar() {
swipeContainer.isRefreshing = false
}
- override fun showNoInternetConnection() {
+ fun showNoInternetConnection() {
showRecyclerView(false)
showFineractNoInternetUI()
}
- override fun showError(message: String) {
+ fun showError(message: String) {
showRecyclerView(false)
showFineractErrorUI(getString(R.string.accounts))
}
- override fun onDestroyView() {
- super.onDestroyView()
- accountsPresenter.detachView()
+ override fun onItemClick(childView: View?, position: Int) {
+ val intent = Intent(context, AccountDetailsActivity::class.java).apply {
+ putExtra(Constants.ACCOUNT, accountList[position])
+ }
+ startActivity(intent)
}
+ override fun onItemLongPress(childView: View?, position: Int) {}
+
+ @OnClick(R.id.fabAddAccount)
+ fun addAccount() {
+ val intent = Intent(activity, CreateAccountActivity::class.java).apply {
+ putExtra(Constants.ACCOUNT_ACTION, AccountAction.CREATE)
+ }
+ startActivity(intent)
+ }
}
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accountDetails/AccountDetailsActivity.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accountDetails/AccountDetailsActivity.kt
new file mode 100644
index 00000000..d17e8331
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accountDetails/AccountDetailsActivity.kt
@@ -0,0 +1,21 @@
+package org.apache.fineract.ui.online.accounting.accounts.accountDetails
+
+import android.os.Bundle
+import org.apache.fineract.R
+import org.apache.fineract.ui.base.FineractBaseActivity
+import org.apache.fineract.utils.Constants
+
+/**
+ * Created by Varun Jain on 17/July/2021
+ */
+
+class AccountDetailsActivity : FineractBaseActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_toolbar_container)
+
+ replaceFragment(AccountDetailsFragment.newInstance(intent.getParcelableExtra(Constants.ACCOUNT)), false, R.id.container)
+ showBackButton()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accountDetails/AccountDetailsFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accountDetails/AccountDetailsFragment.kt
new file mode 100644
index 00000000..9bb25993
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accountDetails/AccountDetailsFragment.kt
@@ -0,0 +1,155 @@
+package org.apache.fineract.ui.online.accounting.accounts.accountDetails
+
+import android.content.DialogInterface
+import android.content.Intent
+import android.os.Bundle
+import android.view.*
+import androidx.lifecycle.ViewModelProviders
+import butterknife.ButterKnife
+import butterknife.OnClick
+import kotlinx.android.synthetic.main.fragment_account_details.*
+import kotlinx.android.synthetic.main.fragment_account_details.view.*
+import org.apache.fineract.R
+import org.apache.fineract.data.models.accounts.Account
+import org.apache.fineract.ui.adapters.NameListAdapter
+import org.apache.fineract.ui.base.FineractBaseActivity
+import org.apache.fineract.ui.base.FineractBaseFragment
+import org.apache.fineract.ui.online.accounting.accounts.AccountAction
+import org.apache.fineract.ui.online.accounting.accounts.accounttasks.AccountTaskBottomSheetFragment
+import org.apache.fineract.ui.online.accounting.accounts.createaccount.CreateAccountActivity
+import org.apache.fineract.ui.online.accounting.accounts.viewmodel.AccountsViewModel
+import org.apache.fineract.ui.online.accounting.accounts.viewmodel.AccountsViewModelFactory
+import org.apache.fineract.ui.views.CircularImageView
+import org.apache.fineract.utils.Constants
+import org.apache.fineract.utils.MaterialDialog
+import org.apache.fineract.utils.Utils
+import javax.inject.Inject
+
+
+/*
+ * Created by Varun Jain on 17/July/2021
+*/
+
+class AccountDetailsFragment : FineractBaseFragment() {
+
+ lateinit var rootView: View
+ lateinit var account: Account
+
+ @Inject
+ lateinit var holdersNameAdapter: NameListAdapter
+
+ @Inject
+ lateinit var signatureAuthoritiesNameAdapter: NameListAdapter
+
+ private lateinit var viewModel: AccountsViewModel
+
+ @Inject
+ lateinit var viewModelFactory: AccountsViewModelFactory
+
+ companion object {
+ fun newInstance(account: Account) : AccountDetailsFragment{
+ val fragment = AccountDetailsFragment()
+ val args = Bundle()
+ args.putParcelable(Constants.ACCOUNT, account)
+ fragment.arguments = args
+ return fragment
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ account = arguments?.get(Constants.ACCOUNT) as Account
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ rootView = inflater.inflate(R.layout.fragment_account_details, container, false)
+ (activity as FineractBaseActivity).activityComponent.inject(this)
+ viewModel = ViewModelProviders.of(this, viewModelFactory).get(AccountsViewModel::class.java)
+ ButterKnife.bind(this, rootView)
+ rootView.rvHoldersAccount.adapter = holdersNameAdapter
+ holdersNameAdapter.setReview(true)
+ rootView.rvSignatureAuthoritiesAccount.adapter = signatureAuthoritiesNameAdapter
+ signatureAuthoritiesNameAdapter.setReview(true)
+ setToolbarTitle(account.identifier)
+ setHasOptionsMenu(true)
+ return rootView
+ }
+
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+ tvIdentifierAccount.text = account.identifier
+ tvAccountType.text = account.type.toString()
+ setAccountStatusIcon(account.state, civStateAccount)
+ account.holders?.let{
+ holdersNameAdapter.submitList(it as ArrayList)
+ }
+ account.signatureAuthorities?.let {
+ signatureAuthoritiesNameAdapter.submitList(it as ArrayList)
+ }
+ tvStateAccount.text = account.state.toString()
+ tvNameAccount.text = account.name
+ tvBalanceAccount.text = account.balance.toString()
+ tvReferenceAmountAccount.text = account.referenceAccount
+ tvLedgersAccount.text = account.ledger
+ tvAltAccountNo.text = account.alternativeAccountNumber
+ }
+
+ override fun onPrepareOptionsMenu(menu: Menu) {
+ super.onPrepareOptionsMenu(menu)
+ Utils.setToolbarIconColor(context, menu, R.color.white)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+ super.onCreateOptionsMenu(menu, inflater)
+ inflater.inflate(R.menu.menu_account_details, menu)
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.menuEditAccount -> {
+ val intent = Intent(activity, CreateAccountActivity::class.java).apply {
+ putExtra(Constants.ACCOUNT, account)
+ putExtra(Constants.ACCOUNT_ACTION, AccountAction.EDIT)
+ }
+ startActivity(intent)
+ activity!!.finish()
+ }
+ R.id.menuDeleteAccount -> {
+ MaterialDialog.Builder().init(context).apply {
+ setTitle(getString(R.string.dialog_title_confirm_deletion))
+ setMessage(getString(R.string.dialog_message_confirm_name_deletion, account.name))
+ setPositiveButton(getString(R.string.delete)
+ ) { dialog: DialogInterface?, _ ->
+ viewModel.deleteAccount(account)
+ dialog?.dismiss()
+ activity!!.finish()
+ }
+ setNegativeButton(getString(R.string.dialog_action_cancel))
+ createMaterialDialog()
+ }.run { show() }
+ }
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+ @OnClick(R.id.cvTasksAccount)
+ fun onTasksCardViewClicked() {
+ val bottomSheet = AccountTaskBottomSheetFragment(account)
+ bottomSheet.show(childFragmentManager, getString(R.string.tasks))
+ }
+
+ private fun setAccountStatusIcon(status: Account.State?, imageView: CircularImageView) {
+ when (status) {
+ Account.State.OPEN -> {
+ imageView.setImageDrawable(Utils.setCircularBackground(R.color.blue, context))
+ }
+ Account.State.CLOSED -> {
+ imageView.setImageDrawable(Utils.setCircularBackground(R.color.red_dark, context))
+ }
+ Account.State.LOCKED -> {
+ imageView.setImageDrawable(Utils.setCircularBackground(R.color.light_yellow, context))
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accounttasks/AccountCommand.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accounttasks/AccountCommand.kt
new file mode 100644
index 00000000..f15a1bd4
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accounttasks/AccountCommand.kt
@@ -0,0 +1,27 @@
+package org.apache.fineract.ui.online.accounting.accounts.accounttasks
+
+import com.google.gson.annotations.SerializedName
+
+
+/**
+ * Created by Varun Jain on 23/July/2021
+ */
+
+data class AccountCommand(
+ @SerializedName("action") var action: AccountTaskAction? = null,
+ @SerializedName("comment") var comment: String? = null
+) {
+ enum class AccountTaskAction {
+ @SerializedName("LOCK")
+ LOCK,
+
+ @SerializedName("UNLOCK")
+ UNLOCK,
+
+ @SerializedName("REOPEN")
+ REOPEN,
+
+ @SerializedName("CLOSE")
+ CLOSE,
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accounttasks/AccountTaskBottomSheetFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accounttasks/AccountTaskBottomSheetFragment.kt
new file mode 100644
index 00000000..3fdce78a
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accounttasks/AccountTaskBottomSheetFragment.kt
@@ -0,0 +1,171 @@
+package org.apache.fineract.ui.online.accounting.accounts.accounttasks
+
+import android.app.Dialog
+import android.os.Bundle
+import android.view.View
+import android.widget.Toast
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import butterknife.ButterKnife
+import butterknife.OnClick
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import kotlinx.android.synthetic.main.fragment_account_tasks_bottom_sheet.view.*
+import kotlinx.android.synthetic.main.fragment_group_tasks_bottom_sheet.view.*
+import org.apache.fineract.R
+import org.apache.fineract.data.Status
+import org.apache.fineract.data.models.accounts.Account
+import org.apache.fineract.ui.base.FineractBaseActivity
+import org.apache.fineract.ui.base.FineractBaseBottomSheetDialogFragment
+import org.apache.fineract.ui.base.Toaster
+import org.apache.fineract.ui.online.accounting.accounts.viewmodel.AccountsViewModel
+import org.apache.fineract.ui.online.accounting.accounts.viewmodel.AccountsViewModelFactory
+import javax.inject.Inject
+
+
+/**
+ * Created by Varun Jain on 24/July/2021
+ */
+
+class AccountTaskBottomSheetFragment(val account: Account) : FineractBaseBottomSheetDialogFragment() {
+
+ lateinit var rootView: View
+ private var accountCommand = AccountCommand()
+ lateinit var behavior: BottomSheetBehavior<*>
+ private lateinit var viewModel: AccountsViewModel
+
+ @Inject
+ lateinit var viewModelFactory: AccountsViewModelFactory
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
+ rootView = View.inflate(context, R.layout.fragment_account_tasks_bottom_sheet, null)
+ dialog.setContentView(rootView)
+ behavior = BottomSheetBehavior.from(rootView.parent as View)
+ (activity as FineractBaseActivity).activityComponent.inject(this)
+ ButterKnife.bind(this, rootView)
+ viewModel = ViewModelProviders.of(this, viewModelFactory).get(AccountsViewModel::class.java)
+ setDataOnViews()
+
+ subscribeUI()
+ return dialog
+ }
+
+ private fun subscribeUI() {
+ viewModel.status.observe(this, Observer { status ->
+ when (status) {
+ Status.LOADING -> {
+ showMifosProgressDialog(getString(R.string.please_wait_updating_account_status))
+ }
+ Status.ERROR -> {
+ hideMifosProgressDialog()
+ Toaster.show(rootView, R.string.error_while_updating_account_status, Toast.LENGTH_SHORT)
+ }
+ Status.DONE -> {
+ Toaster.show(rootView, getString(R.string.account_identifier_updated_successfully, account.identifier), Toast.LENGTH_SHORT)
+ hideMifosProgressDialog()
+ dismiss()
+ }
+ }
+ })
+ }
+
+ private fun setDataOnViews() {
+ when (account.state) {
+ Account.State.OPEN -> {
+ rootView.ivAccountTask.setImageDrawable(
+ ContextCompat.getDrawable(activity!!, R.drawable.ic_lock_black_24dp))
+ rootView.ivAccountTask.setColorFilter(ContextCompat.getColor(activity!!, R.color.red_dark))
+ rootView.tvAccountTask.text = getString(R.string.lock)
+ rootView.llAccountTask2.visibility = View.VISIBLE
+ rootView.ivAccountTask2.setImageDrawable(
+ ContextCompat.getDrawable(activity!!, R.drawable.ic_close_black_24dp))
+ rootView.ivAccountTask2.setColorFilter(ContextCompat.getColor(activity!!, R.color.red_dark))
+ rootView.tvAccountTask2.text = getString(R.string.close)
+
+ }
+ Account.State.LOCKED -> {
+ rootView.ivAccountTask.setImageDrawable(
+ ContextCompat.getDrawable(activity!!, R.drawable.ic_lock_open_black_24dp))
+ rootView.ivAccountTask.setColorFilter(ContextCompat.getColor(activity!!, R.color.status))
+ rootView.tvAccountTask.text = getString(R.string.un_lock)
+
+ }
+ Account.State.CLOSED -> {
+ rootView.ivAccountTask.setImageDrawable(
+ ContextCompat.getDrawable(activity!!, R.drawable.ic_check_circle_black_24dp))
+ rootView.ivAccountTask.setColorFilter(ContextCompat.getColor(activity!!, R.color.status))
+ rootView.tvAccountTask.text = getString(R.string.reopen)
+
+ }
+ }
+ }
+
+ @OnClick(R.id.ivAccountTask)
+ fun onTaskImageViewClicked() {
+ when (account.state) {
+ Account.State.OPEN -> {
+ accountCommand.action = AccountCommand.AccountTaskAction.LOCK
+ rootView.tvAccountTaskHeader.text = getString(R.string.lock)
+ rootView.tvAccountTaskSubHeader.text = getString(R.string.please_verify_following_account_task, getString(R.string.lock))
+ rootView.btnSubmitAccountTask.text = getString(R.string.lock)
+ }
+ Account.State.LOCKED -> {
+ accountCommand.action = AccountCommand.AccountTaskAction.UNLOCK
+ rootView.tvAccountTaskHeader.text = getString(R.string.un_lock)
+ rootView.tvAccountTaskSubHeader.text = getString(R.string.please_verify_following_account_task, getString(R.string.un_lock))
+ rootView.btnSubmitAccountTask.text = getString(R.string.un_lock)
+ }
+ Account.State.CLOSED -> {
+ accountCommand.action = AccountCommand.AccountTaskAction.REOPEN
+ rootView.tvAccountTaskHeader.text = getString(R.string.reopen)
+ rootView.tvAccountTaskSubHeader.text = getString(R.string.please_verify_following_account_task, getString(R.string.reopen))
+ rootView.btnSubmitAccountTask.text = getString(R.string.reopen)
+ }
+ }
+ rootView.llAccountTaskList.visibility = View.GONE
+ rootView.llAccountTaskForm.visibility = View.VISIBLE
+ }
+
+ @OnClick(R.id.ivAccountTask2)
+ fun onTaskImageView2Clicked() {
+ when (account.state) {
+ Account.State.OPEN -> {
+ accountCommand.action = AccountCommand.AccountTaskAction.CLOSE
+ rootView.tvAccountTaskHeader.text = getString(R.string.close)
+ rootView.tvAccountTaskSubHeader.text = getString(R.string.please_verify_following_account_task, getString(R.string.close))
+ rootView.btnSubmitAccountTask.text = getString(R.string.close)
+ }
+ }
+ rootView.llAccountTask2.visibility = View.INVISIBLE
+ rootView.llAccountTaskList.visibility = View.GONE
+ rootView.llAccountTaskForm.visibility = View.VISIBLE
+ }
+
+ @OnClick(R.id.btnSubmitAccountTask)
+ fun submitTask() {
+ accountCommand.comment = rootView.etCommentAccountTasks.text.toString().trim { it <= ' ' }
+ rootView.etCommentAccountTasks.isEnabled = false
+ account.identifier?.let {
+ viewModel.changeAccountStatus(it, account, accountCommand)
+ }
+ activity!!.finish()
+ }
+
+ @OnClick(R.id.btnCancelAccountTasks)
+ fun onCancel() {
+ dismiss()
+ }
+
+ override fun onStart() {
+ super.onStart()
+ behavior.state = BottomSheetBehavior.STATE_EXPANDED
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ hideMifosProgressBar()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AccountDetailsStepFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AccountDetailsStepFragment.kt
new file mode 100644
index 00000000..3897e1f9
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AccountDetailsStepFragment.kt
@@ -0,0 +1,166 @@
+package org.apache.fineract.ui.online.accounting.accounts.createaccount
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import com.stepstone.stepper.Step
+import com.stepstone.stepper.VerificationError
+import com.wajahatkarim3.easyvalidation.core.view_ktx.validator
+import kotlinx.android.synthetic.main.fragment_step_account_details.*
+import kotlinx.android.synthetic.main.fragment_step_account_details.view.*
+import kotlinx.android.synthetic.main.fragment_step_group_details.*
+import kotlinx.android.synthetic.main.fragment_step_group_details.view.*
+import org.apache.fineract.R
+import org.apache.fineract.data.models.accounts.AccountType
+import org.apache.fineract.ui.base.FineractBaseFragment
+import org.apache.fineract.ui.base.OnItemClickListener
+import org.apache.fineract.ui.online.accounting.accounts.AccountAction
+import org.apache.fineract.utils.Constants
+
+
+/*
+ * Created by Varun Jain on 21/July/2021
+*/
+
+class AccountDetailsStepFragment : FineractBaseFragment(), Step {
+
+
+ lateinit var rootView: View
+ private lateinit var accountAction: AccountAction
+
+ companion object {
+ fun newInstance(accountAction: AccountAction) =
+ AccountDetailsStepFragment().apply {
+ val bundle = Bundle().apply {
+ putSerializable(Constants.ACCOUNT_ACTION, accountAction)
+ }
+ arguments = bundle
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.getSerializable(Constants.ACCOUNT_ACTION)?.let {
+ accountAction = it as AccountAction
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ rootView = inflater.inflate(R.layout.fragment_step_account_details, container, false)
+ if (accountAction == AccountAction.EDIT) {
+ showDataOnViews()
+ }
+
+ return rootView
+ }
+
+ private fun showDataOnViews() {
+ val account = (activity as CreateAccountActivity).getAccount()
+ rootView.etIdentifierAccountDetailsStep.setText(account.identifier)
+ rootView.etIdentifierAccountDetailsStep.isEnabled = false
+ rootView.spinnerTypeAccountDetailsStep.setSelection(getIndexFromAccountType(account.type))
+ rootView.etNameAccountDetailsStep.setText(account.name)
+ rootView.etAltAccountNumAccountDetailsStep.setText(account.alternativeAccountNumber)
+ rootView.etLedgerAccountDetailsStep.setText(account.ledger)
+ rootView.etRefAccountNumAccountDetailsStep.setText(account.referenceAccount)
+ rootView.etBalanceAccountDetailsStep.setText(account.balance.toString())
+ }
+
+ private fun getIndexFromAccountType(accountType: AccountType?): Int {
+ when (accountType) {
+ AccountType.ASSET -> return 0
+ AccountType.LIABILITY -> return 1
+ AccountType.EQUITY -> return 2
+ AccountType.REVENUE -> return 3
+ AccountType.EXPENSE -> return 4
+ else -> return 0
+ }
+ }
+
+ private fun getAccountTypeFromIndex(index: Int): AccountType {
+ when (index) {
+ 0 -> return AccountType.ASSET
+ 1 -> return AccountType.LIABILITY
+ 2 -> return AccountType.EQUITY
+ 3 -> return AccountType.REVENUE
+ 4 -> return AccountType.EXPENSE
+ else -> return AccountType.ASSET
+ }
+ }
+
+ override fun verifyStep(): VerificationError? {
+ if (!validateAlternateAccNo() || !validateBalance() || !validateName()
+ || !validateLedger() || !validateRefAccountNum()
+ ) {
+ return VerificationError(null)
+ }
+ (activity as CreateAccountActivity).setAccountDetails(
+ etIdentifierAccountDetailsStep.text.toString(),
+ etBalanceAccountDetailsStep.text.toString().toDouble(),
+ if (getAccountTypeFromIndex(spinnerTypeAccountDetailsStep.selectedItemPosition) != null) getAccountTypeFromIndex(
+ spinnerTypeAccountDetailsStep.selectedItemPosition
+ ) else AccountType.ASSET,
+ etAltAccountNumAccountDetailsStep.text.toString(),
+ etNameAccountDetailsStep.text.toString(),
+ etLedgerAccountDetailsStep.text.toString(),
+ etRefAccountNumAccountDetailsStep.text.toString()
+ )
+ return null
+ }
+
+ override fun onSelected() {}
+
+ override fun onError(p0: VerificationError) {}
+
+ private fun validateLedger(): Boolean {
+ return etLedgerAccountDetailsStep.validator()
+ .minLength(5)
+ .addErrorCallback {
+ etLedgerAccountDetailsStep.error = it
+ }
+ .check()
+ }
+
+ private fun validateName(): Boolean {
+ return etNameAccountDetailsStep.validator()
+ .nonEmpty()
+ .addErrorCallback {
+ etNameAccountDetailsStep.error = it
+ }
+ .check()
+ }
+
+ private fun validateBalance(): Boolean {
+ return etBalanceAccountDetailsStep.validator()
+ .addErrorCallback {
+ etBalanceAccountDetailsStep.error = it
+ }
+ .nonEmpty()
+ .check()
+ }
+
+ private fun validateRefAccountNum(): Boolean {
+ return etRefAccountNumAccountDetailsStep.validator()
+ .minLength(5)
+ .addErrorCallback {
+ etRefAccountNumAccountDetailsStep.error = it
+ }
+ .check()
+ }
+
+ private fun validateAlternateAccNo(): Boolean {
+ return etAltAccountNumAccountDetailsStep.validator()
+ .minLength(5)
+ .addErrorCallback {
+ etAltAccountNumAccountDetailsStep.error = it
+ }
+ .check()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AccountReviewStepFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AccountReviewStepFragment.kt
new file mode 100644
index 00000000..ff1ef0c8
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AccountReviewStepFragment.kt
@@ -0,0 +1,80 @@
+package org.apache.fineract.ui.online.accounting.accounts.createaccount
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.stepstone.stepper.Step
+import com.stepstone.stepper.VerificationError
+import kotlinx.android.synthetic.main.fragment_account_details.view.*
+import kotlinx.android.synthetic.main.fragment_step_account_review.*
+import kotlinx.android.synthetic.main.fragment_step_account_review.view.*
+import org.apache.fineract.R
+import org.apache.fineract.data.models.accounts.Account
+import org.apache.fineract.ui.adapters.NameListAdapter
+import org.apache.fineract.ui.base.FineractBaseActivity
+import org.apache.fineract.ui.base.FineractBaseFragment
+import javax.inject.Inject
+
+
+/*
+ * Created by Varun Jain on 21/July/2021
+*/
+
+class AccountReviewStepFragment : FineractBaseFragment(), Step {
+
+ lateinit var rootView: View
+
+ @Inject
+ lateinit var holdersAdapter: NameListAdapter
+
+ @Inject
+ lateinit var signatureAuthoritiesAdapter: NameListAdapter
+
+ companion object {
+ fun newInstance(): AccountReviewStepFragment {
+ return AccountReviewStepFragment()
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ rootView = inflater.inflate(R.layout.fragment_step_account_review, container, false)
+ (activity as FineractBaseActivity).activityComponent.inject(this)
+ rootView.rvSignatureAuthoritiesAccountStepReview.adapter = signatureAuthoritiesAdapter
+ signatureAuthoritiesAdapter.setReview(true)
+ rootView.rvHoldersAccountStepReview.adapter = holdersAdapter
+ holdersAdapter.setReview(true)
+
+ return rootView
+ }
+
+ override fun verifyStep(): VerificationError? {
+ return null
+ }
+
+ private fun populateView(account : Account) {
+ tvIdentifierAccountStepReview.text = account.identifier
+ tvTypeAccountStepReview.text = account.type.toString()
+ tvNameAccountStepReview.text = account.name
+ account.holders?.let {
+ holdersAdapter.submitList(it as ArrayList)
+ }
+ account.signatureAuthorities?.let {
+ signatureAuthoritiesAdapter.submitList(it as ArrayList)
+ }
+ tvBalanceAccountStepReview.text = account.balance.toString()
+ tvRefAccountStepReview.text = account.referenceAccount
+ tvLedgerAccountStepReview.text = account.ledger
+ tvAltAccountNoAccountStepReview.text = account.alternativeAccountNumber
+ }
+
+ override fun onSelected() {
+ populateView((activity as CreateAccountActivity).getAccount())
+ }
+
+ override fun onError(p0: VerificationError) {}
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AddAccountHoldersStepFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AddAccountHoldersStepFragment.kt
new file mode 100644
index 00000000..d622af35
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AddAccountHoldersStepFragment.kt
@@ -0,0 +1,180 @@
+package org.apache.fineract.ui.online.accounting.accounts.createaccount
+
+import android.content.Context
+import android.content.DialogInterface
+import android.os.Bundle
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import com.stepstone.stepper.Step
+import org.apache.fineract.ui.adapters.NameListAdapter
+import org.apache.fineract.ui.base.FineractBaseActivity
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import butterknife.ButterKnife
+import butterknife.OnClick
+import butterknife.Optional
+import com.stepstone.stepper.VerificationError
+import com.wajahatkarim3.easyvalidation.core.view_ktx.validator
+import kotlinx.android.synthetic.main.fragment_step_account_review.view.*
+import kotlinx.android.synthetic.main.fragment_step_add_account_holder.*
+import kotlinx.android.synthetic.main.fragment_step_add_account_holder.view.*
+import org.apache.fineract.R
+import org.apache.fineract.ui.base.FineractBaseFragment
+import org.apache.fineract.ui.online.accounting.accounts.AccountAction
+import org.apache.fineract.utils.Constants
+import org.apache.fineract.utils.MaterialDialog
+import org.apache.fineract.utils.Utils
+import javax.inject.Inject
+
+/*
+ * Created by Varun Jain on 21/July/2021
+*/
+
+class AddAccountHoldersStepFragment : FineractBaseFragment(), Step, NameListAdapter.OnItemClickListener {
+
+ lateinit var rootView: View
+ var holders: ArrayList = ArrayList()
+ private var currentAccountAction = AccountAction.CREATE
+ private var editItemPosition = 0
+ private lateinit var accountAction: AccountAction
+
+ @Inject
+ lateinit var nameListAdapter: NameListAdapter
+
+ companion object {
+ fun newInstance (accountAction: AccountAction) =
+ AddAccountHoldersStepFragment().apply {
+ val bundle = Bundle().apply {
+ putSerializable(Constants.ACCOUNT_ACTION, accountAction)
+ }
+ arguments = bundle
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.getSerializable(Constants.ACCOUNT_ACTION)?.let {
+ accountAction = it as AccountAction
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ rootView = inflater.inflate(R.layout.fragment_step_add_account_holder, container, false)
+ ButterKnife.bind(this, rootView)
+ (activity as FineractBaseActivity).activityComponent.inject(this)
+ rootView.rvHolderName.adapter = nameListAdapter
+ nameListAdapter.setOnItemClickListener(this)
+ if (accountAction == AccountAction.EDIT) {
+ populateViews()
+ }
+ return rootView
+ }
+
+ private fun populateViews() {
+ val account = (activity as CreateAccountActivity).getAccount()
+ holders = account.holders as ArrayList
+ if (holders.size == 0) {
+ showRecyclerView(false)
+ } else {
+ showRecyclerView(true)
+ }
+ nameListAdapter.submitList(holders)
+ }
+
+ @Optional
+ @OnClick(R.id.ivAddHolder)
+ fun showAddHolderView() {
+ showAddHolderView(AccountAction.CREATE, null)
+ }
+
+ private fun showAddHolderView(action: AccountAction, name: String?) {
+ currentAccountAction = action
+ llAddHolderAccountStep.visibility = View.VISIBLE
+ when (action) {
+ AccountAction.CREATE -> {
+ btnAddHolder.text = getString(R.string.add)
+ }
+ AccountAction.EDIT -> {
+ etNewHolder.setText(name)
+ btnAddHolder.text = getString(R.string.update)
+ }
+ }
+ }
+
+ @Optional
+ @OnClick(R.id.btnAddHolder)
+ fun addHolder() {
+ if (etNewHolder.validator()
+ .nonEmpty()
+ .addErrorCallback { etNewHolder.error = it }.check()) {
+ if (currentAccountAction == AccountAction.CREATE) {
+ holders.add(etNewHolder.text.toString().trim { it <= ' ' })
+ } else {
+ holders[editItemPosition] = etNewHolder.text.toString().trim { it <= ' ' }
+ }
+ etNewHolder.text.clear()
+ llAddHolderAccountStep.visibility = View.GONE
+ Utils.hideKeyboard(context, etNewHolder)
+ showRecyclerView(true)
+ nameListAdapter.submitList(holders)
+ }
+ }
+
+ fun showRecyclerView(isShow: Boolean) {
+ if (isShow) {
+ rootView.rvHolderName.visibility = View.VISIBLE
+ rootView.tvAddedHolder.visibility = View.GONE
+ } else {
+ rootView.rvHolderName.visibility = View.GONE
+ rootView.tvAddedHolder.visibility = View.VISIBLE
+ }
+ }
+
+ @Optional
+ @OnClick(R.id.btnCancelAddHolder)
+ fun cancelHolderAddition() {
+ etNewHolder.text.clear()
+ llAddHolderAccountStep.visibility = View.GONE
+ }
+
+ override fun verifyStep(): VerificationError? {
+ if (holders.size == 0) {
+ Toast.makeText(context, getString(R.string.error_acc_atleast_1_holder), Toast.LENGTH_SHORT).show()
+ return VerificationError("")
+ }
+ (activity as CreateAccountActivity).setHolders(holders)
+ return null
+ }
+
+ override fun onSelected() {}
+
+ override fun onError(p0: VerificationError) {}
+
+ override fun onEditClicked(position: Int) {
+ editItemPosition = position
+ showAddHolderView(AccountAction.EDIT, holders[position])
+ }
+
+ override fun onDeleteClicked(position: Int) {
+ MaterialDialog.Builder().init(context).apply {
+ setTitle(getString(R.string.dialog_title_confirm_deletion))
+ setMessage(getString(R.string.dialog_message_confirm_name_deletion, holders[position]))
+ setPositiveButton(getString(R.string.delete)
+ ) { dialog: DialogInterface?, _ ->
+ holders.removeAt(position)
+ nameListAdapter.submitList(holders)
+ if (holders.size == 0) {
+ showRecyclerView(false)
+ }
+ dialog?.dismiss()
+ }
+ setNegativeButton(getString(R.string.dialog_action_cancel))
+ createMaterialDialog()
+ }.run { show() }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AddAccountSignAuthoritiesFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AddAccountSignAuthoritiesFragment.kt
new file mode 100644
index 00000000..cd8c110f
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AddAccountSignAuthoritiesFragment.kt
@@ -0,0 +1,186 @@
+package org.apache.fineract.ui.online.accounting.accounts.createaccount
+
+import android.content.Context
+import android.content.DialogInterface
+import android.opengl.Visibility
+import android.os.Bundle
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import butterknife.ButterKnife
+import butterknife.OnClick
+import butterknife.Optional
+import com.stepstone.stepper.Step
+import com.stepstone.stepper.VerificationError
+import com.wajahatkarim3.easyvalidation.core.view_ktx.validator
+import kotlinx.android.synthetic.main.fragment_step_account_review.view.*
+import kotlinx.android.synthetic.main.fragment_step_add_account_holder.*
+import kotlinx.android.synthetic.main.fragment_step_add_group_member.view.*
+import kotlinx.android.synthetic.main.fragment_step_add_signature_authorities.*
+import kotlinx.android.synthetic.main.fragment_step_add_signature_authorities.view.*
+import org.apache.fineract.R
+import org.apache.fineract.ui.adapters.NameListAdapter
+import org.apache.fineract.ui.base.FineractBaseActivity
+import org.apache.fineract.ui.base.FineractBaseFragment
+import org.apache.fineract.ui.online.accounting.accounts.AccountAction
+import org.apache.fineract.ui.online.groups.GroupAction
+import org.apache.fineract.utils.Constants
+import org.apache.fineract.utils.MaterialDialog
+import org.apache.fineract.utils.Utils
+import javax.inject.Inject
+
+
+/*
+ * Created by Varun Jain on 21/July/2021
+*/
+
+class AddAccountSignAuthoritiesFragment : FineractBaseFragment(), Step, NameListAdapter.OnItemClickListener {
+
+ lateinit var rootView: View
+ var signatureAuthorities: ArrayList = ArrayList()
+ private var currentAccountAction = AccountAction.CREATE
+ private var editItemPosition = 0
+ private lateinit var accountAction: AccountAction
+
+ @Inject
+ lateinit var namesListAdapter: NameListAdapter
+
+ companion object {
+ fun newInstance (accountAction: AccountAction) =
+ AddAccountSignAuthoritiesFragment().apply {
+ val bundle = Bundle().apply {
+ putSerializable(Constants.ACCOUNT_ACTION, accountAction)
+ }
+ arguments = bundle
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.getSerializable(Constants.ACCOUNT_ACTION)?.let {
+ accountAction = it as AccountAction
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ rootView = inflater.inflate(R.layout.fragment_step_add_signature_authorities, container, false)
+ ButterKnife.bind(this, rootView)
+ (activity as FineractBaseActivity).activityComponent.inject(this)
+ rootView.rvAddSignatureAuthoritiesAccountStep.adapter = namesListAdapter
+ namesListAdapter.setOnItemClickListener(this)
+ if (accountAction == AccountAction.EDIT) {
+ showDataOnViews()
+ }
+ return rootView
+ }
+
+ private fun showDataOnViews() {
+ val account = (activity as CreateAccountActivity).getAccount()
+ signatureAuthorities = account.signatureAuthorities as ArrayList
+ if (signatureAuthorities.size == 0) {
+ showRecyclerView(false)
+ } else {
+ showRecyclerView(true)
+ }
+ namesListAdapter.submitList(signatureAuthorities)
+ }
+
+ @Optional
+ @OnClick(R.id.ivAddSignatureAuthorities)
+ fun showAddSignatureAuthoritiesView() {
+ showAddSignatureAuthoritiesView(AccountAction.CREATE, null)
+ }
+
+ private fun showAddSignatureAuthoritiesView(action: AccountAction, name: String?) {
+ currentAccountAction = action
+ llAddSignatureAuthoritiesAccountStep.visibility = View.VISIBLE
+ when (action) {
+ AccountAction.CREATE -> {
+ btnAddSignatureAuthority.text = getString(R.string.add)
+ }
+ AccountAction.EDIT -> {
+ etNewSignatureAuthorities.setText(name)
+ btnAddSignatureAuthority.text = getString(R.string.update)
+ }
+ }
+ }
+
+ @Optional
+ @OnClick(R.id.btnAddSignatureAuthority)
+ fun addSignatureAuthority() {
+ if (etNewSignatureAuthorities.validator()
+ .nonEmpty()
+ .addErrorCallback { etNewSignatureAuthorities.error = it }.check()) {
+ if (currentAccountAction == AccountAction.CREATE) {
+ signatureAuthorities.add(etNewSignatureAuthorities.text.toString().trim { it <= ' ' })
+ } else {
+ signatureAuthorities[editItemPosition] = etNewSignatureAuthorities.text.toString().trim { it <= ' ' }
+ }
+ etNewSignatureAuthorities.text.clear()
+ llAddSignatureAuthoritiesAccountStep.visibility = View.GONE
+ Utils.hideKeyboard(context, etNewSignatureAuthorities)
+ showRecyclerView(true)
+ namesListAdapter.submitList(signatureAuthorities)
+ }
+ }
+
+
+ private fun showRecyclerView(show: Boolean) {
+ if (show) {
+ rootView.rvAddSignatureAuthoritiesAccountStep.visibility = View.VISIBLE
+ rootView.tvAddedSignatureAuthorities.visibility = View.GONE
+ } else {
+ rootView.rvAddSignatureAuthoritiesAccountStep.visibility = View.GONE
+ rootView.tvAddedSignatureAuthorities.visibility = View.VISIBLE
+ }
+ }
+
+ @Optional
+ @OnClick(R.id.btnCancelAddSignatureAuthority)
+ fun cancelSignatureAuthorityAddition() {
+ etNewSignatureAuthorities.text.clear()
+ llAddSignatureAuthoritiesAccountStep.visibility = View.GONE
+ }
+
+ override fun verifyStep(): VerificationError? {
+ if (signatureAuthorities.size == 0) {
+ Toast.makeText(context, getString(R.string.error_acc_atleast_1_signature_authority), Toast.LENGTH_SHORT).show()
+ return VerificationError("")
+ }
+ (activity as CreateAccountActivity).setSignatureAuthorities(signatureAuthorities)
+ return null
+ }
+
+ override fun onSelected() {}
+
+ override fun onError(p0: VerificationError) {}
+
+ override fun onEditClicked(position: Int) {
+ editItemPosition = position
+ showAddSignatureAuthoritiesView(AccountAction.EDIT, signatureAuthorities[position])
+ }
+
+ override fun onDeleteClicked(position: Int) {
+ MaterialDialog.Builder().init(context).apply {
+ setTitle(getString(R.string.dialog_title_confirm_deletion))
+ setMessage(getString(R.string.dialog_message_confirm_name_deletion, signatureAuthorities[position]))
+ setPositiveButton(getString(R.string.delete)
+ ) { dialog: DialogInterface?, _ ->
+ signatureAuthorities.removeAt(position)
+ namesListAdapter.submitList(signatureAuthorities)
+ if (signatureAuthorities.size == 0) {
+ showRecyclerView(false)
+ }
+ dialog?.dismiss()
+ }
+ setNegativeButton(getString(R.string.dialog_action_cancel))
+ createMaterialDialog()
+ }.run { show() }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/CreateAccountActivity.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/CreateAccountActivity.kt
new file mode 100644
index 00000000..7f8b1c4f
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/CreateAccountActivity.kt
@@ -0,0 +1,164 @@
+package org.apache.fineract.ui.online.accounting.accounts.createaccount
+
+import android.os.Bundle
+import android.view.View
+import android.widget.Toast
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import com.stepstone.stepper.StepperLayout
+import com.stepstone.stepper.VerificationError
+import kotlinx.android.synthetic.main.activity_create_account.*
+import kotlinx.android.synthetic.main.activity_create_group.*
+import org.apache.fineract.R
+import org.apache.fineract.data.Status
+import org.apache.fineract.data.models.accounts.Account
+import org.apache.fineract.data.models.accounts.AccountType
+import org.apache.fineract.ui.base.FineractBaseActivity
+import org.apache.fineract.ui.base.Toaster
+import org.apache.fineract.ui.online.accounting.accounts.AccountAction
+import org.apache.fineract.ui.online.accounting.accounts.viewmodel.AccountsViewModel
+import org.apache.fineract.ui.online.accounting.accounts.viewmodel.AccountsViewModelFactory
+import org.apache.fineract.utils.Constants
+import javax.inject.Inject
+
+/*
+ * Created by Varun Jain on 20/July/2021
+*/
+
+class CreateAccountActivity : FineractBaseActivity(), StepperLayout.StepperListener {
+
+ private var account = Account()
+ private var accountAction = AccountAction.CREATE
+
+
+ @Inject
+ lateinit var accountsViewModelFactory: AccountsViewModelFactory
+
+ lateinit var accountsViewModel: AccountsViewModel
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_create_account)
+ activityComponent.inject(this)
+ accountAction = intent.getSerializableExtra(Constants.ACCOUNT_ACTION) as AccountAction
+ when (accountAction) {
+ AccountAction.CREATE -> {
+ setToolbarTitle(getString(R.string.create_account))
+ }
+ AccountAction.EDIT -> {
+ setToolbarTitle(getString(R.string.edit_account))
+ intent?.extras?.getParcelable(Constants.ACCOUNT)?.let {
+ account = it
+ }
+ }
+ }
+ accountsViewModel =
+ ViewModelProviders.of(this, accountsViewModelFactory).get(AccountsViewModel::class.java)
+ subscribeUI()
+ showBackButton()
+ slCreateAccount.adapter = CreateAccountAdapter(supportFragmentManager, this, accountAction)
+ slCreateAccount.setOffscreenPageLimit(slCreateAccount.adapter.count)
+ slCreateAccount.setListener(this)
+ }
+
+ override fun onCompleted(p0: View?) {
+ when (accountAction) {
+ AccountAction.CREATE -> account.identifier?.let {
+ accountsViewModel.createAccount(account)
+ }
+ AccountAction.EDIT -> account.identifier?.let {
+ accountsViewModel.updateAccount(account)
+ }
+ }
+ }
+
+ override fun onError(verificationError: VerificationError?) {}
+
+ override fun onStepSelected(newStepPosition: Int) {}
+
+ override fun onReturn() {}
+
+
+ private fun subscribeUI() {
+ accountsViewModel.status.observe(this, Observer { status ->
+ when (status) {
+ Status.LOADING ->
+ if (accountAction == AccountAction.CREATE) {
+ showMifosProgressDialog(getString(R.string.creating_account_please_wait))
+ } else {
+ showMifosProgressDialog(getString(R.string.updating_account_please_wait))
+ }
+ Status.ERROR -> {
+ hideMifosProgressDialog()
+ if (accountAction == AccountAction.CREATE) {
+ Toaster.show(
+ findViewById(android.R.id.content),
+ R.string.error_while_creating_account,
+ Toast.LENGTH_SHORT
+ )
+ } else {
+ Toaster.show(
+ findViewById(android.R.id.content),
+ R.string.error_while_updating_account,
+ Toast.LENGTH_SHORT
+ )
+ }
+ }
+ Status.DONE -> {
+ hideMifosProgressDialog()
+ if (accountAction == AccountAction.CREATE) {
+ Toast.makeText(
+ this,
+ getString(
+ R.string.account_identifier_created_successfully,
+ account.identifier
+ ),
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ Toast.makeText(
+ this,
+ getString(
+ R.string.account_identifier_updated_successfully,
+ account.identifier
+ ),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ finish()
+ }
+ }
+ })
+ }
+
+ fun setHolders(holders: List) {
+ account.holders = holders
+ }
+
+ fun setSignatureAuthorities(setSignatureAuthorities: List) {
+ account.signatureAuthorities = setSignatureAuthorities
+ }
+
+ fun setAccountDetails(
+ identifier: String,
+ balance: Double,
+ type: AccountType,
+ alternativeAccountNum: String,
+ name: String,
+ ledger: String,
+ refAccount: String
+ ) {
+ account.identifier = identifier
+ account.balance = balance
+ account.type = type
+ account.alternativeAccountNumber = alternativeAccountNum
+ account.name = name
+ account.ledger = ledger
+ account.referenceAccount = refAccount
+ }
+
+ fun getAccount(): Account {
+ return account
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/CreateAccountAdapter.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/CreateAccountAdapter.kt
new file mode 100644
index 00000000..b48cd998
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/CreateAccountAdapter.kt
@@ -0,0 +1,39 @@
+package org.apache.fineract.ui.online.accounting.accounts.createaccount
+
+import android.content.Context
+import androidx.fragment.app.FragmentManager
+import com.stepstone.stepper.Step
+import com.stepstone.stepper.adapter.AbstractFragmentStepAdapter
+import com.stepstone.stepper.viewmodel.StepViewModel
+import org.apache.fineract.R
+import org.apache.fineract.ui.online.accounting.accounts.AccountAction
+
+/*
+ * Created by Varun Jain on 21/July/2021
+*/
+
+class CreateAccountAdapter constructor(fm: FragmentManager,
+ context: Context,
+ val accountAction: AccountAction
+) : AbstractFragmentStepAdapter(fm, context) {
+
+ private var createAccountSteps = context.resources.getStringArray(R.array.create_account_steps)
+
+ override fun getCount(): Int {
+ return createAccountSteps.size
+ }
+
+ override fun createStep(position: Int): Step? {
+ when (position) {
+ 0 -> return AccountDetailsStepFragment.newInstance(accountAction)
+ 1 -> return AddAccountHoldersStepFragment.newInstance(accountAction)
+ 2 -> return AddAccountSignAuthoritiesFragment.newInstance(accountAction)
+ 3 -> return AccountReviewStepFragment.newInstance()
+ }
+ return null
+ }
+
+ override fun getViewModel(position: Int): StepViewModel {
+ return StepViewModel.Builder(context).setTitle(createAccountSteps[position]).create()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/viewmodel/AccountsViewModel.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/viewmodel/AccountsViewModel.kt
new file mode 100644
index 00000000..803511a1
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/viewmodel/AccountsViewModel.kt
@@ -0,0 +1,167 @@
+package org.apache.fineract.ui.online.accounting.accounts.viewmodel
+
+import org.apache.fineract.data.models.accounts.Account
+import android.annotation.SuppressLint
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.couchbase.lite.Expression
+import io.reactivex.Observable
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.observers.DisposableCompletableObserver
+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.DataManagerAccounting
+import org.apache.fineract.data.datamanager.api.DataManagerAnonymous
+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.ui.online.accounting.accounts.accounttasks.AccountCommand
+import org.apache.fineract.utils.DateUtils
+import org.apache.fineract.utils.serializeToMap
+import org.apache.fineract.utils.toDataClass
+
+/*
+ * Created by Varun Jain on 18/July/2021
+*/
+
+class AccountsViewModel constructor(private val synchronizationManager: SynchronizationManager,
+ private val dataManagerAnonymous: DataManagerAnonymous,
+ private val preferencesHelper: PreferencesHelper,
+ private val dataManagerAccounting: DataManagerAccounting
+) : ViewModel() {
+
+ var accountsList = MutableLiveData>()
+ 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()
+ val status: LiveData
+ get() = _status
+
+ @SuppressLint("CheckResult")
+ fun getAccounts(): MutableLiveData>? {
+ val expression = Expression.property("documentType")
+ .equalTo(Expression.string(DocumentType.ACCOUNT.value))
+ .and(Expression.property("state").notEqualTo(Expression.string("null")))
+ val hashMapList = synchronizationManager.getDocuments(expression)
+ if (hashMapList?.isEmpty() == null) {
+ return null
+ }
+ val list = arrayListOf()
+ for (map in hashMapList) {
+ list.add(map.toDataClass())
+ }
+ accountsList.value = list
+
+ return accountsList
+ }
+
+ fun searchAccount(
+ accounts: ArrayList,
+ query: String,
+ searchedAccount: (ArrayList) -> Unit
+ ) {
+ searchedAccount(
+ ArrayList(
+ Observable.fromIterable(accounts).filter { account ->
+ account.identifier?.toLowerCase()?.contains(query.toLowerCase()).toString()
+ .toBoolean()
+ }.toList().blockingGet()
+ )
+ )
+ }
+
+ @SuppressLint("CheckResult")
+ fun createAccount(account: Account) {
+ uiScope.launch {
+ withContext(Dispatchers.Main) {
+ try {
+ _status.value = Status.LOADING
+ account.createdBy = preferencesHelper.userName
+ account.createdOn = DateUtils.getCurrentDate()
+ account.lastModifiedBy = preferencesHelper.userName
+ account.lastModifiedOn = DateUtils.getCurrentDate()
+ account.state = Account.State.OPEN
+ synchronizationManager.saveDocument(account.identifier!!, account.serializeToMap())
+ _status.value = Status.DONE
+ } catch (exception: Exception) {
+ _status.value = Status.ERROR
+ }
+ }
+ }
+ }
+
+ fun updateAccount(account: Account) {
+ uiScope.launch {
+ withContext(Dispatchers.Main) {
+ try {
+ _status.value = Status.LOADING
+ account.createdBy = preferencesHelper.userName
+ account.createdOn = DateUtils.getCurrentDate()
+ account.lastModifiedBy = preferencesHelper.userName
+ account.lastModifiedOn = DateUtils.getCurrentDate()
+ account.identifier?.let {
+ synchronizationManager.updateDocument(account.identifier!!, account.serializeToMap())
+ _status.value = Status.DONE
+ }
+ } catch (exception: Exception) {
+ _status.value = Status.ERROR
+ }
+ }
+ }
+ }
+
+ @SuppressLint("CheckResult")
+ fun deleteAccount(account: Account) {
+ uiScope.launch {
+ withContext(Dispatchers.Main) {
+ try {
+ _status.value = Status.LOADING
+ account.lastModifiedBy = preferencesHelper.userName
+ account.lastModifiedOn = DateUtils.getCurrentDate()
+ account.state = Account.State.CLOSED
+ synchronizationManager.deleteDocument(account.identifier!!)
+ _status.value = Status.DONE
+ } catch (exception: Exception) {
+ _status.value = Status.ERROR
+ }
+ }
+ }
+ }
+
+ fun changeAccountStatus(identifier: String, account: Account, command: AccountCommand) {
+ uiScope.launch {
+ withContext(Dispatchers.Main) {
+ try {
+ _status.value = Status.LOADING
+ when (command.action) {
+ AccountCommand.AccountTaskAction.UNLOCK -> account.state = Account.State.OPEN
+ AccountCommand.AccountTaskAction.REOPEN -> account.state = Account.State.OPEN
+ AccountCommand.AccountTaskAction.LOCK -> account.state = Account.State.LOCKED
+ AccountCommand.AccountTaskAction.CLOSE -> account.state = Account.State.CLOSED
+ else -> account.state = Account.State.OPEN
+ }
+ synchronizationManager.updateDocument(identifier, account.serializeToMap())
+ _status.value = Status.DONE
+ } catch (e: Exception) {
+ _status.value = Status.ERROR
+ }
+ }
+ }
+ }
+
+ /**
+ * When the [ViewModel] is finished, we cancel our coroutine [viewModelJob], which tells the
+ * Retrofit service to stop.
+ */
+ 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/accounting/accounts/viewmodel/AccountsViewModelFactory.kt b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/viewmodel/AccountsViewModelFactory.kt
new file mode 100644
index 00000000..cfe49db2
--- /dev/null
+++ b/app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/viewmodel/AccountsViewModelFactory.kt
@@ -0,0 +1,31 @@
+package org.apache.fineract.ui.online.accounting.accounts.viewmodel
+
+import android.content.Context
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import org.apache.fineract.couchbase.SynchronizationManager
+import org.apache.fineract.data.datamanager.DataManagerAccounting
+import org.apache.fineract.data.datamanager.api.DataManagerAnonymous
+import org.apache.fineract.data.local.PreferencesHelper
+import org.apache.fineract.injection.ApplicationContext
+import javax.inject.Inject
+
+
+/*
+ * Created by Varun Jain on 18/July/2021
+*/
+
+
+class AccountsViewModelFactory @Inject constructor(@ApplicationContext var context: Context,
+ private val synchronizationManager: SynchronizationManager,
+ private val dataManagerAnonymous: DataManagerAnonymous,
+ private val dataManagerAccounting: DataManagerAccounting,
+ private val preferencesHelper: PreferencesHelper
+)
+ : ViewModelProvider.NewInstanceFactory() {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class): T {
+ return AccountsViewModel(synchronizationManager, dataManagerAnonymous, preferencesHelper, dataManagerAccounting) as T
+ }
+}
\ No newline at end of file
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 072c90f3..c8e4fc35 100644
--- a/app/src/main/java/org/apache/fineract/utils/Constants.kt
+++ b/app/src/main/java/org/apache/fineract/utils/Constants.kt
@@ -12,4 +12,6 @@ object Constants {
const val BASIC_AUTH_KEY = "basic_auth_key"
const val GATEWAY_USER_NAME = "fineract-cn"
const val GATEWAY_PASSWORD = "password"
+ const val ACCOUNT = "account"
+ const val ACCOUNT_ACTION = "account_Action"
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_create_account.xml b/app/src/main/res/layout/activity_create_account.xml
new file mode 100644
index 00000000..7ec89587
--- /dev/null
+++ b/app/src/main/res/layout/activity_create_account.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_account_details.xml b/app/src/main/res/layout/fragment_account_details.xml
new file mode 100644
index 00000000..78c4021b
--- /dev/null
+++ b/app/src/main/res/layout/fragment_account_details.xml
@@ -0,0 +1,291 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_account_tasks_bottom_sheet.xml b/app/src/main/res/layout/fragment_account_tasks_bottom_sheet.xml
new file mode 100644
index 00000000..db0a3e88
--- /dev/null
+++ b/app/src/main/res/layout/fragment_account_tasks_bottom_sheet.xml
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_accounts.xml b/app/src/main/res/layout/fragment_accounts.xml
index b398d139..73e349e1 100644
--- a/app/src/main/res/layout/fragment_accounts.xml
+++ b/app/src/main/res/layout/fragment_accounts.xml
@@ -1,8 +1,8 @@
-
+ android:layout_width="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_step_account_details.xml b/app/src/main/res/layout/fragment_step_account_details.xml
new file mode 100644
index 00000000..52af33ca
--- /dev/null
+++ b/app/src/main/res/layout/fragment_step_account_details.xml
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_step_account_review.xml b/app/src/main/res/layout/fragment_step_account_review.xml
new file mode 100644
index 00000000..1d80eb0e
--- /dev/null
+++ b/app/src/main/res/layout/fragment_step_account_review.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_step_add_account_holder.xml b/app/src/main/res/layout/fragment_step_add_account_holder.xml
new file mode 100644
index 00000000..3772e1cb
--- /dev/null
+++ b/app/src/main/res/layout/fragment_step_add_account_holder.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_step_add_signature_authorities.xml b/app/src/main/res/layout/fragment_step_add_signature_authorities.xml
new file mode 100644
index 00000000..fc791300
--- /dev/null
+++ b/app/src/main/res/layout/fragment_step_add_signature_authorities.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_account_details.xml b/app/src/main/res/menu/menu_account_details.xml
new file mode 100644
index 00000000..43996611
--- /dev/null
+++ b/app/src/main/res/menu/menu_account_details.xml
@@ -0,0 +1,16 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b25c3ac7..8336dc74 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -181,7 +181,9 @@
%1$s created successfully
%1$s updated successfully
Group %1$s created successfully
+ Account %1$s created successfully
Group %1$s updated successfully
+ Account %1$s updated successfully
Created by
Created on
No deposit account
@@ -228,8 +230,11 @@
Status
Group Definition Identifier
Create Group
+ Create Account
No Group Member Added
+ No Account Holder Added
No Group Leader Added
+ No Signature Authority Added
Small Text
@@ -324,7 +329,9 @@
Failed to fetch deposit product
Failed to refresh customers
Group should have atleast 1 Member
+ Account should have atleast 1 Holder
Group should have atleast 1 Leader
+ Account should have atleast 1 Signature authority
OK
@@ -449,6 +456,21 @@
- Review
+
+ - Account Details
+ - Add Holders
+ - Add Signature Authorities
+ - Review
+
+
+
+ - ASSET
+ - LIABILITY
+ - EQUITY
+ - REVENUE
+ - EXPENSE
+
+
- Customer payroll
- Payroll allocations
@@ -538,10 +560,26 @@
Update
Do you want to delete %s?
Edit Group
+ Edit Account
Updating Group, please wait...
+ Updating Account, please wait...
+ Creating Account, please wait...
Please verify the following tasks before you can %1$s this group
+ Please verify the following tasks before you can %1$s this account
Change the status of group
"Updating group status, please wait... "
+ "Updating account status, please wait... "
Error while updating group status
+ Error while updating account status
+ Error while updating account
Error while creating group
+ Error while creating account
+ Alternate Account Number
+ Reference Account
+ Change the status of Account
+ Signature Authorities
+ Holders
+ State
+ Ledger
+ Reference Account Number
diff --git a/app/src/main/resources/accountsPage.json b/app/src/main/resources/accountsPage.json
index 09b69fb6..a1d1a14c 100644
--- a/app/src/main/resources/accountsPage.json
+++ b/app/src/main/resources/accountsPage.json
@@ -59,7 +59,7 @@
"balance": 1500,
"referenceAccount": "referenceAccount",
"ledger": "ledger",
- "state": "CLOSE",
+ "state": "CLOSED",
"alternativeAccountNumber": "alternativeAccountNumber",
"createdOn": "createdOn",
"createdBy": "createdBy",