/** * 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/. */ import { Component, OnInit, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { catchError } from 'rxjs/operators'; import { of } from 'rxjs'; import { CashierService } from 'app/cashier/cashier.service'; import { SharesService } from 'app/shares/shares.service'; import { SettingsService } from 'app/settings/settings.service'; /** * Full detail for one additional-share request, opened from the Approval Center list. * * Everything a checker needs to decide without leaving the queue: the board resolution, the tranche * value, and — the piece a bare list row cannot show — the actual proof of funding. A cash tranche * shows every receipt behind it (a member paying in instalments has more than one), a savings * tranche shows the account already debited and its balance, so the approval is never a guess about * where the money came from. */ @Component({ selector: 'mifosx-share-addition-request-detail-dialog', templateUrl: './share-addition-request-detail-dialog.component.html', styleUrls: ['./share-addition-request-detail-dialog.component.scss'], standalone: true, imports: [ CommonModule, MatDialogModule, MatButtonModule, MatIconModule, MatProgressSpinnerModule ] }) export class ShareAdditionRequestDetailDialogComponent implements OnInit { private cashierService = inject(CashierService); private sharesService = inject(SharesService); private settingsService = inject(SettingsService); loading = true; errorMsg = ''; actioning = false; detail: any = null; public dialogRef = inject(MatDialogRef); public data = inject<{ transactionId: number }>(MAT_DIALOG_DATA); ngOnInit(): void { this.cashierService .getShareAdditionRequest(this.data.transactionId) .pipe( catchError((err) => { this.errorMsg = this.readError(err, 'Could not load this request.'); this.loading = false; return of(null); }) ) .subscribe((res: any) => { if (res) { this.detail = res; } this.loading = false; }); } /** How many receipts fund this tranche — the lead one plus any further instalments. */ get voucherCount(): number { return this.detail?.vouchers?.length || 0; } approve(): void { this.act('approveadditionalshares'); } reject(): void { this.act('rejectadditionalshares'); } private act(command: string): void { if (this.actioning || !this.detail) { return; } this.actioning = true; this.errorMsg = ''; const data = { requestedShares: [{ id: this.detail.transactionId }], dateFormat: this.settingsService.dateFormat, locale: this.settingsService.language.code }; this.sharesService .executeSharesAccountCommand(this.detail.shareAccountId, command, data) .pipe( catchError((err) => { this.errorMsg = this.readError(err, 'The request could not be actioned.'); this.actioning = false; return of(null); }) ) .subscribe((res: any) => { if (res) { this.dialogRef.close(true); } else { this.actioning = false; } }); } cancel(): void { this.dialogRef.close(false); } private readError(err: any, fallback: string): string { return ( err?.error?.errors?.[0]?.defaultUserMessage || err?.error?.defaultUserMessage || err?.error?.developerMessage || fallback ); } }