/** * 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/. */ import { Component, OnInit, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MatIconModule } from '@angular/material/icon'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { of } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { CashierService } from '../cashier.service'; import { businessToday } from 'app/core/utils/business-today'; interface BranchDenomRow { denominationId: number; denominationValue: number; kind: string; vaultCount: number; cashierCount: number; totalCount: number; totalAmount: number; /** Notes taken in less notes given out by exchanges on the day. */ exchangeNet: number; } interface BranchPosition { officeId: number; officeName: string; asOfDate: string; vaultHasBreakdown: boolean; vaultAmount: number; cashiersAmount: number; totalAmount: number; denominations: BranchDenomRow[]; } /** * What the branch holds, denomination by denomination: the vault plus every cashier's drawer. An exchange * (a customer hands in 10 x ₹500 and leaves with 50 x ₹100) leaves the vault alone and changes a drawer, so * it only shows up in this total -- +10 on ₹500, -50 on ₹100. */ @Component({ selector: 'mifosx-branch-cash-position', templateUrl: './branch-cash-position.component.html', styleUrls: [ '../cashier-shared.scss', '../cashier-position/cashier-position.component.scss', './branch-cash-position.component.scss' ], standalone: true, imports: [ CommonModule, MatIconModule, MatFormFieldModule, MatInputModule ] }) export class BranchCashPositionComponent implements OnInit { private service = inject(CashierService); asOfDate = ''; loading = false; errorMsg = ''; position: BranchPosition | null = null; ngOnInit(): void { const d = businessToday(); this.asOfDate = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; this.load(); } load(): void { this.loading = true; this.errorMsg = ''; this.position = null; this.service .branchCashPosition(this.asOfDate) .pipe(catchError(() => of(null))) .subscribe((data: BranchPosition | null) => { this.loading = false; if (!data) { this.errorMsg = 'Could not load the branch cash position.'; return; } this.position = data; }); } onDateChange(value: string): void { this.asOfDate = value; this.load(); } notes(): BranchDenomRow[] { return (this.position?.denominations || []).filter((d) => d.kind !== 'coin'); } coins(): BranchDenomRow[] { return (this.position?.denominations || []).filter((d) => d.kind === 'coin'); } /** "+10", "-50", or a dash when the day's exchanges did not touch the denomination. */ movement(net: number): string { if (!net) return '—'; return net > 0 ? `+${net}` : `${net}`; } }