diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bad499ef..13801073 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,10 +90,16 @@ + + + + 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..0bce9bd3 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"), + TELLER("Teller") } \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/data/datamanager/DataManagerTeller.kt b/app/src/main/java/org/apache/fineract/data/datamanager/DataManagerTeller.kt index 898ad3b0..66f93ce1 100644 --- a/app/src/main/java/org/apache/fineract/data/datamanager/DataManagerTeller.kt +++ b/app/src/main/java/org/apache/fineract/data/datamanager/DataManagerTeller.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 @@ -10,6 +11,7 @@ import javax.inject.Inject import org.apache.fineract.FakeRemoteDataSource import org.apache.fineract.data.datamanager.api.DataManagerAuth import org.apache.fineract.data.datamanager.api.FineractBaseDataManager +import org.apache.fineract.data.models.teller.TellerCommand import javax.inject.Singleton @Singleton @@ -18,13 +20,23 @@ class DataManagerTeller @Inject constructor(val baseManagerApi: BaseApiManager, val preferencesHelper: PreferencesHelper) : FineractBaseDataManager(dataManagerAuth, preferencesHelper) { - fun getTellers(): Observable> = - baseManagerApi.tellerService.getTellerList(preferencesHelper.tenantIdentifier) - .onErrorResumeNext(Function>> - { Observable.just(FakeRemoteDataSource.getTeller()) }) + fun getTellers(): Observable> = baseManagerApi.tellerService + .getTellerList(preferencesHelper.tenantIdentifier) + .onErrorResumeNext(Function>> + { Observable.just(FakeRemoteDataSource.getTeller()) }) fun findTeller(tellerCode: String): Observable = baseManagerApi.tellerService .searchTeller(preferencesHelper.tenantIdentifier, tellerCode) .onErrorResumeNext(Function> { Observable.just(FakeRemoteDataSource.getTeller()[0]) }) + + fun createTeller(teller: Teller): Completable = baseManagerApi.tellerService + .createTeller(preferencesHelper.tenantIdentifier, teller) + + fun updateTeller(teller: Teller): Completable = baseManagerApi.tellerService + .updateTeller(preferencesHelper.tenantIdentifier, teller.tellerAccountIdentifier!!, teller) + + fun changeTellerStatus(teller: Teller, tellerCommand: TellerCommand): Completable = baseManagerApi.tellerService + .changeTellerStatus(preferencesHelper.tenantIdentifier, teller.tellerAccountIdentifier!!, tellerCommand) + } \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/data/models/teller/Teller.kt b/app/src/main/java/org/apache/fineract/data/models/teller/Teller.kt index 61bb53ec..f294a380 100644 --- a/app/src/main/java/org/apache/fineract/data/models/teller/Teller.kt +++ b/app/src/main/java/org/apache/fineract/data/models/teller/Teller.kt @@ -3,28 +3,29 @@ package org.apache.fineract.data.models.teller import android.os.Parcelable import com.google.gson.annotations.SerializedName import kotlinx.android.parcel.Parcelize +import org.apache.fineract.couchbase.DocumentType import java.math.BigDecimal @Parcelize data class Teller( - @SerializedName("code") val code: String? = null, - @SerializedName("password") val password: String? = null, - @SerializedName("cashdrawLimit") val cashdrawLimit: BigDecimal? = null, - @SerializedName("tellerAccountIdentifier") val tellerAccountIdentifier: String? = null, - @SerializedName("vaultAccountIdentifier") val vaultAccountIdentifier: String? = null, - @SerializedName("chequesReceivableAccount") val chequesReceivableAccount: String? = null, - @SerializedName("cashOverShortAccount") val cashOverShortAccount: String? = null, - @SerializedName("denominationRequired") val denominationRequired: Boolean = false, - @SerializedName("assignedEmployee") val assignedEmployee: String? = null, - @SerializedName("state") val state: State? = null, - @SerializedName("createdBy") val createdBy: String? = null, - @SerializedName("createdOn") val createdOn: String? = null, - @SerializedName("lastModifiedBy") val lastModifiedBy: String? = null, - @SerializedName("lastModifiedOn") val lastModifiedOn: String? = null, - @SerializedName("lastOpenedBy") val lastOpenedBy: String? = null, - @SerializedName("lastOpenedOn") val lastOpenedOn: String? = null - + var code: String? = null, + var password: String? = null, + var cashdrawLimit: BigDecimal? = null, + var tellerAccountIdentifier: String? = null, + var vaultAccountIdentifier: String? = null, + var chequesReceivableAccount: String? = null, + var cashOverShortAccount: String? = null, + var denominationRequired: Boolean = false, + var assignedEmployee: String? = null, + var state: State? = State.OPEN, + var createdBy: String? = null, + var createdOn: String? = null, + var lastModifiedBy: String? = null, + var lastModifiedOn: String? = null, + var lastOpenedBy: String? = null, + var lastOpenedOn: String? = null, + var documentType: String = DocumentType.TELLER.value ) : Parcelable { enum class State { diff --git a/app/src/main/java/org/apache/fineract/data/models/teller/tellerCommand.kt b/app/src/main/java/org/apache/fineract/data/models/teller/tellerCommand.kt new file mode 100644 index 00000000..e752244f --- /dev/null +++ b/app/src/main/java/org/apache/fineract/data/models/teller/tellerCommand.kt @@ -0,0 +1,22 @@ +package org.apache.fineract.data.models.teller + +import com.google.gson.annotations.SerializedName + +data class TellerCommand ( + @SerializedName("action") var action: TellerAction? = null, + @SerializedName("adjustment") var adjustment: String? = "NONE", + @SerializedName("assignedEmployeeIdentifier") var assignedEmployeeIdentifier: String? = null +) { + enum class TellerAction { + + @SerializedName("CLOSE") + CLOSE, + + @SerializedName("ACTIVATE") + ACTIVATE, + + @SerializedName("REOPEN") + REOPEN, + + } +} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/data/services/TellersService.kt b/app/src/main/java/org/apache/fineract/data/services/TellersService.kt index 08b6213f..e331ad0d 100644 --- a/app/src/main/java/org/apache/fineract/data/services/TellersService.kt +++ b/app/src/main/java/org/apache/fineract/data/services/TellersService.kt @@ -1,10 +1,11 @@ package org.apache.fineract.data.services +import io.reactivex.Completable import io.reactivex.Observable import org.apache.fineract.data.models.teller.Teller +import org.apache.fineract.data.models.teller.TellerCommand import org.apache.fineract.data.remote.EndPoints -import retrofit2.http.GET -import retrofit2.http.Path +import retrofit2.http.* interface TellersService { @@ -14,4 +15,18 @@ interface TellersService { @GET(EndPoints.API_TELLER_PATH + "/offices/{officeIdentifier}/teller/{tellerCode}") fun searchTeller(@Path("officeIdentifier") officeIdentifier: String, @Path("tellerCode") tellerCode: String): Observable + + @POST(EndPoints.API_TELLER_PATH + "/offices/{officeIdentifier}/teller") + fun createTeller(@Path("officeIdentifier") officeIdentifier: String, + @Body teller: Teller): Completable + + @PUT(EndPoints.API_TELLER_PATH + "/offices/{officeIdentifier}/teller/{tellerIdentifier}") + fun updateTeller(@Path("officeIdentifier") officeIdentifier: String, + @Path("tellerIdentifier") tellerIdentifier: String, + @Body teller: Teller): Completable + + @POST(EndPoints.API_TELLER_PATH + "/offices/{officeIdentifier}/teller/{tellerIdentifier}/commands") + fun changeTellerStatus(@Path("officeIdentifier") officeIdentifier: String, + @Path("tellerIdentifier") tellerIdentifier: String, + @Body tellerCommand: TellerCommand): 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..f8345065 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 @@ -59,6 +59,11 @@ import org.apache.fineract.ui.online.review.AddLoanReviewFragment; import org.apache.fineract.ui.online.roles.roleslist.RolesFragment; import org.apache.fineract.ui.online.teller.TellerFragment; +import org.apache.fineract.ui.online.teller.createteller.CreateTellerActivity; +import org.apache.fineract.ui.online.teller.createteller.TellerDetailsStepFragment; +import org.apache.fineract.ui.online.teller.createteller.TellerReviewStepFragment; +import org.apache.fineract.ui.online.teller.tellerdetails.TellerDetailsFragment; +import org.apache.fineract.ui.online.teller.tellertasks.TellerTasksBottomSheetFragment; import org.apache.fineract.ui.product.ProductFragment; import dagger.Subcomponent; @@ -159,5 +164,15 @@ public interface ActivityComponent { void inject(GroupDetailsFragment groupDetailsFragment); void inject(GroupTasksBottomSheetFragment groupTasksBottomSheetFragment); + + void inject(TellerDetailsFragment tellerDetailsFragment); + + void inject(CreateTellerActivity createTellerActivity); + + void inject(TellerDetailsStepFragment tellerDetailsStepFragment); + + void inject(TellerReviewStepFragment tellerReviewStepFragment); + + void inject(TellerTasksBottomSheetFragment tellerTasksBottomSheetFragment); } diff --git a/app/src/main/java/org/apache/fineract/ui/adapters/TellerAdapter.kt b/app/src/main/java/org/apache/fineract/ui/adapters/TellerAdapter.kt index bcf86bda..1ec9e65a 100644 --- a/app/src/main/java/org/apache/fineract/ui/adapters/TellerAdapter.kt +++ b/app/src/main/java/org/apache/fineract/ui/adapters/TellerAdapter.kt @@ -7,11 +7,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_teller.view.* import org.apache.fineract.R import org.apache.fineract.data.models.teller.Teller 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,7 @@ class TellerAdapter @Inject constructor(@ApplicationContext val context: Context : RecyclerView.Adapter() { var tellers: List = ArrayList() + lateinit var onItemClickListener: OnItemClickListener override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_teller, @@ -56,12 +59,27 @@ class TellerAdapter @Inject constructor(@ApplicationContext val context: Context 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 llTeller: LinearLayout = itemView.ll_teller val tellerIdentifier: TextView = itemView.tv_teller_identifier val tvModifiedBy: TextView = itemView.tv_modified_by val tvModifiedOn: TextView = itemView.tv_modified_on val withDrawLimit: TextView = itemView.tv_cashWithdraw_limit val statusIndicator: AppCompatImageView = itemView.iv_status_indicator + + init { + llTeller.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/teller/TellerAction.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/TellerAction.kt new file mode 100644 index 00000000..9130417e --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/TellerAction.kt @@ -0,0 +1,6 @@ +package org.apache.fineract.ui.online.teller + +enum class TellerAction { + EDIT, + CREATE +} diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/TellerContract.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/TellerContract.kt deleted file mode 100644 index a9b204ad..00000000 --- a/app/src/main/java/org/apache/fineract/ui/online/teller/TellerContract.kt +++ /dev/null @@ -1,31 +0,0 @@ -package org.apache.fineract.ui.online.teller - -import org.apache.fineract.data.models.teller.Teller -import org.apache.fineract.ui.base.MvpView - -interface TellerContract { - - interface View : MvpView { - - fun showUserInterface() - - fun showTellers(tellers: List) - - fun showEmptyTellers() - - fun showRecyclerView(status: Boolean) - - fun showProgressbar() - - fun hideProgressbar() - - fun searchedTeller(tellers: List) - } - - interface Presenter { - - fun fetchTellers() - - fun searchTeller(tellers: List, query: String) - } -} diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/TellerFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/TellerFragment.kt index 9a889297..3be699ad 100644 --- a/app/src/main/java/org/apache/fineract/ui/online/teller/TellerFragment.kt +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/TellerFragment.kt @@ -2,13 +2,19 @@ package org.apache.fineract.ui.online.teller 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.util.Log.e import android.view.* +import androidx.appcompat.widget.SearchView +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import butterknife.ButterKnife +import butterknife.OnClick import kotlinx.android.synthetic.main.fragment_teller.* import kotlinx.android.synthetic.main.layout_exception_handler.* import org.apache.fineract.R @@ -16,18 +22,27 @@ import org.apache.fineract.data.models.teller.Teller import org.apache.fineract.ui.adapters.TellerAdapter 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.teller.createteller.CreateTellerActivity +import org.apache.fineract.ui.online.teller.tellerdetails.TellerDetailsActivity +import org.apache.fineract.ui.online.teller.tellerlist.TellerViewModel +import org.apache.fineract.ui.online.teller.tellerlist.TellerViewModelFactory +import org.apache.fineract.utils.Constants import javax.inject.Inject -class TellerFragment : FineractBaseFragment(), TellerContract.View, SwipeRefreshLayout.OnRefreshListener { +class TellerFragment : FineractBaseFragment(), OnItemClickListener, SwipeRefreshLayout.OnRefreshListener { - @Inject - lateinit var tellPresenter: TellerPresenter + lateinit var rootView: View + + lateinit var viewModel: TellerViewModel @Inject lateinit var tellerAdapter: TellerAdapter + @Inject + lateinit var tellerViewModelFactory: TellerViewModelFactory + lateinit var tellerList: List companion object { @@ -46,28 +61,44 @@ class TellerFragment : FineractBaseFragment(), TellerContract.View, SwipeRefresh override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.fragment_teller, container, false) - + rootView = inflater.inflate(R.layout.fragment_teller, container, false) (activity as FineractBaseActivity).activityComponent.inject(this) - tellPresenter.attachView(this) + viewModel = ViewModelProviders.of(this, tellerViewModelFactory).get(TellerViewModel::class.java) initializeFineractUIErrorHandler(activity, rootView) - return rootView } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - + ButterKnife.bind(this, rootView) + tellerAdapter.setItemClickListener(this) showUserInterface() - tellPresenter.fetchTellers() btn_try_again.setOnClickListener { + showProgressbar() layoutError.visibility = View.GONE - tellPresenter.fetchTellers() + viewModel.getTellers() + hideProgressbar() } } - override fun showUserInterface() { + override fun onStart() { + super.onStart() + viewModel.getTellers()?.observe(this, Observer { + it?.let { + tellerList = it + tellerAdapter.setTellerList(it) + } + }) + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + super.onCreateOptionsMenu(menu, inflater) + inflater.inflate(R.menu.menu_teller_search, menu) + setUpSearchInterface(menu) + } + + fun showUserInterface() { setToolbarTitle(getString(R.string.teller)) val llManager = LinearLayoutManager(activity) @@ -81,27 +112,29 @@ class TellerFragment : FineractBaseFragment(), TellerContract.View, SwipeRefresh swipeContainer.setOnRefreshListener(this) } - override fun showTellers(tellers: List) { + fun showTellers(tellers: List) { showRecyclerView(true) tellerList = tellers tellerAdapter.setTellerList(tellers) } override fun onRefresh() { - tellPresenter.fetchTellers() + showProgressbar() + viewModel.getTellers()?.observe(this, Observer { + it?.let { + tellerList = it + tellerAdapter.setTellerList(it) + } + }) + hideProgressbar() } - override fun showEmptyTellers() { + fun showEmptyTellers() { showRecyclerView(false) showFineractEmptyUI(getString(R.string.teller), getString(R.string.teller), R.drawable.ic_person_outline_black_24dp) } - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - super.onCreateOptionsMenu(menu, inflater) - inflater.inflate(R.menu.menu_teller_search, menu) - setUpSearchInterface(menu) - } private fun setUpSearchInterface(menu: Menu?) { @@ -112,7 +145,7 @@ class TellerFragment : FineractBaseFragment(), TellerContract.View, SwipeRefresh searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { - tellPresenter.searchTeller(tellerList, query) + viewModel.searchTeller(tellerList as ArrayList, query, searchedTeller) return false } @@ -121,19 +154,18 @@ class TellerFragment : FineractBaseFragment(), TellerContract.View, SwipeRefresh showRecyclerView(true) tellerAdapter.setTellerList(tellerList) } - tellPresenter.searchTeller(tellerList, newText) + viewModel.searchTeller(tellerList as ArrayList, newText, searchedTeller) return false } }) } - override fun searchedTeller(tellers: List) { - showRecyclerView(true) + val searchedTeller: (ArrayList) -> Unit = { tellers -> tellerAdapter.setTellerList(tellers) } - override fun showRecyclerView(status: Boolean) { + fun showRecyclerView(status: Boolean) { if (status) { rvTellers.visibility = View.VISIBLE layoutError.visibility = View.GONE @@ -143,26 +175,39 @@ class TellerFragment : FineractBaseFragment(), TellerContract.View, SwipeRefresh } } - override fun showProgressbar() { + fun showProgressbar() { swipeContainer.isRefreshing = true } - override fun hideProgressbar() { + fun hideProgressbar() { swipeContainer.isRefreshing = false } - override fun showError(message: String) { + fun showError(message: String) { showRecyclerView(false) showFineractErrorUI(getString(R.string.teller)) } - override fun showNoInternetConnection() { + fun showNoInternetConnection() { showRecyclerView(false) showFineractNoInternetUI() } - override fun onDestroyView() { - super.onDestroyView() - tellPresenter.detachView() + override fun onItemClick(childView: View?, position: Int) { + val intent = Intent(context, TellerDetailsActivity::class.java).apply { + putExtra(Constants.TELLER, tellerList[position]) + } + startActivity(intent) + } + + override fun onItemLongPress(childView: View?, position: Int) { + } + + @OnClick(R.id.fabAddTeller) + fun addTeller() { + val intent = Intent(activity, CreateTellerActivity::class.java).apply { + putExtra(Constants.TELLER_ACTION, TellerAction.CREATE) + } + startActivity(intent) } } diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/TellerPresenter.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/TellerPresenter.kt deleted file mode 100644 index a94c351a..00000000 --- a/app/src/main/java/org/apache/fineract/ui/online/teller/TellerPresenter.kt +++ /dev/null @@ -1,66 +0,0 @@ -package org.apache.fineract.ui.online.teller - -import android.content.Context -import io.reactivex.Observable -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.disposables.CompositeDisposable -import io.reactivex.functions.Predicate -import io.reactivex.observers.DisposableObserver -import io.reactivex.schedulers.Schedulers -import org.apache.fineract.R -import org.apache.fineract.data.datamanager.DataManagerTeller -import org.apache.fineract.data.models.teller.Teller -import org.apache.fineract.injection.ApplicationContext -import org.apache.fineract.ui.base.BasePresenter -import javax.inject.Inject - -class TellerPresenter @Inject constructor(@ApplicationContext context: Context, - private val dataManagerTeller: DataManagerTeller) : - BasePresenter(context), TellerContract.Presenter { - - val compositeDisposable = CompositeDisposable() - - override fun fetchTellers() { - - checkViewAttached() - mvpView.showProgressbar() - - compositeDisposable.add(dataManagerTeller.getTellers() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeWith(object : DisposableObserver>() { - override fun onComplete() { - - } - - override fun onNext(tellerList: List) { - mvpView.hideProgressbar() - - if (!tellerList.isEmpty()) { - mvpView.showTellers(tellerList) - } else { - mvpView.showEmptyTellers() - } - } - - override fun onError(throwable: Throwable) { - mvpView.hideProgressbar() - showExceptionError(throwable, - context.getString(R.string.error_fetching_teller)) - } - })) - } - - override fun searchTeller(tellers: List, query: String) { - checkViewAttached() - mvpView.searchedTeller(Observable.fromIterable(tellers) - .filter(object: Predicate { - override fun test(teller: Teller): Boolean { - return teller.tellerAccountIdentifier?.toLowerCase() - ?.contains(query.toLowerCase()).toString().toBoolean() - } - }).toList().blockingGet()) - } - - -} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/CreateTellerActivity.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/CreateTellerActivity.kt new file mode 100644 index 00000000..c5daf2ab --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/CreateTellerActivity.kt @@ -0,0 +1,130 @@ +package org.apache.fineract.ui.online.teller.createteller + +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_teller.* +import org.apache.fineract.R +import org.apache.fineract.data.Status +import org.apache.fineract.data.models.teller.Teller +import org.apache.fineract.ui.base.FineractBaseActivity +import org.apache.fineract.ui.base.Toaster +import org.apache.fineract.ui.online.teller.TellerAction +import org.apache.fineract.ui.online.teller.tellerlist.TellerViewModel +import org.apache.fineract.ui.online.teller.tellerlist.TellerViewModelFactory +import org.apache.fineract.utils.Constants +import java.math.BigDecimal +import javax.inject.Inject + +/* + * Created by Varun Jain on 16.06.2021 +*/ + +class CreateTellerActivity : FineractBaseActivity(), StepperLayout.StepperListener { + + private var teller = Teller() + private var tellerAction = TellerAction.CREATE + + @Inject + lateinit var tellerViewModelFactory: TellerViewModelFactory + + lateinit var tellerViewModel: TellerViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_create_teller) + activityComponent.inject(this) + tellerAction = intent.getSerializableExtra(Constants.TELLER_ACTION) as TellerAction + when (tellerAction) { + TellerAction.CREATE -> { + setToolbarTitle(getString(R.string.create_teller)) + } + TellerAction.EDIT -> { + setToolbarTitle(getString(R.string.edit_teller)) + intent?.extras?.getParcelable(Constants.TELLER)?.let { + teller = it + } + } + } + tellerViewModel = ViewModelProviders.of(this, tellerViewModelFactory).get(TellerViewModel::class.java) + subscribeUI() + showBackButton() + slCreateTeller.adapter = CreateTellerAdapter(supportFragmentManager, this, tellerAction) + slCreateTeller.setOffscreenPageLimit(slCreateTeller.adapter.count) + slCreateTeller.setListener(this) + } + + private fun subscribeUI() { + tellerViewModel.status.observe(this, Observer { status -> + when (status) { + Status.LOADING -> + if (tellerAction == TellerAction.CREATE) { + showMifosProgressDialog(getString(R.string.creating_teller)) + } else { + showMifosProgressDialog(getString(R.string.updating_teller_please_wait)) + } + Status.ERROR -> { + hideMifosProgressDialog() + if (tellerAction == TellerAction.CREATE) { + Toaster.show(findViewById(android.R.id.content), R.string.error_while_creating_teller, Toast.LENGTH_SHORT) + } else { + Toaster.show(findViewById(android.R.id.content), R.string.error_while_updating_teller, Toast.LENGTH_SHORT) + } + } + Status.DONE -> { + hideMifosProgressDialog() + if (tellerAction == TellerAction.CREATE) { + Toast.makeText(this, getString(R.string.teller_identifier_created_successfully, teller.tellerAccountIdentifier), Toast.LENGTH_SHORT).show() + } else { + Toast.makeText(this, getString(R.string.teller_identifier_updated_successfully, teller.tellerAccountIdentifier), Toast.LENGTH_SHORT).show() + } + finish() + } + } + }) + } + + override fun onCompleted(completeButton: View?) { + when (tellerAction) { + TellerAction.EDIT -> teller.tellerAccountIdentifier?.let { + tellerViewModel.updateTeller(teller) + } + TellerAction.CREATE -> tellerViewModel.createTeller(teller) + } + } + + override fun onError(verificationError: VerificationError?) {} + + override fun onStepSelected(newStepPosition: Int) {} + + override fun onReturn() {} + + fun setTellerDetails(code: String, + password: String, + cashwithdrawlimit: BigDecimal, + telleracc_identifier: String, + vaultacc_identifier: String, + cheaquesrecievableamount: String, + cashovershortacc: String, + denomation_req: Boolean, + assignedEmployee: String) { + teller.code = code + teller.password = password + teller.cashdrawLimit = cashwithdrawlimit + teller.tellerAccountIdentifier = telleracc_identifier + teller.vaultAccountIdentifier = vaultacc_identifier + teller.chequesReceivableAccount = cheaquesrecievableamount + teller.cashOverShortAccount = cashovershortacc + teller.denominationRequired = denomation_req + teller.assignedEmployee = assignedEmployee + + } + + fun getTeller(): Teller { + return teller + } +} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/CreateTellerAdapter.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/CreateTellerAdapter.kt new file mode 100644 index 00000000..91364e3d --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/CreateTellerAdapter.kt @@ -0,0 +1,38 @@ +package org.apache.fineract.ui.online.teller.createteller + +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.teller.TellerAction + +/* + * Created by Varun Jain on 16.06.2021 +*/ + +class CreateTellerAdapter constructor(fm: FragmentManager, + context: Context, + val tellerAction: TellerAction +) + : AbstractFragmentStepAdapter(fm, context){ + + private var createTellerSteps = context.resources.getStringArray(R.array.create_teller_steps) + + override fun getCount(): Int { + return createTellerSteps.size + } + + override fun createStep(position: Int): Step? { + when (position) { + 0 -> return TellerDetailsStepFragment.newInstance(tellerAction) + 1 -> return TellerReviewStepFragment.newInstance() + } + return null + } + + override fun getViewModel(position: Int): StepViewModel { + return StepViewModel.Builder(context).setTitle(createTellerSteps[position]).create() + } +} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/TellerDetailsStepFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/TellerDetailsStepFragment.kt new file mode 100644 index 00000000..9abc3fc5 --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/TellerDetailsStepFragment.kt @@ -0,0 +1,103 @@ +package org.apache.fineract.ui.online.teller.createteller + +import android.os.Bundle +import android.view.LayoutInflater +import com.stepstone.stepper.Step +import com.stepstone.stepper.VerificationError +import org.apache.fineract.ui.base.FineractBaseFragment +import org.apache.fineract.ui.online.teller.TellerAction +import org.apache.fineract.utils.Constants +import android.view.View +import android.view.ViewGroup +import android.widget.EditText +import com.wajahatkarim3.easyvalidation.core.view_ktx.validator +import kotlinx.android.synthetic.main.fragment_step_group_details.view.* +import kotlinx.android.synthetic.main.fragment_step_teller_details.* +import kotlinx.android.synthetic.main.fragment_step_teller_details.view.* +import org.apache.fineract.R +import java.math.BigDecimal + +/* + * Created by Varun Jain on 16.06.2021 +*/ + +class TellerDetailsStepFragment : FineractBaseFragment(), Step { + + lateinit var rootView: View + private lateinit var tellerAction: TellerAction + + companion object { + fun newInstance(tellerAction: TellerAction) = + TellerDetailsStepFragment().apply { + val bundle = Bundle().apply { + putSerializable(Constants.TELLER_ACTION, tellerAction) + } + arguments = bundle + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + arguments?.getSerializable(Constants.TELLER_ACTION)?.let { + tellerAction = it as TellerAction + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + rootView = inflater.inflate(R.layout.fragment_step_teller_details, container, false) + if (tellerAction == TellerAction.EDIT) { + populateData() + } + return rootView + } + + private fun populateData() { + val teller = (activity as CreateTellerActivity).getTeller() + rootView.etTellerCode.setText(teller.code) + rootView.etTellerAccountIdentifier.isEnabled = false + rootView.etTellerPassword.setText(teller.password) + rootView.etTellerCashdrawlimit.setText(teller.cashdrawLimit.toString()) + rootView.etTellerAccountIdentifier.setText(teller.tellerAccountIdentifier) + rootView.etTellerVaultIdentifier.setText(teller.vaultAccountIdentifier) + rootView.cbTellerDenominationRequired.isChecked = teller.denominationRequired + rootView.etTellerCheaque.setText(teller.chequesReceivableAccount) + rootView.etTellerCashOverShortAccount.setText(teller.cashOverShortAccount) + rootView.etTellerAssignedEmployee.setText(teller.assignedEmployee) + } + + override fun verifyStep(): VerificationError? { + if ( !(validateIdentifier(etTellerCode)) || !(validateIdentifier(etTellerPassword)) || !(validateIdentifier(etTellerCashdrawlimit)) + || !(validateIdentifier(etTellerAccountIdentifier)) || !(validateIdentifier(etTellerVaultIdentifier)) || !(validateIdentifier(etTellerCheaque)) + || !(validateIdentifier(etTellerCashOverShortAccount)) || !(validateIdentifier(etTellerAssignedEmployee))) { + return VerificationError(null) + } + (activity as CreateTellerActivity).setTellerDetails( + etTellerCode.text.toString(), + etTellerPassword.text.toString(), + BigDecimal(etTellerCashdrawlimit.text.toString()), + etTellerAccountIdentifier.text.toString(), + etTellerVaultIdentifier.text.toString(), + etTellerCheaque.text.toString(), + etTellerCashOverShortAccount.text.toString(), + cbTellerDenominationRequired.isChecked, + etTellerAssignedEmployee.text.toString() + ) + return null + } + + private fun validateIdentifier(editText: EditText): Boolean { + return editText.validator() + .nonEmpty() + .addErrorCallback { + editText.error = it + }.check() + } + + override fun onSelected() {} + + override fun onError(error: VerificationError) {} +} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/TellerReviewStepFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/TellerReviewStepFragment.kt new file mode 100644 index 00000000..18a1e5ca --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/createteller/TellerReviewStepFragment.kt @@ -0,0 +1,60 @@ +package org.apache.fineract.ui.online.teller.createteller + +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_step_teller_review.* +import org.apache.fineract.R +import org.apache.fineract.data.models.teller.Teller +import org.apache.fineract.ui.base.FineractBaseFragment + +/* + * Created by Varun Jain on 16.06.2021 +*/ + +class TellerReviewStepFragment : FineractBaseFragment(), Step { + + lateinit var rootView: View + + companion object { + fun newInstance(): TellerReviewStepFragment { + return TellerReviewStepFragment() + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + rootView = inflater.inflate(R.layout.fragment_step_teller_review, container, false) + (activity as CreateTellerActivity).activityComponent.inject(this) + + return rootView + } + + private fun fillViews(teller: Teller) { + tvTellerReviewCode.text = teller.code + tvTellerReviewPassword.text = teller.password + tvTellerReviewCashdrawLimit.text = teller.cashdrawLimit.toString() + tvTellerReviewAccountIdentifier.text = teller.tellerAccountIdentifier + tvTellerReviewVaultAccountIdentifier.text = teller.vaultAccountIdentifier + tvTellerReviewDenomination.isChecked = teller.denominationRequired + tvTellerReviewCra.text = teller.chequesReceivableAccount + tvTellerReviewCashoverShortAccount.text = teller.cashOverShortAccount + tvTellerReviewAssignedEmployee.text = teller.assignedEmployee + } + + override fun verifyStep(): VerificationError? { + return null + } + + override fun onSelected() { + fillViews((activity as CreateTellerActivity).getTeller()) + } + + override fun onError(error: VerificationError) {} +} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/tellerdetails/TellerDetailsActivity.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/tellerdetails/TellerDetailsActivity.kt new file mode 100644 index 00000000..013576d2 --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/tellerdetails/TellerDetailsActivity.kt @@ -0,0 +1,22 @@ +package org.apache.fineract.ui.online.teller.tellerdetails + +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 14.06.2021 +*/ + +class TellerDetailsActivity : FineractBaseActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_toolbar_container) + + replaceFragment(TellerDetailsFragment.newInstance(intent.getParcelableExtra(Constants.TELLER)), false, R.id.container) + showBackButton() + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/tellerdetails/TellerDetailsFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/tellerdetails/TellerDetailsFragment.kt new file mode 100644 index 00000000..c9953e8d --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/tellerdetails/TellerDetailsFragment.kt @@ -0,0 +1,112 @@ +package org.apache.fineract.ui.online.teller.tellerdetails + +import android.content.Intent +import android.os.Bundle +import android.view.* +import butterknife.ButterKnife +import butterknife.OnClick +import kotlinx.android.synthetic.main.fragment_teller_details.* +import org.apache.fineract.R +import org.apache.fineract.data.models.teller.Teller +import org.apache.fineract.ui.base.FineractBaseFragment +import org.apache.fineract.ui.base.FineractBaseActivity +import org.apache.fineract.ui.online.teller.TellerAction +import org.apache.fineract.ui.online.teller.createteller.CreateTellerActivity +import org.apache.fineract.ui.online.teller.tellertasks.TellerTasksBottomSheetFragment +import org.apache.fineract.ui.views.CircularImageView +import org.apache.fineract.utils.Constants +import org.apache.fineract.utils.Utils + +class TellerDetailsFragment : FineractBaseFragment() { + + lateinit var rootView: View + lateinit var teller: Teller + + companion object { + fun newInstance(teller: Teller) : TellerDetailsFragment{ + val fragment = TellerDetailsFragment() + val args = Bundle() + args.putParcelable(Constants.TELLER, teller) + fragment.arguments = args + return fragment + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + teller = arguments?.get(Constants.TELLER) as Teller + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + rootView = inflater.inflate(R.layout.fragment_teller_details, container, false) + (activity as FineractBaseActivity).activityComponent.inject(this) + ButterKnife.bind(this, rootView) + setToolbarTitle(teller.tellerAccountIdentifier) + setHasOptionsMenu(true) + return rootView + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + tellerDetailsCode.text = teller.code + tellerDetailsPassword.text = teller.password + setTellerStatusIcon(teller.state, tellerDetailsCiv) + tellerDetailsState.text = teller.state.toString() + tellerDetailsAccountIdentifier.text = teller.tellerAccountIdentifier + tellerDetailsVaultIdentifier.text = teller.vaultAccountIdentifier + tellerCra.text = teller.chequesReceivableAccount + tellerDetailsCashdrawLimit.text = teller.cashdrawLimit.toString() + tellerDetailsCosAccount.text = teller.cashOverShortAccount + tellerDetailsAssignedEmployee.text = teller.assignedEmployee + tellerDetailsDenominationReq.text = if (teller.denominationRequired) "YES" else "NO" + + } + + 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_teller_details, menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.menuEditTeller -> { + val intent = Intent(activity, CreateTellerActivity::class.java).apply { + putExtra(Constants.TELLER, teller) + putExtra(Constants.TELLER_ACTION, TellerAction.EDIT) + } + startActivity(intent) + activity!!.finish() + } + } + return super.onOptionsItemSelected(item) + } + + @OnClick(R.id.tellerDetailsTasks) + fun onTasksCardViewClicked() { + val bottomSheet = TellerTasksBottomSheetFragment(teller) + bottomSheet.show(childFragmentManager, getString(R.string.tasks)) + } + + private fun setTellerStatusIcon(status: Teller.State?, imageView: CircularImageView) { + when (status) { + Teller.State.OPEN -> { + imageView.setImageDrawable(Utils.setCircularBackground(R.color.blue, context)) + } + Teller.State.PAUSED -> { + imageView.setImageDrawable(Utils.setCircularBackground(R.color.light_yellow, context)) + } + Teller.State.ACTIVE -> { + imageView.setImageDrawable(Utils.setCircularBackground(R.color.deposit_green, context)) + } + Teller.State.CLOSED -> { + imageView.setImageDrawable(Utils.setCircularBackground(R.color.red_dark, context)) + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/tellerlist/TellerViewModel.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/tellerlist/TellerViewModel.kt new file mode 100644 index 00000000..6b4f0cec --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/tellerlist/TellerViewModel.kt @@ -0,0 +1,172 @@ +package org.apache.fineract.ui.online.teller.tellerlist + +import android.annotation.SuppressLint +import android.util.Log.e +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.schedulers.Schedulers +import kotlinx.coroutines.* +import org.apache.fineract.couchbase.DocumentType +import org.apache.fineract.couchbase.SynchronizationManager +import org.apache.fineract.data.Status +import org.apache.fineract.data.datamanager.api.DataManagerAnonymous +import org.apache.fineract.data.local.PreferencesHelper +import org.apache.fineract.data.models.Group +import org.apache.fineract.data.models.customer.Country +import org.apache.fineract.data.models.teller.Teller +import org.apache.fineract.data.models.teller.TellerCommand +import org.apache.fineract.utils.DateUtils +import org.apache.fineract.utils.serializeToMap +import org.apache.fineract.utils.toDataClass +import java.lang.Exception + +/* + * Created by Varun Jain on 14.06.2021 +*/ + +/** + * Adding the SynchronizationManager as a constructor parameter so as to implement Couchbase afterwards + */ +class TellerViewModel(private val synchronizationManager: SynchronizationManager, + private val dataManagerAnonymous: DataManagerAnonymous, + private val preferencesHelper: PreferencesHelper +) : ViewModel() { + + var tellersList = 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 getTellers(): MutableLiveData>? { + val expression = Expression.property("documentType") + .equalTo(Expression.string(DocumentType.TELLER.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()) + } + tellersList.value = list + return tellersList + } + + fun searchTeller(tellers: ArrayList, query: String, searchedTeller: (ArrayList) -> Unit) { + searchedTeller(ArrayList(Observable.fromIterable(tellers).filter { teller -> teller.tellerAccountIdentifier?.toLowerCase()?.contains(query.toLowerCase()).toString().toBoolean() }.toList().blockingGet())) + } + + @SuppressLint("CheckResult") + fun getCountries(): MutableLiveData> { + val countries = MutableLiveData>() + dataManagerAnonymous.countries.subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + countries.value = it + } + return countries + } + + @SuppressLint("CheckResult") + fun createTeller(teller: Teller) { + uiScope.launch { + withContext(Dispatchers.Main) { + try { + _status.value = Status.LOADING + teller.createdBy = preferencesHelper.userName + teller.createdOn = DateUtils.getCurrentDate() + teller.lastModifiedBy = preferencesHelper.userName + teller.lastModifiedOn = DateUtils.getCurrentDate() + teller.lastOpenedBy = preferencesHelper.userName + teller.lastOpenedOn = DateUtils.getCurrentDate() + synchronizationManager.saveDocument(teller.tellerAccountIdentifier!!, teller.serializeToMap()) + _status.value = Status.DONE + } catch (exception: Exception) { + _status.value = Status.ERROR + } + } + } + } + + fun updateTeller(teller: Teller) { + uiScope.launch { + withContext(Dispatchers.Main) { + try { + _status.value = Status.LOADING + teller.createdBy = preferencesHelper.userName + teller.createdOn = DateUtils.getCurrentDate() + teller.lastModifiedBy = preferencesHelper.userName + teller.lastModifiedOn = DateUtils.getCurrentDate() + teller.lastOpenedBy = preferencesHelper.userName + teller.lastOpenedOn = DateUtils.getCurrentDate() + synchronizationManager.updateDocument(teller.tellerAccountIdentifier!!, teller.serializeToMap()) + _status.value = Status.DONE + } catch (exception: Exception) { + _status.value = Status.ERROR + } + } + } + } + + fun changeTellerStatus(teller: Teller, command: TellerCommand) { + uiScope.launch { + withContext(Dispatchers.Main) { + try { + _status.value = Status.LOADING + when (command.action) { + TellerCommand.TellerAction.ACTIVATE -> teller.state = Teller.State.ACTIVE + TellerCommand.TellerAction.CLOSE -> teller.state = Teller.State.CLOSED + TellerCommand.TellerAction.REOPEN -> teller.state = Teller.State.OPEN + else -> teller.state = Teller.State.PAUSED + } + synchronizationManager.updateDocument(teller.tellerAccountIdentifier!!, teller.serializeToMap()) + _status.value = Status.DONE + } catch (e: Exception) { + _status.value = Status.ERROR + } + } + } + } + + fun getCountryNames(countries: List): List { + return Observable.fromIterable(countries).map { country: Country -> country.name }.toList().blockingGet() + } + + fun getCountryCode(countries: List, countryName: String): String? { + for (country in countries) { + if (country.name == countryName) { + return country.alphaCode + } + } + return null + } + + fun isCountryValid(countries: List, countryName: String): Boolean { + for (country in countries) { + if (country.name == countryName) { + return true + } + } + return false + } + /** + * 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/teller/tellerlist/TellerViewModelFactory.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/tellerlist/TellerViewModelFactory.kt new file mode 100644 index 00000000..f841332a --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/tellerlist/TellerViewModelFactory.kt @@ -0,0 +1,27 @@ +package org.apache.fineract.ui.online.teller.tellerlist + +import android.content.Context +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import org.apache.fineract.couchbase.SynchronizationManager +import org.apache.fineract.data.datamanager.DataManagerTeller +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 14.06.2021 +*/ + +class TellerViewModelFactory @Inject constructor(@ApplicationContext var context: Context, + private val synchronizationManager: SynchronizationManager, + private val dataManagerAnonymous: DataManagerAnonymous, + private val preferencesHelper: PreferencesHelper +) : ViewModelProvider.NewInstanceFactory() { + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): T { + return TellerViewModel(synchronizationManager, dataManagerAnonymous, preferencesHelper) as T + } +} \ No newline at end of file diff --git a/app/src/main/java/org/apache/fineract/ui/online/teller/tellertasks/TellerTasksBottomSheetFragment.kt b/app/src/main/java/org/apache/fineract/ui/online/teller/tellertasks/TellerTasksBottomSheetFragment.kt new file mode 100644 index 00000000..70bc5c2e --- /dev/null +++ b/app/src/main/java/org/apache/fineract/ui/online/teller/tellertasks/TellerTasksBottomSheetFragment.kt @@ -0,0 +1,158 @@ +package org.apache.fineract.ui.online.teller.tellertasks + +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_teller_tasks_bottom_sheet.view.* +import org.apache.fineract.R +import org.apache.fineract.data.Status +import org.apache.fineract.data.models.teller.Teller +import org.apache.fineract.data.models.teller.TellerCommand +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.teller.tellerlist.TellerViewModel +import org.apache.fineract.ui.online.teller.tellerlist.TellerViewModelFactory +import javax.inject.Inject + +/* + * Created by Varun Jain on 21.06.2021 +*/ + +class TellerTasksBottomSheetFragment(val teller: Teller) : FineractBaseBottomSheetDialogFragment() { + + lateinit var rootView: View + private var command = TellerCommand() + lateinit var behavior: BottomSheetBehavior<*> + private lateinit var viewModel: TellerViewModel + + @Inject + lateinit var viewModelFactory: TellerViewModelFactory + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog + rootView = View.inflate(context, R.layout.fragment_teller_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(TellerViewModel::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_teller_status)) + } + Status.ERROR -> { + hideMifosProgressDialog() + Toaster.show(rootView, R.string.error_while_updating_teller_status, Toast.LENGTH_SHORT) + } + Status.DONE -> { + Toaster.show(rootView, getString(R.string.teller_identifier_updated_successfully, teller.tellerAccountIdentifier), Toast.LENGTH_SHORT) + hideMifosProgressDialog() + dismiss() + } + } + }) + } + + private fun setDataOnViews() { + when (teller.state) { + Teller.State.ACTIVE -> { + rootView.ivTellerTask.setImageDrawable( + ContextCompat.getDrawable(activity!!, R.drawable.ic_close_black_24dp)) + rootView.ivTellerTask.setColorFilter(ContextCompat.getColor(activity!!, R.color.red_dark)) + rootView.tvTellerTask.text = getString(R.string.close) + } + Teller.State.OPEN -> { + rootView.ivTellerTask.setImageDrawable( + ContextCompat.getDrawable(activity!!, R.drawable.ic_close_black_24dp)) + rootView.ivTellerTask.setColorFilter(ContextCompat.getColor(activity!!, R.color.red_dark)) + rootView.tvTellerTask.text = getString(R.string.close) + } + Teller.State.CLOSED -> { + rootView.ivTellerTask.setImageDrawable( + ContextCompat.getDrawable(activity!!, R.drawable.ic_check_circle_black_24dp)) + rootView.ivTellerTask.setColorFilter(ContextCompat.getColor(activity!!, R.color.status)) + rootView.tvTellerTask.text = getString(R.string.reopen) + } + Teller.State.PAUSED -> { + rootView.ivTellerTask.setImageDrawable( + ContextCompat.getDrawable(activity!!, R.drawable.ic_check_circle_black_24dp)) + rootView.ivTellerTask.setColorFilter(ContextCompat.getColor(activity!!, R.color.status)) + rootView.tvTellerTask.text = getString(R.string.activate) + } + } + } + + @OnClick(R.id.ivTellerTask) + fun onTaskImageViewClicked() { + when (teller.state) { + Teller.State.ACTIVE -> { + command.action = TellerCommand.TellerAction.CLOSE + command.assignedEmployeeIdentifier = teller.assignedEmployee.toString() + rootView.tvTellerHeader.text = getString(R.string.close) + rootView.tvTellerSubHeader.text = getString(R.string.please_verify_following_teller_task, getString(R.string.close)) + rootView.btnTellerSubmitTask.text = getString(R.string.close) + } + Teller.State.PAUSED -> { + command.action = TellerCommand.TellerAction.ACTIVATE + command.assignedEmployeeIdentifier = teller.assignedEmployee.toString() + rootView.tvTellerHeader.text = getString(R.string.activate) + rootView.tvTellerSubHeader.text = getString(R.string.please_verify_following_teller_task, getString(R.string.activate)) + rootView.btnTellerSubmitTask.text = getString(R.string.activate) + } + Teller.State.CLOSED -> { + command.action = TellerCommand.TellerAction.REOPEN + command.assignedEmployeeIdentifier = teller.assignedEmployee.toString() + rootView.tvTellerHeader.text = getString(R.string.reopen) + rootView.tvTellerSubHeader.text = getString(R.string.please_verify_following_teller_task, getString(R.string.reopen)) + rootView.btnTellerSubmitTask.text = getString(R.string.reopen) + } + Teller.State.OPEN -> { + command.action = TellerCommand.TellerAction.CLOSE + command.assignedEmployeeIdentifier = teller.assignedEmployee.toString() + rootView.tvTellerHeader.text = getString(R.string.close) + rootView.tvTellerSubHeader.text = getString(R.string.please_verify_following_teller_task, getString(R.string.close)) + rootView.btnTellerSubmitTask.text = getString(R.string.close) + } + } + rootView.llTellerTaskList.visibility = View.GONE + rootView.llTellerTaskForm.visibility = View.VISIBLE + } + + @OnClick(R.id.btnTellerSubmitTask) + fun submitTask() { + viewModel.changeTellerStatus(teller, command) + activity!!.finish() + } + + @OnClick(R.id.btnTellerCancel) + 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/utils/Constants.kt b/app/src/main/java/org/apache/fineract/utils/Constants.kt index 072c90f3..ffbb89fa 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 TELLER = "teller" + const val TELLER_ACTION = "teller_action" } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_create_teller.xml b/app/src/main/res/layout/activity_create_teller.xml new file mode 100644 index 00000000..c0c54fb5 --- /dev/null +++ b/app/src/main/res/layout/activity_create_teller.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_step_teller_details.xml b/app/src/main/res/layout/fragment_step_teller_details.xml new file mode 100644 index 00000000..508bbf2f --- /dev/null +++ b/app/src/main/res/layout/fragment_step_teller_details.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_step_teller_review.xml b/app/src/main/res/layout/fragment_step_teller_review.xml new file mode 100644 index 00000000..e4931553 --- /dev/null +++ b/app/src/main/res/layout/fragment_step_teller_review.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_teller.xml b/app/src/main/res/layout/fragment_teller.xml index 7cdccbe5..5027e450 100644 --- a/app/src/main/res/layout/fragment_teller.xml +++ b/app/src/main/res/layout/fragment_teller.xml @@ -1,8 +1,8 @@ - + android:layout_height="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_teller_tasks_bottom_sheet.xml b/app/src/main/res/layout/fragment_teller_tasks_bottom_sheet.xml new file mode 100644 index 00000000..62212032 --- /dev/null +++ b/app/src/main/res/layout/fragment_teller_tasks_bottom_sheet.xml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +