/** * Copyright since 2025 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 http://mozilla.org/MPL/2.0/. */ /** Angular Imports */ import { Component, OnInit, inject } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; /** Custom Services */ import { NachClearingService } from '../../nachclearing.service'; import { ClearingService } from '../../../clearing-network/clearing.service'; import { clearingError } from '../../../clearing-network/clearing-status'; /** Pass or return a single NACH transaction. Return requires a standardized reason code. */ @Component({ selector: 'mifosx-nach-txn-decision-dialog', templateUrl: './txn-decision-dialog.component.html', styleUrls: ['./txn-decision-dialog.component.scss'], imports: [ ...STANDALONE_SHARED_IMPORTS, MatButtonModule, MatDialogModule, MatSnackBarModule ] }) export class TxnDecisionDialogComponent implements OnInit { dialogRef = inject>(MatDialogRef); data = inject<{ transaction: any }>(MAT_DIALOG_DATA); private formBuilder = inject(UntypedFormBuilder); private nachService = inject(NachClearingService); private clearingService = inject(ClearingService); private snackBar = inject(MatSnackBar); decision: 'PASS' | 'RETURN' = 'PASS'; reasonCodes: any[] = []; busy = false; form: UntypedFormGroup; constructor() { this.form = this.formBuilder.group({ returnReasonCode: [''], reason: [''] }); } ngOnInit(): void { this.clearingService.getReturnReasonCodes('NACH').subscribe((res: any) => { this.reasonCodes = Array.isArray(res) ? res : (res?.pageItems ?? []); }); } setDecision(decision: 'PASS' | 'RETURN'): void { this.decision = decision; const rc = this.form.get('returnReasonCode'); if (decision === 'RETURN') { rc?.setValidators([Validators.required]); } else { rc?.clearValidators(); } rc?.updateValueAndValidity(); } private notify(message: string, isError = false): void { this.snackBar.open(message, 'Dismiss', { duration: isError ? 6000 : 3000 }); } submit(): void { if (this.busy) { return; } const id = this.data.transaction.id; this.busy = true; if (this.decision === 'PASS') { this.nachService.passTransaction(id).subscribe({ next: () => this.done('Transaction passed'), error: (err: any) => this.fail(err, 'Could not pass the transaction') }); } else { if (this.form.invalid) { this.busy = false; return; } this.nachService.returnTransaction(id, this.form.value).subscribe({ next: () => this.done('Transaction returned'), error: (err: any) => this.fail(err, 'Could not return the transaction') }); } } private done(message: string): void { this.busy = false; this.notify(message); this.dialogRef.close({ actioned: true }); } private fail(err: any, fallback: string): void { this.busy = false; this.notify(clearingError(err, fallback), true); } }