/** * 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/. */ /** Angular Imports */ import { Component, OnInit, OnDestroy, inject, ElementRef, ViewChild } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { UntypedFormBuilder } from '@angular/forms'; import { CurrencyPipe } from '@angular/common'; import { Subject, takeUntil } from 'rxjs'; /** Custom Services */ import { SettingsService } from 'app/settings/settings.service'; import { Dates } from 'app/core/utils/dates'; import { Currency } from 'app/shared/models/general.model'; import { CurrentAccountTransaction, CurrentAccountTransactionType } from 'app/current-accounts/models/current-account-transaction.model'; import { MatIcon } from '@angular/material/icon'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { DateFormatPipe } from '../../../pipes/date-format.pipe'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; @Component({ selector: 'mifosx-passbook-tab', templateUrl: './passbook-tab.component.html', styleUrls: ['./passbook-tab.component.scss'], standalone: true, imports: [ ...STANDALONE_SHARED_IMPORTS, MatIcon, FaIconComponent, DateFormatPipe, CurrencyPipe ] }) export class PassbookTabComponent implements OnInit, OnDestroy { private route = inject(ActivatedRoute); private formBuilder = inject(UntypedFormBuilder); private settingsService = inject(SettingsService); private dateUtils = inject(Dates); private destroy$ = new Subject(); @ViewChild('passbookContent') passbookContent: ElementRef; /** Account data */ accountNo: string = ''; clientName: string = ''; productName: string = ''; currency: Currency | null = null; status: string = ''; interestRate: number = 0; accountBalance: number = 0; availableBalance: number = 0; activatedOnDate: any = null; /** Transactions */ allTransactions: CurrentAccountTransaction[] = []; filteredTransactions: CurrentAccountTransaction[] = []; /** Date range form */ minDate = new Date(2000, 0, 1); maxDate = new Date(); dateRangeForm: any; isFiltered = false; ngOnInit(): void { this.maxDate = this.settingsService.businessDate; this.route.parent.data.pipe(takeUntil(this.destroy$)).subscribe((data: { currentAccountData: any }) => { const account = data.currentAccountData; this.accountNo = account.accountNo || ''; this.clientName = account.clientName || account.groupName || ''; this.productName = account.currentAccountProductName || ''; this.currency = account.currency || null; this.status = account.status?.value || ''; this.interestRate = account.nominalAnnualInterestRate || 0; this.accountBalance = account.summary?.accountBalance || 0; this.availableBalance = account.summary?.availableBalance || 0; this.activatedOnDate = account.timeline?.activatedOnDate || null; this.allTransactions = this.computeRunningBalances(account.transactions || []); this.filteredTransactions = [...this.allTransactions]; }); this.dateRangeForm = this.formBuilder.group({ fromDate: [''], toDate: [''] }); } private computeRunningBalances(transactions: CurrentAccountTransaction[]): CurrentAccountTransaction[] { let balance = 0; return transactions.map((txn) => { if (txn.runningBalance != null) { balance = txn.runningBalance; } else { const amount = txn.amount || 0; if (this.isDebit(txn.transactionType)) { balance = balance - amount; } else { balance = balance + amount; } txn = { ...txn, runningBalance: balance }; } return txn; }); } isDebit(transactionType: CurrentAccountTransactionType): boolean { return ( transactionType.withdrawal === true || transactionType.feeDeduction === true || transactionType.overdraftInterest === true || transactionType.withholdTax === true ); } filterTransactions(): void { const fromDate = this.dateRangeForm.value.fromDate; const toDate = this.dateRangeForm.value.toDate; this.filteredTransactions = this.allTransactions.filter((txn: CurrentAccountTransaction) => { const txnDate = this.getTransactionDateAsTime(txn.date); if (fromDate && new Date(fromDate).getTime() > txnDate) return false; if (toDate) { const toEnd = new Date(toDate); toEnd.setHours(23, 59, 59, 999); if (toEnd.getTime() < txnDate) return false; } return true; }); this.isFiltered = true; } clearFilter(): void { this.dateRangeForm.reset(); this.filteredTransactions = [...this.allTransactions]; this.isFiltered = false; } private getTransactionDateAsTime(date: any): number { if (Array.isArray(date) && date.length >= 3) { return new Date(date[0], date[1] - 1, date[2]).getTime(); } return new Date(date).getTime(); } printPassbook(): void { const content = this.passbookContent?.nativeElement?.innerHTML; if (!content) return; const printWindow = window.open('', 'Passbook', 'height=700,width=900'); printWindow.document.write(` Current Account Passbook - ${this.accountNo} ${content} `); printWindow.document.close(); printWindow.focus(); printWindow.print(); printWindow.close(); } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } }