Skip to content

Commit 3528b46

Browse files
committed
feat(feature/loan): loan foreclosurescreen
feat(feature/loan): loan foreclosurescreen feat(feature/loan): loan foreclosurescreen feat(feature/loan): loan foreclosurescreen
1 parent b3ed04e commit 3528b46

15 files changed

Lines changed: 736 additions & 0 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import com.mifos.core.data.repository.LoanAccountRepository
4646
import com.mifos.core.data.repository.LoanAccountSummaryRepository
4747
import com.mifos.core.data.repository.LoanChargeFormRepository
4848
import com.mifos.core.data.repository.LoanChargeRepository
49+
import com.mifos.core.data.repository.LoanForeclosureRepository
4950
import com.mifos.core.data.repository.LoanRepaymentRepository
5051
import com.mifos.core.data.repository.LoanRepaymentScheduleRepository
5152
import com.mifos.core.data.repository.LoanReschedulesRepository
@@ -115,6 +116,7 @@ import com.mifos.core.data.repositoryImp.LoanAccountRepositoryImp
115116
import com.mifos.core.data.repositoryImp.LoanAccountSummaryRepositoryImp
116117
import com.mifos.core.data.repositoryImp.LoanChargeFormRepositoryImp
117118
import com.mifos.core.data.repositoryImp.LoanChargeRepositoryImp
119+
import com.mifos.core.data.repositoryImp.LoanForeclosureRepositoryImp
118120
import com.mifos.core.data.repositoryImp.LoanRepaymentRepositoryImp
119121
import com.mifos.core.data.repositoryImp.LoanRepaymentScheduleRepositoryImp
120122
import com.mifos.core.data.repositoryImp.LoanReschedulesRepositoryImpl
@@ -197,6 +199,7 @@ val RepositoryModule = module {
197199
singleOf(::LoanRepaymentScheduleRepositoryImp) bind LoanRepaymentScheduleRepository::class
198200
singleOf(::LoanTransactionsRepositoryImp) bind LoanTransactionsRepository::class
199201
singleOf(::LoanReschedulesRepositoryImpl) bind LoanReschedulesRepository::class
202+
singleOf(::LoanForeclosureRepositoryImp) bind LoanForeclosureRepository::class
200203

201204
// Account Transfer
202205
singleOf(::AmountTransferRepositoryImp) bind AmountTransferRepository::class
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2026 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.core.data.repository
11+
12+
import com.mifos.core.common.utils.DataState
13+
import com.mifos.core.model.objects.template.loan.LoanForeclosureTemplate
14+
import com.mifos.core.model.objects.template.loan.SubmitLoanForeclosureInput
15+
import kotlinx.coroutines.flow.Flow
16+
17+
interface LoanForeclosureRepository {
18+
19+
fun getLoanForeclosureTemplate(
20+
loanId: Int,
21+
transactionDate: String,
22+
dateFormat: String,
23+
locale: String,
24+
): Flow<DataState<LoanForeclosureTemplate>>
25+
26+
suspend fun submitLoanForeclosure(
27+
loanId: Int,
28+
input: SubmitLoanForeclosureInput,
29+
): DataState<Unit>
30+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2026 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.core.data.repositoryImp
11+
12+
import com.mifos.core.common.utils.DataState
13+
import com.mifos.core.common.utils.asDataStateFlow
14+
import com.mifos.core.data.repository.LoanForeclosureRepository
15+
import com.mifos.core.data.util.NetworkMonitor
16+
import com.mifos.core.data.util.withNetworkCheck
17+
import com.mifos.core.model.objects.template.loan.LoanForeclosureTemplate
18+
import com.mifos.core.model.objects.template.loan.SubmitLoanForeclosureInput
19+
import com.mifos.core.network.datamanager.DataManagerLoan
20+
import com.mifos.core.network.mappers.loan.toDomain
21+
import com.mifos.core.network.mappers.loan.toDto
22+
import kotlinx.coroutines.flow.Flow
23+
import kotlinx.coroutines.flow.flowOn
24+
import kotlinx.coroutines.flow.map
25+
import kotlinx.coroutines.withContext
26+
import template.core.base.common.manager.DispatcherManager
27+
28+
class LoanForeclosureRepositoryImp(
29+
private val dataManager: DataManagerLoan,
30+
private val networkMonitor: NetworkMonitor,
31+
private val dispatcher: DispatcherManager,
32+
) : LoanForeclosureRepository {
33+
34+
override fun getLoanForeclosureTemplate(
35+
loanId: Int,
36+
transactionDate: String,
37+
dateFormat: String,
38+
locale: String,
39+
): Flow<DataState<LoanForeclosureTemplate>> =
40+
networkMonitor.withNetworkCheck(
41+
dataManager
42+
.getLoanForeclosureTemplate(
43+
loanId = loanId,
44+
transactionDate = transactionDate,
45+
dateFormat = dateFormat,
46+
locale = locale,
47+
)
48+
.map { it.toDomain() }
49+
.asDataStateFlow(),
50+
).flowOn(dispatcher.io)
51+
52+
override suspend fun submitLoanForeclosure(
53+
loanId: Int,
54+
input: SubmitLoanForeclosureInput,
55+
): DataState<Unit> {
56+
return withContext(dispatcher.io) {
57+
try {
58+
dataManager.submitLoanForeclosure(loanId, input.toDto())
59+
DataState.Success(Unit)
60+
} catch (e: Exception) {
61+
DataState.Error(e)
62+
}
63+
}
64+
}
65+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2026 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.core.model.objects.template.loan
11+
12+
data class LoanForeclosureTemplate(
13+
val loanId: Int? = null,
14+
val amount: Double? = null,
15+
val principalPortion: Double? = null,
16+
val interestPortion: Double? = null,
17+
val feeChargesPortion: Double? = null,
18+
val penaltyChargesPortion: Double? = null,
19+
)
20+
data class SubmitLoanForeclosureInput(
21+
val transactionDate: String,
22+
val note: String,
23+
val dateFormat: String,
24+
val locale: String,
25+
)

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import com.mifos.core.model.objects.account.loan.transfer.AccountTransferTemplat
2424
import com.mifos.core.network.BaseApiManager
2525
import com.mifos.core.network.GenericResponse
2626
import com.mifos.core.network.model.LoansPayload
27+
import com.mifos.core.network.model.loan.LoanForeclosureSubmitRequestDto
28+
import com.mifos.core.network.model.loan.LoanForeclosureTemplateDto
2729
import com.mifos.room.entities.PaymentTypeOptionEntity
2830
import com.mifos.room.entities.accounts.loans.LoanRepaymentRequestEntity
2931
import com.mifos.room.entities.accounts.loans.LoanRepaymentResponseEntity
@@ -412,4 +414,39 @@ class DataManagerLoan(
412414
throw IllegalStateException(extractErrorMessage(response))
413415
}
414416
}
417+
418+
fun getLoanForeclosureTemplate(
419+
loanId: Int,
420+
transactionDate: String,
421+
dateFormat: String,
422+
locale: String,
423+
): Flow<LoanForeclosureTemplateDto> {
424+
return mBaseApiManager.loanService.getLoanForeclosureTemplate(
425+
loanId = loanId,
426+
transactionDate = transactionDate,
427+
dateFormat = dateFormat,
428+
locale = locale,
429+
).map { response ->
430+
if (!response.status.isSuccess()) {
431+
val errorMessage = extractErrorMessage(response)
432+
433+
throw IllegalStateException(errorMessage)
434+
}
435+
436+
Json { ignoreUnknownKeys = true }.decodeFromString<LoanForeclosureTemplateDto>(response.bodyAsText())
437+
}
438+
}
439+
440+
suspend fun submitLoanForeclosure(
441+
loanId: Int,
442+
request: LoanForeclosureSubmitRequestDto,
443+
) {
444+
val response = mBaseApiManager.loanService.submitLoanForeclosure(
445+
loanId = loanId,
446+
body = request,
447+
)
448+
if (!response.status.isSuccess()) {
449+
throw IllegalStateException(extractErrorMessage(response))
450+
}
451+
}
415452
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2026 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.core.network.mappers.loan
11+
12+
import com.mifos.core.model.objects.template.loan.LoanForeclosureTemplate
13+
import com.mifos.core.model.objects.template.loan.SubmitLoanForeclosureInput
14+
import com.mifos.core.network.model.loan.LoanForeclosureSubmitRequestDto
15+
import com.mifos.core.network.model.loan.LoanForeclosureTemplateDto
16+
17+
fun LoanForeclosureTemplateDto.toDomain(): LoanForeclosureTemplate =
18+
LoanForeclosureTemplate(
19+
loanId = loanId,
20+
amount = amount,
21+
principalPortion = principalPortion,
22+
interestPortion = interestPortion,
23+
feeChargesPortion = feeChargesPortion,
24+
penaltyChargesPortion = penaltyChargesPortion,
25+
)
26+
27+
fun SubmitLoanForeclosureInput.toDto(): LoanForeclosureSubmitRequestDto =
28+
LoanForeclosureSubmitRequestDto(
29+
transactionDate = transactionDate,
30+
note = note,
31+
dateFormat = dateFormat,
32+
locale = locale,
33+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2026 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.core.network.model.loan
11+
12+
import kotlinx.serialization.Serializable
13+
14+
@Serializable
15+
data class LoanForeclosureSubmitRequestDto(
16+
val transactionDate: String,
17+
val note: String,
18+
val dateFormat: String,
19+
val locale: String,
20+
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright 2026 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.core.network.model.loan
11+
12+
import kotlinx.serialization.Serializable
13+
14+
@Serializable
15+
data class LoanForeclosureTemplateDto(
16+
val loanId: Int? = null,
17+
val amount: Double? = null,
18+
val principalPortion: Double? = null,
19+
val interestPortion: Double? = null,
20+
val feeChargesPortion: Double? = null,
21+
val penaltyChargesPortion: Double? = null,
22+
)

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.mifos.core.model.objects.payloads.GroupLoanPayload
2424
import com.mifos.core.model.objects.template.loan.GroupLoanTemplate
2525
import com.mifos.core.network.GenericResponse
2626
import com.mifos.core.network.model.LoansPayload
27+
import com.mifos.core.network.model.loan.LoanForeclosureSubmitRequestDto
2728
import com.mifos.room.basemodel.APIEndPoint
2829
import com.mifos.room.entities.accounts.loans.Loan
2930
import com.mifos.room.entities.accounts.loans.LoanRepaymentRequestEntity
@@ -196,4 +197,18 @@ interface LoanService {
196197
@Path("scheduleId") scheduleId: Int,
197198
@Body request: LoanRescheduleRejectionRequest,
198199
): HttpResponse
200+
201+
@GET(APIEndPoint.LOANS + "/{loanId}/transactions/template?command=foreclosure")
202+
fun getLoanForeclosureTemplate(
203+
@Path("loanId") loanId: Int,
204+
@Query("transactionDate") transactionDate: String,
205+
@Query("dateFormat") dateFormat: String,
206+
@Query("locale") locale: String,
207+
): Flow<HttpResponse>
208+
209+
@POST(APIEndPoint.LOANS + "/{loanId}/transactions?command=foreclosure")
210+
suspend fun submitLoanForeclosure(
211+
@Path("loanId") loanId: Int,
212+
@Body body: LoanForeclosureSubmitRequestDto,
213+
): HttpResponse
199214
}

feature/loan/src/commonMain/composeResources/values/strings.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,4 +475,14 @@
475475
<string name="feature_loan_reschedule_fetch_failed">Failed to load reschedule history.</string>
476476
<string name="feature_loan_reschedule_approve_failed">Failed to approve reschedule.</string>
477477
<string name="feature_loan_reschedule_delete_failed">Failed to delete reschedule.</string>
478+
479+
<!-- Loan Foreclosure -->
480+
<string name="feature_loan_transaction_date">Transaction Date*</string>
481+
<string name="feature_loan_interest">Interest</string>
482+
<string name="feature_loan_fee_amount">Fee Amount</string>
483+
<string name="feature_loan_penalty_amount">Penalty Amount*</string>
484+
<string name="feature_loan_note">Note*</string>
485+
<string name="feature_loan_last_transaction_date_error">transactionDate cannot be earlier than the last transaction date</string>
486+
<string name="feature_loan_foreclosure">Foreclosure</string>
487+
<string name="feature_loan_transaction_amount_mandatory">Transaction Amount*</string>
478488
</resources>

0 commit comments

Comments
 (0)