- Current Account module with full CRUD, transactions, charges, hold/release, block/unblock - Current Products management under Products module - DIP mobile number verification with real API call to /lookup/check - Sanctions verification dialog - Charges support for Current Account (chargeAppliesTo=5) in create/edit - Fixed permissions from SAVINGSACCOUNT to CURRENTACCOUNT across all current account components - Added all missing translation keys for Current Account in en-US.json Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
152 lines
5.9 KiB
HTML
152 lines
5.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="passbook-container">
|
|
<!-- Date Range Filter -->
|
|
<div class="passbook-filter-bar">
|
|
<form [formGroup]="dateRangeForm" class="passbook-filter-form">
|
|
<mat-form-field appearance="outline" class="passbook-date-field" (click)="fromDatePicker.open()">
|
|
<mat-label>{{ 'labels.inputs.From Date' | translate }}</mat-label>
|
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="fromDatePicker" formControlName="fromDate" />
|
|
<mat-datepicker-toggle matSuffix [for]="fromDatePicker"></mat-datepicker-toggle>
|
|
<mat-datepicker #fromDatePicker></mat-datepicker>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline" class="passbook-date-field" (click)="toDatePicker.open()">
|
|
<mat-label>{{ 'labels.inputs.To Date' | translate }}</mat-label>
|
|
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="toDatePicker" formControlName="toDate" />
|
|
<mat-datepicker-toggle matSuffix [for]="toDatePicker"></mat-datepicker-toggle>
|
|
<mat-datepicker #toDatePicker></mat-datepicker>
|
|
</mat-form-field>
|
|
|
|
<button
|
|
mat-raised-button
|
|
color="primary"
|
|
type="button"
|
|
[disabled]="!dateRangeForm.valid"
|
|
(click)="filterTransactions()"
|
|
>
|
|
<mat-icon>filter_list</mat-icon>
|
|
{{ 'labels.buttons.Filter' | translate }}
|
|
</button>
|
|
|
|
@if (isFiltered) {
|
|
<button mat-stroked-button type="button" (click)="clearFilter()">
|
|
<mat-icon>clear</mat-icon>
|
|
{{ 'labels.buttons.Clear' | translate }}
|
|
</button>
|
|
}
|
|
|
|
<span class="passbook-filter-spacer"></span>
|
|
|
|
<button mat-raised-button color="accent" type="button" (click)="printPassbook()">
|
|
<mat-icon>print</mat-icon>
|
|
{{ 'labels.buttons.Print Passbook' | translate }}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Passbook Preview (Printable Content) -->
|
|
<div class="passbook-preview" #passbookContent>
|
|
<div class="passbook-header">
|
|
<h2>{{ 'labels.heading.Current Account Passbook' | translate }}</h2>
|
|
<h3>{{ productName }}</h3>
|
|
</div>
|
|
|
|
<!-- Account Info -->
|
|
<div class="passbook-info-grid">
|
|
<div class="passbook-info-item">
|
|
<div class="label">{{ 'labels.inputs.Account Number' | translate }}</div>
|
|
<div class="value">{{ accountNo }}</div>
|
|
</div>
|
|
<div class="passbook-info-item">
|
|
<div class="label">{{ 'labels.inputs.Account Holder' | translate }}</div>
|
|
<div class="value">{{ clientName }}</div>
|
|
</div>
|
|
<div class="passbook-info-item">
|
|
<div class="label">{{ 'labels.inputs.Current Account Product' | translate }}</div>
|
|
<div class="value">{{ productName }}</div>
|
|
</div>
|
|
<div class="passbook-info-item">
|
|
<div class="label">{{ 'labels.inputs.Opening Date' | translate }}</div>
|
|
<div class="value">{{ activatedOnDate | dateFormat }}</div>
|
|
</div>
|
|
<div class="passbook-info-item">
|
|
<div class="label">{{ 'labels.inputs.Status' | translate }}</div>
|
|
<div class="value">{{ status }}</div>
|
|
</div>
|
|
<div class="passbook-info-item">
|
|
<div class="label">{{ 'labels.inputs.Interest Rate' | translate }}</div>
|
|
<div class="value">{{ interestRate }}%</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Balance Summary -->
|
|
<div class="passbook-balance-row">
|
|
<div class="balance-item">
|
|
<span>{{ 'labels.inputs.Current Balance' | translate }}: </span>
|
|
<b>{{ accountBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}</b>
|
|
</div>
|
|
<div class="balance-item">
|
|
<span>{{ 'labels.inputs.Available Balance' | translate }}: </span>
|
|
<b>{{ availableBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}</b>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Transactions Table -->
|
|
@if (filteredTransactions.length > 0) {
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>{{ 'labels.inputs.Date' | translate }}</th>
|
|
<th>{{ 'labels.inputs.Description' | translate }}</th>
|
|
<th class="text-right">{{ 'labels.inputs.Debit' | translate }}</th>
|
|
<th class="text-right">{{ 'labels.inputs.Credit' | translate }}</th>
|
|
<th class="text-right">{{ 'labels.inputs.Balance' | translate }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (txn of filteredTransactions; track txn.id; let i = $index) {
|
|
<tr [class.reversed]="txn.reversed">
|
|
<td>{{ i + 1 }}</td>
|
|
<td>{{ txn.date | dateFormat }}</td>
|
|
<td>{{ txn.transactionType.value }}</td>
|
|
<td class="text-right">
|
|
@if (isDebit(txn.transactionType)) {
|
|
{{ txn.amount | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
|
|
}
|
|
</td>
|
|
<td class="text-right">
|
|
@if (!isDebit(txn.transactionType)) {
|
|
{{ txn.amount | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
|
|
}
|
|
</td>
|
|
<td class="text-right">
|
|
{{ txn.runningBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
} @else {
|
|
<div class="passbook-no-data">
|
|
<mat-icon>info_outline</mat-icon>
|
|
<span>{{ 'labels.text.No transactions found for the selected date range.' | translate }}</span>
|
|
</div>
|
|
}
|
|
|
|
<!-- Footer -->
|
|
<div class="passbook-footer">
|
|
{{ 'labels.text.Generated on' | translate }}: {{ maxDate | dateFormat }}
|
|
|
|
|
{{ 'labels.text.Total Transactions' | translate }}: {{ filteredTransactions.length }}
|
|
</div>
|
|
</div>
|
|
</div>
|