Files
cbsnexora/src/app/shares/reports/share-distinctive-numbers/share-distinctive-numbers.component.html
T
niteshandClaude Sonnet 5 c7428d0cb2 feat(shares): dynamic Share Reports module, voucher attach/GL sync fixes
- Add the full Share Reports surface (final balance, account statement,
  issued/status/nominal/share-wise/guarantor/member-interest reports, enquiry,
  payment certificate, share detail, dividend statement, folio statement,
  distinctive numbers, area-wise, mailing labels/letters, share transfer) as
  standalone routed components, wired into the Share menu
- Wire the unattributed Share Collection receipt list into Apply Collection
  and Apply Additional Shares, with an Attach action independent of
  account/client
- Sync the GL Account and Voucher No fields to whichever receipt is ticked or
  found, and surface the receipt's real Dr/Cr GL entries in its detail popup
- Block Apply Additional Shares until the account's original application is
  settled

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-18 13:06:02 +05:30

153 lines
5.5 KiB
HTML

<!--
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/.
-->
<div class="cert-root">
<div class="cert-head">
<div class="cert-head-l">
<fa-icon icon="tag" class="cert-head-ic"></fa-icon>
<div>
<h2 class="cert-head-t">Share Distinctive Number Detail</h2>
<div class="cert-head-s">
Which numbered shares each member holds — the range every allotment covers, per share class.
</div>
</div>
</div>
<div class="cert-head-r">
<button class="cert-cta-btn" (click)="exportCsv()" [disabled]="loading || !filteredRows.length">
<fa-icon icon="file-alt"></fa-icon> Export CSV
</button>
<button class="cert-cta-btn" (click)="print()" [disabled]="loading || !filteredRows.length">
<fa-icon icon="print"></fa-icon> Print
</button>
</div>
</div>
@if (totals) {
<div class="cert-kpis">
<div class="cert-kpi cert-kpi--blue">
<fa-icon icon="file-alt" class="cert-kpi-ic"></fa-icon>
<div>
<div class="cert-kpi-n">{{ totals.allotmentCount | number }}</div>
<div class="cert-kpi-l">Numbered Allotments</div>
</div>
</div>
<div class="cert-kpi cert-kpi--green">
<fa-icon icon="coins" class="cert-kpi-ic"></fa-icon>
<div>
<div class="cert-kpi-n">{{ totals.sharesNumbered | number }}</div>
<div class="cert-kpi-l">Shares Numbered</div>
</div>
</div>
</div>
}
<!-- The numbers are derived, not recorded. Said plainly so nobody reads them as an independent
register the society has been maintaining. -->
<div class="srep-warn">
<fa-icon icon="info-circle"></fa-icon>
<span>
Distinctive numbers are <b>derived from issue order</b> within each share class — no distinctive-number column
exists in the system, so each paid-up allotment takes the next block in sequence. Redeemed shares leave a gap
rather than renumbering everybody else, exactly as a physical register would. Only paid-up allotments are
numbered.
</span>
</div>
<div class="cert-filters">
<div class="cert-filter">
<label>Find share number</label>
<div class="cert-input-ic">
<fa-icon icon="search"></fa-icon>
<input type="number" min="1" [(ngModel)]="shareNumberLookup" placeholder="e.g. 175 — who holds it?" />
</div>
</div>
<div class="cert-filter">
<label>Member / A/c No / Resolution</label>
<div class="cert-input-ic">
<fa-icon icon="search"></fa-icon>
<input type="text" [(ngModel)]="search" placeholder="e.g. member name" />
</div>
</div>
<div class="cert-filter">
<label>Share class</label>
<select [(ngModel)]="productFilter">
<option value="">All classes</option>
@for (p of productOptions; track p) {
<option [value]="p">{{ p }}</option>
}
</select>
</div>
<div class="cert-filter">
<label>&nbsp;</label>
<button class="cert-cta-btn" (click)="clearFilters()">Clear filters</button>
</div>
</div>
@if (loading) {
<div class="srep-state">Loading the distinctive number register…</div>
} @else if (loadError) {
<div class="srep-state srep-state--error"><fa-icon icon="exclamation-circle"></fa-icon> {{ loadError }}</div>
} @else if (!rows.length) {
<div class="srep-state">No paid-up allotment has been made yet, so no share carries a number.</div>
} @else if (!filteredRows.length) {
<div class="srep-state">
@if (shareNumberLookup) {
Share number {{ shareNumberLookup | number }} has not been allotted in this share class.
} @else {
No allotment matches the filters applied.
}
</div>
} @else {
<div class="srep-table-wrap">
<table class="srep-table">
<thead>
<tr>
<th>Share Class</th>
<th>Distinctive Numbers</th>
<th class="srep-num">Shares</th>
<th>Member</th>
<th>Membership No</th>
<th>Share A/c No</th>
<th>Branch</th>
<th>Allotment Date</th>
<th>Funded By</th>
<th>Board Resolution</th>
</tr>
</thead>
<tbody>
@for (row of filteredRows; track row.transactionId) {
<tr class="srep-row--click" (click)="openAccount(row)">
<td>{{ row.productName }}</td>
<td class="srep-mono">
<b>{{ range(row) }}</b>
</td>
<td class="srep-num">{{ row.shares | number }}</td>
<td>{{ row.clientName }}</td>
<td class="srep-mono">{{ row.cifNumber || '—' }}</td>
<td class="srep-mono">{{ row.accountNo }}</td>
<td>{{ row.officeName || '—' }}</td>
<td>{{ row.allotmentDate }}</td>
<td>{{ funding(row.fundingSource) }}</td>
<td class="srep-mono">{{ row.resolutionNumber || '—' }}</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="2">
{{ isFiltered ? 'Total (filtered)' : 'Total' }} — {{ filteredRows.length | number }} allotments
</td>
<td class="srep-num">{{ shownShares | number }}</td>
<td colspan="7"></td>
</tr>
</tfoot>
</table>
</div>
}
</div>