Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import com.mifos.core.data.repository.GroupListRepository
import com.mifos.core.data.repository.GroupLoanAccountRepository
import com.mifos.core.data.repository.GroupsListRepository
import com.mifos.core.data.repository.IndividualCollectionSheetDetailsRepository
import com.mifos.core.data.repository.LoanRejectRepository
import com.mifos.core.data.repository.LoginRepository
import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository
import com.mifos.core.data.repository.NoteRepository
Expand Down Expand Up @@ -152,6 +153,7 @@ import com.mifos.core.data.repositoryImp.loan.LoanChargeRepositoryImp
import com.mifos.core.data.repositoryImp.loan.LoanCreateGuarantorRepositoryImp
import com.mifos.core.data.repositoryImp.loan.LoanDisburseRepositoryImpl
import com.mifos.core.data.repositoryImp.loan.LoanOfficerRepositoryImpl
import com.mifos.core.data.repositoryImp.loan.LoanRejectRepositoryImpl
import com.mifos.core.data.repositoryImp.loan.LoanRepaymentRepositoryImp
import com.mifos.core.data.repositoryImp.loan.LoanRepaymentScheduleRepositoryImp
import com.mifos.core.data.repositoryImp.loan.LoanReschedulesRepositoryImpl
Expand Down Expand Up @@ -206,6 +208,7 @@ val RepositoryModule = module {
singleOf(::LoanDisburseRepositoryImpl) bind LoanDisburseRepository::class
singleOf(::LoanCreateGuarantorRepositoryImp) bind LoanCreateGuarantorRepository::class
singleOf(::LoanOfficerRepositoryImpl) bind LoanOfficerRepository::class
singleOf(::LoanRejectRepositoryImpl) bind LoanRejectRepository::class

// Account Transfer
singleOf(::AmountTransferRepositoryImp) bind AmountTransferRepository::class
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2026 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
*/
package com.mifos.core.data.repository

import com.mifos.core.common.utils.DataState
import com.mifos.core.model.objects.account.loan.RejectLoanInput

interface LoanRejectRepository {
suspend fun rejectLoan(loanId: Int, request: RejectLoanInput): DataState<Unit>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2026 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
*/
package com.mifos.core.data.repositoryImp.loan

import com.mifos.core.common.utils.DataState
import com.mifos.core.data.repository.LoanRejectRepository
import com.mifos.core.data.util.NetworkMonitor
import com.mifos.core.data.util.runAsDataState
import com.mifos.core.model.objects.account.loan.RejectLoanInput
import com.mifos.core.network.datamanager.DataManagerLoan
import com.mifos.core.network.dto.loans.RejectLoanRequestDto
import template.core.base.common.manager.DispatcherManager

class LoanRejectRepositoryImpl(
private val dataManagerLoan: DataManagerLoan,
private val networkMonitor: NetworkMonitor,
private val dispatcher: DispatcherManager,
) : LoanRejectRepository {
override suspend fun rejectLoan(
loanId: Int,
request: RejectLoanInput,
): DataState<Unit> {
return runAsDataState(
networkMonitor = networkMonitor,
context = dispatcher.io,
) {
dataManagerLoan.rejectLoan(
loanId = loanId,
request = RejectLoanRequestDto(
rejectedOnDate = request.rejectedOnDate,
note = request.note,
locale = request.locale,
dateFormat = request.dateFormat,
),
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ import com.mifos.core.domain.useCases.loanChargeOff.GetLoanChargeOffTemplateUseC
import com.mifos.core.domain.useCases.loanChargeOff.LoanChargeOffUseCase
import com.mifos.core.domain.useCases.loanDisburse.GetLoanDisburseTemplateUseCase
import com.mifos.core.domain.useCases.loanDisburse.LoanDisburseUseCase
import com.mifos.core.domain.useCases.loanReject.RejectLoanUseCase
import org.koin.core.module.dsl.factoryOf
import org.koin.dsl.module

Expand Down Expand Up @@ -189,6 +190,7 @@ val UseCaseModule = module {
factoryOf(::LoanChargeOffUseCase)
factoryOf(::GetLoanDisburseTemplateUseCase)
factoryOf(::LoanDisburseUseCase)
factoryOf(::RejectLoanUseCase)
factoryOf(::GetLoanOfficerOptionsUseCase)
factoryOf(::AssignLoanOfficerUseCase)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2026 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
*/
package com.mifos.core.domain.useCases.loanReject

import com.mifos.core.common.utils.DataState
import com.mifos.core.data.repository.LoanRejectRepository
import com.mifos.core.model.objects.account.loan.RejectLoanInput

class RejectLoanUseCase(
private val repository: LoanRejectRepository,
) {
suspend operator fun invoke(
loanId: Int,
request: RejectLoanInput,
): DataState<Unit> = repository.rejectLoan(loanId, request)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2026 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
*/
package com.mifos.core.model.objects.account.loan

import com.mifos.core.model.utils.DateConstants

data class RejectLoanInput(
val rejectedOnDate: String,
val note: String? = null,
val locale: String = DateConstants.LOCALE,
val dateFormat: String = "dd-MM-yyyy",
)
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import com.mifos.core.network.dto.loans.CreateGuarantorResponseDto
import com.mifos.core.network.dto.loans.GuarantorRequestDto
import com.mifos.core.network.dto.loans.LoanChargeOffRequestDto
import com.mifos.core.network.dto.loans.LoanChargeOffResponseDto
import com.mifos.core.network.dto.loans.RejectLoanRequestDto
import com.mifos.core.network.dto.loans.RejectLoanResponseDto
import com.mifos.core.network.dto.loans.assignLoanOfficer.AssignLoanOfficerRequestDto
import com.mifos.core.network.dto.loans.assignLoanOfficer.AssignLoanOfficerResponseDto
import com.mifos.core.network.dto.loans.disburse.LoanDisburseRequestDto
Expand Down Expand Up @@ -156,6 +158,13 @@ class DataManagerLoan(
return mBaseApiManager.loanService.chargeOff(loanId, loanChargeOffRequestDto)
}

suspend fun rejectLoan(
loanId: Int,
request: RejectLoanRequestDto,
): RejectLoanResponseDto {
return mBaseApiManager.loanService.rejectLoan(loanId, request)
}

fun createLoansAccount(loansPayload: LoansPayload?): Flow<HttpResponse> {
return mBaseApiManager.loanService.createLoansAccount(loansPayload).map { response ->

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2026 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
*/
package com.mifos.core.network.dto.loans
import kotlinx.serialization.Serializable

@Serializable
data class RejectLoanRequestDto(
val rejectedOnDate: String,
val note: String? = null,
val locale: String,
val dateFormat: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2026 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
*/
package com.mifos.core.network.dto.loans
import kotlinx.serialization.Serializable

@Serializable
data class RejectLoanResponseDto(
val officeId: Int,
val clientId: Int,
val loanId: Int,
val resourceId: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import com.mifos.core.network.dto.loans.CreateGuarantorResponseDto
import com.mifos.core.network.dto.loans.GuarantorRequestDto
import com.mifos.core.network.dto.loans.LoanChargeOffRequestDto
import com.mifos.core.network.dto.loans.LoanChargeOffResponseDto
import com.mifos.core.network.dto.loans.RejectLoanRequestDto
import com.mifos.core.network.dto.loans.RejectLoanResponseDto
import com.mifos.core.network.dto.loans.assignLoanOfficer.AssignLoanOfficerRequestDto
import com.mifos.core.network.dto.loans.assignLoanOfficer.AssignLoanOfficerResponseDto
import com.mifos.core.network.dto.loans.disburse.LoanDisburseRequestDto
Expand Down Expand Up @@ -88,6 +90,12 @@ interface LoanService {
@Body loanChargeOffRequest: LoanChargeOffRequestDto,
): LoanChargeOffResponseDto

@POST(APIEndPoint.LOANS + "/{loanId}?command=reject")
suspend fun rejectLoan(
@Path("loanId") loanId: Int,
@Body request: RejectLoanRequestDto,
): RejectLoanResponseDto

@GET(APIEndPoint.LOANS + "/{loanId}?associations=repaymentSchedule")
fun getLoanRepaymentSchedule(@Path("loanId") loanId: Int): Flow<LoanWithAssociationsEntity>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<string name="feature_loan_application">Loan Application</string>
<string name="feature_loan_account_created_successfully">Loan account created successfully</string>
<string name="feature_error_network_not_available">Network is not Available</string>

<string name="feature_loan_note_optional">Note (Optional)</string>

<string name="feature_loan_product">Loan Product</string>
<string name="feature_loan_purpose">Loan Purpose</string>
Expand Down Expand Up @@ -151,6 +151,11 @@
<string name="feature_loan_profile_item_documents_title">Loan Documents</string>
<string name="feature_loan_profile_item_documents_subtitle">Contracts and attachments</string>
<string name="feature_loan_profile_item_notes_title">Notes</string>
<string name="feature_loan_reject">Reject Loan</string>
<string name="feature_loan_reject_date">Rejection Date</string>
<string name="feature_loan_reject_submit">Submit Rejection</string>
<string name="feature_loan_reject_failed">Failed to reject loan</string>
<string name="feature_loan_reject_success">Loan rejected successfully</string>
<string name="feature_loan_profile_item_notes_subtitle">Additional internal comments</string>
<string name="feature_loan_profile_item_standing_instructions_title">Standing Instructions</string>
<string name="feature_loan_profile_item_standing_instructions_subtitle">Automated payment settings</string>
Expand All @@ -159,7 +164,6 @@
<string name="feature_loan_charge_off_transaction_date">Transaction Date</string>
<string name="feature_loan_charge_off_reason">Charge Off Reason</string>
<string name="feature_loan_charge_off_external_id">External ID (Optional)</string>
<string name="feature_loan_charge_off_note">Note (Optional)</string>
<string name="feature_loan_charge_off_submit">Submit Charge-Off</string>
<string name="feature_loan_charge_off_failed">Failed to charge off loan</string>
<string name="feature_loan_charge_off_success">Successfully charged off loan</string>
Expand Down Expand Up @@ -733,5 +737,4 @@
<string name="feature_loan_disburse_failed">Failed to disburse loan</string>
<string name="feature_loan_disburse_failed_to_load_template">Failed to load disburse template</string>
<string name="feature_loan_disburse_amount_greater_than_zero">Amount must be greater than 0</string>
<string name="feature_loan_disburse_note">Note (Optional)</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.mifos.feature.loan.loanCharge.LoanChargeViewModel
import com.mifos.feature.loan.loanChargeOff.LoanChargeOffViewModel
import com.mifos.feature.loan.loanDashboard.LoanDashboardViewModel
import com.mifos.feature.loan.loanDisburse.LoanDisburseViewModel
import com.mifos.feature.loan.loanReject.LoanRejectViewModel
import com.mifos.feature.loan.loanRepayment.LoanRepaymentViewModel
import com.mifos.feature.loan.loanRepaymentSchedule.LoanRepaymentScheduleViewModel
import com.mifos.feature.loan.loanReschedules.LoanReschedulesViewModel
Expand All @@ -39,6 +40,7 @@ val LoanModule = module {
viewModelOf(::LoanAccountApprovalViewModel)
viewModelOf(::LoanChargeViewModel)
viewModelOf(::LoanChargeOffViewModel)
viewModelOf(::LoanRejectViewModel)
viewModelOf(::LoanRepaymentViewModel)
viewModelOf(::LoanRepaymentScheduleViewModel)
viewModelOf(::LoanTransactionsViewModel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fun NavGraphBuilder.loanAccountActionDestination(
onNavigateBack: () -> Unit,
navigateToPaymentsActionScreen: () -> Unit,
navigateToChargeOff: (loanId: Int) -> Unit,
navigateToReject: (loanId: Int) -> Unit,
navigateToCreateGuarantor: (loanId: Int) -> Unit,
navigateToAssignLoanOfficerScreen: (loanId: Int) -> Unit,
navigateToDisburse: (loanId: Int) -> Unit,
Expand Down Expand Up @@ -67,7 +68,7 @@ fun NavGraphBuilder.loanAccountActionDestination(
LoanAccountActionItem.ReAmortize -> {}
LoanAccountActionItem.RecoverFromGuarantor -> {}
LoanAccountActionItem.RecoveryPayment -> {}
LoanAccountActionItem.Reject -> {}
LoanAccountActionItem.Reject -> navigateToReject(loanId)
LoanAccountActionItem.Reschedule -> {}
LoanAccountActionItem.SellLoan -> {}
LoanAccountActionItem.TransferFunds -> {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@ fun NavController.navigateToLoanAccountProfileScreen(loanId: Int) {
),
)
}

fun NavController.reloadLoanAccountProfileScreen(loanId: Int) {
navigate(LoanAccountRoute(loanId)) {
popUpTo(LoanAccountRoute(loanId)) {
inclusive = true
}
launchSingleTop = true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import androidclient.feature.loan.generated.resources.cancel
import androidclient.feature.loan.generated.resources.feature_loan_charge_off
import androidclient.feature.loan.generated.resources.feature_loan_charge_off_external_id
import androidclient.feature.loan.generated.resources.feature_loan_charge_off_no_reasons_available
import androidclient.feature.loan.generated.resources.feature_loan_charge_off_note
import androidclient.feature.loan.generated.resources.feature_loan_charge_off_please_select_reason
import androidclient.feature.loan.generated.resources.feature_loan_charge_off_reason
import androidclient.feature.loan.generated.resources.feature_loan_charge_off_submit
import androidclient.feature.loan.generated.resources.feature_loan_charge_off_transaction_date
import androidclient.feature.loan.generated.resources.feature_loan_note_optional
import androidclient.feature.loan.generated.resources.ok
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -221,7 +221,7 @@ private fun LoanChargeOffForm(
MifosOutlinedTextField(
value = state.note,
onValueChange = { onAction(LoanChargeOffAction.NoteChanged(it)) },
label = stringResource(Res.string.feature_loan_charge_off_note),
label = stringResource(Res.string.feature_loan_note_optional),
maxLines = 4,
singleLine = false,
keyboardType = KeyboardType.Text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import androidclient.feature.loan.generated.resources.feature_loan_disburse_bank
import androidclient.feature.loan.generated.resources.feature_loan_disburse_cheque_number
import androidclient.feature.loan.generated.resources.feature_loan_disburse_date
import androidclient.feature.loan.generated.resources.feature_loan_disburse_external_id
import androidclient.feature.loan.generated.resources.feature_loan_disburse_note
import androidclient.feature.loan.generated.resources.feature_loan_disburse_receipt_number
import androidclient.feature.loan.generated.resources.feature_loan_disburse_routing_code
import androidclient.feature.loan.generated.resources.feature_loan_disburse_show_payment_details
import androidclient.feature.loan.generated.resources.feature_loan_disburse_transaction_amount
import androidclient.feature.loan.generated.resources.feature_loan_note_optional
import androidclient.feature.loan.generated.resources.feature_loan_payment_type
import androidclient.feature.loan.generated.resources.feature_loan_submit
import androidclient.feature.loan.generated.resources.ok
Expand Down Expand Up @@ -278,7 +278,7 @@ private fun LoanDisburseForm(
MifosOutlinedTextField(
value = state.note,
onValueChange = { onAction(LoanDisburseAction.NoteChanged(it)) },
label = stringResource(Res.string.feature_loan_disburse_note),
label = stringResource(Res.string.feature_loan_note_optional),
keyboardType = KeyboardType.Text,
)

Expand Down
Loading
Loading