Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ class CreateSavingsAccountUseCase(
private val repository: SavingsAccountRepository,
) {

operator fun invoke(savingsPayload: SavingsPayload?): Flow<DataState<Savings?>> =
operator fun invoke(savingsPayload: SavingsPayload?): Flow<DataState<Savings>> =
repository.createSavingsAccount(savingsPayload)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ class SavingsPayload {
var allowOverdraft: Boolean? = null
var enforceMinRequiredBalance: Boolean? = null
var minRequiredOpeningBalance: String? = null
var minRequiredBalance: String? = null
var lockinPeriodFrequency: Int? = null
var lockinPeriodFrequencyType: Int? = null

var charges: List<ChargesPayload>? = null
var nominalAnnualInterestRateOverdraft: String? = null
var overdraftLimit: String? = null
var minOverdraftForInterestCalculation: String? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ package com.mifos.core.network.datamanager
import com.mifos.core.datastore.UserPreferencesRepository
import com.mifos.core.model.objects.account.loan.SavingsApproval
import com.mifos.core.model.objects.account.saving.SavingsAccountTransactionResponse
import com.mifos.core.model.objects.error.MifosError
import com.mifos.core.model.objects.organisations.ProductSavings
import com.mifos.core.model.objects.payloads.SavingsPayload
import com.mifos.core.network.BaseApiManager
Expand All @@ -22,11 +23,14 @@ import com.mifos.room.entities.client.Savings
import com.mifos.room.entities.templates.savings.SavingProductsTemplate
import com.mifos.room.entities.templates.savings.SavingsAccountTransactionTemplateEntity
import com.mifos.room.helper.SavingsDaoHelper
import io.ktor.client.statement.bodyAsText
import io.ktor.http.isSuccess
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.serialization.json.Json

/**
* Created by Rajan Maurya on 17/08/16.
Expand Down Expand Up @@ -285,7 +289,24 @@ class DataManagerSavings(
get() = mBaseApiManager.savingsService.allSavingsAccounts()

fun createSavingsAccount(savingsPayload: SavingsPayload?): Flow<Savings> {
return mBaseApiManager.savingsService.createSavingsAccount(savingsPayload)
return mBaseApiManager.savingsService.createSavingsAccount(savingsPayload).map { response ->
val responseText = response.bodyAsText()
val json = Json { ignoreUnknownKeys = true }

if (!response.status.isSuccess()) {
val errorMessage = try {
val errorResponse = json.decodeFromString<MifosError>(responseText)
errorResponse.errors.firstOrNull()?.defaultUserMessage
?: errorResponse.defaultUserMessage
?: "HTTP ${response.status.value} ${response.status.description}"
} catch (e: Exception) {
"HTTP ${response.status.value} ${response.status.description}"
}
throw IllegalStateException(errorMessage)
}

json.decodeFromString<Savings>(responseText)
}
}

val getSavingsAccountTemplate: Flow<SavingProductsTemplate>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import com.mifos.core.network.GenericResponse
import com.mifos.room.basemodel.APIEndPoint
import com.mifos.room.entities.accounts.savings.SavingsAccountTransactionRequestEntity
import com.mifos.room.entities.accounts.savings.SavingsAccountWithAssociationsEntity
import com.mifos.room.entities.client.Savings
import com.mifos.room.entities.templates.savings.SavingProductsTemplate
import com.mifos.room.entities.templates.savings.SavingsAccountTransactionTemplateEntity
import de.jensklingenberg.ktorfit.http.Body
import de.jensklingenberg.ktorfit.http.GET
import de.jensklingenberg.ktorfit.http.POST
import de.jensklingenberg.ktorfit.http.Path
import de.jensklingenberg.ktorfit.http.Query
import io.ktor.client.statement.HttpResponse
import kotlinx.coroutines.flow.Flow

/**
Expand Down Expand Up @@ -106,7 +106,7 @@ interface SavingsAccountService {
fun allSavingsAccounts(): Flow<List<ProductSavings>>

@POST(APIEndPoint.CREATE_SAVINGS_ACCOUNTS)
fun createSavingsAccount(@Body savingsPayload: SavingsPayload?): Flow<Savings>
fun createSavingsAccount(@Body savingsPayload: SavingsPayload?): Flow<HttpResponse>

@GET(APIEndPoint.CREATE_SAVINGS_PRODUCTS + "/template")
fun savingsAccountTemplate(): Flow<SavingProductsTemplate>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* 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/android-client/blob/master/LICENSE.md
*/
package com.mifos.core.ui.components

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.mifos.core.designsystem.theme.DesignToken
import com.mifos.core.designsystem.theme.MifosTypography
import org.jetbrains.compose.ui.tooling.preview.Preview

@Composable
fun MifosGeneralCardComponentOutline(
modifier: Modifier = Modifier,
borderCorner: Dp = DesignToken.sizes.iconMiny,
content: @Composable () -> Unit,
) {
Box(
modifier = modifier
.border(
width = 1.dp,
shape = RoundedCornerShape(
topStart = 12.dp,
topEnd = 12.dp,
bottomStart = borderCorner,
bottomEnd = borderCorner,
),
color = MaterialTheme.colorScheme.secondaryContainer,
),
) {
content()
}
}

@Composable
fun MifosGeneralRowItem(
keyContent: @Composable () -> Unit,
valueContent: @Composable () -> Unit,
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Box(
modifier = Modifier.weight(1f),
contentAlignment = Alignment.CenterStart,
) { keyContent() }

Box(
modifier = Modifier.weight(1f),
contentAlignment = Alignment.CenterEnd,
) { valueContent() }
}
}

@Composable
fun MifosGeneralCard(
modifier: Modifier = Modifier,
contentMap: Map<String, String>,
separator: String = " : ",
) {
MifosGeneralCardComponentOutline {
Column(
modifier = modifier.padding(DesignToken.padding.large),
) {
contentMap.entries.forEachIndexed { index, map ->
MifosGeneralRowItem(
keyContent = { Text(text = map.key + separator, style = MifosTypography.labelMediumEmphasized) },
valueContent = { Text(text = map.value, style = MifosTypography.labelMediumEmphasized) },
)
if (index < contentMap.size - 1) {
Spacer(modifier = Modifier.height(DesignToken.padding.small))
}
}
}
}
}

@Preview
@Composable
fun MifosPreviewGeneralCard() {
MaterialTheme {
MifosGeneralCard(
contentMap = mapOf(
"title" to "answer",
"title1" to "ans1",
"title2" to "ans2",
"title3" to "ans3",
"title4" to "ans4",
),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ package com.mifos.feature.client.clientGeneral
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import com.mifos.feature.client.clientProfile.ClientProfileRoute
import com.mifos.feature.client.navigation.ClientListScreenRoute
import kotlinx.serialization.Serializable

@Serializable
Expand Down Expand Up @@ -51,3 +53,12 @@ fun NavController.navigateToClientProfileGeneralRoute(id: Int) {
ClientProfileGeneralRoute(id = id),
)
}

fun NavController.navigateToClientProfileGeneralRouteOnStatus(id: Int) {
popBackStack(0, true)
navigate(ClientListScreenRoute)
navigate(ClientProfileRoute(id))
navigate(ClientProfileGeneralRoute(id = id)) {
launchSingleTop = true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import com.mifos.feature.client.clientEditProfile.clientEditProfileDestination
import com.mifos.feature.client.clientEditProfile.navigateToClientProfileEditProfileRoute
import com.mifos.feature.client.clientGeneral.clientProfileGeneralDestination
import com.mifos.feature.client.clientGeneral.navigateToClientProfileGeneralRoute
import com.mifos.feature.client.clientGeneral.navigateToClientProfileGeneralRouteOnStatus
import com.mifos.feature.client.clientIdentifiersAddUpdate.clientIdentifiersAddUpdateDestination
import com.mifos.feature.client.clientIdentifiersAddUpdate.onNavigateToClientIdentifiersAddUpdateScreen
import com.mifos.feature.client.clientIdentifiersList.clientIdentifiersListDestination
Expand Down Expand Up @@ -339,6 +340,7 @@ fun NavGraphBuilder.clientNavGraph(
onBackPressed = navController::popBackStack,
loadMoreSavingsAccountInfo = navController::navigateToDataTable,
loadDocuments = navController::navigateToDocumentListScreen,
onFinish = navController::navigateToClientProfileGeneralRouteOnStatus,
)

shareAccountDestination()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<string name="feature_savings_savingsAccountSummary">Savings Account Summary</string>
<string name="feature_savings_documents">Documents</string>
<string name="feature_savings_client_name">Client Name</string>
<string name="feature_savings_product_name">Product Name</string>
<string name="feature_savings_product_name">Product Name*</string>
<string name="feature_savings_account_balance">Account Balance</string>
<string name="feature_savings_total_deposits">Total Deposits</string>
<string name="feature_savings_total_withdrawals">Total Withdrawals</string>
Expand All @@ -28,7 +28,7 @@
<string name="feature_savings_running_balance">Running Balance</string>
<string name="feature_savings_saving_account_id">Saving Account Id</string>
<string name="feature_savings_account_number">Account Number</string>
<string name="feature_savings_currency">Currency</string>
<string name="feature_savings_currency">Currency*</string>
<string name="feature_savings_approve_savings">Approve Savings</string>
<string name="feature_savings_activate_savings">Activate Savings</string>
<string name="feature_savings_savings_account_closed">Savings Account Closed</string>
Expand Down Expand Up @@ -67,7 +67,7 @@
<string name="feature_savings_back">Back</string>
<string name="feature_savings_create_savings_account">Add Savings Account</string>
<string name="feature_savings_savings_account_submitted_for_approval">The Savings Account has been submitted forApproval</string>
<string name="feature_savings_field_officer">Field Officer</string>
<string name="feature_savings_field_officer">Field Officer*</string>
<string name="feature_savings_external_id">External ID</string>
<string name="feature_savings_submitted_on">Submitted On</string>
<string name="feature_savings_nominal">Nominal annual interest </string>
Expand Down Expand Up @@ -139,6 +139,17 @@
<string name="step_charges_active">Active</string>
<string name="step_charges_edit_charge">Edit Charge</string>

<string name="feature_savings_yes">Yes</string>
<string name="feature_savings_no">No</string>
<string name="feature_savings_continue">Continue</string>
<string name="feature_savings_success">Success</string>
<string name="feature_savings_failed">Failed</string>

<string name="feature_savings_new_savings_account_submitted_success">New Savings Account Application Submitted Successfully</string>
<string name="feature_savings_new_savings_account_submitted_failed">Failed to apply for new savings account with the provided details</string>

<string name="feature_savings_charges_active_count">%1$d active charges</string>

</resources>


Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import kotlinx.serialization.Serializable
fun NavGraphBuilder.savingsDestination(
navController: NavController,
onBackPressed: () -> Unit,
onFinish: (id: Int) -> Unit,
loadMoreSavingsAccountInfo: (String, Int) -> Unit,
loadDocuments: (Int, String) -> Unit,
) {
Expand Down Expand Up @@ -85,7 +86,7 @@ fun NavGraphBuilder.savingsDestination(
savingsAccountDestination(
navController = navController,
onNavigateBack = onBackPressed,
onFinish = onBackPressed,
onFinish = onFinish,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does onFinish achieve here? if it is the same as onBackPressed then use onBackPressed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onFinish is not same as onBackPressed.

onFinish = navController::navigateToClientProfileGeneralRouteOnStatus,

where

fun NavController.navigateToClientProfileGeneralRouteOnStatus(id: Int) {
    this.navigate(
        ClientProfileGeneralRoute(id = id),
    ) {
        popBackStack(0, true)
        navigate(ClientListScreenRoute)
        navigate(ClientProfileRoute(id))

        popUpTo(ClientProfileGeneralRoute(id = id)) { inclusive = true }
        launchSingleTop = true
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically we need to navigate to client profile general route after applying for the savings account. That is what onFinish Achieves

)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.mifos.core.domain.useCases.GetGroupSavingsAccountTemplateByProductUse
import com.mifos.core.domain.useCases.LoadSavingsAccountsAndTemplateUseCase
import com.mifos.core.model.objects.payloads.SavingsPayload
import com.mifos.feature.savings.navigation.SavingsAccountRoute
import com.mifos.room.entities.client.Savings
import com.mifos.room.entities.templates.savings.SavingProductsTemplate
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -128,11 +129,13 @@ class SavingAccountViewModel(
_savingAccountUiState.value =
SavingAccountUiState.ShowProgress

is DataState.Success ->
is DataState.Success -> {
_savingAccountUiState.value =
SavingAccountUiState.ShowSavingsAccountCreatedSuccessfully(
dataState.data,
Savings(),
// dataState.data,
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ data class SavingsAccountRoute(
fun NavGraphBuilder.savingsAccountDestination(
navController: NavController,
onNavigateBack: () -> Unit,
onFinish: () -> Unit,
onFinish: (id: Int) -> Unit,
) {
composable<SavingsAccountRoute> {
SavingsAccountScreen(
Expand Down
Loading