Account Statement is no longer a jsPDF file that downloads the moment the dialog opens. It now shows a live, on-screen preview styled the same way the working Passbook screen already is (bank header, branch line, account-details band, balance strip, transaction table), with its own date-range filter, and only prints via the browser's print dialog on an explicit click -- exactly the same clone-into-a-popup-window mechanism Passbook already uses, so "Save as PDF" is the reader's own choice rather than something forced on open. Both Passbook and the new Statement preview pull the bank name, license number, and branch name/address/IFSC/MICR from Institution Profile and Branch Profile instead of a hardcoded bank name -- a printed passbook or statement now actually identifies which bank and branch issued it. Cheque Book's own issuance detail screen gets a matching "Print" action, laying out a one-page issuance-slip PDF from data already on that screen (which book/series, leaf range, issued-to account, issue date). Cash Hold and Clearing Hold on the Transaction Entry balance strip were both hardcoded 0.00 placeholders; they now read the account's real hold-category breakdown, and a stray "Freeze Amount" placeholder a few rows up is wired to the working getter that was already sitting right next to it. A clerk withdrawal's own terminal status is WITHDRAWN, not APPROVED -- the Day Book screen had the same status-string gap the backend GL report did: neither its running CR/DR totals nor its status badge recognized a completed withdrawal, so real money that had gone out never moved the totals off zero. The Closing Cash Report's GL Entries panel also never refreshed for a newly picked date once it had already been opened once -- "Load" hid the panel instead of refreshing it, leaving a stale, wrong-date table under a header that had already relabelled itself correctly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
156 lines
5.8 KiB
HTML
156 lines
5.8 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="container">
|
||
<div class="page-header">
|
||
<h2>{{ 'labels.inputs.Cheque Book' | translate }} #{{ book.id }}</h2>
|
||
<div>
|
||
<button mat-stroked-button (click)="printIssuanceSlip()">
|
||
<fa-icon icon="print"></fa-icon> {{ 'labels.buttons.Print' | translate }}
|
||
</button>
|
||
<button mat-raised-button [routerLink]="['/chequebook', 'books']">{{ 'labels.buttons.Back' | translate }}</button>
|
||
</div>
|
||
</div>
|
||
|
||
<mat-card class="info-card">
|
||
<mat-card-content>
|
||
<div class="info-grid">
|
||
<div>
|
||
<span class="k">{{ 'labels.inputs.Account' | translate }}</span>
|
||
<span>
|
||
{{ book.accountNo || book.accountId }}
|
||
@if (book.clientName) {
|
||
— {{ book.clientName }}
|
||
}
|
||
</span>
|
||
</div>
|
||
<div>
|
||
<span class="k">{{ 'labels.inputs.Account Type' | translate }}</span
|
||
><span>{{ book.accountType }}</span>
|
||
</div>
|
||
<div>
|
||
<span class="k">{{ 'labels.inputs.Office' | translate }}</span
|
||
><span>{{ book.officeName }}</span>
|
||
</div>
|
||
<div>
|
||
<span class="k">{{ 'labels.inputs.Series' | translate }}</span
|
||
><span>{{ book.seriesCode || '–' }}</span>
|
||
</div>
|
||
<div>
|
||
<span class="k">{{ 'labels.inputs.Leaf Range' | translate }}</span>
|
||
<span>{{ book.rangeStart ? book.rangeStart + ' – ' + book.rangeEnd : '–' }}</span>
|
||
</div>
|
||
<div>
|
||
<span class="k">{{ 'labels.inputs.Quantity' | translate }}</span
|
||
><span>{{ book.noOfBooks }} {{ 'labels.inputs.books' | translate }}</span>
|
||
</div>
|
||
<div>
|
||
<span class="k">{{ 'labels.inputs.Status' | translate }}</span
|
||
><span>{{ book.status }}</span>
|
||
</div>
|
||
<div>
|
||
<span class="k">{{ 'labels.inputs.Issue Date' | translate }}</span
|
||
><span>{{ book.issueDate ? (book.issueDate | dateFormat) : '–' }}</span>
|
||
</div>
|
||
</div>
|
||
</mat-card-content>
|
||
</mat-card>
|
||
|
||
@if (book.status === 'ISSUED') {
|
||
<div class="action-toolbar">
|
||
<button mat-stroked-button color="warn" (click)="startAction('stoppayment')">
|
||
{{ 'labels.buttons.Stop Payment' | translate }}
|
||
</button>
|
||
<button mat-stroked-button (click)="startAction('revokestoppayment')">
|
||
{{ 'labels.buttons.Revoke Stop Payment' | translate }}
|
||
</button>
|
||
<button mat-stroked-button color="warn" (click)="startAction('reportlost')">
|
||
{{ 'labels.buttons.Report Lost' | translate }}
|
||
</button>
|
||
<button mat-stroked-button (click)="startAction('cancelleaf')">
|
||
{{ 'labels.buttons.Cancel Leaf' | translate }}
|
||
</button>
|
||
<button mat-stroked-button color="primary" (click)="startAction('markused')">
|
||
{{ 'labels.buttons.Mark as Used' | translate }}
|
||
</button>
|
||
<button mat-stroked-button color="warn" (click)="startAction('return')">
|
||
{{ 'labels.buttons.Flag Returned' | translate }}
|
||
</button>
|
||
</div>
|
||
}
|
||
|
||
@if (activeAction) {
|
||
<mat-card class="add-form">
|
||
<mat-card-content>
|
||
<form [formGroup]="actionForm" (ngSubmit)="submitAction()">
|
||
<div class="form-grid">
|
||
<mat-form-field appearance="fill">
|
||
<mat-label>{{ 'labels.inputs.From Leaf Seq' | translate }}</mat-label>
|
||
<input matInput type="number" formControlName="fromLeafSeq" />
|
||
<mat-hint>{{ 'labels.text.Leave blank for the whole book' | translate }}</mat-hint>
|
||
</mat-form-field>
|
||
<mat-form-field appearance="fill">
|
||
<mat-label>{{ 'labels.inputs.To Leaf Seq' | translate }}</mat-label>
|
||
<input matInput type="number" formControlName="toLeafSeq" />
|
||
</mat-form-field>
|
||
@if (activeAction !== 'revokestoppayment') {
|
||
<mat-form-field appearance="fill">
|
||
<mat-label>{{ 'labels.inputs.Reason' | translate }}</mat-label>
|
||
<input matInput formControlName="reason" [required]="activeAction !== 'markused'" />
|
||
@if (activeAction === 'markused') {
|
||
<mat-hint>{{
|
||
'labels.text.Optional — e.g. cleared per bank statement dated ...' | translate
|
||
}}</mat-hint>
|
||
}
|
||
</mat-form-field>
|
||
}
|
||
</div>
|
||
<div class="form-actions">
|
||
<button mat-raised-button type="button" (click)="activeAction = null">
|
||
{{ 'labels.buttons.Cancel' | translate }}
|
||
</button>
|
||
<button mat-raised-button color="warn" type="submit" [disabled]="actionForm.invalid || busy">
|
||
{{ 'labels.buttons.Submit' | translate }}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</mat-card-content>
|
||
</mat-card>
|
||
}
|
||
|
||
<div class="leaf-grid-wrapper mat-elevation-z1">
|
||
<div class="leaf-grid">
|
||
@for (l of leaves; track l.leafSerialNo) {
|
||
<button
|
||
type="button"
|
||
class="serial-circle"
|
||
[ngClass]="
|
||
l.status === 'ACTIVE'
|
||
? 'ok'
|
||
: l.status === 'USED'
|
||
? 'used'
|
||
: l.status === 'STOP_PAYMENT'
|
||
? 'warn'
|
||
: l.status === 'LOST'
|
||
? 'bad'
|
||
: l.status === 'RETURNED'
|
||
? 'returned'
|
||
: 'neutral'
|
||
"
|
||
(click)="selectLeaf(l)"
|
||
>
|
||
{{ l.leafSerialNo }}
|
||
</button>
|
||
}
|
||
</div>
|
||
@if (leaves.length === 0) {
|
||
<div class="empty-state">{{ 'labels.text.No records to display' | translate }}</div>
|
||
}
|
||
</div>
|
||
</div>
|