diff --git a/src/app/loans/common-resolvers/loan-action-button.resolver.ts b/src/app/loans/common-resolvers/loan-action-button.resolver.ts
index 5549e3cb5..ed17c6810 100644
--- a/src/app/loans/common-resolvers/loan-action-button.resolver.ts
+++ b/src/app/loans/common-resolvers/loan-action-button.resolver.ts
@@ -79,6 +79,8 @@ export class LoanActionButtonResolver {
return this.loansService.getLoanActionTemplate(loanId, 'contractTermination');
} else if (loanActionButton === 'Buy Down Fee') {
return this.loansService.getLoanActionTemplate(loanId, 'buyDownFee');
+ } else if (loanActionButton === 'Undo Write-off') {
+ return undefined;
} else {
return undefined;
}
diff --git a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html
index be7954dd6..c13b67ae2 100644
--- a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html
+++ b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.html
@@ -66,3 +66,4 @@
[dataObject]="navigationData"
*ngIf="actions['Add Interest Pause']"
>
+
diff --git a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts
index 3edb352eb..65fb34cf6 100644
--- a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts
+++ b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts
@@ -30,6 +30,7 @@ import { AssetTransferLoanComponent } from './asset-transfer-loan/asset-transfer
import { LoanReagingComponent } from './loan-reaging/loan-reaging.component';
import { LoanReamortizeComponent } from './loan-reamortize/loan-reamortize.component';
import { AddInterestPauseComponent } from './add-interest-pause/add-interest-pause.component';
+import { UndoWriteOffComponent } from './undo-write-off/undo-write-off.component';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
/**
@@ -69,7 +70,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
AssetTransferLoanComponent,
LoanReagingComponent,
LoanReamortizeComponent,
- AddInterestPauseComponent
+ AddInterestPauseComponent,
+ UndoWriteOffComponent
]
})
export class LoanAccountActionsComponent {
@@ -116,6 +118,7 @@ export class LoanAccountActionsComponent {
'Capitalized Income': boolean;
'Contract Termination': boolean;
'Buy Down Fee': boolean;
+ 'Undo Write-off': boolean;
} = {
Close: false,
'Undo Approval': false,
@@ -154,7 +157,8 @@ export class LoanAccountActionsComponent {
'Add Interest Pause': false,
'Capitalized Income': false,
'Contract Termination': false,
- 'Buy Down Fee': false
+ 'Buy Down Fee': false,
+ 'Undo Write-off': false
};
actionButtonData: any;
diff --git a/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.html b/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.html
new file mode 100644
index 000000000..83655be95
--- /dev/null
+++ b/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.html
@@ -0,0 +1,32 @@
+
diff --git a/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.scss b/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.scss
new file mode 100644
index 000000000..4ea838079
--- /dev/null
+++ b/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.scss
@@ -0,0 +1,32 @@
+.container {
+ max-width: 37rem;
+}
+
+.mat-card {
+ padding: 20px;
+}
+
+.layout-column {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+}
+
+.mat-card-actions {
+ padding-top: 20px;
+}
+
+.gap-5px {
+ gap: 5px;
+}
+
+.responsive-column {
+ @media (width <= 768px) {
+ flex-direction: column;
+ align-items: stretch;
+ }
+}
+
+.m-b-20 {
+ margin-bottom: 20px;
+}
diff --git a/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.ts b/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.ts
new file mode 100644
index 000000000..ba1722077
--- /dev/null
+++ b/src/app/loans/loans-view/loan-account-actions/undo-write-off/undo-write-off.component.ts
@@ -0,0 +1,102 @@
+/** Angular Imports */
+import { Component, OnInit, Input } from '@angular/core';
+import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+/** Custom Services */
+import { LoansService } from 'app/loans/loans.service';
+import { SettingsService } from 'app/settings/settings.service';
+import { AlertService } from 'app/core/alert/alert.service';
+import { Dates } from 'app/core/utils/dates';
+import { CdkTextareaAutosize } from '@angular/cdk/text-field';
+import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
+
+/**
+ * Loan Undo Write-off Action
+ */
+@Component({
+ selector: 'mifosx-undo-write-off',
+ templateUrl: './undo-write-off.component.html',
+ styleUrls: ['./undo-write-off.component.scss'],
+ imports: [
+ ...STANDALONE_SHARED_IMPORTS,
+ CdkTextareaAutosize
+ ]
+})
+export class UndoWriteOffComponent implements OnInit {
+ @Input() dataObject: any;
+ /** Loan Id */
+ loanId: string;
+ /** Minimum Date allowed. */
+ minDate = new Date(2000, 0, 1);
+ /** Maximum Date allowed. */
+ maxDate = new Date();
+ /** Undo Write-off Loan Form */
+ undoWriteOffLoanForm: UntypedFormGroup;
+
+ /**
+ * @param {FormBuilder} formBuilder Form Builder.
+ * @param {LoansService} loanService Loan Service.
+ * @param {ActivatedRoute} route Activated Route.
+ * @param {Router} router Router for navigation.
+ * @param {SettingsService} settingsService Settings Service
+ */
+ constructor(
+ private formBuilder: UntypedFormBuilder,
+ private loanService: LoansService,
+ private route: ActivatedRoute,
+ private router: Router,
+ private dateUtils: Dates,
+ private settingsService: SettingsService,
+ private alertService: AlertService
+ ) {
+ this.loanId = this.route.snapshot.params['loanId'];
+ }
+
+ /**
+ * Creates the undo write-off loan form
+ * and initialize with the required values
+ */
+ ngOnInit() {
+ this.maxDate = this.settingsService.businessDate;
+ this.createUndoWriteOffLoanForm();
+ }
+
+ /**
+ * Creates the undo write-off loan form
+ */
+ createUndoWriteOffLoanForm() {
+ this.undoWriteOffLoanForm = this.formBuilder.group({
+ note: ['']
+ });
+ }
+
+ /** Submits the undo write-off form */
+ submit() {
+ const undoWriteOffLoanFormData = this.undoWriteOffLoanForm.value;
+ const locale = this.settingsService.language.code;
+ const dateFormat = this.settingsService.dateFormat;
+ const operationDate = this.settingsService.businessDate;
+ const data = {
+ ...undoWriteOffLoanFormData,
+ transactionDate: this.dateUtils.formatDate(operationDate && new Date(operationDate), dateFormat),
+ transactionAmount: 0,
+ dateFormat,
+ locale
+ };
+
+ this.loanService.submitLoanActionButton(this.loanId, data, 'undowriteoff').subscribe({
+ next: (response: any) => {
+ this.router.navigate(['../../general'], { relativeTo: this.route });
+ },
+ error: (error) => {
+ console.error('Undo write-off failed:', error);
+ this.alertService.alert({
+ type: 'Undo Write-off Failed',
+ message:
+ 'An error occurred while processing the undo write-off transaction. Please try again or contact support if the problem persists.'
+ });
+ }
+ });
+ }
+}
diff --git a/src/app/loans/loans-view/loan-accounts-button-config.ts b/src/app/loans/loans-view/loan-accounts-button-config.ts
index 728388465..c78e5f262 100644
--- a/src/app/loans/loans-view/loan-accounts-button-config.ts
+++ b/src/app/loans/loans-view/loan-accounts-button-config.ts
@@ -124,6 +124,11 @@ export class LoansAccountButtonConfiguration {
name: 'Recovery Payment',
icon: 'briefcase',
taskPermissionName: 'RECOVERYPAYMENT_LOAN'
+ },
+ {
+ name: 'Undo Write-off',
+ icon: 'undo',
+ taskPermissionName: 'UNDOWRITEOFF_LOAN'
}
];
break;
diff --git a/src/assets/translations/en-US.json b/src/assets/translations/en-US.json
index 7fdd159e0..2d0a67cbf 100644
--- a/src/assets/translations/en-US.json
+++ b/src/assets/translations/en-US.json
@@ -2616,6 +2616,7 @@
"Recover From Guarantor": "Recover From Guarantor",
"Recovery Payment": "Recovery Payment",
"Reject": "Reject",
+ "Undo Write-off": "Undo Write-off",
"Reports": "Reports",
"Reschedule": "Reschedule",
"Savings": "Savings",
@@ -3428,7 +3429,8 @@
"Voluntary": "Voluntary",
"Write a note": "Write a note",
"“Maker-Checker” principle requires every tasks": "The “Maker-Checker” principle requires every tasks to be completed by two people to reduce the chance of errors and misuse. One person initiates the process and the second completes it.",
- "Buy Down Fees": "Buy Down Fees"
+ "Buy Down Fees": "Buy Down Fees",
+ "Undo Write-off Description": "This action will reverse the write-off transaction and restore the loan to its previous active status. Please provide a note explaining the reason for this action."
},
"titles": {
"Dashboard": "Dashboard",