diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/FixedDepositRepository.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/FixedDepositRepository.kt index 718586da33a..15f45764885 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/FixedDepositRepository.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/FixedDepositRepository.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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.data.repository import com.mifos.core.common.utils.DataState @@ -7,8 +16,6 @@ import kotlinx.coroutines.flow.Flow interface FixedDepositRepository { fun getFixedDepositTemplate( clientId: Int, - productId: Int? + productId: Int?, ): Flow> - - -} \ No newline at end of file +} diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/FixedDepositRepositoryImpl.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/FixedDepositRepositoryImpl.kt index e1882e9b8bd..2c585ea8981 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/FixedDepositRepositoryImpl.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/FixedDepositRepositoryImpl.kt @@ -1,6 +1,14 @@ +/* + * Copyright 2024 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.data.repositoryImp - import com.mifos.core.common.utils.DataState import com.mifos.core.common.utils.asDataStateFlow import com.mifos.core.data.repository.FixedDepositRepository @@ -8,13 +16,14 @@ import com.mifos.core.network.datamanager.DataManagerFixedDeposit import com.mifos.core.network.model.FixedDepositTemplate import kotlinx.coroutines.flow.Flow -class FixedDepositRepositoryImpl (private val dataManagerFixedDeposit: DataManagerFixedDeposit): FixedDepositRepository{ +class FixedDepositRepositoryImpl(private val dataManagerFixedDeposit: DataManagerFixedDeposit) : + FixedDepositRepository { - override fun getFixedDepositTemplate(clientId: Int,productId: Int?): Flow> { - return dataManagerFixedDeposit.getFixedDepositTemplate(clientId,productId).asDataStateFlow() + override fun getFixedDepositTemplate( + clientId: Int, + productId: Int?, + ): Flow> { + return dataManagerFixedDeposit.getFixedDepositTemplate(clientId, productId) + .asDataStateFlow() } - - - - } diff --git a/core/database/src/commonMain/kotlin/com/mifos/room/basemodel/APIEndPoint.kt b/core/database/src/commonMain/kotlin/com/mifos/room/basemodel/APIEndPoint.kt index d2b27dd47d3..4a8ee456ffe 100644 --- a/core/database/src/commonMain/kotlin/com/mifos/room/basemodel/APIEndPoint.kt +++ b/core/database/src/commonMain/kotlin/com/mifos/room/basemodel/APIEndPoint.kt @@ -42,5 +42,5 @@ object APIEndPoint { const val MAKER_CHECKER = "makercheckers" const val SHARE = "share" - const val FIXED_DEPOSIT ="fixeddepositaccounts" + const val FIXED_DEPOSIT = "fixeddepositaccounts" } diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/BaseApiManager.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/BaseApiManager.kt index dac3d167a83..6825aa0329c 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/BaseApiManager.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/BaseApiManager.kt @@ -33,6 +33,7 @@ import com.mifos.core.network.services.ClientService import com.mifos.core.network.services.CollectionSheetService import com.mifos.core.network.services.DataTableService import com.mifos.core.network.services.DocumentService +import com.mifos.core.network.services.FixedDepositService import com.mifos.core.network.services.GroupService import com.mifos.core.network.services.LoanService import com.mifos.core.network.services.NoteService @@ -44,7 +45,6 @@ import com.mifos.core.network.services.SearchService import com.mifos.core.network.services.ShareAccountService import com.mifos.core.network.services.StaffService import com.mifos.core.network.services.SurveyService -import com.mifos.core.network.services.FixedDepositService import com.mifos.core.network.services.createCenterService import com.mifos.core.network.services.createChargeService import com.mifos.core.network.services.createCheckerInboxService @@ -53,6 +53,7 @@ import com.mifos.core.network.services.createClientService import com.mifos.core.network.services.createCollectionSheetService import com.mifos.core.network.services.createDataTableService import com.mifos.core.network.services.createDocumentService +import com.mifos.core.network.services.createFixedDepositService import com.mifos.core.network.services.createGroupService import com.mifos.core.network.services.createLoanService import com.mifos.core.network.services.createNoteService @@ -60,7 +61,6 @@ import com.mifos.core.network.services.createOfficeService import com.mifos.core.network.services.createRecurringAccountService import com.mifos.core.network.services.createRunReportsService import com.mifos.core.network.services.createSavingsAccountService -import com.mifos.core.network.services.createFixedDepositService import com.mifos.core.network.services.createSearchService import com.mifos.core.network.services.createShareAccountService import com.mifos.core.network.services.createStaffService diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerFixedDeposit.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerFixedDeposit.kt index 8a7847edc9b..fff6ce3f961 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerFixedDeposit.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerFixedDeposit.kt @@ -1,12 +1,20 @@ +/* + * 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.network.datamanager import com.mifos.core.network.BaseApiManager import com.mifos.core.network.model.FixedDepositTemplate import kotlinx.coroutines.flow.Flow -class DataManagerFixedDeposit (private val baseApiManager: BaseApiManager){ +class DataManagerFixedDeposit(private val baseApiManager: BaseApiManager) { - fun getFixedDepositTemplate(clientId:Int,productId: Int?): Flow = - baseApiManager.fixedDepositService.fixedDepositProductTemplate(clientId,productId) - -} \ No newline at end of file + fun getFixedDepositTemplate(clientId: Int, productId: Int?): Flow = + baseApiManager.fixedDepositService.fixedDepositProductTemplate(clientId, productId) +} diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/di/DataMangerModule.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/di/DataMangerModule.kt index 0d398353f5c..48b426c7ab2 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/di/DataMangerModule.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/di/DataMangerModule.kt @@ -19,9 +19,9 @@ import com.mifos.core.network.datamanager.DataManagerClient import com.mifos.core.network.datamanager.DataManagerCollectionSheet import com.mifos.core.network.datamanager.DataManagerDataTable import com.mifos.core.network.datamanager.DataManagerDocument +import com.mifos.core.network.datamanager.DataManagerFixedDeposit import com.mifos.core.network.datamanager.DataManagerGroups import com.mifos.core.network.datamanager.DataManagerIdentifiers -import com.mifos.core.network.datamanager.DataManagerFixedDeposit import com.mifos.core.network.datamanager.DataManagerLoan import com.mifos.core.network.datamanager.DataManagerNote import com.mifos.core.network.datamanager.DataManagerOffices diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/model/FixedDepositProductOption.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/model/FixedDepositProductOption.kt index 0f84440d742..7bfb43e51f1 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/model/FixedDepositProductOption.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/model/FixedDepositProductOption.kt @@ -1,6 +1,14 @@ +/* + * 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.network.model - import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -14,4 +22,4 @@ data class FixedDepositProductOption( @SerialName("withHoldTax") val withHoldTax: Boolean? = null, -) \ No newline at end of file +) diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/model/FixedDepositTemplate.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/model/FixedDepositTemplate.kt index 5c25f8fb704..b86dde9856a 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/model/FixedDepositTemplate.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/model/FixedDepositTemplate.kt @@ -1,24 +1,55 @@ +/* + * 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.network.model import com.mifos.core.model.objects.account.saving.FieldOfficerOptions -import com.mifos.core.model.utils.IgnoredOnParcel +import com.mifos.core.model.objects.template.recurring.Currency +import com.mifos.core.model.objects.template.recurring.interest.InterestCalculationDaysInYearTypeOption +import com.mifos.core.model.objects.template.recurring.interest.InterestCalculationTypeOption +import com.mifos.core.model.objects.template.recurring.interest.InterestCompoundingPeriodTypeOption +import com.mifos.core.model.objects.template.recurring.interest.InterestPostingPeriodTypeOption +import com.mifos.core.model.objects.template.recurring.period.PeriodFrequencyTypeOption import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable - - @Serializable data class FixedDepositTemplate( + @SerialName("clientId") val clientId: Int? = null, @SerialName(value = "clientName") val clientName: String? = null, + @SerialName(value = "currency") + val currency: Currency? = null, + @SerialName("productOptions") val productOptions: List? = null, @SerialName("fieldOfficerOptions") val fieldOfficerOptions: List? = null, -) \ No newline at end of file + @SerialName("periodFrequencyTypeOptions") + val periodFrequencyTypeOptions: List? = null, + + @SerialName("interestCompoundingPeriodTypeOptions") + val interestCompoundingPeriodTypeOptions: List? = null, + + @SerialName("interestPostingPeriodTypeOptions") + val interestPostingPeriodTypeOptions: List? = null, + + @SerialName("interestCalculationDaysInYearTypeOptions") + val interestCalculationDaysInYearTypeOptions: List? = null, + + @SerialName("interestCalculationTypeOptions") + val interestCalculationTypeOptions: List? = null, + +) diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/services/FixedDepositService.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/services/FixedDepositService.kt index cfa5ce0fccb..1cfe0cd1a56 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/services/FixedDepositService.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/services/FixedDepositService.kt @@ -1,26 +1,25 @@ +/* + * 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.network.services import com.mifos.core.network.model.FixedDepositTemplate import com.mifos.room.basemodel.APIEndPoint -import de.jensklingenberg.ktorfit.http.Query import de.jensklingenberg.ktorfit.http.GET +import de.jensklingenberg.ktorfit.http.Query import kotlinx.coroutines.flow.Flow - - - - - interface FixedDepositService { - @GET( APIEndPoint.FIXED_DEPOSIT + "/template") + @GET(APIEndPoint.FIXED_DEPOSIT + "/template") fun fixedDepositProductTemplate( @Query("clientId") clientId: Int, @Query("productId") productId: Int?, ): Flow } - - - - - diff --git a/feature/client/src/commonMain/composeResources/values/strings.xml b/feature/client/src/commonMain/composeResources/values/strings.xml index 141d4034217..c50f5cab4a4 100644 --- a/feature/client/src/commonMain/composeResources/values/strings.xml +++ b/feature/client/src/commonMain/composeResources/values/strings.xml @@ -578,4 +578,14 @@ View Charges Updating client charges is not supported. Please delete the existing charge and create a new one. + Deposit Amount + Deposit Period Type + Interest Compounding + Interest Compounding Period + Interest Posting Period + Interest Calculated Using + Days in year + Terms + Deposit Period + \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt index 0207ccc9b92..e8745af3e27 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt @@ -76,7 +76,6 @@ import com.mifos.feature.client.documentPreviewScreen.createDocumentPreviewRoute import com.mifos.feature.client.documentPreviewScreen.navigateToDocumentPreviewRoute import com.mifos.feature.client.fixedDepositAccount.clientFixedDepositAccountDestination import com.mifos.feature.client.fixedDepositAccount.navigateToFixedDepositAccountRoute -import com.mifos.feature.client.newFixedDepositAccount.createFixedDepositAccountRoute import com.mifos.feature.client.newFixedDepositAccount.createFixedDepositAccountDestination import com.mifos.feature.client.newFixedDepositAccount.navigateToCreateFixedDepositRoute import com.mifos.feature.client.recurringDepositAccount.clientRecurringDepositAccountDestination diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountRoute.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountRoute.kt similarity index 86% rename from feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountRoute.kt rename to feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountRoute.kt index 7656af5fbf6..5cc86168490 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountRoute.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountRoute.kt @@ -15,15 +15,12 @@ import androidx.navigation.compose.composable import kotlinx.serialization.Serializable @Serializable - -data class createFixedDepositAccountRoute( +data class CreateFixedDepositAccountRoute( val clientId: Int, ) - - fun NavGraphBuilder.createFixedDepositAccountDestination(navController: NavController) { - composable { + composable { CreateFixedDepositAccountScreen( onNavigateBack = navController::popBackStack, onFinish = {}, @@ -31,8 +28,9 @@ fun NavGraphBuilder.createFixedDepositAccountDestination(navController: NavContr ) } } + fun NavController.navigateToCreateFixedDepositRoute(clientId: Int) { this.navigate( - createFixedDepositAccountRoute(clientId=clientId) + CreateFixedDepositAccountRoute(clientId = clientId), ) } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountScreen.kt similarity index 97% rename from feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountScreen.kt rename to feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountScreen.kt index 6ef231cb054..fea67931450 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountScreen.kt @@ -22,7 +22,6 @@ 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 androidx.navigation.NavController import com.mifos.core.designsystem.component.MifosScaffold import com.mifos.core.ui.components.MifosBreadcrumbNavBar @@ -79,7 +78,8 @@ private fun FixedDepositAccountScaffold( }, Step(name = stringResource(Res.string.step_terms)) { TermsPage( - onNext = { onAction(NewFixedDepositAccountAction.OnNextPress) }, + state = newFixedDepositAccountState, + onAction = onAction, ) }, @@ -132,10 +132,9 @@ private fun FixedDepositAccountScaffold( modifier = Modifier .fillMaxWidth(), - ) + ) } } } - } } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountViewmodel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountViewmodel.kt similarity index 57% rename from feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountViewmodel.kt rename to feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountViewmodel.kt index 81c39d9183f..a4ab7b3b214 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/createFixedDepositAccountViewmodel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/CreateFixedDepositAccountViewmodel.kt @@ -30,16 +30,15 @@ class CreateFixedDepositAccountViewmodel( private val fixedDepositRepository: FixedDepositRepository, ) : BaseViewModel< - NewFixedDepositAccountState, - NewFixedDepositAccountEvent, - NewFixedDepositAccountAction, - >( + NewFixedDepositAccountState, + NewFixedDepositAccountEvent, + NewFixedDepositAccountAction, + >( NewFixedDepositAccountState( clientId = savedStateHandle.toRoute().clientId, ), ) { - init { loadFixedDepositAccountTemplate() } @@ -57,16 +56,21 @@ class CreateFixedDepositAccountViewmodel( is NewFixedDepositAccountAction.OnExternalIdChange -> handleExternalIdChange(action) NewFixedDepositAccountAction.OnDetailsSubmit -> handleOnDetailsSubmit() NewFixedDepositAccountAction.Retry -> handleRetry() + is NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositAmount -> handleSetFixedDepositAmount(action) + is NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositPeriod -> handleSetFixedDepositPeriod(action) + is NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositPeriodType -> handleSetFixedDepositPeriodType(action) + is NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCompoundingPeriod -> handleSetInterestCompoundingPeriod(action) + is NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestPostingPeriod -> handleSetInterestPostingPeriod(action) + is NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCalculationType -> handleInterestCalculationType(action) + is NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCalculationDaysInYearType -> handleSetInterestCalculationDaysInYearType(action) } } - private fun handleRetry(){ + private fun handleRetry() { loadFixedDepositAccountTemplate() } - private fun loadFixedDepositAccountTemplate() = viewModelScope.launch { - fixedDepositRepository.getFixedDepositTemplate( clientId = state.clientId, productId = state.template.productOptions?.get(state.fixedDepositAccountDetail.productSelected)?.id, @@ -117,8 +121,8 @@ class CreateFixedDepositAccountViewmodel( mutableStateFlow.update { it.copy( fixedDepositAccountDetail = it.fixedDepositAccountDetail.copy( - submissionDate = action.date - ) + submissionDate = action.date, + ), ) } } @@ -177,6 +181,75 @@ class CreateFixedDepositAccountViewmodel( ) } } + private fun handleSetFixedDepositAmount(action: NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositAmount) { + mutableStateFlow.update { + it.copy( + fixedDepositAccountTerms = it.fixedDepositAccountTerms.copy( + depositAmount = action.depositAmount, + ), + ) + } + } + + private fun handleSetFixedDepositPeriod(action: NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositPeriod) { + mutableStateFlow.update { + it.copy( + fixedDepositAccountTerms = it.fixedDepositAccountTerms.copy( + depositPeriod = action.period, + ), + ) + } + } + + private fun handleSetFixedDepositPeriodType(action: NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositPeriodType) { + mutableStateFlow.update { + it.copy( + fixedDepositAccountTerms = it.fixedDepositAccountTerms.copy( + depositPeriodTypeIndex = action.depositPeriodTypeIndex, + ), + ) + } + } + + private fun handleSetInterestCompoundingPeriod(action: NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCompoundingPeriod) { + mutableStateFlow.update { + it.copy( + fixedDepositAccountTerms = it.fixedDepositAccountTerms.copy( + interestCompoundingPeriodTypeIndex = action.interestCompoundingPeriodTypeIndex, + ), + ) + } + } + + private fun handleInterestCalculationType(action: NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCalculationType) { + mutableStateFlow.update { + it.copy( + fixedDepositAccountTerms = it.fixedDepositAccountTerms.copy( + interestCalculationTypeIndex = action.interestCalculationPeriodTypeIndex, + ), + ) + } + } + + private fun handleSetInterestPostingPeriod(action: NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestPostingPeriod) { + mutableStateFlow.update { + it.copy( + fixedDepositAccountTerms = it.fixedDepositAccountTerms.copy( + interestPostingPeriodTypeIndex = action.interestPostingPeriodTypeIndex, + ), + ) + } + } + + private fun handleSetInterestCalculationDaysInYearType(action: NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCalculationDaysInYearType) { + mutableStateFlow.update { + it.copy( + fixedDepositAccountTerms = it.fixedDepositAccountTerms.copy( + interestCalculationDaysInYearTypeIndex = action.periodTypeIndex, + ), + ) + } + } private fun moveToNextStep() { val current = state.currentStep @@ -190,18 +263,17 @@ class CreateFixedDepositAccountViewmodel( sendEvent(NewFixedDepositAccountEvent.Finish) } } - - } -data class NewFixedDepositAccountState constructor( +data class NewFixedDepositAccountState( val clientId: Int = -1, val currentStep: Int = 0, val dialogState: Any? = null, val totalSteps: Int = 4, val screenState: ScreenState = ScreenState.Loading, val fixedDepositAccountDetail: FixedDepositAccountDetailsState = FixedDepositAccountDetailsState(), - val template: FixedDepositTemplate = FixedDepositTemplate() + val fixedDepositAccountTerms: FixedDepositAccountTermsState = FixedDepositAccountTermsState(), + val template: FixedDepositTemplate = FixedDepositTemplate(), ) { sealed interface ScreenState { data class Error(val message: String) : ScreenState @@ -210,7 +282,21 @@ data class NewFixedDepositAccountState constructor( } } -data class FixedDepositAccountDetailsState @OptIn(ExperimentalTime::class) constructor( +data class FixedDepositAccountTermsState( + val depositAmount: String = "", + val depositPeriod: String = "", + val depositPeriodTypeIndex: Int = -1, + val interestCompoundingPeriodTypeIndex: Int = -1, + val interestPostingPeriodTypeIndex: Int = -1, + val interestCalculationTypeIndex: Int = -1, + val interestCalculationDaysInYearTypeIndex: Int = -1, +) { + val isTermsNextEnabled = depositAmount.isNotEmpty() && depositPeriod.isNotEmpty() && + depositPeriodTypeIndex != -1 && interestCompoundingPeriodTypeIndex != -1 && interestCalculationTypeIndex != -1 && interestCalculationDaysInYearTypeIndex != -1 +} +data class FixedDepositAccountDetailsState +@OptIn(ExperimentalTime::class) +constructor( val submittedOnDate: String = "", val fieldOfficer: FieldOfficerOption? = null, val showSubmissionDatePick: Boolean = false, @@ -228,22 +314,30 @@ data class FixedDepositAccountDetailsState @OptIn(ExperimentalTime::class) const val isDetailsNextEnabled = submissionDate.isNotEmpty() && fieldOfficerIndex != -1 } -sealed class NewFixedDepositAccountAction() { - object OnNextPress : NewFixedDepositAccountAction() +sealed class NewFixedDepositAccountAction { + data object OnNextPress : NewFixedDepositAccountAction() data class OnStepChange(val newIndex: Int) : NewFixedDepositAccountAction() - object NavigateBack : NewFixedDepositAccountAction() + data object NavigateBack : NewFixedDepositAccountAction() data class OnSubmissionDatePick(val state: Boolean) : NewFixedDepositAccountAction() data class OnSubmissionDateChange(val date: String) : NewFixedDepositAccountAction() data class OnProductNameChange(val index: Int) : NewFixedDepositAccountAction() - object Finish : NewFixedDepositAccountAction() + data object Finish : NewFixedDepositAccountAction() data class OnFieldOfficerChange(val index: Int) : NewFixedDepositAccountAction() data class OnExternalIdChange(val value: String) : NewFixedDepositAccountAction() data object OnDetailsSubmit : NewFixedDepositAccountAction() data object Retry : NewFixedDepositAccountAction() - + sealed class NewFixedDepositAccountTermsAction : NewFixedDepositAccountAction() { + data class SetFixedDepositAmount(val depositAmount: String) : NewFixedDepositAccountAction() + data class SetFixedDepositPeriod(val period: String) : NewFixedDepositAccountAction() + data class SetFixedDepositPeriodType(val depositPeriodTypeIndex: Int) : NewFixedDepositAccountAction() + data class SetInterestCompoundingPeriod(val interestCompoundingPeriodTypeIndex: Int) : NewFixedDepositAccountAction() + data class SetInterestPostingPeriod(val interestPostingPeriodTypeIndex: Int) : NewFixedDepositAccountAction() + data class SetInterestCalculationType(val interestCalculationPeriodTypeIndex: Int) : NewFixedDepositAccountAction() + data class SetInterestCalculationDaysInYearType(val periodTypeIndex: Int) : NewFixedDepositAccountAction() + } } sealed class NewFixedDepositAccountEvent() { diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/pages/DetailsPage.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/pages/DetailsPage.kt index 9e1c35ca6ff..7405a559c76 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/pages/DetailsPage.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/pages/DetailsPage.kt @@ -15,15 +15,9 @@ 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.step_charges -import androidclient.feature.client.generated.resources.step_details -import androidclient.feature.client.generated.resources.step_interest import androidclient.feature.client.generated.resources.one_year_fixed_deposit import androidclient.feature.client.generated.resources.submission_on - - import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -59,8 +53,7 @@ fun DetailsPage( state: NewFixedDepositAccountState, onAction: (NewFixedDepositAccountAction) -> Unit, modifier: Modifier = Modifier, - - ) { +) { val submissionDatePickerState = rememberDatePickerState( initialSelectedDateMillis = Clock.System.now().toEpochMilliseconds(), selectableDates = object : SelectableDates { @@ -69,7 +62,7 @@ fun DetailsPage( } }, - ) + ) if (state.fixedDepositAccountDetail.showSubmissionDatePick) { DatePickerDialog( onDismissRequest = { @@ -99,13 +92,11 @@ fun DetailsPage( ) { DatePicker(state = submissionDatePickerState) } - } Column( modifier = modifier.fillMaxSize() .verticalScroll(rememberScrollState()), ) { - MifosTextFieldDropdown( value = if (state.fixedDepositAccountDetail.productSelected == -1) { "" @@ -121,8 +112,7 @@ fun DetailsPage( it.name ?: "" } ?: emptyList(), - - ) + ) if (!state.template.fieldOfficerOptions.isNullOrEmpty()) { MifosDatePickerTextField( @@ -149,7 +139,7 @@ fun DetailsPage( it.displayName ?: "" } ?: emptyList(), - ) + ) MifosOutlinedTextField( value = state.fixedDepositAccountDetail.externalId, onValueChange = { @@ -172,5 +162,4 @@ fun DetailsPage( modifier = Modifier.padding(top = DesignToken.padding.small), ) } - } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/pages/TermsPage.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/pages/TermsPage.kt index 6327f7e4ed6..44246e82094 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/pages/TermsPage.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/newFixedDepositAccount/pages/TermsPage.kt @@ -10,25 +10,180 @@ package com.mifos.feature.client.newFixedDepositAccount.pages import androidclient.feature.client.generated.resources.Res -import androidclient.feature.client.generated.resources.step_terms +import androidclient.feature.client.generated.resources.btn_back +import androidclient.feature.client.generated.resources.feature_client_next +import androidclient.feature.client.generated.resources.feature_fixed_days_in_year +import androidclient.feature.client.generated.resources.feature_fixed_deposit_deposit_amount +import androidclient.feature.client.generated.resources.feature_fixed_deposit_deposit_period +import androidclient.feature.client.generated.resources.feature_fixed_deposit_deposit_period_type +import androidclient.feature.client.generated.resources.feature_fixed_deposit_terms_page +import androidclient.feature.client.generated.resources.feature_fixed_interest_calculated_using +import androidclient.feature.client.generated.resources.feature_fixed_interest_compounding +import androidclient.feature.client.generated.resources.feature_fixed_interest_compounding_period +import androidclient.feature.client.generated.resources.feature_fixed_interest_posting_period import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.material3.Button +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp +import com.mifos.core.designsystem.component.MifosOutlinedTextField +import com.mifos.core.designsystem.component.MifosTextFieldConfig +import com.mifos.core.designsystem.component.MifosTextFieldDropdown +import com.mifos.core.designsystem.theme.DesignToken +import com.mifos.core.designsystem.theme.MifosTypography +import com.mifos.core.ui.components.MifosTwoButtonRow +import com.mifos.feature.client.newFixedDepositAccount.NewFixedDepositAccountAction +import com.mifos.feature.client.newFixedDepositAccount.NewFixedDepositAccountState import org.jetbrains.compose.resources.stringResource @Composable -fun TermsPage(onNext: () -> Unit) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text(stringResource(Res.string.step_terms)) +fun TermsPage( + state: NewFixedDepositAccountState, + onAction: (NewFixedDepositAccountAction) -> Unit, +) { + Column( + modifier = Modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + modifier = Modifier.align(Alignment.Start), + text = stringResource(Res.string.feature_fixed_deposit_terms_page), + style = MifosTypography.labelLargeEmphasized, + ) Spacer(Modifier.height(8.dp)) - Button(onClick = onNext) { - Text("Next Button") - } + MifosOutlinedTextField( + value = state.fixedDepositAccountTerms.depositAmount, + onValueChange = { onAction(NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositAmount(it)) }, + label = stringResource(Res.string.feature_fixed_deposit_deposit_amount), + config = MifosTextFieldConfig( + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number, + imeAction = ImeAction.Next, + ), + prefix = { + Text(state.template.currency?.displaySymbol.orEmpty()) + }, + ), + modifier = Modifier.fillMaxWidth(), + ) + MifosOutlinedTextField( + value = state.fixedDepositAccountTerms.depositPeriod, + onValueChange = { onAction(NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositPeriod(it)) }, + label = stringResource(Res.string.feature_fixed_deposit_deposit_period), + config = MifosTextFieldConfig( + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number, + imeAction = ImeAction.Next, + ), + ), + modifier = Modifier.fillMaxWidth(), + ) + MifosTextFieldDropdown( + value = if (state.fixedDepositAccountTerms.depositPeriodTypeIndex != -1) { + state.template.periodFrequencyTypeOptions?.getOrNull(state.fixedDepositAccountTerms.depositPeriodTypeIndex)?.value.orEmpty() + } else { + "" + }, + options = state.template.periodFrequencyTypeOptions?.map { + it.value.orEmpty() + } ?: emptyList(), + onValueChanged = {}, + onOptionSelected = { id, name -> + onAction(NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetFixedDepositPeriodType(id)) + }, + label = stringResource(Res.string.feature_fixed_deposit_deposit_period_type), + modifier = Modifier.fillMaxWidth(), + ) + Text( + modifier = Modifier + .align(Alignment.Start), + text = stringResource(Res.string.feature_fixed_interest_compounding), + style = MifosTypography.labelLargeEmphasized, + ) + Spacer(modifier = Modifier.height(DesignToken.padding.extraSmall)) + MifosTextFieldDropdown( + value = if (state.fixedDepositAccountTerms.interestCompoundingPeriodTypeIndex != -1) { + state.template.interestCompoundingPeriodTypeOptions?.getOrNull(state.fixedDepositAccountTerms.interestCompoundingPeriodTypeIndex)?.value.orEmpty() + } else { + "" + }, + options = state.template.interestCompoundingPeriodTypeOptions?.map { + it.value.orEmpty() + } ?: emptyList(), + onValueChanged = {}, + onOptionSelected = { id, name -> + onAction(NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCompoundingPeriod(id)) + }, + label = stringResource(Res.string.feature_fixed_interest_compounding_period), + modifier = Modifier.fillMaxWidth(), + ) + MifosTextFieldDropdown( + value = if (state.fixedDepositAccountTerms.interestPostingPeriodTypeIndex != -1) { + state.template.interestPostingPeriodTypeOptions?.getOrNull(state.fixedDepositAccountTerms.interestPostingPeriodTypeIndex)?.value.orEmpty() + } else { + "" + }, + options = state.template.interestPostingPeriodTypeOptions?.map { + it.value.orEmpty() + } ?: emptyList(), + onValueChanged = {}, + onOptionSelected = { id, name -> + onAction(NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestPostingPeriod(id)) + }, + label = stringResource(Res.string.feature_fixed_interest_posting_period), + modifier = Modifier.fillMaxWidth(), + ) + MifosTextFieldDropdown( + value = if (state.fixedDepositAccountTerms.interestCalculationTypeIndex != -1) { + state.template.interestCalculationTypeOptions?.getOrNull(state.fixedDepositAccountTerms.interestCalculationTypeIndex)?.value.orEmpty() + } else { + "" + }, + options = state.template.interestCalculationTypeOptions?.map { + it.value.orEmpty() + } ?: emptyList(), + onValueChanged = {}, + onOptionSelected = { id, name -> + onAction(NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCalculationType(id)) + }, + label = stringResource(Res.string.feature_fixed_interest_calculated_using), + modifier = Modifier.fillMaxWidth(), + ) + MifosTextFieldDropdown( + value = if (state.fixedDepositAccountTerms.interestCalculationDaysInYearTypeIndex != -1) { + state.template.interestCalculationDaysInYearTypeOptions?.getOrNull(state.fixedDepositAccountTerms.interestCalculationDaysInYearTypeIndex)?.value.orEmpty() + } else { + "" + }, + options = state.template.interestCalculationDaysInYearTypeOptions?.map { + it.value.orEmpty() + } ?: emptyList(), + onValueChanged = {}, + onOptionSelected = { id, name -> + onAction(NewFixedDepositAccountAction.NewFixedDepositAccountTermsAction.SetInterestCalculationDaysInYearType(id)) + }, + label = stringResource(Res.string.feature_fixed_days_in_year), + modifier = Modifier.fillMaxWidth(), + ) + MifosTwoButtonRow( + firstBtnText = stringResource(Res.string.btn_back), + secondBtnText = stringResource(Res.string.feature_client_next), + onFirstBtnClick = { onAction(NewFixedDepositAccountAction.NavigateBack) }, + onSecondBtnClick = { onAction(NewFixedDepositAccountAction.OnNextPress) }, + isButtonIconVisible = true, + isSecondButtonEnabled = state.fixedDepositAccountTerms.isTermsNextEnabled, + ) } }