-
Notifications
You must be signed in to change notification settings - Fork 698
fix: Loan repayment calendar showing wrong dates and status (MIFOSAC-705) #2618
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| /* | ||
| * 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.domain.useCases | ||
|
|
||
| import com.mifos.core.common.utils.DataState | ||
| import com.mifos.core.data.repository.LoanAccountRepository | ||
| import com.mifos.core.model.objects.account.loan.RepaymentSchedule | ||
| import com.mifos.core.network.model.LoansPayload | ||
| import kotlinx.coroutines.flow.Flow | ||
|
|
||
| /** | ||
| * Use case to calculate loan repayment schedule without creating the loan. | ||
| * This is used to preview the schedule before submitting the loan application. | ||
| */ | ||
| class CalculateLoanScheduleUseCase( | ||
| private val loanAccountRepository: LoanAccountRepository, | ||
| ) { | ||
|
|
||
| operator fun invoke(loansPayload: LoansPayload): Flow<DataState<RepaymentSchedule>> = | ||
| loanAccountRepository.calculateLoanSchedule(loansPayload) | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ package com.mifos.core.network.datamanager | |||||||||||||||||||||||||
| import com.mifos.core.common.utils.extractErrorMessage | ||||||||||||||||||||||||||
| import com.mifos.core.datastore.UserPreferencesRepository | ||||||||||||||||||||||||||
| import com.mifos.core.model.objects.account.loan.LoanDisbursement | ||||||||||||||||||||||||||
| import com.mifos.core.model.objects.account.loan.RepaymentSchedule | ||||||||||||||||||||||||||
| import com.mifos.core.network.BaseApiManager | ||||||||||||||||||||||||||
| import com.mifos.core.network.GenericResponse | ||||||||||||||||||||||||||
| import com.mifos.core.network.model.LoansPayload | ||||||||||||||||||||||||||
|
|
@@ -24,13 +25,15 @@ import com.mifos.room.entities.templates.loans.LoanTemplate | |||||||||||||||||||||||||
| import com.mifos.room.entities.templates.loans.LoanTransactionTemplate | ||||||||||||||||||||||||||
| import com.mifos.room.helper.LoanDaoHelper | ||||||||||||||||||||||||||
| import io.ktor.client.statement.HttpResponse | ||||||||||||||||||||||||||
| import io.ktor.client.statement.bodyAsText | ||||||||||||||||||||||||||
| import io.ktor.http.isSuccess | ||||||||||||||||||||||||||
| import kotlinx.coroutines.ExperimentalCoroutinesApi | ||||||||||||||||||||||||||
| import kotlinx.coroutines.flow.Flow | ||||||||||||||||||||||||||
| import kotlinx.coroutines.flow.first | ||||||||||||||||||||||||||
| 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 15/07/16. | ||||||||||||||||||||||||||
|
|
@@ -291,4 +294,23 @@ class DataManagerLoan( | |||||||||||||||||||||||||
| ): Flow<GenericResponse> { | ||||||||||||||||||||||||||
| return mBaseApiManager.loanService.disburseLoan(loanId, loanDisbursement) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||
| * Calculate loan repayment schedule without creating the loan. | ||||||||||||||||||||||||||
| * Used to preview the schedule before submitting the loan application. | ||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||
| * @param loansPayload The loan parameters to calculate the schedule for | ||||||||||||||||||||||||||
| * @return LoanWithAssociationsEntity containing the calculated repayment schedule | ||||||||||||||||||||||||||
|
Comment on lines
+298
to
+303
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. KDoc - * `@return` LoanWithAssociationsEntity containing the calculated repayment schedule
+ * `@return` RepaymentSchedule containing the calculated repayment schedule📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||
| fun calculateLoanSchedule(loansPayload: LoansPayload): Flow<RepaymentSchedule> { | ||||||||||||||||||||||||||
| return mBaseApiManager.loanService.calculateLoanSchedule(loansPayload).map { response -> | ||||||||||||||||||||||||||
| if (!response.status.isSuccess()) { | ||||||||||||||||||||||||||
| val errorMessage = extractErrorMessage(response) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| throw IllegalStateException(errorMessage) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Json { ignoreUnknownKeys = true }.decodeFromString<RepaymentSchedule>(response.bodyAsText()) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: openMF/android-client
Length of output: 705
🏁 Script executed:
Repository: openMF/android-client
Length of output: 35017
🏁 Script executed:
Repository: openMF/android-client
Length of output: 4026
🏁 Script executed:
Repository: openMF/android-client
Length of output: 656
🏁 Script executed:
Repository: openMF/android-client
Length of output: 252
🏁 Script executed:
Repository: openMF/android-client
Length of output: 808
🏁 Script executed:
Repository: openMF/android-client
Length of output: 203
Verify API contract ensures integer format for decimalPlaces field.
Changing
decimalPlacesfromDouble?toInt?is semantically correct — decimal-place counts must be integers. This is the right type. However, one critical verification remains:With
kotlinx.serialization, deserializing a JSON float literal ("decimalPlaces": 2.0) intoInt?throwsJsonDecodingExceptionat runtime. If the Mifos API ever emits float-formatted values for this field, the app will crash during response parsing. Confirm the API contract always returns an integer literal (not2.0).Downstream callers all expect
Int?formaximumFractionDigitsand passdecimalPlacesdirectly without transformation—no compilation issues. However, note that other Currency classes in the codebase (template/loan/Currency.kt,template/client/Currency.kt) still useDouble?for the same field, creating inconsistency across the domain model.🤖 Prompt for AI Agents