Files
cbsnexora/src/app/investment/investment-masters/investment-masters.component.html
T
niteshandClaude Sonnet 5 ebe67cc410 feat(investment,npa): RBI-grounded targets, GL-tracked interest posting, date/search pickers
- Correct Investment portfolio allocation and Loan Origination product-mix targets against
  RBI's UCB SLR/Non-SLR framework and PSL circulars, with a Target Basis column distinguishing
  RBI-mandated vs board-policy rows (Excel export included).
- Expand Investment holdings dataset with more near-term maturities so the Due-Date Diary
  reflects a realistic spread across FD/Govt Security/Non-SLR/Bond.
- Add From/To period-based Interest Calculation & Post (with GL selection for both posting and
  receiving) across the Investment Interest module, FD Entry and Bond Entry screens; fix a bug
  where a posted period kept re-appearing as due since accrual wasn't tracked per-holding.
- Add a reusable DD-MM-YYYY date-picker component and roll it out across all Investment date
  fields.
- NPA Summary Report: drop SMA-0/1/2 from the stage-wise table (kept in Day-wise Overdue only).
- NPA Recovery Report: add Account Type / NPA Category / Target-vs-Actual columns, a shared
  Account Type filter driving both the account picker and the register, and a searchable
  (fixed-position, not clipped by card overflow) account select for long lists.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 19:26:19 +05:30

563 lines
18 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 · MASTERS</div>
<h1 class="pg-title">Investment Masters</h1>
<p class="pg-sub">
Bank/Party, Script, SubType, Broker, Control Parameter, LIEN Reason, Mutual Fund Product, SGL Bank and Script
Market Detail masters.
</p>
</div>
<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 === 'party'"
(click)="setTab('party')"
>
04 Bank / Party Master
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'script'"
(click)="setTab('script')"
>
05 Script Master
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'subtype'"
(click)="setTab('subtype')"
>
06 SubType Master
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'broker'"
(click)="setTab('broker')"
>
07 Broker Master
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'control'"
(click)="setTab('control')"
>
08 Control Parameter
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'dailyscript'"
(click)="setTab('dailyscript')"
>
09 Daily Script Master
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'lien'"
(click)="setTab('lien')"
>
10 LIEN Reason Master
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'mfproduct'"
(click)="setTab('mfproduct')"
>
11 Mutual Fund Product Master
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'sglbank'"
(click)="setTab('sglbank')"
>
12 SGL Bank Master
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeTab === 'marketdetail'"
(click)="setTab('marketdetail')"
>
13 Script Market Detail
</button>
</div>
<!-- PARTY MASTER -->
@if (activeTab === 'party') {
<div class="pg-card">
<div class="pos-section-label">Add Bank / Party</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Party Name *</span><input type="text" [(ngModel)]="newParty.partyName"
/></label>
<label class="inv-form-field">
<span>Party Type *</span>
<select [(ngModel)]="newParty.partyType">
<option [ngValue]="undefined">-- Select --</option>
<option value="BANK">BANK</option>
<option value="CORPORATE">CORPORATE</option>
<option value="GOVT">GOVT</option>
<option value="AMC">AMC</option>
<option value="EXCHANGE">EXCHANGE</option>
<option value="COOP_SOCIETY">COOP SOCIETY</option>
</select>
</label>
<label class="inv-form-field"><span>PAN No</span><input type="text" [(ngModel)]="newParty.panNo" /></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addParty()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>Party Code</th>
<th>Party Name</th>
<th>Type</th>
<th>PAN No</th>
</tr>
</thead>
<tbody>
@for (p of parties; track p.partyCode) {
<tr>
<td>
<span class="pg-chip">{{ p.partyCode }}</span>
</td>
<td>{{ p.partyName }}</td>
<td>{{ p.partyType }}</td>
<td>{{ p.panNo }}</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- SCRIPT MASTER -->
@if (activeTab === 'script') {
<div class="pg-card">
<div class="pos-section-label">Add Script</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Script Code</span><input type="text" [(ngModel)]="newScript.scriptCode"
/></label>
<label class="inv-form-field"
><span>Script Name *</span><input type="text" [(ngModel)]="newScript.scriptName"
/></label>
<label class="inv-form-field">
<span>Instrument Type *</span>
<select [(ngModel)]="newScript.instrumentType">
<option [ngValue]="undefined">-- Select --</option>
@for (t of instrumentTypes; track t) {
<option [value]="t">{{ t }}</option>
}
</select>
</label>
<label class="inv-form-field"><span>ISIN</span><input type="text" [(ngModel)]="newScript.isin" /></label>
<label class="inv-form-field"
><span>Face Value / Unit</span><input type="number" [(ngModel)]="newScript.faceValuePerUnit"
/></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addScript()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>Script Code</th>
<th>Script Name</th>
<th>Instrument</th>
<th>ISIN</th>
<th class="num">Face Value/Unit</th>
</tr>
</thead>
<tbody>
@for (s of scripts; track s.scriptCode) {
<tr>
<td>
<span class="pg-chip">{{ s.scriptCode }}</span>
</td>
<td>{{ s.scriptName }}</td>
<td>{{ s.instrumentType }}</td>
<td>{{ s.isin || '—' }}</td>
<td class="num">{{ s.faceValuePerUnit }}</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- SUBTYPE MASTER -->
@if (activeTab === 'subtype') {
<div class="pg-card">
<div class="pos-section-label">Add Sub Type</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Sub Type Name *</span><input type="text" [(ngModel)]="newSubType.subTypeName"
/></label>
<label class="inv-form-field">
<span>Instrument Type *</span>
<select [(ngModel)]="newSubType.instrumentType">
<option [ngValue]="undefined">-- Select --</option>
@for (t of instrumentTypes; track t) {
<option [value]="t">{{ t }}</option>
}
</select>
</label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addSubType()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>Code</th>
<th>Sub Type</th>
<th>Instrument</th>
</tr>
</thead>
<tbody>
@for (s of subTypes; track s.subTypeCode + s.subTypeName) {
<tr>
<td>
<span class="pg-chip">{{ s.subTypeCode }}</span>
</td>
<td>{{ s.subTypeName }}</td>
<td>{{ s.instrumentType }}</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- BROKER MASTER -->
@if (activeTab === 'broker') {
<div class="pg-card">
<div class="pos-section-label">Add Broker</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Broker Name *</span><input type="text" [(ngModel)]="newBroker.brokerName"
/></label>
<label class="inv-form-field"
><span>Contact No</span><input type="text" [(ngModel)]="newBroker.contactNo"
/></label>
<label class="inv-form-field"
><span>Empanelled On</span><mifosx-date-ddmmyyyy [(ngModel)]="newBroker.empanelledOn"></mifosx-date-ddmmyyyy
></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addBroker()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>Broker Code</th>
<th>Broker Name</th>
<th>Contact</th>
<th>Empanelled On</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@for (b of brokers; track b.brokerCode) {
<tr>
<td>
<span class="pg-chip">{{ b.brokerCode }}</span>
</td>
<td>{{ b.brokerName }}</td>
<td>{{ b.contactNo }}</td>
<td>{{ b.empanelledOn }}</td>
<td>
<span class="inv-badge inv-badge--active">{{ b.status }}</span>
</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- CONTROL PARAMETER -->
@if (activeTab === 'control') {
<div class="pg-card">
<div class="pos-section-label">Add Control Parameter</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Parameter Name *</span><input type="text" [(ngModel)]="newControlParam.paramName"
/></label>
<label class="inv-form-field"
><span>Value *</span><input type="text" [(ngModel)]="newControlParam.paramValue"
/></label>
<label class="inv-form-field"
><span>Description</span><input type="text" [(ngModel)]="newControlParam.description"
/></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addControlParam()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>Parameter</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
@for (c of controlParams; track c.paramName) {
<tr>
<td>
<span class="pg-chip">{{ c.paramName }}</span>
</td>
<td class="num">{{ c.paramValue }}</td>
<td>{{ c.description }}</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- DAILY SCRIPT MASTER -->
@if (activeTab === 'dailyscript') {
<div class="pg-card">
<div class="pos-section-label">Add Daily Script Rate</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Rate Date *</span><mifosx-date-ddmmyyyy [(ngModel)]="newDailyRate.rateDate"></mifosx-date-ddmmyyyy
></label>
<label class="inv-form-field">
<span>Script Code *</span>
<select [(ngModel)]="newDailyRate.scriptCode">
<option [ngValue]="undefined">-- Select --</option>
@for (s of scripts; track s.scriptCode) {
<option [value]="s.scriptCode">{{ s.scriptCode }} — {{ s.scriptName }}</option>
}
</select>
</label>
<label class="inv-form-field"
><span>Open Rate</span><input type="number" [(ngModel)]="newDailyRate.openRate" step="0.01"
/></label>
<label class="inv-form-field"
><span>Close Rate *</span><input type="number" [(ngModel)]="newDailyRate.closeRate" step="0.01"
/></label>
<label class="inv-form-field"
><span>High Rate</span><input type="number" [(ngModel)]="newDailyRate.highRate" step="0.01"
/></label>
<label class="inv-form-field"
><span>Low Rate</span><input type="number" [(ngModel)]="newDailyRate.lowRate" step="0.01"
/></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addDailyRate()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>Rate Date</th>
<th>Script Code</th>
<th>Script Name</th>
<th class="num">Open</th>
<th class="num">High</th>
<th class="num">Low</th>
<th class="num">Close</th>
</tr>
</thead>
<tbody>
@for (r of dailyScriptRates; track r.rateDate + r.scriptCode) {
<tr>
<td>{{ r.rateDate }}</td>
<td>
<span class="pg-chip">{{ r.scriptCode }}</span>
</td>
<td>{{ r.scriptName }}</td>
<td class="num">{{ r.openRate | number: '1.2-2' }}</td>
<td class="num">{{ r.highRate | number: '1.2-2' }}</td>
<td class="num">{{ r.lowRate | number: '1.2-2' }}</td>
<td class="num">{{ r.closeRate | number: '1.2-2' }}</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- LIEN REASON MASTER -->
@if (activeTab === 'lien') {
<div class="pg-card">
<div class="pos-section-label">Add LIEN Reason</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Reason Description *</span><input type="text" [(ngModel)]="newLienReason.reasonDescription"
/></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addLienReason()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>Reason Code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
@for (l of lienReasons; track l.reasonCode) {
<tr>
<td>
<span class="pg-chip">{{ l.reasonCode }}</span>
</td>
<td>{{ l.reasonDescription }}</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- MUTUAL FUND PRODUCT MASTER -->
@if (activeTab === 'mfproduct') {
<div class="pg-card">
<div class="pos-section-label">Add Mutual Fund Product</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Product Name *</span><input type="text" [(ngModel)]="newMfProduct.productName"
/></label>
<label class="inv-form-field"
><span>AMC Name *</span><input type="text" [(ngModel)]="newMfProduct.amcName"
/></label>
<label class="inv-form-field"
><span>Category</span><input type="text" [(ngModel)]="newMfProduct.category"
/></label>
<label class="inv-form-field">
<span>Risk Level</span>
<select [(ngModel)]="newMfProduct.riskLevel">
<option value="LOW">LOW</option>
<option value="MODERATE">MODERATE</option>
<option value="HIGH">HIGH</option>
</select>
</label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addMfProduct()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>Product Code</th>
<th>Product Name</th>
<th>AMC</th>
<th>Category</th>
<th>Risk</th>
</tr>
</thead>
<tbody>
@for (m of mfProducts; track m.productCode) {
<tr>
<td>
<span class="pg-chip">{{ m.productCode }}</span>
</td>
<td>{{ m.productName }}</td>
<td>{{ m.amcName }}</td>
<td>{{ m.category }}</td>
<td>{{ m.riskLevel }}</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- SGL BANK MASTER -->
@if (activeTab === 'sglbank') {
<div class="pg-card">
<div class="pos-section-label">Add SGL Bank</div>
<div class="inv-form-grid">
<label class="inv-form-field"
><span>Bank Name *</span><input type="text" [(ngModel)]="newSglBank.bankName"
/></label>
<label class="inv-form-field"><span>Branch</span><input type="text" [(ngModel)]="newSglBank.branch" /></label>
</div>
<div class="inv-form-actions">
<button type="button" class="pg-btn pg-btn--primary" (click)="addSglBank()">Save</button>
</div>
<table class="pg-table">
<thead>
<tr>
<th>SGL Code</th>
<th>Bank Name</th>
<th>Branch</th>
</tr>
</thead>
<tbody>
@for (s of sglBanks; track s.sglCode) {
<tr>
<td>
<span class="pg-chip">{{ s.sglCode }}</span>
</td>
<td>{{ s.bankName }}</td>
<td>{{ s.branch }}</td>
</tr>
}
</tbody>
</table>
</div>
}
<!-- SCRIPT MARKET DETAIL (also covers "09 Daily Script Master") -->
@if (activeTab === 'marketdetail') {
<div class="pg-card">
<div class="pos-section-label">Script Market Detail (Daily Script Rates)</div>
<table class="pg-table">
<thead>
<tr>
<th>Script Code</th>
<th class="num">Market Price</th>
<th>As On</th>
<th class="num">YTM (%)</th>
</tr>
</thead>
<tbody>
@for (m of marketDetails; track m.scriptCode) {
<tr>
<td>
<span class="pg-chip">{{ m.scriptCode }}</span>
</td>
<td class="num">₹{{ m.marketPrice | number: '1.2-2' }}</td>
<td>{{ m.asOnDate }}</td>
<td class="num">{{ m.ytm }}%</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
<div class="inv-toast" [class.show]="toastVisible">{{ toastMsg }}</div>