Skip to content

feat(loan): implement loan disburse screen - #2700

Merged
revanthkumarJ merged 3 commits into
openMF:devfrom
sahilshivekar:disburse-screen
Jul 22, 2026
Merged

feat(loan): implement loan disburse screen#2700
revanthkumarJ merged 3 commits into
openMF:devfrom
sahilshivekar:disburse-screen

Conversation

@sahilshivekar

Copy link
Copy Markdown
Contributor

Fixes - Jira-#681

Before

(Clicking on the Disburse option doesn't open the disburse screen as it wasn't implemented)
Screenshot 2026-07-21 225521

After

loan_disburse_success.mp4

@sahilshivekar
sahilshivekar requested a review from a team July 21, 2026 17:46
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e55dc3b8-d214-4f98-86ab-c43de5c7b580

📥 Commits

Reviewing files that changed from the base of the PR and between dc84165 and 6df9a30.

📒 Files selected for processing (4)
  • feature/loan/src/commonMain/composeResources/values-es/strings.xml
  • feature/loan/src/commonMain/composeResources/values/strings.xml
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
💤 Files with no reviewable changes (1)
  • feature/loan/src/commonMain/composeResources/values-es/strings.xml
🚧 Files skipped from review as they are similar to previous changes (1)
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
📜 Recent review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: PR Checks / Static Analysis Check
🧰 Additional context used
📓 Path-based instructions (3)
**/*Screen.kt

⚙️ CodeRabbit configuration file

**/*Screen.kt: Screen architecture rules:

Each screen must follow a 2-layer structure:

  1. Layer 1 (Entry/Route Composable):

    • Function Name: Typically *ScreenRoute or the entry-point composable.
    • Responsibilities: Inject ViewModel (e.g., koinViewModel), take navigation lambdas, collect the StateFlow, and handle ViewModel events.
    • Logic: Should only handle ViewModel interaction, state collection, and triggering navigation in response to ViewModel events.
  2. Layer 2 (Stateful/Content Composable — *Screen or *ScreenContent):

    • Parameters: MUST only take state (the UI state object) and a single onAction lambda (e.g., onAction: (FeatureAction) -> Unit).
    • Responsibilities: Render the UI based strictly on the provided state.
    • Rule: MUST NOT pass multiple separate lambda functions for different UI interactions; consolidate them into the single onAction.
    • Constraint: Must NOT contain any business logic or ViewModel/Navigation references.

Internal/private helper composables (e.g., dialogs, sections, sub-components):

  • These are NOT subject to the single onAction rule.
  • They may accept specific, focused lambdas (e.g., onRetry: () -> Unit) or a narrowed onAction as appropriate.
  • However, they must NOT be passed the ViewModel or navigation controllers directly.

UI consistency:

  • Avoid hardcoded values (dp, sp, padding, fontSize, colors)
  • Use DesignToken, KptTheme, AppColors, MifosTypography for spacing, typography, and colors

Code quality:

  • Keep Composables small and readable
  • Avoid deeply nested UI

Flag:

  • Missing Layer 2 (*Screen/*ScreenContent) separation from the entry-point composable
  • Layer 2 (*Screen/*ScreenContent) receiving multiple separate lambdas instead of a single onAction
  • UI logic inside the entry-point composable
  • Business logic inside any Composable
  • Hardcoded strings instead of using string resources
  • Hardcoded dp/sp values
  • Direct styling instead of using DesignToken or KptTheme

Files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt
**/*.kt

⚙️ CodeRabbit configuration file

**/*.kt: Additional Code Review Guidelines:

  1. Null Safety & Stability
  • Avoid using !! operator
  • Handle null cases explicitly using safe calls or proper state handling
  • Do not assume values are always non-null without guarantees
  1. Architecture Boundaries
  • ViewModel must not depend on specific network/library implementations
  • Ensure proper separation between data, domain, and presentation layers
  • Do not format data (currency, dates, calculations) inside the UI layer
  • All formatting must be handled in the ViewModel and exposed via state (e.g., StateFlow)
  1. Performance Considerations
  • Avoid unnecessary recompositions in Compose
  • Do not attach heavy logic to frequently changing states (e.g., scrollState)
  • Prefer lifting state up instead of recomputing in child composables
  1. Compose & Navigation Best Practices
  • NEVER trigger navigation functions or side-effects directly during composition
  • Always wrap navigation calls inside LaunchedEffect or EventsEffect to avoid repeated execution on recomposition
  • Avoid triggering intensive side-effects during recomposition
  • Navigation routes must be type-safe.
  • Ensure all route classes or objects used for navigation are annotated with @Serializable.
  1. UI Structure
  • Dialogs must be separated into their own composables
  • Do not embed dialogs inline within complex main screens
  1. Localization Consistency
  • Ensure all supported languages are updated consistently across modules
  • Verify translations exist for newly added UI strings
  1. Code Cleanliness
  • Avoid unnecessary inline comments unless critical
  • Remove leftover debug or commented code
  1. Focus on correctness, readability, and maintainability over cosmetic nitpicks.
  • Avoid reviewing README, config, or asset files.
  • Prioritize identifying bugs, performance issues, and architectural concerns.
  1. Naming & Intent Rules:

Files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt
**/composeResources/values*/strings.xml

⚙️ CodeRabbit configuration file

**/composeResources/values*/strings.xml: String resource conventions:

Naming:

  • All keys must follow:
    feature_{feature_name}_{ui_text_in_snake_case}

Examples:
"In Advance" → feature_loan_in_advance
"Outstanding" → feature_loan_outstanding

  • Avoid generic names like: title, text1, label
  • The suffix should be a short, readable representation of the UI text
  • Avoid multiple keys representing the same UI text
  • Keys must be lowercase and use snake_case

Flag:

  • Incorrect naming pattern
  • Generic or unclear key names
  • Duplicate keys for same UI text

Files:

  • feature/loan/src/commonMain/composeResources/values/strings.xml
🧠 Learnings (3)
📚 Learning: 2026-02-06T13:15:16.968Z
Learnt from: sahilshivekar
Repo: openMF/android-client PR: 2603
File: feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/LoanTransactionsViewModel.kt:43-106
Timestamp: 2026-02-06T13:15:16.968Z
Learning: Guideline: When a Kotlin function parameter is nullable (e.g., balance: Double?, currencyCode: String?, maximumFractionDigits: Int?) and downstream calls require a non-null value, add null-safety handling in all implementations. Specifically, avoid calling Currency.getInstance(currencyCode) with a possibly null currencyCode; provide a safe default (e.g., currencyCode ?: "$") or validate before use. Ensure all platform targets (Android/Desktop/Native) follow consistent null handling, and consider centralizing currencyCode normalization in the common layer if feasible. Add tests covering null currencyCode to prevent NPEs.

Applied to files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt
📚 Learning: 2026-04-01T05:03:14.323Z
Learnt from: kartikey004
Repo: openMF/mifos-x-field-officer-app PR: 2659
File: feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementScreen.kt:190-195
Timestamp: 2026-04-01T05:03:14.323Z
Learning: In this repo, existing `SelectableDates` / `SelectableDates.isSelectableDate(utcTimeMillis: Long)` implementations use `Clock.System.now().toEpochMilliseconds()` (UTC epoch millis) for date-boundary checks. During PR reviews, do not flag these checks for not using a timezone-aware `LocalDate` start-of-day approach; treat it as an established project-wide pattern. If a change is desired, handle it as a coordinated project-wide improvement rather than as a per-PR review issue.

Applied to files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt
📚 Learning: 2026-07-08T13:55:15.322Z
Learnt from: sahilshivekar
Repo: openMF/mifos-x-field-officer-app PR: 2698
File: feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/createGuarantor/CreateGuarantorViewModel.kt:366-397
Timestamp: 2026-07-08T13:55:15.322Z
Learning: In Kotlin ViewModels (e.g., using `mutableStateFlow` + `collect {}` to handle async results), it’s acceptable to directly update a single piece of state (and call `sendEvent`) inside the `collect {}` block for simple cases (e.g., updating one property like `searchedClientOptions`). Reserve the internal-action/reducer pattern (`sendAction(...)` + `handleAction`) for async results that affect multiple properties and/or require more complex state transitions, to avoid unnecessary ceremony for trivial cases.

Applied to files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryScreen.kt
🔇 Additional comments (3)
feature/loan/src/commonMain/composeResources/values/strings.xml (2)

720-722: Reuse the existing transaction amount resource.

feature_loan_disburse_transaction_amount has the same text as feature_loan_transaction_amount at Line 85. Remove the duplicate and update its call site to use the existing key, so translators maintain one resource per UI string.

As per path instructions, avoid multiple keys representing the same UI text.

Source: Path instructions


90-92: LGTM!

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

21-21: LGTM!

Also applies to: 424-424


Summary by CodeRabbit

  • New Features
    • Added a template-based loan disbursement flow, including constrained date selection, transaction amount validation, payment type selection, optional payment details, and success/failure feedback (including template-load failure messaging).
    • Updated navigation so the Disburse action takes users to the new loan disbursement screen.
  • Bug Fixes
    • Loan account balance and arrears now show an em dash when summary values are unavailable.
  • Refactor
    • Replaced the previous disbursement request/response handling and legacy disbursement UI with the new template + disbursement flow.

Walkthrough

The loan disbursement flow now uses new network, data, domain, and feature-layer contracts. A Compose form loads templates, validates and submits disbursement details, and integrates with typed loan navigation.

Changes

Loan disbursement flow

View checkpoints
Layer / File(s) Summary
Network disbursement contracts
core/network/...
New serializable DTOs and service methods replace the previous disbursement API contract.
Data and domain pipeline
core/data/..., core/domain/..., core/model/...
Models, mappers, repository operations, implementations, use cases, and Koin bindings carry template and submission data through DataState.
Disbursement state and form
loanDisburse/..., strings.xml
A new ViewModel and Compose UI manage template loading, payment details, amount validation, submission, and feedback states.
Navigation and account integration
LoanNavigation.kt, LoanDisburseNavigation.kt
Loan actions open the typed disbursement route, successful submission reloads the account action destination, and nullable balance and arrears values display safely.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LoanAccount
  participant LoanNavigation
  participant LoanDisburseScreen
  participant LoanDisburseViewModel
  participant LoanDisburseRepositoryImpl
  LoanAccount->>LoanNavigation: select Disburse(loanId)
  LoanNavigation->>LoanDisburseScreen: navigate with LoanDisburseRoute
  LoanDisburseScreen->>LoanDisburseViewModel: load template
  LoanDisburseViewModel->>LoanDisburseRepositoryImpl: getDisburseTemplate(loanId)
  LoanDisburseScreen->>LoanDisburseViewModel: submit form
  LoanDisburseViewModel->>LoanDisburseRepositoryImpl: disburse(loanId, LoanDisburseInput)
  LoanDisburseViewModel-->>LoanDisburseScreen: show result dialog
  LoanDisburseScreen-->>LoanNavigation: notify success
Loading

Possibly related PRs

Related pull requests

Suggested reviewers: revanthkumarj

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required commit-message format and clearly matches the loan disbursement screen changes.
Description check ✅ Passed The description is directly related to the PR and explains the disburse screen fix and its before/after behavior.
Jira Link And Before/After Sections ✅ Passed PR description includes a Jira URL plus non-empty Before/After media sections (image and video link).
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

revanthkumarJ
revanthkumarJ previously approved these changes Jul 21, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt (1)

192-197: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mixed design-token systems: KptTheme.spacing.md alongside DesignToken.spacing.*.

Every other spacing/padding call in this file uses DesignToken; this one lone use of KptTheme (from the base template package) is inconsistent and risks a visually mismatched scale.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt`
around lines 192 - 197, Update the Column modifier in LoanDisburseScreen to
replace KptTheme.spacing.md with the corresponding DesignToken spacing value,
matching the spacing token system used throughout the rest of the file.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@feature/loan/src/commonMain/composeResources/values/strings.xml`:
- Around line 728-744: Remove the duplicate resources feature_loan_disburse,
feature_loan_disburse_transaction_amount, and
feature_loan_disburse_payment_type, and update their call sites to reuse the
existing feature_loan_disburse_loan, feature_loan_transaction_amount, and
feature_loan_payment_type keys. Keep the displayed text unchanged and avoid
introducing parallel keys in the strings resources.

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileScreen.kt`:
- Around line 240-245: Move the CurrencyFormatter.format calls for balance and
arrears out of the composable in LoanAccountProfileScreen and into the
corresponding ViewModel or mapper. Expose the pre-formatted values through the
screen state model, then have the composable render those state properties
directly while preserving the existing "—" fallback.

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt`:
- Around line 278-283: Replace the hardcoded "Note" label in the
MifosOutlinedTextField used by LoanDisburseScreen with
stringResource(Res.string.feature_loan_disburse_note), and add the corresponding
feature_loan_disburse_note entry to strings.xml so the field is localized
consistently with the other screen labels.
- Around line 206-224: Update the transaction amount state flow used by
LoanDisburseScreen and its ViewModel so it preserves the raw text, including
empty or otherwise invalid intermediate input, instead of only accepting values
parsed by toDoubleOrNull(). Make LoanDisburseAction.TransactionAmountChanged
carry the raw value, update the displayed text from that state, and validate or
derive the Double separately while setting transactionAmountError for empty or
invalid input.

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseViewModel.kt`:
- Around line 89-101: Update the Success branch of the template-loading flow to
clamp the existing disbursed date against minDate before updating state. Use
that same clamped value for both disbursedDate and disbursedDateText, while
preserving the existing minDisbursementDate assignment and other
LoanDisburseState fields.

---

Nitpick comments:
In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt`:
- Around line 192-197: Update the Column modifier in LoanDisburseScreen to
replace KptTheme.spacing.md with the corresponding DesignToken spacing value,
matching the spacing token system used throughout the rest of the file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: afe26685-029e-4c63-a8b9-a313e707f404

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa9041 and 221c9ef.

📒 Files selected for processing (34)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/CurrencyMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/PaymentTypeMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/LoanDisburseMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanAccountDisbursementRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanDisburseRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanAccountDisbursementRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanDisburseRepositoryImpl.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/GetLoanDisburseTemplateUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/LoanDisburseUseCase.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/LoanDisbursement.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseInput.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseTemplate.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/CurrencyDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/PaymentTypeOptionDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseResponseDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • feature/loan/src/commonMain/composeResources/values/strings.xml
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/di/LoanModule.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountAction/LoanAccountActionNavigation.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseNavigation.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementUiState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanDisbursementScreenRoute.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
💤 Files with no reviewable changes (7)
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementUiState.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/LoanDisbursement.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanAccountDisbursementRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanAccountDisbursementRepositoryImp.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanDisbursementScreenRoute.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementScreen.kt
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: PR Checks / Static Analysis Check
🧰 Additional context used
📓 Path-based instructions (11)
**/data/mappers/**/*.kt

⚙️ CodeRabbit configuration file

**/data/mappers/**/*.kt: Mapper Consistency Rules (:core:data:mappers):

  • All mapping logic MUST be centralized in this directory.
  • Allowed mappings:
    1. DTO -> Domain Model
    2. Entity <-> Domain Model
  • Flag: Any mapper functions found in any module outside of :core:data:mappers.

Files:

  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/PaymentTypeMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/CurrencyMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/LoanDisburseMapper.kt
**/{core-base,core}/**/*.kt

⚙️ CodeRabbit configuration file

**/{core-base,core}/**/*.kt: Critical Module Change Detection:

  • Changes in core-base module must be treated as high-impact.
  • Flag any PR that modifies files inside core-base for careful review.
  • Verify that modifications in core-base are necessary and minimal.
    Output:
  • Clearly highlight that core-base is a shared foundational module and requires extra review attention.

Files:

  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/PaymentTypeMapper.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/CurrencyDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/GetLoanDisburseTemplateUseCase.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/CurrencyMapper.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseTemplate.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/PaymentTypeOptionDto.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/LoanDisburseUseCase.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanDisburseRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/LoanDisburseMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanDisburseRepositoryImpl.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseResponseDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
**/*.kt

⚙️ CodeRabbit configuration file

**/*.kt: Additional Code Review Guidelines:

  1. Null Safety & Stability
  • Avoid using !! operator
  • Handle null cases explicitly using safe calls or proper state handling
  • Do not assume values are always non-null without guarantees
  1. Architecture Boundaries
  • ViewModel must not depend on specific network/library implementations
  • Ensure proper separation between data, domain, and presentation layers
  • Do not format data (currency, dates, calculations) inside the UI layer
  • All formatting must be handled in the ViewModel and exposed via state (e.g., StateFlow)
  1. Performance Considerations
  • Avoid unnecessary recompositions in Compose
  • Do not attach heavy logic to frequently changing states (e.g., scrollState)
  • Prefer lifting state up instead of recomputing in child composables
  1. Compose & Navigation Best Practices
  • NEVER trigger navigation functions or side-effects directly during composition
  • Always wrap navigation calls inside LaunchedEffect or EventsEffect to avoid repeated execution on recomposition
  • Avoid triggering intensive side-effects during recomposition
  • Navigation routes must be type-safe.
  • Ensure all route classes or objects used for navigation are annotated with @Serializable.
  1. UI Structure
  • Dialogs must be separated into their own composables
  • Do not embed dialogs inline within complex main screens
  1. Localization Consistency
  • Ensure all supported languages are updated consistently across modules
  • Verify translations exist for newly added UI strings
  1. Code Cleanliness
  • Avoid unnecessary inline comments unless critical
  • Remove leftover debug or commented code
  1. Focus on correctness, readability, and maintainability over cosmetic nitpicks.
  • Avoid reviewing README, config, or asset files.
  • Prioritize identifying bugs, performance issues, and architectural concerns.
  1. Naming & Intent Rules:

Files:

  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/PaymentTypeMapper.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/CurrencyDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/GetLoanDisburseTemplateUseCase.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/CurrencyMapper.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseTemplate.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/PaymentTypeOptionDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseNavigation.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/LoanDisburseUseCase.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileScreen.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanDisburseRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/LoanDisburseMapper.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/di/LoanModule.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanDisburseRepositoryImpl.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountAction/LoanAccountActionNavigation.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseResponseDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseViewModel.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
**/network/**/*.kt

⚙️ CodeRabbit configuration file

**/network/**/*.kt: Network Layer API Guidelines:

  • One-shot API calls MUST use suspend, return raw response T, and MUST NOT use Flow or DataState.
  • Streaming APIs MUST return Flow<T> and MUST NOT use suspend or DataState.

Files:

  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/CurrencyDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/PaymentTypeOptionDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseResponseDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
**/network/dto/**/*.kt

⚙️ CodeRabbit configuration file

**/network/dto/**/*.kt: DTO Rules (:core:network:dto):

  • Classes here are Data Transfer Objects (DTOs) used strictly for API communication.
  • Rule: DTOs MUST NOT be used in ViewModels, Screens, or the Domain layer.
  • Flag: If a DTO is returned directly by a Repository interface or used in UI state.

Files:

  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/CurrencyDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/PaymentTypeOptionDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseResponseDto.kt
**/composeResources/values*/strings.xml

⚙️ CodeRabbit configuration file

**/composeResources/values*/strings.xml: String resource conventions:

Naming:

  • All keys must follow:
    feature_{feature_name}_{ui_text_in_snake_case}

Examples:
"In Advance" → feature_loan_in_advance
"Outstanding" → feature_loan_outstanding

  • Avoid generic names like: title, text1, label
  • The suffix should be a short, readable representation of the UI text
  • Avoid multiple keys representing the same UI text
  • Keys must be lowercase and use snake_case

Flag:

  • Incorrect naming pattern
  • Generic or unclear key names
  • Duplicate keys for same UI text

Files:

  • feature/loan/src/commonMain/composeResources/values/strings.xml
**/core/model/**/*.kt

⚙️ CodeRabbit configuration file

**/core/model/**/*.kt: Domain Model Rules (:core:model):

  • Classes defined in this module are strictly Domain Models.
  • They must be plain Kotlin data classes.
  • They MUST NOT contain network-specific annotations (e.g., @Serializable) or database-specific annotations (e.g., @Entity).
  • Rule: These are the ONLY models that should be passed to or used within ViewModels and UI Screens.
  • Flag: If a Domain model is used directly as an API request/response body or a Room database table.

Files:

  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseTemplate.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseInput.kt
**/*Screen.kt

⚙️ CodeRabbit configuration file

**/*Screen.kt: Screen architecture rules:

Each screen must follow a 2-layer structure:

  1. Layer 1 (Entry/Route Composable):

    • Function Name: Typically *ScreenRoute or the entry-point composable.
    • Responsibilities: Inject ViewModel (e.g., koinViewModel), take navigation lambdas, collect the StateFlow, and handle ViewModel events.
    • Logic: Should only handle ViewModel interaction, state collection, and triggering navigation in response to ViewModel events.
  2. Layer 2 (Stateful/Content Composable — *Screen or *ScreenContent):

    • Parameters: MUST only take state (the UI state object) and a single onAction lambda (e.g., onAction: (FeatureAction) -> Unit).
    • Responsibilities: Render the UI based strictly on the provided state.
    • Rule: MUST NOT pass multiple separate lambda functions for different UI interactions; consolidate them into the single onAction.
    • Constraint: Must NOT contain any business logic or ViewModel/Navigation references.

Internal/private helper composables (e.g., dialogs, sections, sub-components):

  • These are NOT subject to the single onAction rule.
  • They may accept specific, focused lambdas (e.g., onRetry: () -> Unit) or a narrowed onAction as appropriate.
  • However, they must NOT be passed the ViewModel or navigation controllers directly.

UI consistency:

  • Avoid hardcoded values (dp, sp, padding, fontSize, colors)
  • Use DesignToken, KptTheme, AppColors, MifosTypography for spacing, typography, and colors

Code quality:

  • Keep Composables small and readable
  • Avoid deeply nested UI

Flag:

  • Missing Layer 2 (*Screen/*ScreenContent) separation from the entry-point composable
  • Layer 2 (*Screen/*ScreenContent) receiving multiple separate lambdas instead of a single onAction
  • UI logic inside the entry-point composable
  • Business logic inside any Composable
  • Hardcoded strings instead of using string resources
  • Hardcoded dp/sp values
  • Direct styling instead of using DesignToken or KptTheme

Files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
**/data/repository/**/*.kt

⚙️ CodeRabbit configuration file

**/data/repository/**/*.kt: Repository Interface Guidelines:

  • One-shot operations MUST use suspend fun and return DataState<T>. MUST NOT use Flow.
  • Streaming operations MUST return Flow<DataState<T>> and MUST NOT use suspend.
  • Repository interfaces must consistently return Domain models (from :core:model) wrapped in DataState or Flow.
  • Flag: Any interface method that returns a DTO or an Entity.

Files:

  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanDisburseRepository.kt
**/data/repositoryImp/**/*.kt

⚙️ CodeRabbit configuration file

**/data/repositoryImp/**/*.kt: Repository Implementation Guidelines:

  • MUST convert T -> DataState<T> for one-shot APIs, and Flow<T> -> Flow<DataState<T>> using .asDataStateFlow().
  • MUST perform network availability checks, handle exceptions, and apply appropriate dispatchers.
  • Repositories act as the boundary translator. They MUST use mappers to convert DTOs (from network) and Entities (from database) into Domain Models (from :core:model) before returning data.
  • Flag: If a repository implementation returns a raw DTO or Entity directly to the caller instead of a Domain model.

Files:

  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanDisburseRepositoryImpl.kt
**/*ViewModel.kt

⚙️ CodeRabbit configuration file

**/*ViewModel.kt: MVI architecture rules:

  • All new features must follow MVI
  • ViewModel must extend BaseViewModel
  • The ViewModel MUST maintain a single UI state (e.g., a single StateFlow)
    instead of multiple separate state variables.

Required:

  • Use *State, *Event, *Action
  • Naming must be consistent (FeatureViewModel, FeatureState, FeatureEvent, FeatureAction)
  • Follow unidirectional flow:
    Action → ViewModel → State → UI

Internal reducer/action architecture rules:

  • Async operations MUST NOT directly mutate UI state repeatedly inside
    Flow collectors, suspend callbacks, or repository result handlers.

  • Repository/network/database results MUST be converted into internal
    actions using sendAction(...).

  • handleAction(...) must act as the primary reducer responsible for:

    • state mutation
    • reducer-style state transitions
    • triggering follow-up actions
  • Large async methods must be split into:

    1. async collection layer
    2. internal action dispatching
    3. reducer/state handling
  • Avoid directly calling another business/data-loading method from
    repository collectors or async callbacks.
    Prefer dispatching follow-up internal actions instead.

Preferred pattern:
repository result
-> sendAction(...)
-> handleAction(...)
-> mutableStateFlow.update { ... }

Anti-pattern examples:
mutableStateFlow.update { ... } inside collect { }
fetchX() -> directly calls fetchY() inside async collector
large methods mixing:
- collection
- state mutation
- navigation
- business chaining

Flag:

  • Multiple mutableStateFlow.update {} calls inside collect { }
  • Direct state mutation inside async repository callbacks
  • Async methods performing both collection and reducer logic
  • Direct business-flow chaining from async collectors
  • Missing internal reducer actions for async results
  • Missing *State / *Event / *Action
  • ViewModel not...

Files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseViewModel.kt
🧠 Learnings (5)
📚 Learning: 2026-02-06T13:15:16.968Z
Learnt from: sahilshivekar
Repo: openMF/android-client PR: 2603
File: feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/LoanTransactionsViewModel.kt:43-106
Timestamp: 2026-02-06T13:15:16.968Z
Learning: Guideline: When a Kotlin function parameter is nullable (e.g., balance: Double?, currencyCode: String?, maximumFractionDigits: Int?) and downstream calls require a non-null value, add null-safety handling in all implementations. Specifically, avoid calling Currency.getInstance(currencyCode) with a possibly null currencyCode; provide a safe default (e.g., currencyCode ?: "$") or validate before use. Ensure all platform targets (Android/Desktop/Native) follow consistent null handling, and consider centralizing currencyCode normalization in the common layer if feasible. Add tests covering null currencyCode to prevent NPEs.

Applied to files:

  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/PaymentTypeMapper.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/CurrencyDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/GetLoanDisburseTemplateUseCase.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/CurrencyMapper.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseTemplate.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/PaymentTypeOptionDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseNavigation.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/LoanDisburseUseCase.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileScreen.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanDisburseRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/LoanDisburseMapper.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/di/LoanModule.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanDisburseRepositoryImpl.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountAction/LoanAccountActionNavigation.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseResponseDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseViewModel.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
📚 Learning: 2026-04-01T05:03:14.323Z
Learnt from: kartikey004
Repo: openMF/mifos-x-field-officer-app PR: 2659
File: feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementScreen.kt:190-195
Timestamp: 2026-04-01T05:03:14.323Z
Learning: In this repo, existing `SelectableDates` / `SelectableDates.isSelectableDate(utcTimeMillis: Long)` implementations use `Clock.System.now().toEpochMilliseconds()` (UTC epoch millis) for date-boundary checks. During PR reviews, do not flag these checks for not using a timezone-aware `LocalDate` start-of-day approach; treat it as an established project-wide pattern. If a change is desired, handle it as a coordinated project-wide improvement rather than as a per-PR review issue.

Applied to files:

  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/PaymentTypeMapper.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/CurrencyDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/GetLoanDisburseTemplateUseCase.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/CurrencyMapper.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseTemplate.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/PaymentTypeOptionDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseNavigation.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/LoanDisburseUseCase.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileScreen.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanDisburseRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/LoanDisburseMapper.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/di/LoanModule.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanDisburseRepositoryImpl.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountAction/LoanAccountActionNavigation.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseResponseDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseViewModel.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
📚 Learning: 2026-07-08T13:55:15.322Z
Learnt from: sahilshivekar
Repo: openMF/mifos-x-field-officer-app PR: 2698
File: feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/createGuarantor/CreateGuarantorViewModel.kt:366-397
Timestamp: 2026-07-08T13:55:15.322Z
Learning: In Kotlin ViewModels (e.g., using `mutableStateFlow` + `collect {}` to handle async results), it’s acceptable to directly update a single piece of state (and call `sendEvent`) inside the `collect {}` block for simple cases (e.g., updating one property like `searchedClientOptions`). Reserve the internal-action/reducer pattern (`sendAction(...)` + `handleAction`) for async results that affect multiple properties and/or require more complex state transitions, to avoid unnecessary ceremony for trivial cases.

Applied to files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseNavigation.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/di/LoanModule.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountAction/LoanAccountActionNavigation.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
📚 Learning: 2025-12-31T08:19:18.178Z
Learnt from: amanna13
Repo: openMF/android-client PR: 2569
File: core-base/designsystem/src/commonMain/kotlin/template/core/base/designsystem/layout/KptResponsiveLayout.kt:140-153
Timestamp: 2025-12-31T08:19:18.178Z
Learning: When syncing template code from kmp-project-template in the android-client repo, avoid introducing functional or behavioral fixes in the synced template code in the initial sync PR. Defer such fixes to follow-up issues to keep the PR focused on template syncing only. If a fix is necessary, create a separate follow-up issue/PR and document the scope so maintainers understand that changes are deferred to template-related refinement.

Applied to files:

  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt
📚 Learning: 2026-03-16T11:58:32.496Z
Learnt from: sahilshivekar
Repo: openMF/mifos-x-field-officer-app PR: 2647
File: feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt:96-96
Timestamp: 2026-03-16T11:58:32.496Z
Learning: In feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt (Kotlin/Compose Multiplatform), navigateToDashboard uses a direct method reference navController::navigateToLoanDashboardScreen without an ID guard. This is intentional: LoanAccountProfileScreen always provides a valid loanId, and LoanDashboardScreen handles invalid/missing data by showing a 'Failed to fetch Loan details' error state. Do not flag the absence of an ID guard here in future reviews.

Applied to files:

  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
🔇 Additional comments (30)
core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt (1)

13-14: LGTM!

Also applies to: 31-36, 342-343, 467-477

core/network/src/commonMain/kotlin/com/mifos/core/network/dto/CurrencyDto.kt (1)

1-24: LGTM!

core/network/src/commonMain/kotlin/com/mifos/core/network/dto/PaymentTypeOptionDto.kt (1)

1-24: LGTM!

core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseRequestDto.kt (1)

1-29: LGTM!

core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/disburse/LoanDisburseResponseDto.kt (1)

1-22: LGTM!

core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanDisburseTemplateDto.kt (1)

1-23: LGTM!

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseNavigation.kt (1)

1-39: LGTM!

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt (1)

16-17: LGTM!

Also applies to: 39-40, 67-67, 137-137, 163-167

core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt (1)

12-13: LGTM!

Also applies to: 31-36, 73-74, 244-254

core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseTemplate.kt (1)

15-20: LGTM!

core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/CurrencyMapper.kt (1)

15-23: LGTM!

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseViewModel.kt (1)

41-51: MVI reducer shape is spot on.

loadTemplate/submitDisburse dispatch results through sendAction(...) into a single handleAction reducer, with a single mutableStateFlow, matching the required unidirectional Action → ViewModel → State → UI flow.

Also applies to: 136-197, 199-221

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt (1)

76-137: Screen/Content split is clean.

LoanDisburseScreen handles ViewModel wiring, state collection, and event-driven navigation only; LoanDisburseScreenContent takes solely state + a single onAction, matching the required two-layer structure.

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/di/LoanModule.kt (1)

26-26: LGTM!

Also applies to: 55-55

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountAction/LoanAccountActionNavigation.kt (1)

23-31: LGTM!

Also applies to: 53-53

core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/loanDisburse/LoanDisburseInput.kt (1)

19-19: 🗄️ Data Integrity & Integration

Align externalId with the API contract
LoanDisburseViewModel still parses free-text input with toIntOrNull(), so non-numeric external IDs are dropped unless LoanDisburseRequestDto / mapper logic uses the same type. Keep the contract consistent end-to-end.

core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/PaymentTypeMapper.kt (1)

15-18: LGTM!

core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/LoanDisburseMapper.kt (2)

19-32: LGTM!


34-39: LGTM!

core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanDisburseRepository.kt (1)

16-21: LGTM!

core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanDisburseRepositoryImpl.kt (1)

23-48: LGTM!

core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt (2)

99-100: LGTM!


190-191: LGTM!

core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/GetLoanDisburseTemplateUseCase.kt (1)

16-22: LGTM!

core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanDisburse/LoanDisburseUseCase.kt (1)

16-23: LGTM!

core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt (3)

80-80: LGTM!


153-153: LGTM!


206-206: LGTM!

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseState.kt (2)

18-50: LGTM!


52-52: LGTM!

Comment thread feature/loan/src/commonMain/composeResources/values/strings.xml
@sonarqubecloud

Copy link
Copy Markdown

@revanthkumarJ
revanthkumarJ merged commit 909158d into openMF:dev Jul 22, 2026
11 checks passed
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