/** * 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 { ActivatedRoute, Router } from '@angular/router'; import { catchError } from 'rxjs/operators'; import { of } from 'rxjs'; import { PendingDividendsService } from './pending-dividends.service'; import { ProductsService } from '../../../products/products.service'; import { ViewDividendComponent } from '../../../products/share-products/view-dividend/view-dividend.component'; /** * Approval Center tab — every Share Product dividend declaration still awaiting approval, across * all products (Fineract's own screens only show one product's dividends at a time). Approving * directly from here calls the same native Fineract "approve dividend" command used by the * per-product View Dividend page. */ @Component({ selector: 'mifosx-dividend-requests', templateUrl: './dividend-requests.component.html', styleUrls: [ '../../../cashier/cashier-shared.scss', '../../../clerk/clerk-shared.scss', './dividend-requests.component.scss' ], standalone: true, imports: [ CommonModule, ViewDividendComponent ] }) export class DividendRequestsComponent implements OnInit { private service = inject(PendingDividendsService); private productsService = inject(ProductsService); private route = inject(ActivatedRoute); private router = inject(Router); rows: any[] = []; loading = false; loaded = false; approvingId: number | null = null; approveError: Record = {}; showViewModal = false; viewProductId: number | null = null; viewDividendId: number | null = null; ngOnInit(): void { this.openRequestedDeclaration(); this.load(); } /** * Opens the breakdown straight away when the officer arrived here from a specific declaration. * * The Dividends list sends them here to approve one declaration in particular, so making them * find its row again in a list of every pending declaration would undo the point of the link. * Read from the query string rather than a service so a refreshed or shared URL still opens the * same declaration. */ private openRequestedDeclaration(): void { const params = this.route.snapshot.queryParams; const productId = Number(params['productId']); const dividendId = Number(params['dividendId']); if (!productId || !dividendId) { return; } this.viewProductId = productId; this.viewDividendId = dividendId; this.showViewModal = true; } openView(row: any): void { this.viewProductId = row.productId; this.viewDividendId = row.dividendId; this.showViewModal = true; } closeViewModal(): void { this.showViewModal = false; this.viewProductId = null; this.viewDividendId = null; // Dropped from the URL as well, or the declaration the officer just closed would reopen on the // next refresh and there would be no way to get back to the plain list. if (this.route.snapshot.queryParams['dividendId']) { this.router.navigate([], { relativeTo: this.route, queryParams: {}, replaceUrl: true }); } } onViewActionCompleted(): void { this.closeViewModal(); this.load(); } load(): void { this.loading = true; this.service .list() .pipe(catchError(() => of([]))) .subscribe((res: any[]) => { this.rows = res ?? []; this.loading = false; this.loaded = true; }); } approve(row: any): void { this.approvingId = row.dividendId; delete this.approveError[row.dividendId]; this.productsService .approveDividend(row.productId, row.dividendId, { productId: row.productId, dividendId: row.dividendId }) .subscribe({ next: () => { this.approvingId = null; this.load(); }, error: (err: any) => { this.approvingId = null; this.approveError[row.dividendId] = err?.error?.defaultUserMessage || err?.error?.message || 'Approve failed.'; } }); } }