Skip to content

Implemented Export Dialog Box in Transaction Screen#2606

Closed
gurnoorpannu wants to merge 23 commits intoopenMF:developmentfrom
gurnoorpannu:feature/loan-transactions-export-dialog
Closed

Implemented Export Dialog Box in Transaction Screen#2606
gurnoorpannu wants to merge 23 commits intoopenMF:developmentfrom
gurnoorpannu:feature/loan-transactions-export-dialog

Conversation

@gurnoorpannu
Copy link
Contributor

@gurnoorpannu gurnoorpannu commented Feb 10, 2026

Fixes - Jira-#657

Before:-
image

After:-

image

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Run the static analysis check ./gradlew check or ci-prepush.sh to make sure you didn't break anything

  • If you have multiple commits please combine them into one commit by squashing them.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added export functionality for loan transactions with customizable date range selection
    • Added transaction report generation capability
    • Added validation for invalid date ranges during export

@coderabbitai
Copy link

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

This PR introduces a state/action-driven architecture for loan account summary, replacing the callback-heavy UI state pattern. It adds export transaction functionality with date range selection, removes the sealed LoanAccountSummaryUiState class, refactors the ViewModel to inherit from BaseViewModel, and introduces new UI strings and dialog components for managing loan exports.

Changes

Cohort / File(s) Summary
String Resources
feature/loan/src/commonMain/composeResources/values/strings.xml
Added six new string resources for loan export UI: feature_loan_export, feature_loan_export_transactions, feature_loan_from_date, feature_loan_to_date, feature_loan_generate_report, feature_loan_invalid_date_range.
Loan Account Summary Architecture
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt, LoanAccountSummaryScreenRoute.kt
Refactored screen composition from UI-state callbacks to state/action-driven pattern. LoanAccountSummaryScreen now consumes LoanAccountSummaryState and onAction handler instead of multiple callbacks. LoanAccountSummaryScreenRoute updated with new onNavigateBack parameter.
ViewModel State Management
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryViewModel.kt
Migrated from standard ViewModel to BaseViewModel<LoanAccountSummaryState, LoanAccountSummaryEvent, LoanAccountSummaryAction>. Introduced centralized state object, action handler (handleAction), new sealed types for events/actions, and currency/date formatting logic integrated into state. Visibility changed to internal.
Removed UI State Definition
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryUiState.kt
Deleted sealed class LoanAccountSummaryUiState and nested variants (ShowProgressbar, ShowFetchingError, ShowLoanById), replaced by unified LoanAccountSummaryState.
Export Transaction Dialog
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt
New internal composable providing date-range selection UI for exporting loan transactions. Includes two date pickers with validation logic (ensuring fromDate ≤ toDate), cancel/generate action buttons, and error messaging for invalid ranges.
Loan Transactions Screen
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/LoanTransactionsScreen.kt
Added export icon button in scaffold actions that triggers ExportTransactionsDialog. Placeholder onGenerateReport callback with TODO comment; integration incomplete.

Sequence Diagram

sequenceDiagram
    participant User
    participant LoanTransactionsScreen
    participant ExportTransactionsDialog
    participant DatePicker
    participant ViewModel

    User->>LoanTransactionsScreen: Clicks Export Icon
    LoanTransactionsScreen->>ExportTransactionsDialog: Show Dialog
    User->>ExportTransactionsDialog: Taps From Date Field
    ExportTransactionsDialog->>DatePicker: Open From Date Picker
    User->>DatePicker: Select Date
    DatePicker->>ExportTransactionsDialog: Confirm (fromDate: Long)
    User->>ExportTransactionsDialog: Taps To Date Field
    ExportTransactionsDialog->>DatePicker: Open To Date Picker
    User->>DatePicker: Select Date
    DatePicker->>ExportTransactionsDialog: Confirm (toDate: Long)
    User->>ExportTransactionsDialog: Clicks Generate Report
    alt Valid Date Range
        ExportTransactionsDialog->>ViewModel: onGenerateReport(fromDate, toDate)
        ViewModel->>ViewModel: Process Export
    else Invalid Date Range
        ExportTransactionsDialog->>ExportTransactionsDialog: Show Error Message
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • itsPronay
  • biplab1
  • TheKalpeshPawar

Poem

🐰 A rabbit refactored the loan display with care,
State and actions now flowing through the air,
Date pickers emerged for exports so fine,
From scattered callbacks to patterns divine,
The architecture hops forward—a well-structured design! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature addition: an export dialog box in the transaction screen, which aligns with the core changes across files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt`:
- Around line 640-659: The composable function name LoadAccountSummaryDialog is
misspelled and should be LoanAccountSummaryDialog; rename the function
declaration (LoadAccountSummaryDialog -> LoanAccountSummaryDialog) and update
every call site (e.g., the route composable that references it) to use the
corrected symbol so references match, then rebuild to ensure imports and usages
(function name, any lambda parameters) are updated accordingly.
- Around line 272-277: The statusDescription uses hardcoded English strings in
LoanAccountSummaryScreen (val statusDescription) which breaks i18n; replace
those literals with stringResource lookups (e.g.,
stringResource(R.string.loan_status_active),
stringResource(R.string.loan_status_pending_approval),
stringResource(R.string.loan_status_waiting_for_disbursal),
stringResource(R.string.loan_status_closed)), add the corresponding string
resources in XML/strings files for translations, and ensure the composable
imports androidx.compose.ui.res.stringResource so the semantics
contentDescription uses localized text derived from
loanWithAssociations.status.active / pendingApproval / waitingForDisbursal
checks.
🧹 Nitpick comments (7)
feature/loan/src/commonMain/composeResources/values/strings.xml (1)

297-298: Duplicate string values: feature_loan_export and feature_loan_export_transactions are both "Export".

These two resources resolve to the same text. If they serve different semantic purposes (e.g., icon content description vs. dialog title), consider giving them distinct values to aid translators and accessibility. Otherwise, consolidate into a single resource.

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt (3)

200-209: Dead code: the !isValidDateRange guard inside onClick is unreachable.

The button is already enabled = isValidDateRange (Line 209), so onClick can never fire when the range is invalid. The early-return block on lines 202-204 is dead code.

♻️ Simplify the onClick handler
 MifosButton(
     onClick = {
-        if (!isValidDateRange) {
-            showInvalidDateRangeError = true
-            return@MifosButton
-        }
-        showInvalidDateRangeError = false
         onGenerateReport(fromDate!!, toDate!!)
     },
     enabled = isValidDateRange,
     modifier = Modifier.weight(1f),
 ) {

225-233: formatDateFromMillis is marked @Composable but uses no Compose APIs.

This unnecessarily restricts where the function can be called. Remove the @Composable annotation.

♻️ Remove unnecessary `@Composable` annotation
 `@OptIn`(ExperimentalTime::class)
-@Composable
 private fun formatDateFromMillis(millis: Long?): String {

72-78: showInvalidDateRangeError uses remember while sibling state variables use rememberSaveable.

This is inconsistent—on configuration change, showInvalidDateRangeError resets to false while the date selections survive. This is likely acceptable since the error is transient, but worth noting the inconsistency. If intentional, no change needed.

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryViewModel.kt (2)

124-131: Error details from DataState.Error are discarded.

dataState likely contains exception/message information, but only a generic "unknown error" string is shown. Consider using the actual error message when available for better user feedback and debugging.

♻️ Use the actual error message with fallback
 is DataState.Error -> {
-    val errorMessage = getString(Res.string.feature_loan_unknown_error_occured)
+    val errorMessage = dataState.exception.message
+        ?: getString(Res.string.feature_loan_unknown_error_occured)
     mutableStateFlow.update {
         it.copy(
             dialogState = LoanAccountSummaryState.DialogState.Error(errorMessage),
         )
     }
 }

288-297: getPrimaryAction() silently defaults unknown/null statuses to CLOSED.

If a new loan status is introduced or all status flags are false/null, the function returns CLOSED, which disables the action button. This is a safe default, but consider logging a warning in the else branch to aid debugging.

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt (1)

220-231: Unused lambda parameter in let block.

state.loanWithAssociations?.let { loanWithAssociations -> ... } introduces loanWithAssociations but the content composable (LoanAccountSummaryContent) receives state directly—so the let parameter is only used as a null-guard. Consider using ?.let { ... } without naming the parameter, or just use an if check.

♻️ Simplify the null check
-                state.loanWithAssociations?.let { loanWithAssociations ->
-                    LoanAccountSummaryContent(
-                        state = state,
-                        onAction = onAction,
-                    )
-                }
+                if (state.loanWithAssociations != null) {
+                    LoanAccountSummaryContent(
+                        state = state,
+                        onAction = onAction,
+                    )
+                }

Comment on lines +272 to +277
val statusDescription = when {
loanWithAssociations.status.active == true -> "Active"
loanWithAssociations.status.pendingApproval == true -> "Pending Approval"
loanWithAssociations.status.waitingForDisbursal == true -> "Waiting for Disbursal"
else -> "Closed"
}
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

Hardcoded English strings in status description break i18n/l10n.

The status descriptions ("Active", "Pending Approval", "Waiting for Disbursal", "Closed") are used in a semantics content description but are not backed by string resources. This will not be localized for non-English users, degrading accessibility.

♻️ Use string resources for status descriptions

Consider defining string resources for these status labels and referencing them via stringResource(...), similar to other UI text in this file.

🤖 Prompt for AI Agents
In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt`
around lines 272 - 277, The statusDescription uses hardcoded English strings in
LoanAccountSummaryScreen (val statusDescription) which breaks i18n; replace
those literals with stringResource lookups (e.g.,
stringResource(R.string.loan_status_active),
stringResource(R.string.loan_status_pending_approval),
stringResource(R.string.loan_status_waiting_for_disbursal),
stringResource(R.string.loan_status_closed)), add the corresponding string
resources in XML/strings files for translations, and ensure the composable
imports androidx.compose.ui.res.stringResource so the semantics
contentDescription uses localized text derived from
loanWithAssociations.status.active / pendingApproval / waitingForDisbursal
checks.

Comment on lines 640 to 659
@Composable
fun getButtonText(status: LoanStatusEntity): String {
return when {
status.active == true || status.closedObligationsMet == true -> {
stringResource(Res.string.feature_loan_make_Repayment)
}

status.pendingApproval == true -> {
stringResource(Res.string.feature_loan_approve_loan)
}

status.waitingForDisbursal == true -> {
stringResource(Res.string.feature_loan_disburse_loan)
private fun LoadAccountSummaryDialog(
dialogState: LoanAccountSummaryState.DialogState?,
onAction: (LoanAccountSummaryAction) -> Unit,
) {
when (dialogState) {
is LoanAccountSummaryState.DialogState.Error -> {
MifosSweetError(
message = dialogState.message,
onclick = { onAction(LoanAccountSummaryAction.OnRetry) },
)
}

status.overpaid == true -> {
stringResource(Res.string.feature_loan_overpaid)
LoanAccountSummaryState.DialogState.Loading -> {
MifosProgressIndicator()
}

else -> {
stringResource(Res.string.feature_loan_closed)
}
null -> Unit
}
}
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

LoadAccountSummaryDialog has a typo in the function name.

Should be LoanAccountSummaryDialog (missing the "n" in "Loan"). This is referenced both here (Line 641) and in the route composable (Line 181).

🤖 Prompt for AI Agents
In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt`
around lines 640 - 659, The composable function name LoadAccountSummaryDialog is
misspelled and should be LoanAccountSummaryDialog; rename the function
declaration (LoadAccountSummaryDialog -> LoanAccountSummaryDialog) and update
every call site (e.g., the route composable that references it) to use the
corrected symbol so references match, then rebuild to ensure imports and usages
(function name, any lambda parameters) are updated accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants