/** * 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, inject, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTooltip } from '@angular/material/tooltip'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; import { CertificatePreviewDialogComponent, CertificatePreviewDialogData } from '../certificate-preview-dialog/certificate-preview-dialog.component'; import { downloadShareCertificatePdf, setBankIdentity } from '../certificate-pdf'; import { DscSignService } from '../../dsc-sign-dialog/dsc-sign.service'; import { OrganizationService } from '../../../organization/organization.service'; import { RealShareAccountsViewComponent } from './real-share-accounts-view/real-share-accounts-view.component'; export type ShareClass = 'ORDINARY' | 'PREFERENCE'; export interface ShareCertificateRecord { certificateNo: string; folioNo: string; memberId: string; memberName: string; memberPan: string; memberAddress: string; branch: string; joiningDate: string; shareClass: ShareClass; shareCount: number; faceValue: number; issueDate: string; /** Distinct numeric range of share numbers held (e.g. 1001–1100). */ shareNoFrom: number; shareNoTo: number; /** Total dividend received since joining. */ dividendYtd: number; } @Component({ selector: 'mifosx-share-certificate', templateUrl: './share-certificate.component.html', styleUrls: ['../certificates.shared.scss'], imports: [ ...STANDALONE_SHARED_IMPORTS, CommonModule, FormsModule, FaIconComponent, MatTooltip, RealShareAccountsViewComponent ] }) export class ShareCertificateComponent implements OnInit { private dialog = inject(MatDialog); private snack = inject(MatSnackBar); private dscSign = inject(DscSignService); private organizationService = inject(OrganizationService); /** Toggles between the static sample table and the live m_share_account view. */ viewMode: 'demo' | 'real' = 'demo'; // ── Filters ── search = ''; classFilter: '' | ShareClass = ''; branchFilter = ''; records: ShareCertificateRecord[] = []; readonly classOptions: { value: ShareClass; label: string }[] = [ { value: 'ORDINARY', label: 'Ordinary' }, { value: 'PREFERENCE', label: 'Preference' } ]; ngOnInit(): void { this.records = seedShareCertificates(); // Download here builds the PDF directly, without necessarily opening the preview dialog first, // so this list must set the shared bank identity itself. this.organizationService.getInstitutionProfile().subscribe({ next: (profile: any) => setBankIdentity(profile || {}), error: () => {} }); } // ── Derived list ── get filteredRecords(): ShareCertificateRecord[] { const q = this.search.trim().toLowerCase(); const branch = this.branchFilter.trim().toLowerCase(); return this.records.filter((r) => { if (this.classFilter && r.shareClass !== this.classFilter) return false; if (branch && !r.branch.toLowerCase().includes(branch)) return false; if (!q) return true; return ( r.certificateNo.toLowerCase().includes(q) || r.folioNo.toLowerCase().includes(q) || r.memberId.toLowerCase().includes(q) || r.memberName.toLowerCase().includes(q) || r.memberPan.toLowerCase().includes(q) ); }); } get branchOptions(): string[] { return Array.from(new Set(this.records.map((r) => r.branch))).sort(); } classLabel(c: ShareClass): string { return this.classOptions.find((o) => o.value === c)?.label || c; } totalShares(): number { return this.filteredRecords.reduce((s, r) => s + r.shareCount, 0); } totalShareValue(): number { return this.filteredRecords.reduce((s, r) => s + r.shareCount * r.faceValue, 0); } // ── Actions ── clearFilters(): void { this.search = ''; this.classFilter = ''; this.branchFilter = ''; } viewCertificate(r: ShareCertificateRecord): void { const data: CertificatePreviewDialogData = { kind: 'share', shareCertificate: r }; this.dialog.open(CertificatePreviewDialogComponent, { width: '880px', maxWidth: '96vw', maxHeight: '92vh', autoFocus: false, panelClass: 'cert-preview-dialog', data }); } downloadCertificate(r: ShareCertificateRecord): void { this.dscSign.promptThenDownload( { title: 'Share Certificate', reference: `${r.certificateNo} · Folio ${r.folioNo} · ${r.memberName}`, filename: `Share-Certificate-${r.certificateNo}.pdf` }, (dsc) => downloadShareCertificatePdf(r, dsc) ); } /** Switches between the static sample table and the live m_share_account view. */ toggleViewMode(): void { this.viewMode = this.viewMode === 'demo' ? 'real' : 'demo'; } } // ───────────────────── Mock seed (top-level export) ───────────────────── export function seedShareCertificates(): ShareCertificateRecord[] { return [ { certificateNo: 'SC-2024-000123', folioNo: 'F-00482', memberId: 'MBR000482', memberName: 'Rohan S. Mehta', memberPan: 'ABCPM1234E', memberAddress: 'Flat 902, Skyline Apt, Andheri (E), Mumbai 400069', branch: 'Mumbai — Andheri (E)', joiningDate: '2018-04-22', shareClass: 'ORDINARY', shareCount: 100, faceValue: 100, issueDate: '2018-04-22', shareNoFrom: 48201, shareNoTo: 48300, dividendYtd: 7200 }, { certificateNo: 'SC-2024-000124', folioNo: 'F-00713', memberId: 'MBR000713', memberName: 'Anita Verma', memberPan: 'EFGHV5678A', memberAddress: 'B-12, Connaught Pl, New Delhi 110001', branch: 'New Delhi — Connaught Place', joiningDate: '2019-08-11', shareClass: 'ORDINARY', shareCount: 50, faceValue: 100, issueDate: '2019-08-11', shareNoFrom: 71301, shareNoTo: 71350, dividendYtd: 3000 }, { certificateNo: 'SC-2024-000125', folioNo: 'F-01102', memberId: 'MBR001102', memberName: 'Karthik Rao', memberPan: 'PQRSR2233Z', memberAddress: '24, MG Road, Bengaluru 560001', branch: 'Bengaluru — MG Road', joiningDate: '2020-02-04', shareClass: 'ORDINARY', shareCount: 200, faceValue: 100, issueDate: '2020-02-04', shareNoFrom: 110201, shareNoTo: 110400, dividendYtd: 14400 }, { certificateNo: 'SC-2024-000126', folioNo: 'F-01277', memberId: 'MBR001277', memberName: 'Madhavi Singh', memberPan: 'TUVWS3344K', memberAddress: 'D-5, Greater Kailash, New Delhi 110048', branch: 'New Delhi — Connaught Place', joiningDate: '2017-11-19', shareClass: 'PREFERENCE', shareCount: 75, faceValue: 1000, issueDate: '2017-11-19', shareNoFrom: 12721, shareNoTo: 12795, dividendYtd: 67500 }, { certificateNo: 'SC-2024-000127', folioNo: 'F-01498', memberId: 'MBR001498', memberName: 'Vikram Joshi', memberPan: 'LMNOJ9988X', memberAddress: 'Office 3B, Koregaon Park Road, Pune 411001', branch: 'Pune — Koregaon Park', joiningDate: '2016-06-30', shareClass: 'PREFERENCE', shareCount: 250, faceValue: 1000, issueDate: '2016-06-30', shareNoFrom: 14981, shareNoTo: 15230, dividendYtd: 225000 }, { certificateNo: 'SC-2024-000128', folioNo: 'F-01902', memberId: 'MBR001902', memberName: 'Lakshmi Naidu', memberPan: 'XYZAN7788Q', memberAddress: 'Plot 14, Road No. 3, Banjara Hills, Hyderabad 500034', branch: 'Hyderabad — Banjara Hills', joiningDate: '2021-03-15', shareClass: 'ORDINARY', shareCount: 30, faceValue: 100, issueDate: '2021-03-15', shareNoFrom: 190201, shareNoTo: 190230, dividendYtd: 1800 }, { certificateNo: 'SC-2024-000129', folioNo: 'F-02011', memberId: 'MBR002011', memberName: 'Arjun Banerjee', memberPan: 'TUVWB4455F', memberAddress: '42, Park Street, Kolkata 700016', branch: 'Kolkata — Park Street', joiningDate: '2021-09-08', shareClass: 'ORDINARY', shareCount: 40, faceValue: 100, issueDate: '2021-09-08', shareNoFrom: 201101, shareNoTo: 201140, dividendYtd: 2400 } ]; }