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.
284 lines
9.9 KiB
HTML
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>
|