From 8f9bffbb383e15ade6e380a634326f2aeebcb0f2 Mon Sep 17 00:00:00 2001 From: varun jain Date: Thu, 29 Jul 2021 02:17:35 +0530 Subject: [PATCH] Add support for all the account related functionalities using couchbase to extend offline support in the application --- app/src/main/AndroidManifest.xml | 6 + .../apache/fineract/couchbase/DocumentType.kt | 3 +- .../data/datamanager/DataManagerAccounting.kt | 6 + .../fineract/data/models/accounts/Account.kt | 31 +- .../data/services/AccountingService.kt | 11 +- .../component/ActivityComponent.java | 24 ++ .../fineract/ui/adapters/AccountsAdapter.kt | 21 +- .../accounting/accounts/AccountAction.kt | 10 + .../accounting/accounts/AccountsFragment.kt | 100 ++++-- .../accountDetails/AccountDetailsActivity.kt | 21 ++ .../accountDetails/AccountDetailsFragment.kt | 155 ++++++++++ .../accounts/accounttasks/AccountCommand.kt | 27 ++ .../AccountTaskBottomSheetFragment.kt | 171 ++++++++++ .../AccountDetailsStepFragment.kt | 166 ++++++++++ .../AccountReviewStepFragment.kt | 80 +++++ .../AddAccountHoldersStepFragment.kt | 180 +++++++++++ .../AddAccountSignAuthoritiesFragment.kt | 186 +++++++++++ .../createaccount/CreateAccountActivity.kt | 164 ++++++++++ .../createaccount/CreateAccountAdapter.kt | 39 +++ .../accounts/viewmodel/AccountsViewModel.kt | 167 ++++++++++ .../viewmodel/AccountsViewModelFactory.kt | 31 ++ .../org/apache/fineract/utils/Constants.kt | 2 + .../res/layout/activity_create_account.xml | 28 ++ .../res/layout/fragment_account_details.xml | 291 ++++++++++++++++++ .../fragment_account_tasks_bottom_sheet.xml | 198 ++++++++++++ app/src/main/res/layout/fragment_accounts.xml | 17 +- .../layout/fragment_step_account_details.xml | 117 +++++++ .../layout/fragment_step_account_review.xml | 247 +++++++++++++++ .../fragment_step_add_account_holder.xml | 128 ++++++++ ...ragment_step_add_signature_authorities.xml | 128 ++++++++ .../main/res/menu/menu_account_details.xml | 16 + app/src/main/res/values/strings.xml | 38 +++ app/src/main/resources/accountsPage.json | 2 +- 33 files changed, 2762 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/AccountAction.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accountDetails/AccountDetailsActivity.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accountDetails/AccountDetailsFragment.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accounttasks/AccountCommand.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/accounttasks/AccountTaskBottomSheetFragment.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AccountDetailsStepFragment.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AccountReviewStepFragment.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AddAccountHoldersStepFragment.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/AddAccountSignAuthoritiesFragment.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/CreateAccountActivity.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/createaccount/CreateAccountAdapter.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/viewmodel/AccountsViewModel.kt create mode 100644 app/src/main/java/org/apache/fineract/ui/online/accounting/accounts/viewmodel/AccountsViewModelFactory.kt create mode 100644 app/src/main/res/layout/activity_create_account.xml create mode 100644 app/src/main/res/layout/fragment_account_details.xml create mode 100644 app/src/main/res/layout/fragment_account_tasks_bottom_sheet.xml create mode 100644 app/src/main/res/layout/fragment_step_account_details.xml create mode 100644 app/src/main/res/layout/fragment_step_account_review.xml create mode 100644 app/src/main/res/layout/fragment_step_add_account_holder.xml create mode 100644 app/src/main/res/layout/fragment_step_add_signature_authorities.xml create mode 100644 app/src/main/res/menu/menu_account_details.xml 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +