- Add Transaction Entry screen with full account details panel (personal info, joint holders, nominees, KYC, balances) - Role-based layout: CASHIER role hides nav/sidebar/ticker, redirects to /cashier/transaction-entry on login - Denomination entry with opening/closing position preview (notes first then coins, stepper +/- round button inputs) - Auto-fetch savings/current/FD/RD accounts with associations, client KYC, nominees, addresses, family members (S/D/W/H/O) - Submit deposit/withdrawal via POST /transactions with denominationBreakdown - Cashier position auto-loads for CASHIER role (no filter dropdowns) - Pagination added to cash-history tabs and currency-exchange-detail - Cashier menu simplified for cashier role permissions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
645 lines
28 KiB
HTML
645 lines
28 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="te-root">
|
||
<!-- ── ENTRY GRID shown when no account loaded yet ────────────────── -->
|
||
@if (!accountDetails && !loadingAccount) {
|
||
<div class="te-grid-wrap">
|
||
<table class="te-grid">
|
||
<thead>
|
||
<tr>
|
||
<th>Typ</th>
|
||
<th>Br.</th>
|
||
<th>Tr.Tp.</th>
|
||
<th>Actyp</th>
|
||
<th>A/c No.</th>
|
||
<th>Ecs A/c No.</th>
|
||
<th>Db./Cr.</th>
|
||
<th>Cheque No.</th>
|
||
<th>Amount</th>
|
||
<th>Description</th>
|
||
<th>Tok.No.</th>
|
||
<th>Cheq.Date</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@for (row of rows; track $index; let i = $index) {
|
||
<tr [class.te-row--selected]="selectedRow === row" (click)="onRowSelect(row, i)">
|
||
<td><input class="te-cell te-cell--xs" [(ngModel)]="row.typ" (click)="$event.stopPropagation()" /></td>
|
||
<td>
|
||
<input
|
||
class="te-cell te-cell--xs"
|
||
type="number"
|
||
[(ngModel)]="row.br"
|
||
(click)="$event.stopPropagation()"
|
||
/>
|
||
</td>
|
||
<td>
|
||
<select class="te-cell te-cell--sm" [(ngModel)]="row.trTp" (click)="$event.stopPropagation()">
|
||
<option value=""></option>
|
||
@for (t of trTpOptions; track t) {
|
||
<option [value]="t">{{ t }}</option>
|
||
}
|
||
</select>
|
||
</td>
|
||
<td>
|
||
<select class="te-cell te-cell--sm" [(ngModel)]="row.acTyp" (click)="$event.stopPropagation()">
|
||
@for (a of acTypOptions; track a) {
|
||
<option [value]="a">{{ a }}</option>
|
||
}
|
||
</select>
|
||
</td>
|
||
<td>
|
||
<input
|
||
class="te-cell te-cell--md"
|
||
[(ngModel)]="row.acNo"
|
||
(click)="$event.stopPropagation()"
|
||
(blur)="onAcNoBlur(row, i)"
|
||
/>
|
||
</td>
|
||
<td>
|
||
<input class="te-cell te-cell--lg" [(ngModel)]="row.ecsAcNo" (click)="$event.stopPropagation()" />
|
||
</td>
|
||
<td>
|
||
<select class="te-cell te-cell--sm" [(ngModel)]="row.dbCr" (click)="$event.stopPropagation()">
|
||
<option value=""></option>
|
||
@for (d of dbCrOptions; track d) {
|
||
<option [value]="d">{{ d }}</option>
|
||
}
|
||
</select>
|
||
</td>
|
||
<td>
|
||
<input class="te-cell te-cell--md" [(ngModel)]="row.chequeNo" (click)="$event.stopPropagation()" />
|
||
</td>
|
||
<td>
|
||
<input
|
||
class="te-cell te-cell--md"
|
||
type="number"
|
||
[(ngModel)]="row.amount"
|
||
(click)="$event.stopPropagation()"
|
||
/>
|
||
</td>
|
||
<td>
|
||
<input class="te-cell te-cell--lg" [(ngModel)]="row.description" (click)="$event.stopPropagation()" />
|
||
</td>
|
||
<td><input class="te-cell te-cell--sm" [(ngModel)]="row.tokNo" (click)="$event.stopPropagation()" /></td>
|
||
<td>
|
||
<input
|
||
class="te-cell te-cell--sm"
|
||
[(ngModel)]="row.cheqDate"
|
||
placeholder="dd/mm/yy"
|
||
(click)="$event.stopPropagation()"
|
||
/>
|
||
</td>
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
</table>
|
||
<div class="te-grid-footer">
|
||
<span class="te-eff-date"
|
||
>Eff. Dt : <strong>{{ today }}</strong></span
|
||
>
|
||
<button class="te-add-btn" type="button" (click)="addRow()" title="Add row">+</button>
|
||
</div>
|
||
</div>
|
||
}
|
||
|
||
<!-- ── STATUS ────────────────────────────────────────────────────────── -->
|
||
@if (loadingAccount) {
|
||
<div class="te-loading">Loading account details…</div>
|
||
}
|
||
@if (accountError && !loadingAccount) {
|
||
<div class="te-error">{{ accountError }}</div>
|
||
}
|
||
|
||
<!-- ── ACCOUNT DETAIL ─────────────────────────────────────────────────── -->
|
||
@if (accountDetails && !loadingAccount) {
|
||
<div class="te-detail">
|
||
<!-- ROW 1: Personal | Joint + Nominees | Other + Balances -->
|
||
<div class="te-detail-top">
|
||
<!-- Personal Information -->
|
||
<div class="te-panel">
|
||
<div class="te-panel__header">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="12" cy="8" r="4" />
|
||
<path d="M4 20c0-4 3.6-7 8-7s8 3 8 7" />
|
||
</svg>
|
||
Personal Information
|
||
</div>
|
||
<div class="te-panel__body">
|
||
<div class="te-field">
|
||
<span class="te-label">Branch</span><span class="te-value">{{ officeName }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">A/c No.</span><span class="te-value te-mono">{{ accountDetails.accountNo }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">Name</span><span class="te-value te-value-name">{{ clientName }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">S/D/W/H/O</span><span class="te-value">{{ guardianName }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">Address</span><span class="te-value te-value-wrap">{{ clientAddress }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">Email</span><span class="te-value">{{ clientEmail }}</span>
|
||
</div>
|
||
<div class="te-field-row">
|
||
<div class="te-field">
|
||
<span class="te-label">Last Txn</span><span class="te-value">{{ lastTransactionDate }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">Type</span
|
||
><span class="te-value">{{ accountDetails.depositType?.value ?? selectedRow?.acTyp ?? '—' }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="te-field-row">
|
||
<div class="te-field">
|
||
<span class="te-label">Opening Dt</span><span class="te-value">{{ openingDate }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">Status</span
|
||
><span class="te-value">{{ accountDetails.status?.value ?? '—' }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">CIF No.</span><span class="te-value te-mono">{{ cifNumber }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Joint Holders + Nominees -->
|
||
<div class="te-panel">
|
||
<div class="te-panel__header">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
||
<circle cx="9" cy="7" r="4" />
|
||
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
|
||
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
|
||
</svg>
|
||
Joint A/c Holders
|
||
@if (accountDetails?.modeOfOperation) {
|
||
<span class="te-mandate-badge">{{ modeOfOperationLabel }}</span>
|
||
}
|
||
</div>
|
||
<div class="te-panel__body">
|
||
@if (jointHolders.length === 0) {
|
||
<span class="te-dim">No joint holders</span>
|
||
}
|
||
@for (jh of jointHolders; track jh.id ?? $index) {
|
||
<div class="te-joint-row">
|
||
<span class="te-joint-name">{{ jh.displayName }}</span>
|
||
<span class="te-badge" [class.te-badge--primary]="jh.isPrimary || jh.primary">
|
||
{{ jh.role ?? (jh.isPrimary || jh.primary ? 'Primary' : 'Co-Holder') }}
|
||
</span>
|
||
@if (jh.sharePercentage) {
|
||
<span class="te-dim">{{ jh.sharePercentage }}%</span>
|
||
}
|
||
@if (jh.signingAuthority) {
|
||
<span
|
||
class="te-sign-badge"
|
||
[class.te-sign-badge--mandatory]="jh.signingAuthority?.toLowerCase() === 'mandatory'"
|
||
[class.te-sign-badge--optional]="jh.signingAuthority?.toLowerCase() === 'optional'"
|
||
>
|
||
{{ jh.signingAuthority }}
|
||
</span>
|
||
}
|
||
</div>
|
||
}
|
||
</div>
|
||
|
||
<div class="te-panel__header te-panel__header--mt">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
||
</svg>
|
||
Nominees
|
||
</div>
|
||
<div class="te-panel__body">
|
||
@if (nominees.length === 0) {
|
||
<span class="te-dim">No nominees</span>
|
||
}
|
||
@for (n of nominees; track n.id ?? $index) {
|
||
<div class="te-joint-row">
|
||
<span class="te-joint-name">{{ n.nomineeDisplayName ?? '—' }}</span>
|
||
<span class="te-dim">{{ n.relationshipName ?? '—' }}</span>
|
||
@if (n.percentageShare) {
|
||
<span class="te-badge">{{ n.percentageShare }}%</span>
|
||
}
|
||
@if (n.nomineeIsMinor) {
|
||
<span class="te-badge" style="background: #fff7ed; color: #c2410c; border-color: #fed7aa">Minor</span>
|
||
}
|
||
</div>
|
||
}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Other Info + KYC + Account Balances -->
|
||
<div class="te-panel">
|
||
<div class="te-panel__header">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="3" y="4" width="18" height="18" rx="2" />
|
||
<line x1="16" y1="2" x2="16" y2="6" />
|
||
<line x1="8" y1="2" x2="8" y2="6" />
|
||
<line x1="3" y1="10" x2="21" y2="10" />
|
||
</svg>
|
||
Other Information
|
||
</div>
|
||
<div class="te-panel__body">
|
||
<div class="te-field">
|
||
<span class="te-label">Phone No.</span><span class="te-value">{{ clientPhone }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">Client ID</span><span class="te-value te-mono">{{ accountDetails.clientId }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">PAN</span><span class="te-value te-mono">{{ panNumber }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">KYC Status</span>
|
||
<span class="te-value" [style.color]="kycDetails?.kycStatus === 300 ? '#059669' : '#f59e0b'">{{
|
||
kycStatus
|
||
}}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">CKYC No.</span><span class="te-value te-mono">{{ ckycNumber }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">Aadhaar</span><span class="te-value te-mono">{{ aadhaarNumber }}</span>
|
||
</div>
|
||
<div class="te-field">
|
||
<span class="te-label">Product</span>
|
||
<span class="te-value">{{
|
||
accountDetails.savingsProductName ||
|
||
accountDetails.depositProductName ||
|
||
accountDetails.productName ||
|
||
'—'
|
||
}}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="te-panel__header te-panel__header--mt">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<line x1="12" y1="1" x2="12" y2="23" />
|
||
<path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" />
|
||
</svg>
|
||
Account Information
|
||
</div>
|
||
<div class="te-panel__body">
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-num">1.</span><span class="te-bal-label">Current Balance</span>
|
||
<span class="te-bal-value te-bal-value--cr"
|
||
>{{ currencySymbol }}{{ currentBalance | number: '1.2-2' }}</span
|
||
>
|
||
</div>
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-num">2.</span><span class="te-bal-label">Today's Clg. Amount</span>
|
||
<span class="te-bal-value">{{ currencySymbol }}{{ todayClgAmount | number: '1.2-2' }}</span>
|
||
</div>
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-num">3.</span><span class="te-bal-label">Clear Balance (2-3)</span>
|
||
<span class="te-bal-value te-bal-value--cr"
|
||
>{{ currencySymbol }}{{ clearBalance | number: '1.2-2' }}</span
|
||
>
|
||
</div>
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-num">4.</span><span class="te-bal-label">Freeze Amount</span>
|
||
<span class="te-bal-value">{{ currencySymbol }}{{ freezeAmount | number: '1.2-2' }}</span>
|
||
</div>
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-num">5.</span><span class="te-bal-label">Withdrawable Amt.</span>
|
||
<span class="te-bal-value te-bal-value--cr"
|
||
>{{ currencySymbol }}{{ withdrawableAmount | number: '1.2-2' }}</span
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- NET BALANCE BAR -->
|
||
<div class="te-balance-bar">
|
||
<div class="te-bal-item">
|
||
<span class="te-bal-item__label">Net Balance</span>
|
||
<span class="te-bal-item__val te-bal-item__val--cr te-bal-item__val--big">
|
||
{{ currencySymbol }}{{ clearBalance | number: '1.2-2' }} CR
|
||
</span>
|
||
</div>
|
||
<div class="te-bal-item">
|
||
<span class="te-bal-item__label">A/c Type</span>
|
||
<span class="te-bal-item__val">{{
|
||
accountDetails.depositType?.value || accountDetails.accountType || selectedRow?.acTyp || '—'
|
||
}}</span>
|
||
</div>
|
||
<div class="te-bal-item">
|
||
<span class="te-bal-item__label">Interest Rate</span>
|
||
<span class="te-bal-item__val">{{ accountDetails.nominalAnnualInterestRate ?? 0 | number: '1.2-2' }}%</span>
|
||
</div>
|
||
<div class="te-bal-item">
|
||
<span class="te-bal-item__label">Currency</span>
|
||
<span class="te-bal-item__val">{{ accountDetails.currency?.code ?? 'INR' }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- BOTTOM: Basic Info -->
|
||
<div class="te-panel">
|
||
<div class="te-panel__header">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||
<polyline points="14 2 14 8 20 8" />
|
||
</svg>
|
||
Basic Information
|
||
</div>
|
||
<div class="te-panel__body te-basic-grid">
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-label">Opening Balance</span
|
||
><span class="te-bal-value">{{ currencySymbol }}{{ currentBalance | number: '1.2-2' }}</span>
|
||
</div>
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-label">Cash Hold</span><span class="te-bal-value">0.00</span>
|
||
</div>
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-label">Transfer Hold</span><span class="te-bal-value">0.00</span>
|
||
</div>
|
||
<div class="te-balance-row">
|
||
<span class="te-bal-label">Clearing Hold</span><span class="te-bal-value">0.00</span>
|
||
</div>
|
||
<div class="te-balance-row te-balance-row--total">
|
||
<span class="te-bal-label">Bal. After This Trans.</span>
|
||
<span class="te-bal-value te-bal-value--cr">{{ currencySymbol }}{{ clearBalance | number: '1.2-2' }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── DENOMINATION + OPENING/CLOSING ──────────────────────────── -->
|
||
<div class="te-denom-wrap">
|
||
<!-- Opening Balance -->
|
||
<div class="te-panel te-panel--denom">
|
||
<div class="te-panel__header">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="12" cy="12" r="10" />
|
||
<polyline points="12 6 12 12 16 14" />
|
||
</svg>
|
||
Opening Position — {{ today }}
|
||
</div>
|
||
<div class="te-panel__body">
|
||
@if (!openingLoaded) {
|
||
<span class="te-dim">Loading…</span>
|
||
}
|
||
@if (openingLoaded && openingDenoms.length === 0) {
|
||
<span class="te-dim">No opening position found</span>
|
||
}
|
||
@if (openingLoaded && openingDenoms.length > 0) {
|
||
<table class="te-denom-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Denomination</th>
|
||
<th class="num">Opening Count</th>
|
||
<th class="num">Amount</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@for (d of sortedOpeningDenoms; track d.denominationId) {
|
||
@if (d.count > 0) {
|
||
<tr>
|
||
<td>
|
||
<span class="te-denom-chip" [class.te-denom-chip--coin]="d.kind === 'coin'"
|
||
>₹{{ d.denominationValue }}</span
|
||
>
|
||
</td>
|
||
<td class="num">{{ d.count }}</td>
|
||
<td class="num te-cr">₹{{ d.count * d.denominationValue | number: '1.2-2' }}</td>
|
||
</tr>
|
||
}
|
||
}
|
||
</tbody>
|
||
<tfoot>
|
||
<tr>
|
||
<td><strong>Total</strong></td>
|
||
<td></td>
|
||
<td class="num te-cr">
|
||
<strong>₹{{ openingTotal | number: '1.2-2' }}</strong>
|
||
</td>
|
||
</tr>
|
||
</tfoot>
|
||
</table>
|
||
}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Denomination Entry -->
|
||
<div class="te-panel te-panel--denom">
|
||
<div class="te-panel__header">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="2" y="7" width="20" height="14" rx="2" />
|
||
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16" />
|
||
</svg>
|
||
Denomination Entry
|
||
@if (denominationTotal > 0) {
|
||
<span class="te-mandate-badge">₹{{ denominationTotal | number: '1.2-2' }}</span>
|
||
}
|
||
</div>
|
||
<div class="te-panel__body">
|
||
<table class="te-denom-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Denomination</th>
|
||
<th class="num">Count</th>
|
||
<th class="num">Amount</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@for (d of allDenominations; track d.id) {
|
||
<tr>
|
||
<td>
|
||
<span class="te-denom-chip" [class.te-denom-chip--coin]="d.kind === 'coin'">
|
||
{{ d.label }}
|
||
</span>
|
||
</td>
|
||
<td class="num">
|
||
<div class="te-denom-stepper">
|
||
<button type="button" (click)="bumpDenom(d, -1)" [disabled]="countFor(d) === 0">−</button>
|
||
<input
|
||
type="number"
|
||
min="0"
|
||
[value]="countFor(d) || ''"
|
||
placeholder="0"
|
||
(input)="onDenomChange(d, $any($event.target).value)"
|
||
/>
|
||
<button type="button" (click)="bumpDenom(d, 1)">+</button>
|
||
</div>
|
||
</td>
|
||
<td class="num te-cr">
|
||
{{ subtotalFor(d) > 0 ? (subtotalFor(d) | number: '1.2-2') : '—' }}
|
||
</td>
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
<tfoot>
|
||
<tr>
|
||
<td><strong>Total</strong></td>
|
||
<td></td>
|
||
<td class="num te-cr">
|
||
<strong>₹{{ denominationTotal | number: '1.2-2' }}</strong>
|
||
</td>
|
||
</tr>
|
||
</tfoot>
|
||
</table>
|
||
|
||
@if (denominationTotal > 0) {
|
||
<div class="te-denom-actions">
|
||
<button class="te-btn te-btn--primary" type="button" (click)="applyDenominationTotal()">
|
||
Apply ₹{{ denominationTotal | number: '1.2-2' }} to Amount
|
||
</button>
|
||
<button class="te-btn" type="button" (click)="clearDenominations()">Clear</button>
|
||
</div>
|
||
}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Closing Position -->
|
||
<div class="te-panel te-panel--denom">
|
||
<div class="te-panel__header">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="20 6 9 17 4 12" />
|
||
</svg>
|
||
Closing Position (Preview)
|
||
</div>
|
||
<div class="te-panel__body">
|
||
@if (closingDenoms.length === 0) {
|
||
<span class="te-dim">Enter denomination to see closing position</span>
|
||
}
|
||
@if (closingDenoms.length > 0) {
|
||
<table class="te-denom-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Denomination</th>
|
||
<th class="num">Opening</th>
|
||
<th class="num">{{ selectedRow?.dbCr === 'Cr' ? '+Deposit' : '-Withdrawal' }}</th>
|
||
<th class="num">Closing</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@for (d of sortedClosingDenoms; track d.denominationValue + d.kind) {
|
||
<tr [class.te-closing-row--neg]="d.closingCount < 0">
|
||
<td>
|
||
<span class="te-denom-chip" [class.te-denom-chip--coin]="d.kind === 'coin'"
|
||
>₹{{ d.denominationValue }}</span
|
||
>
|
||
</td>
|
||
<td class="num">{{ d.openCount }}</td>
|
||
<td class="num" [style.color]="selectedRow?.dbCr === 'Cr' ? '#059669' : '#dc2626'">
|
||
{{ selectedRow?.dbCr === 'Cr' ? '+' : '-' }}{{ d.entered }}
|
||
</td>
|
||
<td class="num" [class.te-cr]="d.closingCount >= 0" [class.te-dr]="d.closingCount < 0">
|
||
{{ d.closingCount }}
|
||
</td>
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
<tfoot>
|
||
<tr>
|
||
<td><strong>Total</strong></td>
|
||
<td class="num">₹{{ openingTotal | number: '1.2-2' }}</td>
|
||
<td class="num" [style.color]="selectedRow?.dbCr === 'Cr' ? '#059669' : '#dc2626'">
|
||
{{ selectedRow?.dbCr === 'Cr' ? '+' : '-' }}₹{{ denominationTotal | number: '1.2-2' }}
|
||
</td>
|
||
<td class="num" [class.te-cr]="closingTotal >= 0" [class.te-dr]="closingTotal < 0">
|
||
<strong>₹{{ closingTotal | number: '1.2-2' }}</strong>
|
||
</td>
|
||
</tr>
|
||
</tfoot>
|
||
</table>
|
||
}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── ENTRY GRID (bottom) ─────────────────────────────────────── -->
|
||
<div class="te-grid-wrap">
|
||
<table class="te-grid">
|
||
<thead>
|
||
<tr>
|
||
<th>Typ</th>
|
||
<th>Br.</th>
|
||
<th>Tr.Tp.</th>
|
||
<th>Actyp</th>
|
||
<th>A/c No.</th>
|
||
<th>Ecs A/c No.</th>
|
||
<th>Db./Cr.</th>
|
||
<th>Cheque No.</th>
|
||
<th>Amount</th>
|
||
<th>Description</th>
|
||
<th>Tok.No.</th>
|
||
<th>Cheq.Date</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@for (row of rows; track $index; let i = $index) {
|
||
<tr [class.te-row--selected]="selectedRow === row" (click)="onRowSelect(row, i)">
|
||
<td><input class="te-cell te-cell--xs" [(ngModel)]="row.typ" /></td>
|
||
<td><input class="te-cell te-cell--xs" type="number" [(ngModel)]="row.br" /></td>
|
||
<td>
|
||
<select class="te-cell te-cell--sm" [(ngModel)]="row.trTp">
|
||
<option value=""></option>
|
||
@for (t of trTpOptions; track t) {
|
||
<option [value]="t">{{ t }}</option>
|
||
}
|
||
</select>
|
||
</td>
|
||
<td>
|
||
<select class="te-cell te-cell--sm" [(ngModel)]="row.acTyp">
|
||
@for (a of acTypOptions; track a) {
|
||
<option [value]="a">{{ a }}</option>
|
||
}
|
||
</select>
|
||
</td>
|
||
<td><input class="te-cell te-cell--md" [(ngModel)]="row.acNo" (blur)="onAcNoBlur(row, i)" /></td>
|
||
<td><input class="te-cell te-cell--lg" [(ngModel)]="row.ecsAcNo" /></td>
|
||
<td>
|
||
<select class="te-cell te-cell--sm" [(ngModel)]="row.dbCr">
|
||
<option value=""></option>
|
||
@for (d of dbCrOptions; track d) {
|
||
<option [value]="d">{{ d }}</option>
|
||
}
|
||
</select>
|
||
</td>
|
||
<td><input class="te-cell te-cell--md" [(ngModel)]="row.chequeNo" /></td>
|
||
<td><input class="te-cell te-cell--md" type="number" [(ngModel)]="row.amount" /></td>
|
||
<td><input class="te-cell te-cell--lg" [(ngModel)]="row.description" /></td>
|
||
<td><input class="te-cell te-cell--sm" [(ngModel)]="row.tokNo" /></td>
|
||
<td><input class="te-cell te-cell--sm" [(ngModel)]="row.cheqDate" placeholder="dd/mm/yy" /></td>
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
</table>
|
||
<div class="te-grid-footer">
|
||
<span class="te-eff-date"
|
||
>Eff. Dt : <strong>{{ today }}</strong></span
|
||
>
|
||
<button class="te-add-btn" type="button" (click)="addRow()" title="Add row">+</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ACTION BUTTONS -->
|
||
<div class="te-actions">
|
||
<button class="te-btn te-btn--exit" type="button" (click)="onExit()">Exit</button>
|
||
<button class="te-btn" type="button" (click)="onCancel()">Cancel</button>
|
||
<button class="te-btn" type="button">Drop</button>
|
||
<button class="te-btn" type="button" (click)="onSearch()">Search</button>
|
||
<button class="te-btn te-btn--mode" type="button">Change Tr.Mode</button>
|
||
<button class="te-btn te-btn--primary" type="button" (click)="onSave()" [disabled]="saving">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
||
<polyline points="20 6 9 17 4 12" />
|
||
</svg>
|
||
{{ saving ? 'Posting…' : 'Save' }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
}
|
||
</div>
|