diff --git a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/LoanStatus.kt b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/LoanStatus.kt index c793dedf5..df70ccea0 100644 --- a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/LoanStatus.kt +++ b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/LoanStatus.kt @@ -14,6 +14,8 @@ enum class LoanStatus(val status: String) { CLOSED("Closed"), + CLOSED_OBLIGATIONS_MET("Closed (obligations met)"), + MATURED("Matured"), APPROVED("Approved"), @@ -25,4 +27,12 @@ enum class LoanStatus(val status: String) { REJECTED("Rejected"), WITHDRAWN("Withdrawn by applicant"), + + OVERPAID("Overpaid"), + ; + + companion object { + fun fromStatus(value: String?): LoanStatus? = + entries.firstOrNull { it.status.equals(value, ignoreCase = true) } + } } diff --git a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/loan/Status.kt b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/loan/Status.kt index 97f579386..ad56457aa 100644 --- a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/loan/Status.kt +++ b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/loan/Status.kt @@ -10,6 +10,7 @@ package org.mifos.mobile.core.model.entity.accounts.loan import kotlinx.serialization.Serializable +import org.mifos.mobile.core.model.LoanStatus import org.mifos.mobile.core.model.Parcelable import org.mifos.mobile.core.model.Parcelize @@ -40,6 +41,9 @@ data class Status( ) : Parcelable { + val loanStatus: LoanStatus? + get() = LoanStatus.fromStatus(value) + fun isLoanTypeWithdrawn(): Boolean { return !( this.active == true || this.closed == true || this.pendingApproval == true || diff --git a/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountDetails/LoanAccountDetailsScreen.kt b/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountDetails/LoanAccountDetailsScreen.kt index f05fb2f03..6de56e667 100644 --- a/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountDetails/LoanAccountDetailsScreen.kt +++ b/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountDetails/LoanAccountDetailsScreen.kt @@ -28,7 +28,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import kotlinx.collections.immutable.ImmutableList import mifos_mobile.feature.loan_account.generated.resources.Res import mifos_mobile.feature.loan_account.generated.resources.feature_account_details_action import mifos_mobile.feature.loan_account.generated.resources.feature_account_details_top_bar_title @@ -163,14 +162,14 @@ internal fun LoanAccountDetailsContent( ) } - if (state.isActive) { - SavingsAccountActions( - items = state.items, - onActionClick = { - onAction(LoanAccountDetailsAction.OnNavigateToAction(it)) - }, - ) - } + val visibleActions = state.accountStatus?.allowedActions ?: emptySet() + + SavingsAccountActions( + visibleActions = visibleActions, + onActionClick = { + onAction(LoanAccountDetailsAction.OnNavigateToAction(it)) + }, + ) } } } @@ -222,8 +221,7 @@ internal fun AccountDetailsGrid( @Composable internal fun SavingsAccountActions( - items: ImmutableList, -// onAction: (LoanAccountDetailsAction) -> Unit, + visibleActions: Set, onActionClick: (String) -> Unit, ) { Column( @@ -237,16 +235,15 @@ internal fun SavingsAccountActions( FlowRow( modifier = Modifier.fillMaxWidth(), ) { - items.forEach { item -> - MifosActionCard( - title = item.title, - subTitle = item.subTitle, - icon = item.icon, - onClick = { - onActionClick(item.route) - }, - ) - } + visibleActions + .forEach { item -> + MifosActionCard( + title = item.title, + subTitle = item.subTitle, + icon = item.icon, + onClick = { onActionClick(item.route) }, + ) + } } } } diff --git a/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountDetails/LoanAccountDetailsViewModel.kt b/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountDetails/LoanAccountDetailsViewModel.kt index 47c0f715e..c362c1c0c 100644 --- a/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountDetails/LoanAccountDetailsViewModel.kt +++ b/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountDetails/LoanAccountDetailsViewModel.kt @@ -178,7 +178,7 @@ internal class LoanAccountDetailsViewModel( mutableStateFlow.update { it.copy( accountId = loan?.id?.toLong() ?: -1L, - isActive = loan?.status?.value == LoanStatus.ACTIVE.status, + accountStatus = loan?.status?.loanStatus, accountNumber = loan?.accountNo, clientName = loan?.clientName, product = loan?.loanProductName, @@ -198,7 +198,7 @@ internal class LoanAccountDetailsViewModel( * @property accountId Unique ID for the loan account. * @property displayItems List of account metadata to be displayed. * @property transactionList List of most recent transaction details. - * @property isActive True if the loan is active. + * @property accountStatus True if the loan is active. * @property items List of quick action items (e.g., Repay, Foreclose). * @property isUpdatable Whether the loan is editable (e.g., in a pending state). * @property dialogState State representing UI dialogs like loading or error. @@ -214,7 +214,7 @@ internal data class LoanAccountDetailsState( val product: String? = "", val displayItems: List = emptyList(), val transactionList: List? = emptyList(), - val isActive: Boolean = false, + val accountStatus: LoanStatus? = LoanStatus.ACTIVE, val items: ImmutableList, val isUpdatable: Boolean = false, val dialogState: DialogState?, @@ -231,6 +231,57 @@ internal data class LoanAccountDetailsState( } } +val LoanStatus.allowedActions: Set + get() = when (this) { + LoanStatus.SUBMIT_AND_PENDING_APPROVAL -> setOf( + LoanActionItems.LoanSummary, + ) + + LoanStatus.APPROVED -> setOf( + LoanActionItems.LoanSummary, + LoanActionItems.Charges, + ) + + LoanStatus.DISBURSED, + LoanStatus.ACTIVE, + -> setOf( + LoanActionItems.MakePayment, + LoanActionItems.LoanSummary, + LoanActionItems.RepaymentSchedule, + LoanActionItems.Transactions, + LoanActionItems.Charges, + LoanActionItems.QrCode, + + ) + + LoanStatus.MATURED -> setOf( + LoanActionItems.LoanSummary, + LoanActionItems.RepaymentSchedule, + LoanActionItems.Transactions, + ) + + LoanStatus.CLOSED -> setOf( + LoanActionItems.LoanSummary, + LoanActionItems.Transactions, + ) + + LoanStatus.CLOSED_OBLIGATIONS_MET -> setOf( + LoanActionItems.LoanSummary, + LoanActionItems.Transactions, + ) + + LoanStatus.REJECTED, + LoanStatus.WITHDRAWN, + -> setOf( + LoanActionItems.LoanSummary, + ) + + LoanStatus.OVERPAID -> setOf( + LoanActionItems.LoanSummary, + LoanActionItems.Transactions, + ) + } + /** * One-time navigation or effect events for the Loan Account Details screen. */ diff --git a/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountSummary/AccountSummaryViewModel.kt b/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountSummary/AccountSummaryViewModel.kt index 4837de12e..0475e475e 100644 --- a/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountSummary/AccountSummaryViewModel.kt +++ b/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/loanAccountSummary/AccountSummaryViewModel.kt @@ -149,7 +149,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_expected_payoff_label, CurrencyFormatter.format( - loan?.summary?.totalExpectedRepayment, + loan?.summary?.totalExpectedRepayment ?: 0.0, currencyCode, maxDigits, ), @@ -157,7 +157,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_interest_payoff_label, CurrencyFormatter.format( - loan?.summary?.interestCharged, + loan?.summary?.interestCharged ?: 0.0, currencyCode, maxDigits, ), @@ -165,7 +165,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_principal_label, CurrencyFormatter.format( - loan?.summary?.principalDisbursed, + loan?.summary?.principalDisbursed ?: 0.0, currencyCode, maxDigits, ), @@ -184,7 +184,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_fees_label, CurrencyFormatter.format( - loan?.summary?.feeChargesCharged, + loan?.summary?.feeChargesCharged ?: 0.0, currencyCode, maxDigits, ), @@ -192,7 +192,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_penalties_label, CurrencyFormatter.format( - loan?.summary?.penaltyChargesCharged, + loan?.summary?.penaltyChargesCharged ?: 0.0, currencyCode, maxDigits, ), @@ -203,7 +203,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_interest_waived_label, CurrencyFormatter.format( - loan?.summary?.interestWaived, + loan?.summary?.interestWaived ?: 0.0, currencyCode, maxDigits, ), @@ -211,7 +211,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_penalty_waived_label, CurrencyFormatter.format( - loan?.summary?.penaltyChargesWaived, + loan?.summary?.penaltyChargesWaived ?: 0.0, currencyCode, maxDigits, ), @@ -219,7 +219,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_fees_waived_label, CurrencyFormatter.format( - loan?.summary?.feeChargesWaived, + loan?.summary?.feeChargesWaived ?: 0.0, currencyCode, maxDigits, ), @@ -230,7 +230,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_interest_paid_off_label, CurrencyFormatter.format( - loan?.summary?.interestPaid, + loan?.summary?.interestPaid ?: 0.0, currencyCode, maxDigits, ), @@ -238,7 +238,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_principal_paid_off_label, CurrencyFormatter.format( - loan?.summary?.principalPaid, + loan?.summary?.principalPaid ?: 0.0, currencyCode, maxDigits, ), @@ -266,7 +266,7 @@ internal class LoanAccountSummaryViewModel( LabelValueItem( Res.string.feature_loan_total_outstanding_label, CurrencyFormatter.format( - loan?.summary?.totalOutstanding, + loan?.summary?.totalOutstanding ?: 0.0, currencyCode, maxDigits, ),