Merge branch 'development' into ttifc

# Conflicts:
#	core/network/src/main/java/org/mifos/mobile/core/network/BaseURL.kt
#	fastlane-config/android_config.rb
This commit is contained in:
Rajan Maurya 2025-03-06 16:05:21 -05:00
commit fdf2aba89f
33 changed files with 333 additions and 182 deletions

View File

@ -26,10 +26,13 @@ import org.mifos.library.passcode.navigateToPasscodeScreen
import org.mifos.mobile.HomeActivity
import org.mifos.mobile.R
import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.enums.AccountType
import org.mifos.mobile.core.model.enums.ChargeType
import org.mifos.mobile.core.model.enums.TransferType
import org.mifos.mobile.feature.about.navigation.aboutUsNavGraph
import org.mifos.mobile.feature.about.navigation.navigateToAboutUsScreen
import org.mifos.mobile.feature.account.navigation.ClientAccountsNavigation
import org.mifos.mobile.feature.account.navigation.clientAccountsNavGraph
import org.mifos.mobile.feature.account.navigation.navigateToClientAccountsScreen
import org.mifos.mobile.feature.auth.navigation.authenticationNavGraph
@ -47,6 +50,7 @@ import org.mifos.mobile.feature.help.navigation.navigateToHelpScreen
import org.mifos.mobile.feature.home.navigation.HomeDestinations
import org.mifos.mobile.feature.home.navigation.HomeNavigation
import org.mifos.mobile.feature.home.navigation.homeNavGraph
import org.mifos.mobile.feature.home.navigation.navigateToHomeScreen
import org.mifos.mobile.feature.loan.navigation.loanNavGraph
import org.mifos.mobile.feature.loan.navigation.navigateToLoanApplication
import org.mifos.mobile.feature.loan.navigation.navigateToLoanDetailScreen
@ -157,7 +161,23 @@ fun MifosNavHost(
},
)
transferProcessNavGraph(navigateBack = navController::popBackStack)
transferProcessNavGraph(
navigateBack = navController::popBackStack,
onTransferSuccessNavigate = { destination ->
when (destination) {
TransferSuccessDestination.HOME -> navController.navigateToHomeScreen()
TransferSuccessDestination.LOAN_ACCOUNT -> navController.navigateToClientAccountsScreen(
AccountType.LOAN,
ClientAccountsNavigation.ClientAccountsBase.route,
)
TransferSuccessDestination.SAVINGS_ACCOUNT -> navController.navigateToClientAccountsScreen(
AccountType.SAVINGS,
ClientAccountsNavigation.ClientAccountsBase.route,
)
}
},
)
beneficiaryNavGraph(
navController = navController,
@ -211,7 +231,11 @@ fun handleHomeNavigation(
}
HomeDestinations.RECENT_TRANSACTIONS -> navController.navigateToRecentTransaction()
HomeDestinations.CHARGES -> navController.navigateToClientChargeScreen(ChargeType.CLIENT, -1L)
HomeDestinations.CHARGES -> navController.navigateToClientChargeScreen(
ChargeType.CLIENT,
-1L,
)
HomeDestinations.THIRD_PARTY_TRANSFER -> navController.navigateToThirdPartyTransfer()
HomeDestinations.SETTINGS -> navController.navigateToSettings()
HomeDestinations.ABOUT_US -> navController.navigateToAboutUsScreen()
@ -228,6 +252,8 @@ fun handleHomeNavigation(
HomeDestinations.TRANSFER -> navController.navigateToSavingsMakeTransfer(
accountId = 1,
transferType = TRANSFER_PAY_TO,
transferTarget = TransferType.SELF,
transferSuccessDestination = TransferSuccessDestination.HOME,
)
HomeDestinations.BENEFICIARIES -> navController.navigateToBeneficiaryListScreen()

View File

@ -28,6 +28,8 @@ object Constants {
const val TRANSACTIONS = "transactions"
const val DFRAG_DATE_PICKER = "Date Picker"
const val TRANSFER_TYPE = "transfer_type"
const val TRANSFER_TARGET = "transfer_target"
const val TRANSFER_SUCCESS_DESTINATION = "transfer_success_destination"
const val TRANSFER_QUICK = "transfer_quick"
const val TRANSFER_PAY_TO = "transfer_pay_to"
const val TRANSFER_PAY_FROM = "transfer_pay_from"

View File

@ -29,5 +29,5 @@ interface BeneficiaryRepository {
suspend fun deleteBeneficiary(beneficiaryId: Long?): Flow<ResponseBody>
suspend fun beneficiaryList(): Flow<List<Beneficiary>>
fun beneficiaryList(): Flow<List<Beneficiary>>
}

View File

@ -39,5 +39,5 @@ interface SavingsAccountRepository {
payload: SavingsAccountWithdrawPayload?,
): Flow<ResponseBody>
fun accountTransferTemplate(accountId: Long?, accountType: Long?): Flow<AccountOptionsTemplate>
fun accountTransferTemplate(): Flow<AccountOptionsTemplate>
}

View File

@ -14,5 +14,5 @@ import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTempla
interface ThirdPartyTransferRepository {
suspend fun thirdPartyTransferTemplate(): Flow<AccountOptionsTemplate>
fun thirdPartyTransferTemplate(): Flow<AccountOptionsTemplate>
}

View File

@ -29,8 +29,6 @@ interface TransferRepository {
transferDescription: String?,
dateFormat: String = "dd MMMM yyyy",
locale: String = "en",
fromAccountNumber: String?,
toAccountNumber: String?,
transferType: TransferType?,
): Flow<ResponseBody>
}

View File

@ -9,9 +9,13 @@
*/
package org.mifos.mobile.core.data.repositoryImpl
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import okhttp3.ResponseBody
import org.mifos.mobile.core.common.network.Dispatcher
import org.mifos.mobile.core.common.network.MifosDispatchers
import org.mifos.mobile.core.data.repository.BeneficiaryRepository
import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary
import org.mifos.mobile.core.model.entity.beneficiary.BeneficiaryPayload
@ -22,6 +26,8 @@ import javax.inject.Inject
class BeneficiaryRepositoryImp @Inject constructor(
private val dataManager: DataManager,
@Dispatcher(MifosDispatchers.IO)
private val ioDispatcher: CoroutineDispatcher,
) : BeneficiaryRepository {
override suspend fun beneficiaryTemplate(): Flow<BeneficiaryTemplate> {
@ -51,9 +57,9 @@ class BeneficiaryRepositoryImp @Inject constructor(
}
}
override suspend fun beneficiaryList(): Flow<List<Beneficiary>> {
override fun beneficiaryList(): Flow<List<Beneficiary>> {
return flow {
emit(dataManager.beneficiaryList())
}
}.flowOn(ioDispatcher)
}
}

View File

@ -9,9 +9,13 @@
*/
package org.mifos.mobile.core.data.repositoryImpl
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import okhttp3.ResponseBody
import org.mifos.mobile.core.common.network.Dispatcher
import org.mifos.mobile.core.common.network.MifosDispatchers
import org.mifos.mobile.core.data.repository.SavingsAccountRepository
import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountApplicationPayload
import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountUpdatePayload
@ -24,6 +28,8 @@ import javax.inject.Inject
class SavingsAccountRepositoryImp @Inject constructor(
private val dataManager: DataManager,
@Dispatcher(MifosDispatchers.IO)
private val ioDispatcher: CoroutineDispatcher,
) : SavingsAccountRepository {
override suspend fun getSavingsWithAssociations(
@ -69,17 +75,9 @@ class SavingsAccountRepositoryImp @Inject constructor(
}
}
override fun accountTransferTemplate(
accountId: Long?,
accountType: Long?,
): Flow<AccountOptionsTemplate> {
override fun accountTransferTemplate(): Flow<AccountOptionsTemplate> {
return flow {
emit(
dataManager.accountTransferTemplate(
accountId = accountType,
accountType = accountType,
),
)
}
emit(dataManager.accountTransferTemplate())
}.flowOn(ioDispatcher)
}
}

View File

@ -9,8 +9,12 @@
*/
package org.mifos.mobile.core.data.repositoryImpl
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import org.mifos.mobile.core.common.network.Dispatcher
import org.mifos.mobile.core.common.network.MifosDispatchers
import org.mifos.mobile.core.data.repository.ThirdPartyTransferRepository
import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTemplate
import org.mifos.mobile.core.network.DataManager
@ -18,11 +22,13 @@ import javax.inject.Inject
class ThirdPartyTransferRepositoryImp @Inject constructor(
private val dataManager: DataManager,
@Dispatcher(MifosDispatchers.IO)
private val ioDispatcher: CoroutineDispatcher,
) : ThirdPartyTransferRepository {
override suspend fun thirdPartyTransferTemplate(): Flow<AccountOptionsTemplate> {
override fun thirdPartyTransferTemplate(): Flow<AccountOptionsTemplate> {
return flow {
emit(dataManager.thirdPartyTransferTemplate())
}
}.flowOn(ioDispatcher)
}
}

View File

@ -35,8 +35,6 @@ class TransferRepositoryImp @Inject constructor(
transferDescription: String?,
dateFormat: String,
locale: String,
fromAccountNumber: String?,
toAccountNumber: String?,
transferType: TransferType?,
): Flow<ResponseBody> {
val transferPayload = TransferPayload().apply {
@ -53,8 +51,6 @@ class TransferRepositoryImp @Inject constructor(
this.transferDescription = transferDescription
this.dateFormat = dateFormat
this.locale = locale
this.fromAccountNumber = fromAccountNumber
this.toAccountNumber = toAccountNumber
}
return flow {
emit(

View File

@ -0,0 +1,16 @@
/*
* Copyright 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
*/
package org.mifos.mobile.core.model.entity
enum class TransferSuccessDestination {
SAVINGS_ACCOUNT,
LOAN_ACCOUNT,
HOME,
}

View File

@ -80,7 +80,6 @@ data class LoanAccount(
parcel.readString(),
parcel.readParcelable(Timeline::class.java.classLoader),
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeLong(loanProductId)
parcel.writeString(externalId)

View File

@ -44,10 +44,8 @@ data class TransferPayload(
var locale: String = "en",
@Transient
var fromAccountNumber: String? = null,
@Transient
var toAccountNumber: String? = null,
) : Parcelable

View File

@ -22,8 +22,4 @@ data class AccountOptionsTemplate(
var fromAccountOptions: List<AccountOption> = ArrayList(),
var toAccountOptions: List<AccountOption> = ArrayList(),
var fromAccountTypeOptions: List<AccountType> = ArrayList(),
var toAccountTypeOptions: List<AccountType> = ArrayList(),
) : Parcelable

View File

@ -110,11 +110,8 @@ class DataManager @Inject constructor(
)
}
suspend fun accountTransferTemplate(
accountId: Long?,
accountType: Long?,
): AccountOptionsTemplate =
baseApiManager.savingAccountsListApi.accountTransferTemplate(accountId, accountType)
suspend fun accountTransferTemplate(): AccountOptionsTemplate =
baseApiManager.savingAccountsListApi.accountTransferTemplate()
suspend fun makeTransfer(transferPayload: TransferPayload?): ResponseBody {
return baseApiManager.savingAccountsListApi.makeTransfer(transferPayload)

View File

@ -33,10 +33,7 @@ interface SavingAccountsListService {
): SavingsWithAssociations
@GET(ApiEndPoints.ACCOUNT_TRANSFER + "/template")
suspend fun accountTransferTemplate(
@Query("fromAccountId") accountId: Long?,
@Query("fromAccountType") accountType: Long?,
): AccountOptionsTemplate
suspend fun accountTransferTemplate(): AccountOptionsTemplate
@POST(ApiEndPoints.ACCOUNT_TRANSFER)
suspend fun makeTransfer(@Body transferPayload: TransferPayload?): ResponseBody

View File

@ -55,9 +55,10 @@ internal fun ClientAccountsScreen(
val context = LocalContext.current
var isDialogActive by rememberSaveable { mutableStateOf(false) }
var currentPage by rememberSaveable { mutableIntStateOf(0) }
val accountType by viewModel.accountType.collectAsStateWithLifecycle()
var currentPage by rememberSaveable { mutableIntStateOf(accountType?.ordinal ?: 0) }
val filterList by viewModel.filterList.collectAsStateWithLifecycle()
LaunchedEffect(key1 = accountType) {

View File

@ -19,8 +19,17 @@ import org.mifos.mobile.core.common.Constants
import org.mifos.mobile.core.model.enums.AccountType
import org.mifos.mobile.feature.account.clientAccount.screens.ClientAccountsScreen
fun NavController.navigateToClientAccountsScreen(accountType: AccountType = AccountType.SAVINGS) {
navigate(ClientAccountsNavigation.ClientAccountsScreen.passArguments(accountType = accountType))
fun NavController.navigateToClientAccountsScreen(
accountType: AccountType = AccountType.SAVINGS,
popUpToDestination: String? = null,
) {
navigate(ClientAccountsNavigation.ClientAccountsScreen.passArguments(accountType = accountType)) {
if (popUpToDestination != null) {
popUpTo(
popUpToDestination,
)
}
}
}
fun NavGraphBuilder.clientAccountsNavGraph(

View File

@ -24,8 +24,10 @@ import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO
import org.mifos.mobile.core.common.Network
import org.mifos.mobile.core.designsystem.components.MifosScaffold
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations
import org.mifos.mobile.core.model.enums.ChargeType
import org.mifos.mobile.core.model.enums.TransferType
import org.mifos.mobile.core.ui.component.EmptyDataView
import org.mifos.mobile.core.ui.component.MifosProgressIndicator
import org.mifos.mobile.core.ui.component.NoInternet
@ -43,7 +45,13 @@ internal fun LoanAccountDetailScreen(
viewRepaymentSchedule: (Long) -> Unit,
viewTransactions: (Long) -> Unit,
viewQr: (String) -> Unit,
makePayment: (accountId: Long, outstandingBalance: Double?, transferType: String) -> Unit,
makePayment: (
accountId: Long,
outstandingBalance: Double?,
transferType: String,
transferTarget: TransferType,
transferSuccessDestination: TransferSuccessDestination,
) -> Unit,
modifier: Modifier = Modifier,
viewModel: LoanAccountsDetailViewModel = hiltViewModel(),
) {
@ -68,6 +76,8 @@ internal fun LoanAccountDetailScreen(
loanId,
viewModel.loanWithAssociations?.summary?.totalOutstanding,
TRANSFER_PAY_TO,
TransferType.SELF,
TransferSuccessDestination.LOAN_ACCOUNT,
)
},
)

View File

@ -16,8 +16,10 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
import androidx.navigation.navArgument
import org.mifos.mobile.core.common.Constants
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.enums.ChargeType
import org.mifos.mobile.core.model.enums.LoanState
import org.mifos.mobile.core.model.enums.TransferType
import org.mifos.mobile.feature.loan.loanAccount.LoanAccountDetailScreen
import org.mifos.mobile.feature.loan.loanAccountApplication.LoanApplicationScreen
import org.mifos.mobile.feature.loan.loanAccountSummary.LoanAccountSummaryScreen
@ -62,7 +64,13 @@ fun NavGraphBuilder.loanNavGraph(
viewGuarantor: (Long) -> Unit,
viewCharges: (ChargeType, Long) -> Unit,
viewQr: (String) -> Unit,
makePayment: (accountId: Long, outstandingBalance: Double?, transferType: String) -> Unit,
makePayment: (
accountId: Long,
outstandingBalance: Double?,
transferType: String,
transferTarget: TransferType,
transferSuccessDestination: TransferSuccessDestination,
) -> Unit,
) {
navigation(
startDestination = LoanNavigation.LoanDetail.route,
@ -138,7 +146,13 @@ fun NavGraphBuilder.loanDetailRoute(
viewRepaymentSchedule: (Long) -> Unit,
viewTransactions: (Long) -> Unit,
viewQr: (String) -> Unit,
makePayment: (accountId: Long, outstandingBalance: Double?, transferType: String) -> Unit,
makePayment: (
accountId: Long,
outstandingBalance: Double?,
transferType: String,
transferTarget: TransferType,
transferSuccessDestination: TransferSuccessDestination,
) -> Unit,
) {
composable(
route = LoanNavigation.LoanDetail.route,

View File

@ -21,7 +21,10 @@ import org.mifos.mobile.core.common.Constants.OUTSTANDING_BALANCE
import org.mifos.mobile.core.common.Constants.SAVINGS_ID
import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_FROM
import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO
import org.mifos.mobile.core.common.Constants.TRANSFER_SUCCESS_DESTINATION
import org.mifos.mobile.core.common.Constants.TRANSFER_TARGET
import org.mifos.mobile.core.common.Constants.TRANSFER_TYPE
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
import org.mifos.mobile.core.model.enums.ChargeType
import org.mifos.mobile.core.model.enums.SavingsAccountState
@ -36,12 +39,16 @@ fun NavController.navigateToSavingsMakeTransfer(
accountId: Long,
outstandingBalance: Double? = null,
transferType: String,
transferTarget: TransferType,
transferSuccessDestination: TransferSuccessDestination,
) {
navigate(
SavingsNavigation.SavingsMakeTransfer.passArguments(
accountId,
(outstandingBalance ?: 0.0).toString(),
transferType,
accountId = accountId,
outstandingBalance = (outstandingBalance ?: 0.0).toString(),
transferType = transferType,
transferTarget = transferTarget,
transferSuccessDestination = transferSuccessDestination,
),
)
}
@ -63,7 +70,7 @@ fun NavGraphBuilder.savingsNavGraph(
navController: NavController,
viewQrCode: (String) -> Unit,
viewCharges: (ChargeType, Long) -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
callHelpline: () -> Unit,
) {
navigation(
@ -76,12 +83,16 @@ fun NavGraphBuilder.savingsNavGraph(
navController.navigateToSavingsMakeTransfer(
accountId = it,
transferType = TRANSFER_PAY_TO,
transferTarget = TransferType.TPT,
transferSuccessDestination = TransferSuccessDestination.SAVINGS_ACCOUNT,
)
},
makeTransfer = {
navController.navigateToSavingsMakeTransfer(
accountId = it,
transferType = TRANSFER_PAY_FROM,
transferTarget = TransferType.TPT,
transferSuccessDestination = TransferSuccessDestination.SAVINGS_ACCOUNT,
)
},
navigateBack = navController::popBackStack,
@ -203,7 +214,7 @@ fun NavGraphBuilder.savingsWithdraw(
fun NavGraphBuilder.savingsMakeTransfer(
navigateBack: () -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
) {
composable(
route = SavingsNavigation.SavingsMakeTransfer.route,
@ -215,6 +226,10 @@ fun NavGraphBuilder.savingsMakeTransfer(
defaultValue = null
},
navArgument(name = TRANSFER_TYPE) { type = NavType.StringType },
navArgument(name = TRANSFER_TARGET) { type = NavType.StringType },
navArgument(name = TRANSFER_SUCCESS_DESTINATION) {
type = NavType.EnumType(TransferSuccessDestination::class.java)
},
),
) {
SavingsMakeTransferScreen(

View File

@ -13,8 +13,12 @@ import org.mifos.mobile.core.common.Constants.ACCOUNT_ID
import org.mifos.mobile.core.common.Constants.OUTSTANDING_BALANCE
import org.mifos.mobile.core.common.Constants.SAVINGS_ACCOUNT_STATE
import org.mifos.mobile.core.common.Constants.SAVINGS_ID
import org.mifos.mobile.core.common.Constants.TRANSFER_SUCCESS_DESTINATION
import org.mifos.mobile.core.common.Constants.TRANSFER_TARGET
import org.mifos.mobile.core.common.Constants.TRANSFER_TYPE
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.enums.SavingsAccountState
import org.mifos.mobile.core.model.enums.TransferType
const val SAVINGS_NAVIGATION_ROUTE_BASE = "savings_route"
const val SAVINGS_DETAIL_SCREEN_ROUTE = "savings_detail_screen_route"
@ -60,14 +64,26 @@ sealed class SavingsNavigation(val route: String) {
}
data object SavingsMakeTransfer : SavingsNavigation(
route = "$SAVINGS_MAKE_TRANSFER_SCREEN_ROUTE/{$ACCOUNT_ID}/{$OUTSTANDING_BALANCE}/{$TRANSFER_TYPE}",
route = "$SAVINGS_MAKE_TRANSFER_SCREEN_ROUTE/" +
"{$ACCOUNT_ID}/" +
"{$OUTSTANDING_BALANCE}/" +
"{$TRANSFER_TYPE}/" +
"{$TRANSFER_TARGET}/" +
"{$TRANSFER_SUCCESS_DESTINATION}",
) {
fun passArguments(
accountId: Long,
outstandingBalance: String? = null,
transferType: String,
transferTarget: TransferType,
transferSuccessDestination: TransferSuccessDestination,
): String {
return "$SAVINGS_MAKE_TRANSFER_SCREEN_ROUTE/$accountId/$outstandingBalance/$transferType"
return "$SAVINGS_MAKE_TRANSFER_SCREEN_ROUTE/" +
"$accountId/" +
"$outstandingBalance/" +
"$transferType/" +
"${transferTarget.name}/" +
transferSuccessDestination
}
}
}

View File

@ -112,7 +112,9 @@ internal fun SavingsMakeTransferContent(
R.string.one -> PayToStepContent(
modifier = processModifier,
processState = payToStepState,
toAccountOptions = uiData.accountOptionsTemplate.fromAccountOptions,
toAccountOptions = uiData.toAccountOptions
.filter { it.accountType?.value == "Loan Account" }
.distinctBy { it.accountId },
prefilledAccount = payToAccount,
onContinueClick = {
payToAccount = it
@ -123,7 +125,8 @@ internal fun SavingsMakeTransferContent(
R.string.two -> PayFromStep(
modifier = processModifier,
processState = payFromStepState,
fromAccountOptions = uiData.accountOptionsTemplate.fromAccountOptions,
fromAccountOptions = uiData.fromAccountOptions.distinctBy { it.accountNo }
.filter { it.accountNo != payToAccount?.accountNo },
prefilledAccount = payFromAccount,
onContinueClick = {
payFromAccount = it
@ -260,7 +263,6 @@ private fun EnterAmountStep(
showAmountError = false
amountError = when {
amount.text.trim() == "" -> R.string.enter_amount
amount.text.contains(".") -> R.string.invalid_amount
amount.text.toDoubleOrNull() == 0.0 -> R.string.amount_greater_than_zero
else -> null
}

View File

@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -23,6 +24,7 @@ import org.mifos.mobile.core.common.Constants
import org.mifos.mobile.core.common.Network
import org.mifos.mobile.core.designsystem.components.MifosScaffold
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
import org.mifos.mobile.core.model.enums.TransferType
import org.mifos.mobile.core.ui.component.MifosErrorComponent
@ -34,27 +36,32 @@ import org.mifos.mobile.feature.savings.R
internal fun SavingsMakeTransferScreen(
onCancelledClicked: () -> Unit,
navigateBack: () -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
modifier: Modifier = Modifier,
viewModel: SavingsMakeTransferViewModel = hiltViewModel(),
) {
val uiState = viewModel.savingsMakeTransferUiState.collectAsStateWithLifecycle()
val uiData = viewModel.savingsMakeTransferUiData.collectAsStateWithLifecycle()
val transferSuccessDestination by
viewModel.transferSuccessDestination.collectAsStateWithLifecycle()
SavingsMakeTransferScreen(
navigateBack = navigateBack,
onCancelledClicked = onCancelledClicked,
uiState = uiState.value,
uiData = uiData.value,
modifier = modifier,
reviewTransfer = { reviewTransfer(it, TransferType.SELF) },
reviewTransfer = {
reviewTransfer(
it,
TransferType.SELF,
transferSuccessDestination,
)
},
)
}
@Composable
private fun SavingsMakeTransferScreen(
uiState: SavingsMakeTransferUiState,
uiData: SavingsMakeTransferUiData,
navigateBack: () -> Unit,
reviewTransfer: (ReviewTransferPayload) -> Unit,
modifier: Modifier = Modifier,
@ -63,10 +70,16 @@ private fun SavingsMakeTransferScreen(
val context = LocalContext.current
MifosScaffold(
topBarTitleResId = if (uiData.transferType == Constants.TRANSFER_PAY_TO) {
R.string.deposit
} else {
R.string.transfer
topBarTitleResId = when (uiState) {
is SavingsMakeTransferUiState.ShowUI -> {
if (uiState.data.transferType == Constants.TRANSFER_PAY_TO) {
R.string.deposit
} else {
R.string.transfer
}
}
else -> R.string.transfer
},
navigateBack = navigateBack,
modifier = modifier,
@ -76,16 +89,17 @@ private fun SavingsMakeTransferScreen(
.padding(it)
.fillMaxSize(),
) {
SavingsMakeTransferContent(
uiData = uiData,
reviewTransfer = reviewTransfer,
onCancelledClicked = onCancelledClicked,
)
when (uiState) {
is SavingsMakeTransferUiState.ShowUI -> Unit
is SavingsMakeTransferUiState.ShowUI -> {
SavingsMakeTransferContent(
uiData = uiState.data,
reviewTransfer = reviewTransfer,
onCancelledClicked = onCancelledClicked,
)
}
is SavingsMakeTransferUiState.Loading -> MifosProgressIndicatorOverlay()
is SavingsMakeTransferUiState.Loading ->
MifosProgressIndicatorOverlay()
is SavingsMakeTransferUiState.Error -> {
MifosErrorComponent(
@ -104,7 +118,9 @@ internal class SavingsMakeTransferUiStatesPreviews :
PreviewParameterProvider<SavingsMakeTransferUiState> {
override val values: Sequence<SavingsMakeTransferUiState>
get() = sequenceOf(
SavingsMakeTransferUiState.ShowUI,
SavingsMakeTransferUiState.ShowUI(
data = SavingsMakeTransferUiData(),
),
SavingsMakeTransferUiState.Error(""),
SavingsMakeTransferUiState.Loading,
)
@ -122,7 +138,6 @@ private fun SavingsMakeTransferContentPreview(
onCancelledClicked = { },
reviewTransfer = { },
uiState = savingsMakeTransferUIState,
uiData = SavingsMakeTransferUiData(),
)
}
}

View File

@ -13,7 +13,6 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
@ -22,83 +21,106 @@ import kotlinx.coroutines.flow.stateIn
import org.mifos.mobile.core.common.Constants
import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO
import org.mifos.mobile.core.data.repository.SavingsAccountRepository
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.templates.account.AccountOption
import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTemplate
import org.mifos.mobile.core.model.enums.TransferType
import org.mifos.mobile.core.network.Result
import org.mifos.mobile.core.network.asResult
import javax.inject.Inject
@HiltViewModel
internal class SavingsMakeTransferViewModel @Inject constructor(
private val savingsAccountRepositoryImp: SavingsAccountRepository,
savingsAccountRepositoryImp: SavingsAccountRepository,
// thirdPartyTransferRepository: ThirdPartyTransferRepository,
savedStateHandle: SavedStateHandle,
) : ViewModel() {
val accountId = savedStateHandle.getStateFlow(key = Constants.ACCOUNT_ID, initialValue = -1L)
private val accountId =
savedStateHandle.getStateFlow(key = Constants.ACCOUNT_ID, initialValue = -1L)
private val transferType: StateFlow<String> = savedStateHandle.getStateFlow(
key = Constants.TRANSFER_TYPE,
initialValue = TRANSFER_PAY_TO,
)
private val transferTarget: StateFlow<String> = savedStateHandle.getStateFlow(
key = Constants.TRANSFER_TARGET,
initialValue = TransferType.TPT.name,
)
val transferSuccessDestination: StateFlow<TransferSuccessDestination> = savedStateHandle.getStateFlow(
key = Constants.TRANSFER_SUCCESS_DESTINATION,
initialValue = TransferSuccessDestination.SAVINGS_ACCOUNT,
)
private val outstandingBalance: StateFlow<Double?> = savedStateHandle.getStateFlow<String?>(
key = Constants.OUTSTANDING_BALANCE,
initialValue = null,
).map { balanceString ->
balanceString?.toDoubleOrNull() ?: 0.0
balanceString?.toDoubleOrNull()
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = 0.0,
initialValue = null,
)
private val _savingsMakeTransferUiData = MutableStateFlow(SavingsMakeTransferUiData())
val savingsMakeTransferUiData: StateFlow<SavingsMakeTransferUiData> get() = _savingsMakeTransferUiData
val savingsMakeTransferUiState = accountId
.flatMapLatest { id ->
savingsAccountRepositoryImp.accountTransferTemplate(accountId = id, accountType = 2L)
val savingsMakeTransferUiState: StateFlow<SavingsMakeTransferUiState> =
transferTarget.flatMapLatest { target ->
savingsAccountRepositoryImp.accountTransferTemplate()
// when (target) {
// TransferType.TPT.name -> thirdPartyTransferRepository.thirdPartyTransferTemplate()
// else -> savingsAccountRepositoryImp.accountTransferTemplate()
// }
}
.asResult()
.map { result ->
when (result) {
is Result.Success ->
SavingsMakeTransferUiState.ShowUI
.also {
_savingsMakeTransferUiData.value = _savingsMakeTransferUiData.value
.copy(
accountOptionsTemplate = result.data,
transferType = transferType.value,
outstandingBalance = if (outstandingBalance.value == 0.0) {
null
} else {
outstandingBalance.value
},
accountId = accountId.value,
)
}
.asResult()
.map { result ->
when (result) {
is Result.Success -> {
SavingsMakeTransferUiState.ShowUI(
data = SavingsMakeTransferUiData(
accountId = accountId.value,
transferType = transferType.value,
outstandingBalance = outstandingBalance.value,
fromAccountOptions = result.data.fromAccountOptions,
toAccountOptions = result.data.toAccountOptions,
// fromAccountOptionPrefilled = result.data.fromAccountOptions.find {
// accountId.value == it.accountId?.toLong()
// },
toAccountOptionPrefilled = result.data.toAccountOptions.find {
accountId.value == it.accountId?.toLong()
},
),
)
}
is Result.Loading -> SavingsMakeTransferUiState.Loading
is Result.Error -> SavingsMakeTransferUiState.Error(result.exception.message)
is Result.Loading -> {
SavingsMakeTransferUiState.Loading
}
is Result.Error -> {
SavingsMakeTransferUiState.Error(result.exception.message)
}
}
}
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = SavingsMakeTransferUiState.Loading,
)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = SavingsMakeTransferUiState.Loading,
)
}
internal sealed class SavingsMakeTransferUiState {
data object Loading : SavingsMakeTransferUiState()
data class Error(val errorMessage: String?) : SavingsMakeTransferUiState()
data object ShowUI : SavingsMakeTransferUiState()
data class ShowUI(val data: SavingsMakeTransferUiData) : SavingsMakeTransferUiState()
}
internal data class SavingsMakeTransferUiData(
var accountId: Long? = null,
var transferType: String? = null,
var outstandingBalance: Double? = null,
var accountOptionsTemplate: AccountOptionsTemplate = AccountOptionsTemplate(),
var fromAccountOptions: List<AccountOption> = ArrayList(),
var toAccountOptions: List<AccountOption> = ArrayList(),
var toAccountOptionPrefilled: AccountOption? = null,
var fromAccountOptionPrefilled: AccountOption? = null,
)

View File

@ -56,7 +56,7 @@ import org.mifos.mobile.core.ui.utils.DevicePreviews
@Composable
internal fun ThirdPartyTransferContent(
accountOption: List<AccountOption>,
fromAccountOption: List<AccountOption>,
toAccountOption: List<AccountOption>,
beneficiaryList: List<Beneficiary>,
navigateBack: () -> Unit,
@ -112,7 +112,7 @@ internal fun ThirdPartyTransferContent(
) { stepModifier ->
when (step.second) {
R.string.one -> PayFromStep(
fromAccountOptions = accountOption,
fromAccountOptions = fromAccountOption,
processState = payFromStepState,
onContinueClick = {
payFromAccount = it
@ -399,7 +399,7 @@ private fun RemarkStep(
private fun ThirdPartyTransferContentPreview() {
MifosMobileTheme {
ThirdPartyTransferContent(
accountOption = listOf(),
fromAccountOption = listOf(),
toAccountOption = listOf(),
beneficiaryList = listOf(),
navigateBack = {},

View File

@ -23,6 +23,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.mifos.mobile.core.common.Network
import org.mifos.mobile.core.designsystem.components.MifosScaffold
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
import org.mifos.mobile.core.model.enums.TransferType
import org.mifos.mobile.core.ui.component.MifosErrorComponent
@ -33,19 +34,17 @@ import org.mifos.mobile.core.ui.utils.DevicePreviews
internal fun ThirdPartyTransferScreen(
navigateBack: () -> Unit,
addBeneficiary: () -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
modifier: Modifier = Modifier,
viewModel: ThirdPartyTransferViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val uiData by viewModel.thirdPartyTransferUiData.collectAsStateWithLifecycle()
ThirdPartyTransferScreen(
uiState = uiState,
uiData = uiData,
navigateBack = navigateBack,
addBeneficiary = addBeneficiary,
reviewTransfer = { reviewTransfer(it, TransferType.TPT) },
reviewTransfer = { reviewTransfer(it, TransferType.TPT, TransferSuccessDestination.HOME) },
modifier = modifier,
)
}
@ -53,7 +52,6 @@ internal fun ThirdPartyTransferScreen(
@Composable
private fun ThirdPartyTransferScreen(
uiState: ThirdPartyTransferUiState,
uiData: ThirdPartyTransferUiData,
navigateBack: () -> Unit,
addBeneficiary: () -> Unit,
reviewTransfer: (ReviewTransferPayload) -> Unit,
@ -69,9 +67,9 @@ private fun ThirdPartyTransferScreen(
when (uiState) {
is ThirdPartyTransferUiState.ShowUI -> {
ThirdPartyTransferContent(
accountOption = uiData.fromAccountDetail,
toAccountOption = uiData.toAccountOption,
beneficiaryList = uiData.beneficiaries,
fromAccountOption = uiState.data.fromAccountDetail,
toAccountOption = uiState.data.toAccountOption,
beneficiaryList = uiState.data.beneficiaries,
navigateBack = navigateBack,
addBeneficiary = addBeneficiary,
reviewTransfer = reviewTransfer,
@ -99,7 +97,7 @@ internal class SavingsMakeTransferUiStatesPreviews :
PreviewParameterProvider<ThirdPartyTransferUiState> {
override val values: Sequence<ThirdPartyTransferUiState>
get() = sequenceOf(
ThirdPartyTransferUiState.ShowUI,
ThirdPartyTransferUiState.ShowUI(data = ThirdPartyTransferUiData()),
ThirdPartyTransferUiState.Error(""),
ThirdPartyTransferUiState.Loading,
)
@ -114,7 +112,6 @@ private fun ThirdPartyTransferScreenPreview(
MifosMobileTheme {
ThirdPartyTransferScreen(
uiState = thirdPartyTransferUiState,
uiData = ThirdPartyTransferUiData(),
navigateBack = {},
addBeneficiary = {},
reviewTransfer = {},

View File

@ -12,12 +12,11 @@ package org.mifos.mobile.feature.third.party.transfer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.stateIn
import org.mifos.mobile.core.data.repository.BeneficiaryRepository
import org.mifos.mobile.core.data.repository.ThirdPartyTransferRepository
import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary
@ -27,51 +26,42 @@ import javax.inject.Inject
@HiltViewModel
internal class ThirdPartyTransferViewModel @Inject constructor(
private val transferRepository: ThirdPartyTransferRepository,
private val beneficiaryRepository: BeneficiaryRepository,
transferRepository: ThirdPartyTransferRepository,
beneficiaryRepository: BeneficiaryRepository,
) : ViewModel() {
private val mUiState = MutableStateFlow<ThirdPartyTransferUiState>(Loading)
val uiState = mUiState.asStateFlow()
private val _thirdPartyTransferUiData = MutableStateFlow(ThirdPartyTransferUiData())
val thirdPartyTransferUiData = _thirdPartyTransferUiData.asStateFlow()
init {
fetchTemplate()
}
private fun fetchTemplate() {
viewModelScope.launch {
combine(
transferRepository.thirdPartyTransferTemplate(),
beneficiaryRepository.beneficiaryList(),
) { templateResult, beneficiariesResult ->
_thirdPartyTransferUiData.update {
it.copy(
fromAccountDetail = templateResult.fromAccountOptions,
toAccountOption = templateResult.toAccountOptions,
beneficiaries = beneficiariesResult,
)
}
}.catch {
mUiState.value =
ThirdPartyTransferUiState.Error(errorMessage = it.message)
}.collect {
mUiState.value = ThirdPartyTransferUiState.ShowUI
}
}
}
// in third part transfer is possible from savings to savings/loan
// cause of that we filter fromAccount only have saings.
val uiState: StateFlow<ThirdPartyTransferUiState> =
combine(
transferRepository.thirdPartyTransferTemplate(),
beneficiaryRepository.beneficiaryList(),
) { templateResult, beneficiariesResult ->
ThirdPartyTransferUiState.ShowUI(
ThirdPartyTransferUiData(
fromAccountDetail = templateResult.fromAccountOptions
.filter { it.accountType?.value == "Savings Account" },
toAccountOption = templateResult.toAccountOptions,
beneficiaries = beneficiariesResult,
),
)
}.catch {
ThirdPartyTransferUiState.Error(errorMessage = it.message)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = Loading,
)
}
internal sealed class ThirdPartyTransferUiState {
data object Loading : ThirdPartyTransferUiState()
data class Error(val errorMessage: String?) : ThirdPartyTransferUiState()
data object ShowUI : ThirdPartyTransferUiState()
data class ShowUI(val data: ThirdPartyTransferUiData) : ThirdPartyTransferUiState()
}
internal data class ThirdPartyTransferUiData(
val fromAccountDetail: List<AccountOption> = listOf(),
val toAccountOption: List<AccountOption> = listOf(),
val beneficiaries: List<Beneficiary> = listOf(),
val fromAccountDetail: List<AccountOption> = emptyList(),
val toAccountOption: List<AccountOption> = emptyList(),
val beneficiaries: List<Beneficiary> = emptyList(),
)

View File

@ -13,6 +13,7 @@ import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
import org.mifos.mobile.core.model.enums.TransferType
import org.mifos.mobile.feature.third.party.transfer.ThirdPartyTransferScreen
@ -24,7 +25,7 @@ fun NavController.navigateToThirdPartyTransfer() {
fun NavGraphBuilder.thirdPartyTransferNavGraph(
navigateBack: () -> Unit,
addBeneficiary: () -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
) {
navigation(
startDestination = ThirdPartyTransferNavigation.ThirdPartyTransferScreen.route,
@ -41,7 +42,7 @@ fun NavGraphBuilder.thirdPartyTransferNavGraph(
fun NavGraphBuilder.thirdPartyTransferRoute(
navigateBack: () -> Unit,
addBeneficiary: () -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
) {
composable(
route = ThirdPartyTransferNavigation.ThirdPartyTransferScreen.route,

View File

@ -41,29 +41,31 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.mifos.mobile.core.common.Network
import org.mifos.mobile.core.designsystem.components.MifosButton
import org.mifos.mobile.core.designsystem.components.MifosScaffold
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.payload.TransferPayload
import org.mifos.mobile.core.ui.component.MifosErrorComponent
import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay
import org.mifos.mobile.core.ui.utils.DevicePreviews
@Composable
internal fun TransferProcessScreen(
navigateBack: () -> Unit,
onTransferSuccessNavigate: (TransferSuccessDestination) -> Unit,
modifier: Modifier = Modifier,
viewModel: TransferProcessViewModel = hiltViewModel(),
) {
val uiState by viewModel.transferUiState.collectAsStateWithLifecycle()
val payload by viewModel.transferPayload.collectAsStateWithLifecycle()
val transferSuccessDestination by viewModel.transferSuccessDestination.collectAsStateWithLifecycle()
TransferProcessScreen(
uiState = uiState,
transfer = viewModel::makeTransfer,
payload = payload,
navigateBack = navigateBack,
onTransferSuccess = { onTransferSuccessNavigate(transferSuccessDestination) },
modifier = modifier,
)
}
@ -74,6 +76,7 @@ private fun TransferProcessScreen(
payload: TransferPayload?,
transfer: () -> Unit,
navigateBack: () -> Unit,
onTransferSuccess: () -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
@ -103,11 +106,11 @@ private fun TransferProcessScreen(
R.string.transferred_successfully,
Toast.LENGTH_SHORT,
).show()
navigateBack()
onTransferSuccess()
}
is TransferProcessUiState.Error -> {
MifosErrorComponent(isNetworkConnected = Network.isConnected(context))
Toast.makeText(context, uiState.errorMessage, Toast.LENGTH_SHORT).show()
}
is TransferProcessUiState.Initial -> Unit
@ -172,7 +175,7 @@ private fun TransferProcessContent(
)
Text(
text = payload?.fromAccountNumber.toString(),
text = payload?.toAccountNumber.toString(),
modifier = Modifier.padding(top = 4.dp, bottom = 2.dp),
)
@ -273,6 +276,7 @@ private fun TransferProcessScreenPreview(
),
transfer = {},
navigateBack = {},
onTransferSuccess = {},
)
}
}

View File

@ -23,8 +23,10 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.mifos.mobile.core.common.Constants.PAYLOAD
import org.mifos.mobile.core.common.Constants.TRANSFER_SUCCESS_DESTINATION
import org.mifos.mobile.core.common.Constants.TRANSFER_TYPE
import org.mifos.mobile.core.data.repository.TransferRepository
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.payload.TransferPayload
import org.mifos.mobile.core.model.enums.TransferType
import org.mifos.mobile.feature.transfer.process.TransferProcessUiState.Initial
@ -48,6 +50,11 @@ internal class TransferProcessViewModel @Inject constructor(
initialValue = null,
)
val transferSuccessDestination = savedStateHandle.getStateFlow(
key = TRANSFER_SUCCESS_DESTINATION,
initialValue = TransferSuccessDestination.SAVINGS_ACCOUNT,
)
val transferPayload: StateFlow<TransferPayload?> = transferPayloadString
.map { jsonString ->
jsonString?.let {
@ -77,8 +84,6 @@ internal class TransferProcessViewModel @Inject constructor(
transferDescription = payload.transferDescription,
dateFormat = payload.dateFormat,
locale = payload.locale,
fromAccountNumber = payload.fromAccountNumber,
toAccountNumber = payload.toAccountNumber,
transferType = transferType.value,
).catch { e ->
_transferUiState.value = TransferProcessUiState.Error(e.message)

View File

@ -19,6 +19,7 @@ import com.google.gson.Gson
import org.mifos.mobile.core.common.Constants
import org.mifos.mobile.core.common.utils.DateHelper
import org.mifos.mobile.core.common.utils.getTodayFormatted
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
import org.mifos.mobile.core.model.entity.payload.TransferPayload
import org.mifos.mobile.core.model.enums.TransferType
@ -28,17 +29,20 @@ import org.mifos.mobile.feature.transfer.process.TransferProcessScreen
fun NavController.navigateToTransferProcessScreen(
transferPayload: ReviewTransferPayload,
transferType: TransferType,
transferSuccessDestination: TransferSuccessDestination,
) {
navigate(
TransferProcessNavigation.TransferProcessScreen.passArguments(
transferType = transferType,
payload = transferPayload.convertToTransferPayloadString(),
transferSuccessDestination = transferSuccessDestination,
),
)
}
fun NavGraphBuilder.transferProcessNavGraph(
navigateBack: () -> Unit,
onTransferSuccessNavigate: (TransferSuccessDestination) -> Unit = {},
) {
navigation(
startDestination = TransferProcessNavigation.TransferProcessScreen.route,
@ -46,12 +50,14 @@ fun NavGraphBuilder.transferProcessNavGraph(
) {
transferProcessScreenRoute(
navigateBack = navigateBack,
onTransferSuccessNavigate = onTransferSuccessNavigate,
)
}
}
private fun NavGraphBuilder.transferProcessScreenRoute(
navigateBack: () -> Unit,
onTransferSuccessNavigate: (TransferSuccessDestination) -> Unit = {},
) {
composable(
route = TransferProcessNavigation.TransferProcessScreen.route,
@ -60,10 +66,14 @@ private fun NavGraphBuilder.transferProcessScreenRoute(
navArgument(name = Constants.TRANSFER_TYPE) {
type = NavType.EnumType(TransferType::class.java)
},
navArgument(name = Constants.TRANSFER_SUCCESS_DESTINATION) {
type = NavType.EnumType(TransferSuccessDestination::class.java)
},
),
) {
TransferProcessScreen(
navigateBack = navigateBack,
onTransferSuccessNavigate = onTransferSuccessNavigate,
)
}
}
@ -75,10 +85,12 @@ private fun ReviewTransferPayload.convertToTransferPayloadString(): String {
fromClientId = payload.payFromAccount?.clientId
fromAccountType = payload.payFromAccount?.accountType?.id
fromOfficeId = payload.payFromAccount?.officeId
toOfficeId = payload.payFromAccount?.officeId
fromAccountNumber = payload.payFromAccount?.accountNo
toOfficeId = payload.payToAccount?.officeId
toAccountId = payload.payToAccount?.accountId
toClientId = payload.payToAccount?.clientId
toAccountType = payload.payToAccount?.accountType?.id
toAccountNumber = payload.payToAccount?.accountNo
transferDate = DateHelper.getSpecificFormat(DateHelper.FORMAT_MMMM, getTodayFormatted())
transferAmount = payload.amount.toDoubleOrNull()
transferDescription = payload.review

View File

@ -10,7 +10,9 @@
package org.mifos.mobile.feature.transfer.process.navigation
import org.mifos.mobile.core.common.Constants.PAYLOAD
import org.mifos.mobile.core.common.Constants.TRANSFER_SUCCESS_DESTINATION
import org.mifos.mobile.core.common.Constants.TRANSFER_TYPE
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
import org.mifos.mobile.core.model.enums.TransferType
// Constants for Routes
@ -24,11 +26,12 @@ internal sealed class TransferProcessNavigation(val route: String) {
)
data object TransferProcessScreen : TransferProcessNavigation(
route = "$TRANSFER_PROCESS_SCREEN_ROUTE/{$PAYLOAD}/{$TRANSFER_TYPE}",
route = "$TRANSFER_PROCESS_SCREEN_ROUTE/{$PAYLOAD}/{$TRANSFER_TYPE}/{$TRANSFER_SUCCESS_DESTINATION}",
) {
fun passArguments(
payload: String,
transferType: TransferType,
) = "$TRANSFER_PROCESS_SCREEN_ROUTE/$payload/$transferType"
transferSuccessDestination: TransferSuccessDestination,
) = "$TRANSFER_PROCESS_SCREEN_ROUTE/$payload/$transferType/$transferSuccessDestination"
}
}