Skip to content
Open
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 @@ -541,7 +541,7 @@
<!-- New Fixed Deposit Account -->
<string name="one_year_fixed_deposit">1 Year Fixed Deposit</string>
<string name="submission_on">Submission On</string>
<string name="Field_officer">Field Officer</string>
<string name="field_officer">Field Officer</string>


<!-- Create Share Account -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
*/
package com.mifos.feature.client.newFixedDepositAccount.pages

import androidclient.feature.client.generated.resources.Field_officer
import androidclient.feature.client.generated.resources.Res
import androidclient.feature.client.generated.resources.btn_back
import androidclient.feature.client.generated.resources.feature_client_charge_cancel
import androidclient.feature.client.generated.resources.feature_client_charge_select
import androidclient.feature.client.generated.resources.feature_client_external_id
import androidclient.feature.client.generated.resources.feature_client_next
import androidclient.feature.client.generated.resources.field_officer
import androidclient.feature.client.generated.resources.one_year_fixed_deposit
import androidclient.feature.client.generated.resources.submission_on
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -130,7 +130,7 @@ fun DetailsPage(
state.template.fieldOfficerOptions?.get(state.fixedDepositAccountDetail.fieldOfficerIndex)?.displayName
?: ""
},
label = stringResource(Res.string.Field_officer),
label = stringResource(Res.string.field_officer),
onValueChanged = {},
onOptionSelected = { index, value ->
onAction(NewFixedDepositAccountAction.OnFieldOfficerChange(index))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,8 @@
<string name="feature_recurring_deposit_next_button">Next Button</string>
<string name="feature_recurring_deposit_interest_page">Interest Page</string>
<string name="feature_recurring_deposit_charges_page">Charges Page</string>
<string name="feature_recurring_deposit_interest_compounding_period">Interest Compounding Period</string>
<string name="feature_recurring_deposit_interest_posting_period">Interest Posting Period</string>
<string name="feature_recurring_deposit_interest_calculation">Interest Calculated Using</string>
<string name="feature_recurring_deposit_calculation_days_in_year">Days In Year </string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ private fun RecurringAccountScaffold(
},
Step(name = stringResource(Res.string.feature_recurring_deposit_step_terms)) {
TermsPage(
onNext = { onAction(RecurringAccountAction.OnNextPress) },
state = state,
onAction = onAction,
)
},
Step(name = stringResource(Res.string.feature_recurring_deposit_step_settings)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,44 @@ class RecurringAccountViewModel(
)
}

private fun handleInterestCalculationDaysInYearType(action: RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCalculationDaysInYearType) {
mutableStateFlow.update {
it.copy(
recurringDepositAccountInterestChart = it.recurringDepositAccountInterestChart.copy(
interestCalculationDaysInYearType = action.interestCalculationTypeDaysInYear,
),

)
}
}
private fun handleInterestCalculationType(action: RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCalculationType) {
mutableStateFlow.update {
it.copy(
recurringDepositAccountInterestChart = it.recurringDepositAccountInterestChart.copy(
interestCalculationType = action.interestCalculationType,
),
)
}
}
private fun handleInterestCompoundingPeriodType(action: RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCompoundingPeriodType) {
mutableStateFlow.update {
it.copy(
recurringDepositAccountInterestChart = it.recurringDepositAccountInterestChart.copy(
interestCompoundingPeriodType = action.interestCompoundingPeriodType,
),
)
}
}
private fun handleInterestPostingPeriodType(action: RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestPostingPeriodType) {
mutableStateFlow.update {
it.copy(
recurringDepositAccountInterestChart = it.recurringDepositAccountInterestChart.copy(
interestPostingPeriodType = action.interestPostingPeriodType,
),
)
}
}

private fun resetForRetry() {
mutableStateFlow.update {
it.copy(
Expand Down Expand Up @@ -577,6 +615,19 @@ class RecurringAccountViewModel(
RecurringAccountAction.OnNextPress -> {
moveToNextStep()
}

is RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCalculationDaysInYearType -> {
handleInterestCalculationDaysInYearType(action)
}
is RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCalculationType -> {
handleInterestCalculationType(action)
}
is RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCompoundingPeriodType -> {
handleInterestCompoundingPeriodType(action)
}
is RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestPostingPeriodType -> {
handleInterestPostingPeriodType(action)
}
}
}
}
Expand All @@ -590,6 +641,7 @@ data class RecurringAccountState(
val recurringDepositAccountDetail: RecurringAccountDetailsState = RecurringAccountDetailsState(),
val template: RecurringDepositAccountTemplate = RecurringDepositAccountTemplate(),
val recurringDepositAccountSettings: RecurringAccountSettingsState = RecurringAccountSettingsState(),
val recurringDepositAccountInterestChart: RecurringAccountInterestChartState = RecurringAccountInterestChartState(),
val currencyIndex: Int = -1,
val currencyError: String? = null,
) {
Expand All @@ -615,6 +667,18 @@ data class RecurringAccountDetailsState(
) {
val isDetailButtonEnabled = fieldOfficerIndex != -1 && submissionDate.isNotEmpty()
}
data class RecurringAccountInterestChartState(
val interestCalculationDaysInYearType: Int? = null,
val interestCalculationType: Int? = null,
val interestCompoundingPeriodType: Int? = null,
val interestPostingPeriodType: Int? = null,


){
val isTermsButtonEnabled = interestCalculationDaysInYearType != -1 && interestPostingPeriodType != -1
&& interestCompoundingPeriodType != -1 && interestCalculationType != -1

}
Comment on lines +670 to +681
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix type inconsistency causing incorrect button state.

The fields are declared as Int? (nullable) with a default of null, but isTermsButtonEnabled checks them against -1. Since null != -1 evaluates to true, the button will always be enabled even when no selections have been made.

Based on the codebase convention (e.g., fieldOfficerIndex: Int = -1 on line 662), use non-nullable Int with -1 as the sentinel value.

Apply this diff:

 data class RecurringAccountInterestChartState(
-    val interestCalculationDaysInYearType: Int? = null,
-    val interestCalculationType: Int? = null,
-    val interestCompoundingPeriodType: Int? = null,
-    val interestPostingPeriodType: Int? = null,
+    val interestCalculationDaysInYearType: Int = -1,
+    val interestCalculationType: Int = -1,
+    val interestCompoundingPeriodType: Int = -1,
+    val interestPostingPeriodType: Int = -1,
 
 
 ){
     val isTermsButtonEnabled = interestCalculationDaysInYearType != -1 && interestPostingPeriodType != -1
             && interestCompoundingPeriodType != -1 && interestCalculationType != -1
 
 }
🤖 Prompt for AI Agents
In
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountViewModel.kt
around lines 670-681, the four fields (interestCalculationDaysInYearType,
interestCalculationType, interestCompoundingPeriodType,
interestPostingPeriodType) are declared as nullable Int? = null but compared to
-1, causing isTermsButtonEnabled to be true when null; change each field to a
non-nullable Int with a sentinel default of -1 (e.g., Int = -1) so the existing
comparison logic works correctly, and keep the isTermsButtonEnabled expression
as-is.


data class RecurringAccountSettingsState(
val canDoNext: Boolean = false,
Expand All @@ -627,6 +691,7 @@ data class RecurringAccountSettingsState(
val minimumDepositTerm: MinimumDepositTerm = MinimumDepositTerm(),
val maxDepositTerm: MaxDepositTerm = MaxDepositTerm(),
val preMatureClosure: PreMatureClosure = PreMatureClosure(),

) {

data class LockInPeriod(
Expand Down Expand Up @@ -677,6 +742,8 @@ data class RecurringAccountSettingsState(
minimumDepositTerm.frequency.isNotBlank() &&
minimumDepositTerm.frequencyAfterInMultiplesOf.isNotBlank() &&
maxDepositTerm.frequency.isNotBlank()


}

sealed class RecurringAccountAction {
Expand Down Expand Up @@ -717,6 +784,12 @@ sealed class RecurringAccountAction {
data class SetPreMatureClosureInterestPeriodIndex(val interestPeriodIndex: Int) : RecurringAccountSettingsAction()
data class SetPreMatureClosureMinimumBalanceForInterestCalculation(val minimumBalanceForInterestCalculation: String) : RecurringAccountSettingsAction()
}
sealed class RecurringAccountInterestChartAction : RecurringAccountAction() {
data class OnInterestCalculationDaysInYearType(val interestCalculationTypeDaysInYear: Int) : RecurringAccountInterestChartAction()
data class OnInterestCompoundingPeriodType(val interestCompoundingPeriodType: Int) : RecurringAccountInterestChartAction()
data class OnInterestCalculationType(val interestCalculationType: Int) : RecurringAccountInterestChartAction()
data class OnInterestPostingPeriodType(val interestPostingPeriodType: Int) : RecurringAccountInterestChartAction()
}
}

sealed class RecurringAccountEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
package com.mifos.feature.recurringDeposit.newRecurringDepositAccount.pages

import androidclient.feature.recurringdeposit.generated.resources.Res
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_interest_page
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_charges_page
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_next_button
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
Expand All @@ -26,7 +26,7 @@ import org.jetbrains.compose.resources.stringResource
@Composable
fun InterestPage(onNext: () -> Unit) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(stringResource(Res.string.feature_recurring_deposit_interest_page))
Text(stringResource(Res.string.feature_recurring_deposit_charges_page))
Spacer(Modifier.height(8.dp))
Button(onClick = onNext) {
Text(stringResource(Res.string.feature_recurring_deposit_next_button))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,128 @@
package com.mifos.feature.recurringDeposit.newRecurringDepositAccount.pages

import androidclient.feature.recurringdeposit.generated.resources.Res
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_next_button
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_terms_page
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_back
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_calculation_days_in_year
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_interest_calculation
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_interest_compounding_period
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_interest_posting_period
import androidclient.feature.recurringdeposit.generated.resources.feature_recurring_deposit_next
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.mifos.core.designsystem.component.MifosTextFieldDropdown
import com.mifos.core.designsystem.theme.DesignToken
import com.mifos.core.ui.components.MifosProgressIndicatorMini
import com.mifos.core.ui.components.MifosTwoButtonRow
import com.mifos.feature.recurringDeposit.newRecurringDepositAccount.RecurringAccountAction
import com.mifos.feature.recurringDeposit.newRecurringDepositAccount.RecurringAccountState
import org.jetbrains.compose.resources.stringResource

@Composable
fun TermsPage(onNext: () -> Unit) {
fun TermsPage(
state: RecurringAccountState,
onAction: (RecurringAccountAction) -> Unit,
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(stringResource(Res.string.feature_recurring_deposit_terms_page))
Spacer(Modifier.height(8.dp))
Button(onClick = onNext) {
Text(stringResource(Res.string.feature_recurring_deposit_next_button))
MifosTextFieldDropdown(
value = if (state.recurringDepositAccountInterestChart.interestCompoundingPeriodType == null) {
" "
} else {
state.template.interestCompoundingPeriodTypeOptions?.getOrNull(state.recurringDepositAccountInterestChart.interestCompoundingPeriodType)?.value
?: ""
},
onValueChanged = { },
onOptionSelected = { index, value ->
onAction(
RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCompoundingPeriodType(
index,
),
)
},
options = state.template.interestCompoundingPeriodTypeOptions?.map {
it.value ?: ""
} ?: emptyList(),
label = stringResource(Res.string.feature_recurring_deposit_interest_compounding_period),
)
Spacer(modifier = Modifier.height(DesignToken.padding.large))
MifosTextFieldDropdown(
value = if (state.recurringDepositAccountInterestChart.interestPostingPeriodType == null) {
" "
} else {
state.template.interestPostingPeriodTypeOptions?.getOrNull(state.recurringDepositAccountInterestChart.interestPostingPeriodType)?.value
?: ""
},
onValueChanged = { },
onOptionSelected = { index, value ->
onAction(
RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestPostingPeriodType(
index,
),
)
},
options = state.template.interestPostingPeriodTypeOptions?.map {
it.value ?: ""
} ?: emptyList(),
label = stringResource(Res.string.feature_recurring_deposit_interest_posting_period),
)
Spacer(modifier = Modifier.height(DesignToken.padding.large))
MifosTextFieldDropdown(
value = if (state.recurringDepositAccountInterestChart.interestCalculationType == null) {
" "
} else {
state.template.interestCalculationTypeOptions?.getOrNull(state.recurringDepositAccountInterestChart.interestCalculationType)?.value
?: ""
},
onValueChanged = { },
onOptionSelected = { index, value ->
onAction(
RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCalculationType(
index,
),
)
},
options = state.template.interestCalculationTypeOptions?.map {
it.value ?: ""
} ?: emptyList(),
label = stringResource(Res.string.feature_recurring_deposit_interest_calculation),
)
Spacer(modifier = Modifier.height(DesignToken.padding.large))
MifosTextFieldDropdown(
value = if (state.recurringDepositAccountInterestChart.interestCalculationDaysInYearType == null) {
" "
} else {
state.template.interestCalculationDaysInYearTypeOptions?.getOrNull(state.recurringDepositAccountInterestChart.interestCalculationDaysInYearType)?.value
?: ""
},
onValueChanged = { },
onOptionSelected = { index, value ->
onAction(
RecurringAccountAction.RecurringAccountInterestChartAction.OnInterestCalculationDaysInYearType(
index,
),
)
},
options = state.template.interestCalculationDaysInYearTypeOptions?.map {
it.value ?: ""
} ?: emptyList(),
label = stringResource(Res.string.feature_recurring_deposit_calculation_days_in_year),
)
if (state.recurringDepositAccountDetail.isMiniLoaderActive) {
MifosProgressIndicatorMini()
}

MifosTwoButtonRow(
firstBtnText = stringResource(Res.string.feature_recurring_deposit_back),
secondBtnText = stringResource(Res.string.feature_recurring_deposit_next),
onFirstBtnClick = { onAction(RecurringAccountAction.OnBackPress) },
onSecondBtnClick = { onAction(RecurringAccountAction.OnNextPress) },
isSecondButtonEnabled = state.recurringDepositAccountInterestChart.isTermsButtonEnabled,
isButtonIconVisible = true,

Copy link
Contributor

Choose a reason for hiding this comment

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

i think you can use isButtonEnabled some thing like that in MifosTwoButtonRow to make sure next button is enabled only after everything is filled

)
}
}
Loading