Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2deac2d
feat: enhance recurring deposit account settings and UI components
TheKalpeshPawar Oct 21, 2025
050a303
feat: add keyboard options for number input in recurring deposit sett…
TheKalpeshPawar Oct 21, 2025
22b3445
feat: add keyboard options for number input in recurring deposit sett…
TheKalpeshPawar Oct 21, 2025
51a427c
fix: add missing commas and improve formatting in recurring deposit a…
TheKalpeshPawar Oct 21, 2025
8b831c7
spotless fixes
TheKalpeshPawar Oct 21, 2025
62df21d
feat: implement loading state indicator and refactor dialog state man…
TheKalpeshPawar Oct 22, 2025
0953fcd
feat: add RecurringDepositAccountDialogBox to RecurringAccountScreen
TheKalpeshPawar Oct 22, 2025
e051c7e
fix: remove unnecessary blank line in RecurringAccountViewModel
TheKalpeshPawar Oct 22, 2025
8ca12c0
Merge branch 'development' into settings-recurring-deposit-account
TheKalpeshPawar Oct 23, 2025
147202c
refactor: rename dialogState to screenState and update related logic …
TheKalpeshPawar Oct 23, 2025
99b5975
fix: clean up formatting and remove unnecessary blank lines in Recurr…
TheKalpeshPawar Oct 23, 2025
53076a5
Fix : New Loan Account Create Bug (#2527)
Arinyadav1 Oct 23, 2025
264ced7
feat(savingsAccount): preview functionality (#2521)
sam-arth07 Oct 27, 2025
504ca32
feat: enhance recurring deposit account settings and UI components
TheKalpeshPawar Oct 21, 2025
54cdd17
refactor: rename dialogState to screenState and update related logic …
TheKalpeshPawar Oct 23, 2025
78a4257
feat: improve amount formatting logic and enhance UI layout in Recurr…
TheKalpeshPawar Oct 28, 2025
725b701
fix: remove duplicate import of RecurringDepositModule in KoinModules
TheKalpeshPawar Oct 28, 2025
414d61b
Merge branch 'development' into settings-recurring-deposit-account
TheKalpeshPawar Oct 28, 2025
96415ce
feat: enhance amount formatting and validate network connectivity in …
TheKalpeshPawar Oct 28, 2025
dbecf67
feat: rename network observation method and enhance connectivity chec…
TheKalpeshPawar Oct 28, 2025
3b4fbdd
refactor: clean up code formatting and improve readability in DataMan…
TheKalpeshPawar Oct 28, 2025
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
1 change: 1 addition & 0 deletions cmp-navigation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ kotlin {
implementation(projects.feature.pathTracking)
implementation(projects.feature.report)
implementation(projects.feature.savings)
implementation(projects.feature.recurringDeposit)
implementation(projects.feature.settings)
implementation(projects.feature.search)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import com.mifos.feature.loan.di.LoanModule
import com.mifos.feature.note.di.NoteModule
import com.mifos.feature.offline.di.OfflineModule
import com.mifos.feature.path.tracking.di.PathTrackingModule
import com.mifos.feature.recurringDeposit.di.RecurringDepositModule
import com.mifos.feature.report.di.ReportModule
import com.mifos.feature.savings.di.SavingsModule
import com.mifos.feature.search.di.SearchModule
Expand Down Expand Up @@ -83,6 +84,7 @@ object KoinModules {
OfflineModule,
PathTrackingModule,
ReportModule,
RecurringDepositModule,
SavingsModule,
SearchModule,
SettingsModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import kotlinx.coroutines.flow.Flow

interface RecurringAccountRepository {

fun getRecuttingAccountRepository(): Flow<DataState<RecurringDepositAccountTemplate>>
fun getRecurringAccountTemplate(): Flow<DataState<RecurringDepositAccountTemplate>>

fun getRecuttingAccountRepositoryBtProduct(
fun getRecurringAccountTemplateByProduct(
clientId: Int,
productId: Int,
): Flow<DataState<RecurringDepositAccountTemplate>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import kotlinx.coroutines.flow.Flow
class RecurringAccountRepositoryImp(
val dataManagerRecurringAccount: DataManagerRecurringAccount,
) : RecurringAccountRepository {
override fun getRecuttingAccountRepository(): Flow<DataState<RecurringDepositAccountTemplate>> {
override fun getRecurringAccountTemplate(): Flow<DataState<RecurringDepositAccountTemplate>> {
return dataManagerRecurringAccount.getRecurringDepositAccountTemplate
.asDataStateFlow()
}

override fun getRecuttingAccountRepositoryBtProduct(
override fun getRecurringAccountTemplateByProduct(
clientId: Int,
productId: Int,
): Flow<DataState<RecurringDepositAccountTemplate>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import kotlinx.serialization.Serializable

@Serializable
data class RecurringDepositAccountPayload(
// val charges: List<Any>? = null,
val adjustAdvanceTowardsFuturePayments: Boolean? = null,
val allowWithdrawal: Boolean? = null,
// val charges: List<Any>? = null,
val clientId: Int? = null,
val dateFormat: String? = null,
val depositPeriod: Int? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
*/
package com.mifos.core.network.datamanager

import com.mifos.core.datastore.UserPreferencesRepository
import com.mifos.core.model.objects.payloads.RecurringDepositAccountPayload
import com.mifos.core.network.BaseApiManager
import com.mifos.room.entities.accounts.recurring.RecurringDeposit
Expand All @@ -18,7 +17,6 @@ import kotlinx.coroutines.flow.Flow

class DataManagerRecurringAccount(
val mBaseApiManager: BaseApiManager,
private val prefManager: UserPreferencesRepository,
) {

fun createRecurringDepositAccount(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.mifos.core.network.datamanager.DataManagerIdentifiers
import com.mifos.core.network.datamanager.DataManagerLoan
import com.mifos.core.network.datamanager.DataManagerNote
import com.mifos.core.network.datamanager.DataManagerOffices
import com.mifos.core.network.datamanager.DataManagerRecurringAccount
import com.mifos.core.network.datamanager.DataManagerRunReport
import com.mifos.core.network.datamanager.DataManagerSavings
import com.mifos.core.network.datamanager.DataManagerSearch
Expand Down Expand Up @@ -51,4 +52,5 @@ val DataManagerModule = module {
single { DataManagerStaff(get(), get(), get()) }
single { DataManagerSurveys(get(), get(), get()) }
single { DataManagerIdentifiers(get()) }
single { DataManagerRecurringAccount(get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fun NavGraphBuilder.clientApplyNewApplicationRoute(
onNavigateApplyLoanAccount: (Int) -> Unit,
onNavigateApplySavingsAccount: (Int) -> Unit,
onNavigateApplyShareAccount: () -> Unit,
onNavigateApplyRecurringAccount: () -> Unit,
onNavigateApplyRecurringAccount: (Int) -> Unit,
onNavigateApplyFixedAccount: () -> Unit,
navController: NavController,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ internal fun ClientApplyNewApplicationsScreen(
onNavigateApplyLoanAccount: (Int) -> Unit,
onNavigateApplySavingsAccount: (Int) -> Unit,
onNavigateApplyShareAccount: () -> Unit,
onNavigateApplyRecurringAccount: () -> Unit,
onNavigateApplyRecurringAccount: (Int) -> Unit,
onNavigateApplyFixedAccount: () -> Unit,
navController: NavController,
viewModel: ClientApplyNewApplicationsViewModel = koinViewModel(),
Expand All @@ -75,15 +75,9 @@ internal fun ClientApplyNewApplicationsScreen(
is ClientApplyNewApplicationsEvent.OnActionClick -> {
when (event.action) {
ClientApplyNewApplicationsItem.NewFixedAccount -> onNavigateApplyFixedAccount()
ClientApplyNewApplicationsItem.NewLoanAccount -> onNavigateApplyLoanAccount(
state.clientId,
)

ClientApplyNewApplicationsItem.NewRecurringAccount -> onNavigateApplyRecurringAccount()
ClientApplyNewApplicationsItem.NewSavingsAccount -> onNavigateApplySavingsAccount(
state.clientId,
)

ClientApplyNewApplicationsItem.NewLoanAccount -> onNavigateApplyLoanAccount(state.clientId)
ClientApplyNewApplicationsItem.NewRecurringAccount -> onNavigateApplyRecurringAccount(state.clientId)
ClientApplyNewApplicationsItem.NewSavingsAccount -> onNavigateApplySavingsAccount(state.clientId)
ClientApplyNewApplicationsItem.NewShareAccount -> onNavigateApplyShareAccount()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,25 @@
<string name="step_interest">Interest</string>
<string name="step_charges">Charges</string>
<string name="create_recurring_deposit_account">Create Recurring Deposit Account</string>
<string name="is_mandatory_deposit">Is Mandatory Deposit?</string>
<string name="adjust_advance_payments">Adjust advance payments toward future installments?</string>
<string name="allow_withdrawals">Allow Withdrawals?</string>
<string name="lock_in_period">Lock-in Period</string>
<string name="frequency">Frequency</string>
<string name="type">Type</string>
<string name="recurring_deposit_details">Recurring Deposit Details</string>
<string name="recurring_deposit_amount">Recurring Deposit Amount</string>
<string name="deposit_period">Deposit Period</string>
<string name="deposit_frequency_same_as_meeting">Deposit Frequency Same as Group/Center meeting</string>
<string name="minimum_deposit_term">Minimum Deposit Term</string>
<string name="in_multiples_of">And thereafter, in Multiples of</string>
<string name="maximum_deposit_term">Maximum Deposit Term</string>
<string name="for_pre_mature_closure">For Pre-mature closure</string>
<string name="apply_penal_interest">Apply Penal Interest (less)</string>
<string name="penal_interest_percentage">Penal Interest (%)</string>
<string name="period">Period</string>
<string name="minimum_balance_for_interest">Minimum Balance For Interest Calculation</string>
<string name="back">Back</string>
<string name="next">Next</string>
<string name="no_internet_connection">No Internet Connection</string>
Comment on lines +18 to +38
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Polish copy for clarity and consistency; avoid question-style labels.

Several labels use title-case/questions and have minor grammar issues. Recommend sentence‑case, remove “?” where not interactive questions, and clearer phrasing.

Apply this diff to update only string values (no key renames):

-    <string name="is_mandatory_deposit">Is Mandatory Deposit?</string>
+    <string name="is_mandatory_deposit">Mandatory deposit</string>
-    <string name="adjust_advance_payments">Adjust advance payments toward future installments?</string>
+    <string name="adjust_advance_payments">Adjust advance payments toward future installments</string>
-    <string name="allow_withdrawals">Allow Withdrawals?</string>
+    <string name="allow_withdrawals">Allow withdrawals</string>
     <string name="lock_in_period">Lock-in Period</string>
     <string name="frequency">Frequency</string>
     <string name="type">Type</string>
     <string name="recurring_deposit_details">Recurring Deposit Details</string>
     <string name="recurring_deposit_amount">Recurring Deposit Amount</string>
     <string name="deposit_period">Deposit Period</string>
-    <string name="deposit_frequency_same_as_meeting">Deposit Frequency Same as Group/Center meeting</string>
+    <string name="deposit_frequency_same_as_meeting">Deposit frequency same as group/center meeting</string>
     <string name="minimum_deposit_term">Minimum Deposit Term</string>
-    <string name="in_multiples_of">And thereafter, in Multiples of</string>
+    <string name="in_multiples_of">And thereafter in multiples of</string>
     <string name="maximum_deposit_term">Maximum Deposit Term</string>
-    <string name="for_pre_mature_closure">For Pre-mature closure</string>
+    <string name="for_pre_mature_closure">For premature closure</string>
-    <string name="apply_penal_interest">Apply Penal Interest (less)</string>
+    <string name="apply_penal_interest">Apply penal interest</string>
-    <string name="penal_interest_percentage">Penal Interest (%)</string>
+    <string name="penal_interest_percentage">Penal interest (%)</string>
     <string name="period">Period</string>
-    <string name="minimum_balance_for_interest">Minimum Balance For Interest Calculation</string>
+    <string name="minimum_balance_for_interest">Minimum balance for interest calculation</string>
     <string name="back">Back</string>
     <string name="next">Next</string>
-    <string name="no_internet_connection">No Internet Connection</string>
+    <string name="no_internet_connection">No internet connection</string>

Optional: “frequency” and “type” are very generic keys; consider namespacing (e.g., recurring_frequency_label, recurring_type_label) to avoid collisions across modules.

🤖 Prompt for AI Agents
In feature/recurringDeposit/src/commonMain/composeResources/values/string.xml
around lines 18-38, several string values use question punctuation, title-case,
or awkward phrasing; update only the string values (do not rename keys) to use
sentence-case, remove trailing question marks for labels, and clarify wording
(e.g., change "Is Mandatory Deposit?" → "Mandatory deposit", "Adjust advance
payments toward future installments?" → "Adjust advance payments toward future
installments", "Allow Withdrawals?" → "Allow withdrawals", "Lock-in Period" →
"Lock-in period", "Type" → "Type" or a clearer label like 'Recurring type',
"Frequency" → "Frequency" or 'Recurring frequency', "For Pre-mature closure" →
"For premature closure", "Apply Penal Interest (less)" → "Apply penal interest
(less)", "Penal Interest (%)" → "Penal interest (%)", "Minimum Balance For
Interest Calculation" → "Minimum balance for interest calculation"); optionally
consider namespacing ambiguous keys like frequency/type in a separate follow-up
if needed.

</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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.feature.recurringDeposit.di

import com.mifos.feature.recurringDeposit.newRecurringDepositAccount.RecurringAccountViewModel
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module

val RecurringDepositModule = module {
viewModelOf(::RecurringAccountViewModel)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import androidx.navigation.compose.composable
import kotlinx.serialization.Serializable

@Serializable
data object RecurringAccountRoute
data class RecurringAccountRoute(
val clientId: Int = -1,
)
Comment on lines +18 to +20
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate or remove the default clientId value.

The default value of -1 suggests an invalid/unset state. Consider either:

  • Removing the default to force callers to provide a valid clientId
  • Adding validation to ensure clientId > 0 before proceeding
-data class RecurringAccountRoute(
-    val clientId: Int = -1,
-)
+data class RecurringAccountRoute(
+    val clientId: Int,
+)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
data class RecurringAccountRoute(
val clientId: Int = -1,
)
data class RecurringAccountRoute(
val clientId: Int,
)
🤖 Prompt for AI Agents
In
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountRoute.kt
around lines 18 to 20, the data class uses a default clientId = -1 which
represents an invalid/unset state; either remove the default so callers must
supply a clientId, or keep the field but add validation where instances are
created/used to enforce clientId > 0 and throw or return a clear error when
invalid; implement one of these two options consistently across
constructors/factory functions and any deserialization paths.


fun NavGraphBuilder.recurringAccountDestination() {
composable<RecurringAccountRoute> {
Expand All @@ -26,8 +28,10 @@ fun NavGraphBuilder.recurringAccountDestination() {
}
}

fun NavController.navigateToRecurringAccountRoute() {
fun NavController.navigateToRecurringAccountRoute(
clientId: Int,
) {
this.navigate(
RecurringAccountRoute,
RecurringAccountRoute(clientId = clientId),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.mifos.core.designsystem.component.MifosScaffold
import com.mifos.core.ui.components.MifosErrorComponent
import com.mifos.core.ui.components.MifosProgressIndicator
import com.mifos.core.ui.components.MifosStepper
import com.mifos.core.ui.components.Step
import com.mifos.core.ui.util.EventsEffect
Expand All @@ -33,13 +34,14 @@ import com.mifos.feature.recurringDeposit.newRecurringDepositAccount.pages.Inter
import com.mifos.feature.recurringDeposit.newRecurringDepositAccount.pages.SettingPage
import com.mifos.feature.recurringDeposit.newRecurringDepositAccount.pages.TermsPage
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel

@Composable
internal fun RecurringAccountScreen(
onNavigateBack: () -> Unit,
onFinish: () -> Unit,
modifier: Modifier = Modifier,
viewModel: RecurringAccountViewModel = viewModel(),
viewModel: RecurringAccountViewModel = koinViewModel(),
) {
val state by viewModel.stateFlow.collectAsStateWithLifecycle()

Expand All @@ -50,6 +52,8 @@ internal fun RecurringAccountScreen(
}
}

RecurringDepositAccountDialogBox(state = state)

RecurringAccountScaffold(
modifier = modifier,
state = state,
Expand All @@ -76,7 +80,8 @@ private fun RecurringAccountScaffold(
},
Step(name = stringResource(Res.string.step_settings)) {
SettingPage(
onNext = { onAction(RecurringAccountAction.NextStep) },
state = state,
onAction = onAction,
)
},
Step(name = stringResource(Res.string.step_interest)) {
Expand All @@ -96,7 +101,7 @@ private fun RecurringAccountScaffold(
onBackPressed = { onAction(RecurringAccountAction.NavigateBack) },
modifier = modifier,
) { paddingValues ->
if (state.dialogState == null) {
if (state.screenState == null) {
MifosStepper(
steps = steps,
currentIndex = state.currentStep,
Expand All @@ -110,3 +115,24 @@ private fun RecurringAccountScaffold(
}
}
}

@Composable
fun RecurringDepositAccountDialogBox(
state: RecurringAccountState,
) {
when (state.screenState) {
is RecurringAccountState.ScreenState.Error -> {
MifosErrorComponent(
message = state.screenState.message,
isRetryEnabled = true,
onRetry = {
// Retry action can be handled here
},
)
}
RecurringAccountState.ScreenState.Loading -> {
MifosProgressIndicator()
}
null -> {}
}
}
Loading