1056 lines
40 KiB
HTML
1056 lines
40 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="glr-root">
|
|
<!-- HEADER -->
|
|
<div class="glr-head">
|
|
<div class="glr-head-left">
|
|
<fa-icon icon="book-open" class="glr-head-ic"></fa-icon>
|
|
<div>
|
|
<h2 class="glr-head-t">General Ledger — {{ reportLabel }}</h2>
|
|
<div class="glr-head-s">
|
|
CBSNexora Bank Ltd · {{ branchLabel }} · Period <strong>{{ rangeLabel }}</strong> ·
|
|
{{ ledgerPeriod.label }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<button class="glr-btn glr-btn-xls" [disabled]="generating" (click)="exportExcel()">
|
|
<fa-icon icon="file-csv"></fa-icon>
|
|
{{ generating ? 'Exporting…' : 'Export to Excel' }}
|
|
</button>
|
|
</div>
|
|
|
|
<!-- FILTER BAR -->
|
|
<div class="glr-filters">
|
|
<div class="glr-filter">
|
|
<label>Period</label>
|
|
<div class="glr-seg">
|
|
<button [class.active]="periodMode === 'day'" (click)="periodMode = 'day'">Day-wise</button>
|
|
<button [class.active]="periodMode === 'month'" (click)="periodMode = 'month'">Month-wise</button>
|
|
<button [class.active]="periodMode === 'range'" (click)="periodMode = 'range'">Date Range</button>
|
|
</div>
|
|
</div>
|
|
|
|
@if (periodMode === 'day') {
|
|
<div class="glr-filter">
|
|
<label>Date</label>
|
|
<input
|
|
class="glr-inp"
|
|
type="date"
|
|
[(ngModel)]="filterDay"
|
|
[min]="ledgerPeriod.fyStart"
|
|
[max]="ledgerPeriod.fyEnd"
|
|
/>
|
|
</div>
|
|
}
|
|
@if (periodMode === 'month') {
|
|
<div class="glr-filter">
|
|
<label>Month</label>
|
|
<input class="glr-inp" type="month" [(ngModel)]="filterMonth" min="2026-04" max="2026-07" />
|
|
</div>
|
|
}
|
|
@if (periodMode === 'range') {
|
|
<div class="glr-filter">
|
|
<label>From</label>
|
|
<input
|
|
class="glr-inp"
|
|
type="date"
|
|
[(ngModel)]="filterFrom"
|
|
[min]="ledgerPeriod.fyStart"
|
|
[max]="ledgerPeriod.fyEnd"
|
|
/>
|
|
</div>
|
|
<div class="glr-filter">
|
|
<label>To</label>
|
|
<input
|
|
class="glr-inp"
|
|
type="date"
|
|
[(ngModel)]="filterTo"
|
|
[min]="ledgerPeriod.fyStart"
|
|
[max]="ledgerPeriod.fyEnd"
|
|
/>
|
|
</div>
|
|
}
|
|
|
|
<div class="glr-filter">
|
|
<label>Branch</label>
|
|
@if (canSelectBranch) {
|
|
<select class="glr-inp" [(ngModel)]="branchCode">
|
|
<option value="">All Branches (Consolidated)</option>
|
|
@for (b of branches; track b.code) {
|
|
<option [value]="b.code">{{ b.code }} — {{ b.name }}</option>
|
|
}
|
|
</select>
|
|
} @else {
|
|
<span class="glr-chip" title="Your login is restricted to this branch">
|
|
<fa-icon icon="university"></fa-icon> {{ scopeName }}
|
|
</span>
|
|
}
|
|
</div>
|
|
|
|
<button class="glr-btn" (click)="resetFilters()">Reset</button>
|
|
</div>
|
|
|
|
@if (scopeIsUnresolved) {
|
|
<div class="glr-balance glr-balance--bad">
|
|
<fa-icon icon="exclamation-triangle"></fa-icon>
|
|
<span>
|
|
Your office <strong>{{ scopeName }}</strong> does not match any branch in the ledger, so no figures can be
|
|
shown. Ask an administrator to align your office name with a branch.
|
|
</span>
|
|
</div>
|
|
}
|
|
|
|
<!-- REPORT SELECTOR -->
|
|
<div class="glr-tabs">
|
|
@for (r of reports; track r.code) {
|
|
<button class="glr-tab" [class.active]="activeReport === r.code" (click)="showReport(r.code)">
|
|
<fa-icon [icon]="r.icon"></fa-icon> {{ r.label }}
|
|
</button>
|
|
}
|
|
</div>
|
|
|
|
<!-- ══════════════ TRIAL BALANCE ══════════════ -->
|
|
@if (activeReport === 'trial-balance') {
|
|
<div class="glr-section">
|
|
<div class="glr-balance" [class.glr-balance--bad]="!tbBalanced">
|
|
<fa-icon [icon]="tbBalanced ? 'check-circle' : 'exclamation-triangle'"></fa-icon>
|
|
<span>
|
|
Closing Dr <strong>₹{{ tbClosingDebit | number: '1.2-2' }}</strong> · Closing Cr
|
|
<strong>₹{{ tbClosingCredit | number: '1.2-2' }}</strong> —
|
|
{{ tbBalanced ? 'trial balance tallies' : 'OUT OF BALANCE — investigate before closing the period' }}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="glr-tbl-wrap">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Account</th>
|
|
<th>Group</th>
|
|
<th class="ta-r">Opening Dr</th>
|
|
<th class="ta-r">Opening Cr</th>
|
|
<th class="ta-r">Period Dr</th>
|
|
<th class="ta-r">Period Cr</th>
|
|
<th class="ta-r">Closing Dr</th>
|
|
<th class="ta-r">Closing Cr</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of data.trialBalance; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>{{ r.name }}</td>
|
|
<td class="muted">{{ r.group }}</td>
|
|
<td class="ta-r mono">{{ r.openingDebit ? (r.openingDebit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono">{{ r.openingCredit ? (r.openingCredit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono">{{ r.periodDebit ? (r.periodDebit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono">{{ r.periodCredit ? (r.periodCredit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono">{{ r.closingDebit ? (r.closingDebit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono">{{ r.closingCredit ? (r.closingCredit | number: '1.2-2') : '' }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="9" class="glr-empty">No ledger activity for this period and branch.</td>
|
|
</tr>
|
|
}
|
|
<tr class="total-row">
|
|
<td colspan="3">TOTAL ({{ data.trialBalance.length }} accounts)</td>
|
|
<td class="ta-r mono">{{ tbOpeningDebit | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ tbOpeningCredit | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ tbPeriodDebit | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ tbPeriodCredit | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ tbClosingDebit | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ tbClosingCredit | number: '1.2-2' }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ PROFIT AND LOSS ══════════════ -->
|
|
@if (activeReport === 'profit-and-loss') {
|
|
<div class="glr-section">
|
|
<div class="glr-kpis">
|
|
<div class="glr-kpi glr-kpi--teal">
|
|
<div class="glr-kpi-n">₹{{ totalIncome | number: '1.2-2' }}</div>
|
|
<div class="glr-kpi-l">Total Income</div>
|
|
</div>
|
|
<div class="glr-kpi glr-kpi--amber">
|
|
<div class="glr-kpi-n">₹{{ totalExpense | number: '1.2-2' }}</div>
|
|
<div class="glr-kpi-l">Total Expenditure</div>
|
|
</div>
|
|
<div class="glr-kpi" [class.glr-kpi--green]="netProfit >= 0" [class.glr-kpi--red]="netProfit < 0">
|
|
<div class="glr-kpi-n">₹{{ netProfit | number: '1.2-2' }}</div>
|
|
<div class="glr-kpi-l">{{ netProfit >= 0 ? 'Net Profit' : 'Net Loss' }}</div>
|
|
<div class="glr-kpi-sub">{{ netProfitPct | number: '1.2-2' }}% of income</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="glr-two-col">
|
|
<div class="glr-tbl-wrap">
|
|
<div class="glr-tbl-h">Expenditure</div>
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Particulars</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of pnlExpense; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>
|
|
{{ r.name }}<span class="muted"> · {{ r.group }}</span>
|
|
</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="3" class="glr-empty">No expenditure posted in this period.</td>
|
|
</tr>
|
|
}
|
|
<tr class="total-row">
|
|
<td colspan="2">Total Expenditure</td>
|
|
<td class="ta-r mono">{{ totalExpense | number: '1.2-2' }}</td>
|
|
</tr>
|
|
@if (netProfit >= 0) {
|
|
<tr class="total-row glr-profit-row">
|
|
<td colspan="2">Net Profit carried to Balance Sheet</td>
|
|
<td class="ta-r mono">{{ netProfit | number: '1.2-2' }}</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="glr-tbl-wrap">
|
|
<div class="glr-tbl-h">Income</div>
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Particulars</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of pnlIncome; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>
|
|
{{ r.name }}<span class="muted"> · {{ r.group }}</span>
|
|
</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="3" class="glr-empty">No income posted in this period.</td>
|
|
</tr>
|
|
}
|
|
<tr class="total-row">
|
|
<td colspan="2">Total Income</td>
|
|
<td class="ta-r mono">{{ totalIncome | number: '1.2-2' }}</td>
|
|
</tr>
|
|
@if (netProfit < 0) {
|
|
<tr class="total-row glr-loss-row">
|
|
<td colspan="2">Net Loss carried to Balance Sheet</td>
|
|
<td class="ta-r mono">{{ -netProfit | number: '1.2-2' }}</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ CONSOLIDATED BALANCE SHEET ══════════════ -->
|
|
@if (activeReport === 'balance-sheet') {
|
|
<div class="glr-section">
|
|
<div class="glr-balance" [class.glr-balance--bad]="!bsBalanced">
|
|
<fa-icon [icon]="bsBalanced ? 'check-circle' : 'exclamation-triangle'"></fa-icon>
|
|
<span>
|
|
Total Assets <strong>₹{{ bsTotalAssets | number: '1.2-2' }}</strong> · Total Liabilities
|
|
<strong>₹{{ bsTotalLiabilities | number: '1.2-2' }}</strong> —
|
|
{{ bsBalanced ? 'balance sheet tallies' : 'OUT OF BALANCE' }}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="glr-two-col">
|
|
<div class="glr-tbl-wrap">
|
|
<div class="glr-tbl-h">Capital & Liabilities — as at {{ range.to }}</div>
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Particulars</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of bsLiabilities; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>
|
|
{{ r.name }}<span class="muted"> · {{ r.group }}</span>
|
|
</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
</tr>
|
|
}
|
|
<tr>
|
|
<td class="mono">—</td>
|
|
<td>Surplus for the period<span class="muted"> · Profit & Loss</span></td>
|
|
<td class="ta-r mono">{{ bsSurplus | number: '1.2-2' }}</td>
|
|
</tr>
|
|
<tr class="total-row">
|
|
<td colspan="2">Total Capital & Liabilities</td>
|
|
<td class="ta-r mono">{{ bsTotalLiabilities | number: '1.2-2' }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="glr-tbl-wrap">
|
|
<div class="glr-tbl-h">Assets — as at {{ range.to }}</div>
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Particulars</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of bsAssets; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>
|
|
{{ r.name }}<span class="muted"> · {{ r.group }}</span>
|
|
</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
</tr>
|
|
}
|
|
<tr class="total-row">
|
|
<td colspan="2">Total Assets</td>
|
|
<td class="ta-r mono">{{ bsTotalAssets | number: '1.2-2' }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ COMPARATIVE BALANCE SHEET ══════════════ -->
|
|
@if (activeReport === 'comparative-balance-sheet') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Compares the closing position as at <strong>{{ range.to }}</strong> against the position immediately before this
|
|
period began. Change the filter above to compare a different span.
|
|
</p>
|
|
|
|
@for (
|
|
block of [
|
|
{ title: 'Capital & Liabilities', rows: compLiabilities },
|
|
{ title: 'Assets', rows: compAssets }
|
|
];
|
|
track block.title
|
|
) {
|
|
<div class="glr-tbl-wrap">
|
|
<div class="glr-tbl-h">{{ block.title }}</div>
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Particulars</th>
|
|
<th class="ta-r">Current (₹)</th>
|
|
<th class="ta-r">Previous (₹)</th>
|
|
<th class="ta-r">Variance (₹)</th>
|
|
<th class="ta-r">Variance %</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of block.rows; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>
|
|
{{ r.name }}<span class="muted"> · {{ r.group }}</span>
|
|
</td>
|
|
<td class="ta-r mono">{{ r.current | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ r.previous | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono" [class.var-up]="r.variance > 0" [class.var-down]="r.variance < 0">
|
|
{{ r.variance | number: '1.2-2' }}
|
|
</td>
|
|
<td class="ta-r mono" [class.var-up]="r.variance > 0" [class.var-down]="r.variance < 0">
|
|
{{ r.variancePct === null ? '—' : (r.variancePct | number: '1.2-2') + '%' }}
|
|
</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="6" class="glr-empty">Nothing to compare for this period and branch.</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ CONTINGENT LIABILITIES ══════════════ -->
|
|
@if (activeReport === 'contingent-liabilities') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Off-balance-sheet commitments outstanding as at <strong>{{ range.to }}</strong
|
|
>. These are memoranda accounts and are deliberately excluded from the Trial Balance and Balance Sheet totals.
|
|
</p>
|
|
<div class="glr-tbl-wrap">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Particulars</th>
|
|
<th>Group</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of data.contingent; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>{{ r.name }}</td>
|
|
<td class="muted">{{ r.group }}</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="4" class="glr-empty">No contingent exposures outstanding for this selection.</td>
|
|
</tr>
|
|
}
|
|
<tr class="total-row">
|
|
<td colspan="3">Total Contingent Liabilities</td>
|
|
<td class="ta-r mono">{{ contingentTotal | number: '1.2-2' }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ GL WISE DR / CR ══════════════ -->
|
|
@if (activeReport === 'gl-wise-dr-cr') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Debit and credit turnover posted between <strong>{{ rangeLabel }}</strong> for {{ branchLabel }}. Every voucher
|
|
is double-entry, so the debit and credit totals below must match.
|
|
</p>
|
|
<div class="glr-tbl-wrap">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Account</th>
|
|
<th>Type</th>
|
|
<th>Group</th>
|
|
<th class="ta-r">Debit (₹)</th>
|
|
<th class="ta-r">Credit (₹)</th>
|
|
<th class="ta-r">Net (Dr − Cr)</th>
|
|
<th class="ta-c">Vouchers</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of data.glWise; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>{{ r.name }}</td>
|
|
<td>
|
|
<span class="type-pill" [class]="'type-' + r.type.toLowerCase()">{{ r.type }}</span>
|
|
</td>
|
|
<td class="muted">{{ r.group }}</td>
|
|
<td class="ta-r mono">{{ r.debit ? (r.debit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono">{{ r.credit ? (r.credit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono" [class.var-up]="r.net > 0" [class.var-down]="r.net < 0">
|
|
{{ r.net | number: '1.2-2' }}
|
|
</td>
|
|
<td class="ta-c mono">{{ r.vouchers }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="8" class="glr-empty">No postings for this period and branch.</td>
|
|
</tr>
|
|
}
|
|
<tr class="total-row">
|
|
<td colspan="4">TOTAL ({{ data.glWise.length }} accounts)</td>
|
|
<td class="ta-r mono">{{ glWiseDebit | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ glWiseCredit | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ glWiseDebit - glWiseCredit | number: '1.2-2' }}</td>
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ MISC EXPENSE LEDGER ══════════════ -->
|
|
@if (activeReport === 'misc-expense-ledger') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Every miscellaneous-expense voucher posted between <strong>{{ rangeLabel }}</strong> for
|
|
{{ branchLabel }} — {{ miscRows.length | number }} entries.
|
|
</p>
|
|
<div class="glr-tbl-wrap glr-tbl-wrap--tall">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Voucher No</th>
|
|
<th>Branch</th>
|
|
<th>GL Code</th>
|
|
<th>Account</th>
|
|
<th>Narration</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of miscRows; track r.voucherNo + r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.date }}</td>
|
|
<td class="mono">{{ r.voucherNo }}</td>
|
|
<td>{{ branchName(r.branchCode) }}</td>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>{{ r.name }}</td>
|
|
<td class="muted">{{ r.narration }}</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="7" class="glr-empty">No miscellaneous expenses posted for this selection.</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="total-row">
|
|
<td colspan="6">Total Miscellaneous Expenses</td>
|
|
<td class="ta-r mono">{{ miscTotal | number: '1.2-2' }}</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ GL AVERAGE BALANCE ══════════════ -->
|
|
@if (activeReport === 'gl-average-balance') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Average of each account's closing balance across every day in
|
|
<strong>{{ rangeLabel }}</strong> for {{ branchLabel }}. Banks work from average balances rather than a closing
|
|
snapshot for interest, CRR/SLR and profitability, because a single day's figure can be dressed up.
|
|
</p>
|
|
<div class="glr-tbl-wrap glr-tbl-wrap--tall">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Account</th>
|
|
<th>Group</th>
|
|
<th class="ta-r">Opening</th>
|
|
<th class="ta-r">Closing</th>
|
|
<th class="ta-r">Average Daily</th>
|
|
<th class="ta-r">Peak</th>
|
|
<th class="ta-r">Lowest</th>
|
|
<th class="ta-c">Active Days</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of averageRows; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>{{ r.name }}</td>
|
|
<td class="muted">{{ r.group }}</td>
|
|
<td class="ta-r mono">{{ r.opening | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ r.closing | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">
|
|
<strong>{{ r.average | number: '1.2-2' }}</strong>
|
|
</td>
|
|
<td class="ta-r mono">{{ r.peak | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ r.lowest | number: '1.2-2' }}</td>
|
|
<td class="ta-c mono">{{ r.activeDays }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="9" class="glr-empty">No ledger activity for this period and branch.</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="total-row">
|
|
<td colspan="5">TOTAL ({{ averageRows.length }} accounts)</td>
|
|
<td class="ta-r mono">{{ avgTotalAverage | number: '1.2-2' }}</td>
|
|
<td colspan="3"></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ GL MAPPING FOR REPORT ══════════════ -->
|
|
@if (activeReport === 'gl-mapping') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Which General Ledger accounts feed each RBI return line. Mappings are created on the OSS 1, OSS 2 and OSS 3
|
|
screens using <strong>Add / Remove GLs</strong>; this is the consolidated view of them, with the value each
|
|
mapping currently produces from the ledger.
|
|
</p>
|
|
|
|
<div class="glr-tbl-wrap">
|
|
<div class="glr-tbl-h">Mapped return lines ({{ mappingRows.length }})</div>
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>Return</th>
|
|
<th>Return line</th>
|
|
<th>Mapped GL accounts</th>
|
|
<th class="ta-r">Ledger value (₹ thousands)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of mappingRows; track r.returnCode + r.lineKey) {
|
|
<tr>
|
|
<td>{{ r.returnLabel }}</td>
|
|
<td class="mono">{{ r.lineKey }}</td>
|
|
<td>
|
|
@for (c of r.codes; track c) {
|
|
<span class="glr-gl-chip mono">{{ c }}</span>
|
|
}
|
|
</td>
|
|
<td class="ta-r mono">{{ r.value | number: '1.2-2' }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="4" class="glr-empty">
|
|
No return lines mapped yet. Open OSS 1, 2 or 3 and use “Add / Remove GLs” to pin accounts to a line.
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="glr-tbl-wrap glr-tbl-wrap--tall">
|
|
<div class="glr-tbl-h">Unmapped GL accounts ({{ unmappedAccounts.length }}) — not feeding any return line</div>
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Account</th>
|
|
<th>Group</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (a of unmappedAccounts; track a.code) {
|
|
<tr>
|
|
<td class="mono">{{ a.code }}</td>
|
|
<td>{{ a.name }}</td>
|
|
<td class="muted">{{ a.group }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="3" class="glr-empty">Every GL account feeds at least one return line.</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ ACCOUNT WISE BALANCE LIST ══════════════ -->
|
|
@if (activeReport === 'account-wise-balance') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Closing balance of every account as at <strong>{{ range.to }}</strong
|
|
>, broken out by branch — which branch is actually carrying each balance.
|
|
</p>
|
|
<div class="glr-tbl-wrap glr-tbl-wrap--tall">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>GL Code</th>
|
|
<th>Account</th>
|
|
<th>Group</th>
|
|
@for (c of branchColumns; track c) {
|
|
<th class="ta-r">{{ branchName(c) }}</th>
|
|
}
|
|
<th class="ta-r">Total</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of accountWiseRows; track r.code) {
|
|
<tr>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>{{ r.name }}</td>
|
|
<td class="muted">{{ r.group }}</td>
|
|
@for (c of branchColumns; track c) {
|
|
<td class="ta-r mono">{{ r.byBranch[c] ? (r.byBranch[c] | number: '1.2-2') : '' }}</td>
|
|
}
|
|
<td class="ta-r mono">
|
|
<strong>{{ r.total | number: '1.2-2' }}</strong>
|
|
</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td [attr.colspan]="branchColumns.length + 4" class="glr-empty">
|
|
No balances for this period and branch.
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="total-row">
|
|
<td colspan="3">TOTAL ({{ accountWiseRows.length }} accounts)</td>
|
|
@for (c of branchColumns; track c) {
|
|
<td class="ta-r mono">{{ branchColumnTotal(c) | number: '1.2-2' }}</td>
|
|
}
|
|
<td class="ta-r mono">{{ accountWiseGrandTotal | number: '1.2-2' }}</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ DISTRIBUTION OF BALANCE ══════════════ -->
|
|
@if (activeReport === 'distribution-of-balance') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Composition of the book as at <strong>{{ range.to }}</strong> for {{ branchLabel }} — how concentrated each side
|
|
of the balance sheet is by account group.
|
|
</p>
|
|
|
|
<div class="glr-two-col">
|
|
@for (
|
|
block of [
|
|
{ title: 'Capital & Liabilities', rows: liabilityDistribution, total: liabilityDistTotal },
|
|
{ title: 'Assets', rows: assetDistribution, total: assetDistTotal }
|
|
];
|
|
track block.title
|
|
) {
|
|
<div class="glr-tbl-wrap">
|
|
<div class="glr-tbl-h">{{ block.title }}</div>
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>Group</th>
|
|
<th class="ta-c">A/cs</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
<th class="ta-r">Share</th>
|
|
<th class="glr-bar-col">Distribution</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of block.rows; track r.group) {
|
|
<tr>
|
|
<td>{{ r.group }}</td>
|
|
<td class="ta-c mono">{{ r.accounts }}</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">
|
|
<strong>{{ r.share | number: '1.2-2' }}%</strong>
|
|
</td>
|
|
<td>
|
|
<div class="glr-bar">
|
|
<div class="glr-bar-fill" [style.width.%]="r.share"></div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="5" class="glr-empty">No balances on this side.</td>
|
|
</tr>
|
|
}
|
|
<tr class="total-row">
|
|
<td colspan="2">Total</td>
|
|
<td class="ta-r mono">{{ block.total | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">100.00%</td>
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ CLIENT WISE BALANCE ══════════════ -->
|
|
@if (activeReport === 'client-wise-balance') {
|
|
<div class="glr-section">
|
|
<div class="glr-kpis">
|
|
<div class="glr-kpi glr-kpi--teal">
|
|
<div class="glr-kpi-n">₹{{ clientDeposits | number: '1.2-2' }}</div>
|
|
<div class="glr-kpi-l">Customer Deposits</div>
|
|
</div>
|
|
<div class="glr-kpi glr-kpi--amber">
|
|
<div class="glr-kpi-n">₹{{ clientAdvances | number: '1.2-2' }}</div>
|
|
<div class="glr-kpi-l">Customer Advances</div>
|
|
</div>
|
|
<div class="glr-kpi glr-kpi--green">
|
|
<div class="glr-kpi-n">{{ clientRows.length | number }}</div>
|
|
<div class="glr-kpi-l">Relationships</div>
|
|
<div class="glr-kpi-sub">as at {{ range.to }} · {{ branchLabel }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="glr-note">
|
|
Customer balances are derived from the General Ledger — each relationship holds a share of its branch's balance
|
|
in that head — so this report always reconciles to the GL rather than drifting as a second source.
|
|
</p>
|
|
|
|
<div class="glr-tbl-wrap glr-tbl-wrap--tall">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>CIF</th>
|
|
<th>Customer</th>
|
|
<th>Branch</th>
|
|
<th>Account No</th>
|
|
<th>Product</th>
|
|
<th class="ta-c">Side</th>
|
|
<th class="ta-r">Balance (₹)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of clientRows; track r.cif) {
|
|
<tr>
|
|
<td class="mono">{{ r.cif }}</td>
|
|
<td>{{ r.name }}</td>
|
|
<td>{{ branchName(r.branchCode) }}</td>
|
|
<td class="mono">{{ r.accountNo }}</td>
|
|
<td class="muted">{{ r.product }}</td>
|
|
<td class="ta-c">
|
|
<span
|
|
class="type-pill"
|
|
[class.type-liability]="r.side === 'DEPOSIT'"
|
|
[class.type-asset]="r.side === 'ADVANCE'"
|
|
>
|
|
{{ r.side }}
|
|
</span>
|
|
</td>
|
|
<td class="ta-r mono">{{ r.balance | number: '1.2-2' }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="7" class="glr-empty">No customer relationships for this period and branch.</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ BANKER HEAD REPORT ══════════════ -->
|
|
@if (activeReport === 'banker-head') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Head-wise abstract for <strong>{{ rangeLabel }}</strong> — the trial balance rolled up to principal heads, with
|
|
opening, turnover and closing for each. Debit and credit turnover must agree.
|
|
</p>
|
|
<div class="glr-tbl-wrap">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>Principal Head</th>
|
|
<th class="ta-c">Accounts</th>
|
|
<th class="ta-r">Opening</th>
|
|
<th class="ta-r">Debit</th>
|
|
<th class="ta-r">Credit</th>
|
|
<th class="ta-r">Closing</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of bankerHeadRows; track r.head) {
|
|
<tr>
|
|
<td>
|
|
<strong>{{ r.head }}</strong>
|
|
</td>
|
|
<td class="ta-c mono">{{ r.accounts }}</td>
|
|
<td class="ta-r mono">{{ r.opening | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ r.debit ? (r.debit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono">{{ r.credit ? (r.credit | number: '1.2-2') : '' }}</td>
|
|
<td class="ta-r mono">
|
|
<strong>{{ r.closing | number: '1.2-2' }}</strong>
|
|
</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="6" class="glr-empty">No activity for this period and branch.</td>
|
|
</tr>
|
|
}
|
|
<tr class="total-row">
|
|
<td colspan="2">TOTAL ({{ bankerHeadRows.length }} heads)</td>
|
|
<td></td>
|
|
<td class="ta-r mono">{{ headDebitTotal | number: '1.2-2' }}</td>
|
|
<td class="ta-r mono">{{ headCreditTotal | number: '1.2-2' }}</td>
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ SUNDRY REGISTER ══════════════ -->
|
|
@if (activeReport === 'sundry-register') {
|
|
<div class="glr-section">
|
|
<p class="glr-note">
|
|
Outstanding items in the sundry, suspense and bills-payable heads as at <strong>{{ range.to }}</strong
|
|
>, aged from their posting date. These heads are where unreconciled entries collect, so ageing is the point of
|
|
the register.
|
|
</p>
|
|
|
|
@if (sundryBuckets.length) {
|
|
<div class="glr-kpis">
|
|
@for (b of sundryBuckets; track b.bucket) {
|
|
<div
|
|
class="glr-kpi"
|
|
[class.glr-kpi--green]="b.bucket === 'Up to 30 days'"
|
|
[class.glr-kpi--amber]="b.bucket === '31 to 90 days'"
|
|
[class.glr-kpi--red]="b.bucket === 'Over 180 days'"
|
|
>
|
|
<div class="glr-kpi-n">₹{{ b.amount | number: '1.2-2' }}</div>
|
|
<div class="glr-kpi-l">{{ b.bucket }}</div>
|
|
<div class="glr-kpi-sub">{{ b.count }} item(s)</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
<div class="glr-tbl-wrap glr-tbl-wrap--tall">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Voucher No</th>
|
|
<th>Branch</th>
|
|
<th>GL Code</th>
|
|
<th>Account</th>
|
|
<th>Narration</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
<th class="ta-c">Age</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of sundryRows; track r.voucherNo + r.code + r.date) {
|
|
<tr>
|
|
<td class="mono">{{ r.date }}</td>
|
|
<td class="mono">{{ r.voucherNo }}</td>
|
|
<td>{{ branchName(r.branchCode) }}</td>
|
|
<td class="mono">{{ r.code }}</td>
|
|
<td>{{ r.name }}</td>
|
|
<td class="muted">{{ r.narration }}</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
<td class="ta-c">
|
|
<span
|
|
class="type-pill"
|
|
[class.type-income]="r.bucket === 'Up to 30 days'"
|
|
[class.type-expense]="r.bucket === '31 to 90 days'"
|
|
[class.type-contingent]="r.bucket === 'Over 180 days'"
|
|
>
|
|
{{ r.ageDays }}d
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="8" class="glr-empty">No sundry or suspense items outstanding for this selection.</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="total-row">
|
|
<td colspan="6">Total outstanding ({{ sundryRows.length }} items)</td>
|
|
<td class="ta-r mono">{{ sundryTotal | number: '1.2-2' }}</td>
|
|
<td></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- ══════════════ VOUCHER REGISTER ══════════════ -->
|
|
@if (activeReport === 'voucher-register') {
|
|
<div class="glr-section">
|
|
<div class="glr-balance" [class.glr-balance--bad]="unbalancedVouchers > 0">
|
|
<fa-icon [icon]="unbalancedVouchers ? 'exclamation-triangle' : 'check-circle'"></fa-icon>
|
|
<span>
|
|
{{ voucherRows.length | number }} voucher(s) raised in {{ rangeLabel }} for {{ branchLabel }} —
|
|
{{
|
|
unbalancedVouchers
|
|
? unbalancedVouchers + ' voucher(s) do NOT balance and must be investigated'
|
|
: 'every voucher is double-entry and balances'
|
|
}}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="glr-tbl-wrap glr-tbl-wrap--tall">
|
|
<table class="glr-tbl">
|
|
<thead>
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Voucher No</th>
|
|
<th>Branch</th>
|
|
<th>Narration</th>
|
|
<th>Debit account(s)</th>
|
|
<th>Credit account(s)</th>
|
|
<th class="ta-r">Amount (₹)</th>
|
|
<th class="ta-c">Legs</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of voucherRows; track r.voucherNo) {
|
|
<tr [class.glr-unbalanced]="!r.balanced">
|
|
<td class="mono">{{ r.date }}</td>
|
|
<td class="mono">{{ r.voucherNo }}</td>
|
|
<td>{{ branchName(r.branchCode) }}</td>
|
|
<td class="muted">{{ r.narration }}</td>
|
|
<td class="mono">{{ r.debitAccounts }}</td>
|
|
<td class="mono">{{ r.creditAccounts }}</td>
|
|
<td class="ta-r mono">{{ r.amount | number: '1.2-2' }}</td>
|
|
<td class="ta-c mono">{{ r.legs }}</td>
|
|
</tr>
|
|
} @empty {
|
|
<tr>
|
|
<td colspan="8" class="glr-empty">No vouchers raised in this period for this branch.</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="total-row">
|
|
<td colspan="6">Total ({{ voucherRows.length }} vouchers)</td>
|
|
<td class="ta-r mono">{{ voucherTotal | number: '1.2-2' }}</td>
|
|
<td></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- TOAST -->
|
|
<div class="glr-toast" [class.show]="toastVisible">{{ toastMsg }}</div>
|
|
</div>
|