Skip to content

feat(loan): implement reject loan screen - #2702

Merged
revanthkumarJ merged 1 commit into
openMF:devfrom
sahilshivekar:reject-loan
Jul 29, 2026
Merged

feat(loan): implement reject loan screen#2702
revanthkumarJ merged 1 commit into
openMF:devfrom
sahilshivekar:reject-loan

Conversation

@sahilshivekar

Copy link
Copy Markdown
Contributor

Fixes - Jira-#703

Before (Reject option doesn't open any screen)

before

After

reject_loan_success.mp4

@sahilshivekar
sahilshivekar requested a review from a team July 28, 2026 16:53
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Summary by CodeRabbit

  • New Features

    • Added a loan rejection flow accessible from loan account actions.
    • Users can select a rejection date, add an optional note, and submit the rejection.
    • Added success and error feedback during submission.
    • Loan account details refresh automatically after a successful rejection.
  • Style

    • Standardized optional note labels across loan disbursement and charge-off forms.

Walkthrough

Adds an end-to-end loan rejection flow: API contracts, repository and use case wiring, rejection form state and UI, navigation from loan actions, success handling, and loan profile refresh.

Changes

The PR follows one functional path from the loan account action to the rejection API and refreshed profile.

Loan rejection implementation
Layer / File(s) Summary
Network contract and request handling
core/model/.../RejectLoanInput.kt, core/network/.../loans/*, core/network/.../LoanService.kt
Defines rejection input and serializable request/response DTOs, exposes the POST rejection endpoint, and forwards calls through DataManagerLoan.
Repository and use-case wiring
core/data/.../LoanRejectRepository.kt, core/data/.../LoanRejectRepositoryImpl.kt, core/domain/.../RejectLoanUseCase.kt, core/{data,domain}/.../*Module.kt
Wraps the network operation in DataState, maps RejectLoanInput to its DTO, delegates through RejectLoanUseCase, and registers both dependencies with Koin.
Rejection form and UI state
feature/loan/.../loanReject/*, feature/loan/.../strings.xml
Adds date selection limited to today or earlier, an optional note, submit progress state, success/error dialogs, and rejection-related resources. Existing charge-off and disbursement note labels now use the shared optional-note resource.
Navigation and profile refresh
feature/loan/.../LoanAccountActionNavigation.kt, feature/loan/.../loanReject/LoanRejectScreenRoute.kt, feature/loan/.../LoanNavigation.kt
Routes the loan Reject action to the new screen, registers the destination, and reloads the loan account profile after successful rejection.

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

Sequence Diagram(s)

sequenceDiagram
  participant LoanAccountActions
  participant LoanRejectScreen
  participant LoanRejectViewModel
  participant RejectLoanUseCase
  participant LoanService
  participant LoanAccountProfile

  LoanAccountActions->>LoanRejectScreen: navigate with loanId
  LoanRejectScreen->>LoanRejectViewModel: submit date and note
  LoanRejectViewModel->>RejectLoanUseCase: rejectLoan(loanId, input)
  RejectLoanUseCase->>LoanService: POST rejection request
  LoanService-->>LoanRejectViewModel: DataState<Unit>
  LoanRejectViewModel-->>LoanRejectScreen: show success dialog
  LoanRejectScreen->>LoanAccountProfile: reload profile after dismissal
Loading

Possibly related PRs

Suggested reviewers: revanthkumarj

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 format and clearly describes the main loan rejection screen change.
Description check ✅ Passed The description is related to the reject-loan flow and matches the implemented UI and backend wiring.
Jira Link And Before/After Sections ✅ Passed PR description has a valid Jira link plus non-empty Before and After sections, each containing media (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.

@sonarqubecloud

Copy link
Copy Markdown

@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: 1

🤖 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/kotlin/com/mifos/feature/loan/loanReject/LoanRejectState.kt`:
- Around line 21-22: Update the LoanRejectState constructor defaults for
rejectedOnDate and rejectedOnDateText so the current default rejection date is
evaluated for each state instance, and ensure rejectedOnDateText is derived from
that instance’s actual rejectedOnDate value rather than a class-load-time
constant.
🪄 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 Plus

Run ID: 37245ee0-5091-4044-867c-50258c5c985e

📥 Commits

Reviewing files that changed from the base of the PR and between 909158d and 02dd8a1.

📒 Files selected for processing (21)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/LoanRejectRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanRejectRepositoryImpl.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanReject/RejectLoanUseCase.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/RejectLoanInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanResponseDto.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/LoanAccountProfileNavigation.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanChargeOff/LoanChargeOffScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreenRoute.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: PR Checks / Static Analysis Check
🧰 Additional context used
📓 Path-based instructions (10)
**/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/loans/RejectLoanRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanResponseDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.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/loans/RejectLoanRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanResponseDto.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/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanRequestDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanReject/RejectLoanUseCase.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanResponseDto.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/LoanRejectRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanRejectRepositoryImpl.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/RejectLoanInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.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/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanRequestDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanReject/RejectLoanUseCase.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanResponseDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/LoanRejectRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanRejectRepositoryImpl.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreenRoute.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
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/RejectLoanInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanChargeOff/LoanChargeOffScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectViewModel.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/LoanRejectRepository.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/LoanRejectRepositoryImpl.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/loanDisburse/LoanDisburseScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanChargeOff/LoanChargeOffScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreen.kt
**/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/RejectLoanInput.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/loanReject/LoanRejectViewModel.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 (4)
📚 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/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanRequestDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanReject/RejectLoanUseCase.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanResponseDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/LoanRejectRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanRejectRepositoryImpl.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreenRoute.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
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/RejectLoanInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanChargeOff/LoanChargeOffScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectViewModel.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/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanRequestDto.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanReject/RejectLoanUseCase.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/RejectLoanResponseDto.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/LoanRejectRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanRejectRepositoryImpl.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreenRoute.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
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/RejectLoanInput.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/LoanService.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanChargeOff/LoanChargeOffScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectViewModel.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/loanAccountProfile/LoanAccountProfileNavigation.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisburse/LoanDisburseScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreenRoute.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/loanChargeOff/LoanChargeOffScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectState.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectViewModel.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 (20)
core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/RejectLoanInput.kt (1)

12-19: LGTM!

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

10-19: LGTM!

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

10-19: LGTM!

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

29-30: LGTM!

Also applies to: 93-97

core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt (1)

29-30: LGTM!

Also applies to: 161-166

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

12-17: LGTM!

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

12-44: LGTM!

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

43-43: LGTM!

Also applies to: 156-156, 211-211

core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanReject/RejectLoanUseCase.kt (1)

12-23: LGTM!

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

101-101: LGTM!

Also applies to: 193-193

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectViewModel.kt (1)

26-119: LGTM!

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreen.kt (1)

58-202: LGTM!

feature/loan/src/commonMain/composeResources/values/strings.xml (1)

15-15: LGTM!

Also applies to: 154-158

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanChargeOff/LoanChargeOffScreen.kt (1)

23-23: LGTM!

Also applies to: 224-224

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

27-27: LGTM!

Also applies to: 281-281

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

27-27: LGTM!

Also applies to: 43-43

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReject/LoanRejectScreenRoute.kt (1)

17-34: LGTM!

feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileNavigation.kt (1)

65-72: LGTM!

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

23-89: LGTM!

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

102-105: LGTM!

Also applies to: 142-142

@revanthkumarJ
revanthkumarJ enabled auto-merge (squash) July 29, 2026 04:42
@revanthkumarJ
revanthkumarJ disabled auto-merge July 29, 2026 04:42
@revanthkumarJ
revanthkumarJ merged commit e09b878 into openMF:dev Jul 29, 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