Skip to content

feat(loan): implement assign loan officer screen - #2699

Merged
revanthkumarJ merged 3 commits into
openMF:devfrom
sahilshivekar:assign-loan-officer
Jul 15, 2026
Merged

feat(loan): implement assign loan officer screen#2699
revanthkumarJ merged 3 commits into
openMF:devfrom
sahilshivekar:assign-loan-officer

Conversation

@sahilshivekar

@sahilshivekar sahilshivekar commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Fixes - Jira-#680

Before (Clicking on assign loan officer doesn't make changes in state)

image

After

assign_loan_officer.mp4

@sahilshivekar
sahilshivekar requested a review from a team July 15, 2026 10:35
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@sahilshivekar, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 4 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8b4f339a-1845-48e7-9894-d721f6e99f52

📥 Commits

Reviewing files that changed from the base of the PR and between fd681ae and 089b209.

📒 Files selected for processing (1)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanOfficerRepositoryImpl.kt

Walkthrough

Adds an end-to-end Assign Loan Officer flow across network, data, domain, and Compose feature layers. It also reorganizes loan repository and template DTO packages and updates dependent imports and model types.

Changes

Loan officer assignment backend and domain

View backend and domain checkpoints
Layer / File(s) Summary
API contracts and mapping
core/network/..., core/model/..., core/data/mappers/...
Adds assignment DTOs, loan officer option templates, domain models, and DTO/domain mappings.
Repository and use-case integration
core/data/..., core/domain/...
Adds the loan officer repository implementation and use cases, registers them with Koin, and relocates loan repository packages.
Loan template alignment
core/database/..., core/model/...
Renames LoanOfficerOptions to LoanOfficerOption and updates loan template property types.

Assign Loan Officer feature

View feature checkpoints
Layer / File(s) Summary
State and Compose UI
feature/loan/.../assignLoanOfficer/*, feature/loan/.../strings.xml
Adds option loading, officer selection, date picking, submission, dialogs, success, and error states.
Navigation and action wiring
feature/loan/.../navigation/*, feature/loan/.../loanAccountAction/*
Adds the typed route, destination registration, and loan-account action callback.
Dependency updates
feature/loan/.../di/LoanModule.kt, feature/loan/.../*ViewModel.kt
Registers the new ViewModel and updates repository imports.

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

Sequence Diagram(s)

Assignment flow
sequenceDiagram
  participant LoanAccountAction
  participant LoanNavigation
  participant AssignLoanOfficerScreen
  participant AssignLoanOfficerViewModel
  participant AssignLoanOfficerUseCase
  LoanAccountAction->>LoanNavigation: open assignment route
  LoanNavigation->>AssignLoanOfficerScreen: provide loanId
  AssignLoanOfficerScreen->>AssignLoanOfficerViewModel: load options and submit actions
  AssignLoanOfficerViewModel->>AssignLoanOfficerUseCase: invoke assignment
  AssignLoanOfficerUseCase-->>AssignLoanOfficerViewModel: return assignment result
Loading

Possibly related PRs

Related pull requests

Suggested reviewers: revanthkumarj, niyajali

🚥 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 commit format and accurately summarizes the main change.
Description check ✅ Passed The description is clearly related to the assign loan officer feature and matches the changeset.
Jira Link And Before/After Sections ✅ Passed PR description includes a valid Jira link and both Before/After sections with media (image and video).
✨ 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.

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

🧹 Nitpick comments (2)
core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/assignLoanOfficer/AssignLoanOfficerInput.kt (1)

17-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer null as the default for optional identifiers.

Since fromLoanOfficerId is typed as a nullable string (String?), it is typically safer and more semantically correct to default to null rather than an empty string "". An empty string sent over the network could be interpreted incorrectly if the backend strictly expects either a valid string identifier or a null value.

💡 Proposed fix for the default value
-    val fromLoanOfficerId: String? = "",
+    val fromLoanOfficerId: String? = null,
🤖 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
`@core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/assignLoanOfficer/AssignLoanOfficerInput.kt`
at line 17, Update the fromLoanOfficerId property in AssignLoanOfficerInput to
default to null instead of an empty string, preserving its nullable String type
and ensuring omitted optional identifiers remain null.
core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt (1)

208-208: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Critical module change detection.

Please note that core-base (and the core layer) is a shared foundational module and requires extra review attention. Ensure that all modifications in RepositoryModule.kt are necessary and minimal as per path instructions. The DI additions here appear safe and well-contained.

🤖 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 `@core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt`
at line 208, Keep the LoanOfficerRepositoryImpl binding in RepositoryModule.kt
minimal and limited to the required singleOf declaration with
LoanOfficerRepository::class. Avoid unrelated changes to this shared
foundational DI module.

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/kotlin/com/mifos/feature/loan/assignLoanOfficer/AssignLoanOfficerScreen.kt`:
- Around line 58-107: Split AssignLoanOfficerScreen into a Layer 1 route that
retains ViewModel injection, state collection, event handling, navigation, and
dialog wiring, and a separate Layer 2 content composable that receives only the
collected state and an onAction callback. Move the MifosScaffold and viewState
rendering logic, including AssignLoanOfficerForm, into the content composable,
and have AssignLoanOfficerScreen delegate to it.
- Line 173: Move loan officer label resolution out of the composable’s options
mapping and into the ViewModel/state that supplies the officers, exposing a
precomputed non-null display label for each LoanOfficerOption. Update the
state-producing logic to prefer displayName and safely fall back to available
firstname/lastname values without producing “null null”, then have
AssignLoanOfficerScreen reuse that state label directly.

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/assignLoanOfficer/AssignLoanOfficerViewModel.kt`:
- Around line 196-209: Remove the file-level cached defaultAssignmentDate and
compute the current timestamp when each AssignLoanOfficerState is constructed,
using that same per-instance value for both assignmentDateMillis and
assignmentDateText. Preserve the existing date formatting behavior and avoid
sharing a timestamp across view-model instances.

---

Nitpick comments:
In `@core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt`:
- Line 208: Keep the LoanOfficerRepositoryImpl binding in RepositoryModule.kt
minimal and limited to the required singleOf declaration with
LoanOfficerRepository::class. Avoid unrelated changes to this shared
foundational DI module.

In
`@core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/assignLoanOfficer/AssignLoanOfficerInput.kt`:
- Line 17: Update the fromLoanOfficerId property in AssignLoanOfficerInput to
default to null instead of an empty string, preserving its nullable String type
and ensuring omitted optional identifiers remain null.
🪄 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: 0a4f57d1-af21-4dc9-a7da-cc5b89ae9502

📥 Commits

Reviewing files that changed from the base of the PR and between e85b158 and ca4c28d.

📒 Files selected for processing (76)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/ChargeOffReasonOptionMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/GuarantorMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/mappers/loan/LoanOfficerMapper.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanAccountApprovalRepository.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/LoanAccountRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanAccountSummaryRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanChargeFormRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanChargeOffRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanChargeRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanCreateGuarantorRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanOfficerRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanRepaymentRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanRepaymentScheduleRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanReschedulesRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/loan/LoanTransactionsRepository.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanAccountApprovalRepositoryImp.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/LoanAccountRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanAccountSummaryRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanChargeFormRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanChargeOffRepositoryImpl.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanChargeRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanCreateGuarantorRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanOfficerRepositoryImpl.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanRepaymentRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanRepaymentScheduleRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanReschedulesRepositoryImpl.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/loan/LoanTransactionsRepositoryImp.kt
  • core/database/src/commonMain/kotlin/com/mifos/room/entities/templates/loans/LoanTemplate.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CalculateLoanScheduleUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CreateLoanAccountUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CreateLoanChargesUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/GetAllLoanUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/GetChargeTemplateUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/GetListOfLoanChargesUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/GetLoansAccountTemplateUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/assignLoanOfficer/AssignLoanOfficerUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/assignLoanOfficer/GetLoanOfficerOptionsUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/createGuarantor/CreateGuarantorUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/createGuarantor/GetGuarantorAccountTemplateUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/createGuarantor/GetGuarantorTemplateUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanChargeOff/GetLoanChargeOffTemplateUseCase.kt
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/loanChargeOff/LoanChargeOffUseCase.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/assignLoanOfficer/AssignLoanOfficerInput.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/account/loan/assignLoanOfficer/AssignLoanOfficerResponse.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/template/loan/GroupLoanTemplate.kt
  • core/model/src/commonMain/kotlin/com/mifos/core/model/objects/template/loan/LoanOfficerOption.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerLoan.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/assignLoanOfficer/AssignLoanOfficerRequestDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/assignLoanOfficer/AssignLoanOfficerResponseDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/GuarantorTemplateDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanChargeOffTemplateDto.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/dto/loans/template/LoanOfficerOptionsTemplateDto.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/amountTransfer/AmountTransferViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/assignLoanOfficer/AssignLoanOfficerRoute.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/assignLoanOfficer/AssignLoanOfficerScreen.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/assignLoanOfficer/AssignLoanOfficerViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/createLoanReschedules/LoanRescheduleFormViewModel.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/loanAccountAction/LoanAccountActionViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountProfile/LoanAccountProfileViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanAccountSummary/LoanAccountSummaryViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanApproval/LoanAccountApprovalViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDashboard/LoanDashboardViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanDisbursement/LoanAccountDisbursementViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanRepayment/LoanRepaymentViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanRepaymentSchedule/LoanRepaymentScheduleViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanReschedules/LoanReschedulesViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/LoanTransactionsViewModel.kt
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/navigation/LoanNavigation.kt

revanthkumarJ
revanthkumarJ previously approved these changes Jul 15, 2026
@sonarqubecloud

Copy link
Copy Markdown

@revanthkumarJ
revanthkumarJ merged commit 6fa9041 into openMF:dev Jul 15, 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.

3 participants