Files
cbsnexora/src/app/investment/share-investment/share-investment.component.html
T
nitesh 0832017508 feat(investment,reconciliation): add Export to Excel across Investment, fix export popup
Adds a shared Export to Excel utility (investment-export.ts) and wires it
into every listing/report screen in the Investment module — Dashboard
(break-up + allocation), Reports (all ~20 report shapes), Interest (per
active tab), the FD/Bond/Share Holdings registers, and Masters (per active
master tab). Entry/transaction forms intentionally have no export button.
No sign-off is included here, matching the request to keep that feature
reconciliation-only.

Also fixes the Reconciliation export flow: the Prepared/Checked/Approved
sign-off is now an optional one-off popup shown when "Export to Excel" is
clicked (fields are blank by default and downloading works whether or not
they're filled), replacing the earlier always-visible sign-off card. Also
fixes three reconciliation reports (Sundry Dr/Cr, NEFT/RTGS, UDIR) whose
labels contain "/" — an Excel-forbidden worksheet-name character — which
was silently aborting their export.
2026-08-01 19:20:53 +05:30

284 lines
9.9 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="pg">
<header class="pg-head">
<div>
<div class="pg-eyebrow">TREASURY · INVESTMENT · SHARE</div>
<h1 class="pg-title">Share Entry</h1>
<p class="pg-sub">
Equity and cooperative-society share holdings — Purchase, Dividend, Sell and Write-off entries.
</p>
</div>
@if (activeTab === 'holdings') {
<div class="pg-toolbar">
<button type="button" class="pg-btn pg-btn--ghost" [disabled]="generating" (click)="exportExcel()">
{{ generating ? 'Exporting…' : 'Export to Excel' }}
</button>
</div>
}
</header>
<div class="cctr-tabs">
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'holdings'"
(click)="setTab('holdings')"
>
Holdings
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'purchase'"
(click)="setTab('purchase')"
>
01 Share Purchase Entry
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'dividend'"
(click)="setTab('dividend')"
>
02 Share Interest / Dividend Entry
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'sell'"
(click)="setTab('sell')"
>
03 Share Sell Entry
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'writeoff'"
(click)="setTab('writeoff')"
>
04 Share Write Off Entry
</button>
</div>
<!-- HOLDINGS -->
@if (activeTab === 'holdings') {
<div class="pg-card">
<div class="pos-section-label">Share Holdings Register</div>
<table class="pg-table">
<thead>
<tr>
<th>Cert No</th>
<th>Script</th>
<th>Party</th>
<th class="num">Units</th>
<th class="num">Rate</th>
<th class="num">Face Value</th>
<th>Purchase Date</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@for (h of holdings; track h.certNo) {
<tr>
<td>
<span class="pg-chip">{{ h.certNo }}</span>
</td>
<td>{{ h.scriptName }}</td>
<td>{{ h.party }}</td>
<td class="num">{{ h.units | number }}</td>
<td class="num">₹{{ h.purchaseRate | number: '1.2-2' }}</td>
<td class="num">₹{{ h.faceValue | number: '1.2-2' }}</td>
<td>{{ h.purchaseDate }}</td>
<td>
<span [class]="statusClass(h)">{{ h.status }}</span>
</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- PURCHASE ENTRY -->
@if (activeTab === 'purchase') {
<div class="pg-card">
<div class="pos-section-label">Investment - Share Purchase Entry</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Cert No</span><input type="text" [(ngModel)]="purchaseForm.certNo" readonly
/></label>
<label class="inv-form-field"
><span>Script Code</span><input type="text" [(ngModel)]="purchaseForm.scriptCode"
/></label>
<label class="inv-form-field"
><span>Script/Company Name *</span><input type="text" [(ngModel)]="purchaseForm.scriptName"
/></label>
<label class="inv-form-field"
><span>Party / Exchange</span><input type="text" [(ngModel)]="purchaseForm.party"
/></label>
<label class="inv-form-field">
<span>Sub Type</span>
<select [(ngModel)]="purchaseForm.subType">
<option value="EQUITY">EQUITY</option>
<option value="CO-OP SHARE">CO-OP SHARE</option>
</select>
</label>
<label class="inv-form-field"
><span>No. of Units *</span><input type="number" [(ngModel)]="purchaseForm.units" min="0"
/></label>
<label class="inv-form-field"
><span>Purchase Rate *</span><input type="number" [(ngModel)]="purchaseForm.purchaseRate" min="0" step="0.01"
/></label>
<label class="inv-form-field"
><span>Purchase Date *</span
><input type="text" [(ngModel)]="purchaseForm.purchaseDate" placeholder="DD-MM-YYYY"
/></label>
<label class="inv-form-field"
><span>Broker Code</span><input type="text" [(ngModel)]="purchaseForm.brokerCode"
/></label>
<label class="inv-form-field"
><span>CR To A/c</span><input type="text" [(ngModel)]="purchaseForm.crToAc"
/></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--ghost" (click)="cancelPurchase()">Cancel</button>
<button type="button" class="pg-btn pg-btn--primary" (click)="savePurchase()">Save</button>
</div>
</div>
}
<!-- DIVIDEND ENTRY -->
@if (activeTab === 'dividend') {
<div class="pg-card">
<div class="pos-section-label">Investment - Share Interest / Dividend Entry</div>
<div class="inv-form-grid">
<label class="inv-form-field">
<span>Cert No *</span>
<select [(ngModel)]="dividendCertNo">
<option value="">-- Select --</option>
@for (h of activeHoldings; track h.certNo) {
<option [value]="h.certNo">{{ h.certNo }} — {{ h.scriptName }}</option>
}
</select>
</label>
@if (dividendHolding; as h) {
<label class="inv-form-field"><span>Units Held</span><input type="text" [value]="h.units" readonly /></label>
}
<label class="inv-form-field"
><span>Dividend per Share *</span><input type="number" [(ngModel)]="dividendPerShare" min="0" step="0.01"
/></label>
<label class="inv-form-field"
><span>Total Dividend (computed)</span
><input type="text" [value]="'₹' + (dividendAmount | number: '1.2-2')" readonly
/></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="saveDividend()">Save</button>
</div>
</div>
}
<!-- SELL ENTRY -->
@if (activeTab === 'sell') {
<div class="pg-card">
<div class="pos-section-label">Investment - Share Sell Entry</div>
<div class="inv-form-grid">
<label class="inv-form-field">
<span>Cert No *</span>
<select [(ngModel)]="sellCertNo">
<option value="">-- Select --</option>
@for (h of activeHoldings; track h.certNo) {
<option [value]="h.certNo">{{ h.certNo }} — {{ h.scriptName }}</option>
}
</select>
</label>
@if (sellHolding; as h) {
<label class="inv-form-field"><span>Units Held</span><input type="text" [value]="h.units" readonly /></label>
}
<label class="inv-form-field"
><span>Units to Sell *</span><input type="number" [(ngModel)]="sellUnits" min="0"
/></label>
<label class="inv-form-field"
><span>Sell Rate *</span><input type="number" [(ngModel)]="sellRate" min="0" step="0.01"
/></label>
<label class="inv-form-field"
><span>Consideration (computed)</span
><input type="text" [value]="'₹' + (sellConsideration | number: '1.2-2')" readonly
/></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="saveSell()">Save</button>
</div>
</div>
}
<!-- WRITE OFF ENTRY -->
@if (activeTab === 'writeoff') {
<div class="pg-card">
<div class="pos-section-label">Investment - Share Write Off Entry</div>
<div class="inv-form-grid">
<label class="inv-form-field">
<span>Cert No *</span>
<select [(ngModel)]="writeoffCertNo">
<option value="">-- Select --</option>
@for (h of activeHoldings; track h.certNo) {
<option [value]="h.certNo">{{ h.certNo }} — {{ h.scriptName }}</option>
}
</select>
</label>
@if (writeoffHolding; as h) {
<label class="inv-form-field"
><span>Face Value to be Written Off</span
><input type="text" [value]="'₹' + (h.faceValue | number: '1.2-2')" readonly
/></label>
}
<label class="inv-form-field"><span>Reason *</span><input type="text" [(ngModel)]="writeoffReason" /></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="saveWriteoff()">Save</button>
</div>
</div>
}
@if (activeTab !== 'holdings') {
<div class="pg-card">
<div class="pos-section-label">Share Transaction Log</div>
<table class="pg-table">
<thead>
<tr>
<th>Date</th>
<th>Voucher No</th>
<th>Cert No</th>
<th>Type</th>
<th>Particulars</th>
<th class="num">Amount</th>
</tr>
</thead>
<tbody>
@for (t of txns; track t.voucherNo) {
<tr>
<td>{{ t.txnDate }}</td>
<td>
<span class="pg-chip">{{ t.voucherNo }}</span>
</td>
<td>{{ t.certNo }}</td>
<td>{{ t.txnType }}</td>
<td>{{ t.particulars }}</td>
<td class="num">₹{{ t.amount | number: '1.2-2' }}</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
<div class="inv-toast" [class.show]="toastVisible">{{ toastMsg }}</div>