/** * 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, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MatButtonModule } from '@angular/material/button'; import { MatSelectModule } from '@angular/material/select'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; /** * Collecting for days other than today - either paid ahead, or owed from days gone by. * * Both are the same act from the counter's side: the customer is paying for a number of days, and * what that comes to is the scheme's business, not the clerk's. So the clerk picks days and the * amount follows. Typing an amount instead would let the daily figure be worked around a little at a * time, and would quote the customer something the scheme does not charge. * * The two differ only in how many days are on offer. Paying ahead is capped by the bank's allowance. * Paying arrears is capped by what is still inside the catch-up window - older instalments are gone, * and offering them would have the clerk asking for money the bank has already written off. */ @Component({ selector: 'mifosx-day-collection-dialog', standalone: true, imports: [ CommonModule, FormsModule, MatDialogModule, MatButtonModule, MatSelectModule, MatFormFieldModule, MatInputModule ], templateUrl: './day-collection-dialog.component.html', styleUrls: ['./day-collection-dialog.component.scss'] }) export class DayCollectionDialogComponent { private dialogRef = inject(MatDialogRef); /** { mode: 'advance' | 'previous', parties: [] } - the agent's parties, as the screen already has them. */ data = inject(MAT_DIALOG_DATA); partyCode = ''; days: number | '' = ''; get isAdvance(): boolean { return this.data?.mode === 'advance'; } get title(): string { return this.isAdvance ? 'Collect in advance' : 'Collect previous days'; } get party(): any { return (this.data?.parties || []).find((p: any) => String(p.partyCode) === this.partyCode) || null; } /** * The parties this can be used on. * * Paying ahead is offered to anyone. Paying arrears is offered only where there are arrears still * inside the window - on an account that is up to date there is nothing to collect for past days, * and listing it would invite an entry that is really an advance in disguise. */ get eligibleParties(): any[] { const parties = this.data?.parties || []; return this.isAdvance ? parties : parties.filter((p: any) => Number(p.recoverableAmount || 0) > 0); } /** * How many days may be picked. Five ahead, matching the bank's allowance and the server's own * check; for arrears, only what has not yet fallen out of the catch-up window. */ get dayOptions(): number[] { const daily = Number(this.party?.dailyDepositAmount || 0); if (!this.party || daily <= 0) { return []; } const limit = this.isAdvance ? 5 : Math.floor(Number(this.party.recoverableAmount || 0) / daily); return Array.from({ length: Math.max(0, limit) }, (_, index) => index + 1); } get amount(): number { return Number(this.party?.dailyDepositAmount || 0) * Number(this.days || 0); } /** Clearing the days when the party changes - a count valid for one account is not for another. */ partyChanged(): void { this.days = ''; } get canAdd(): boolean { return !!this.partyCode && Number(this.days) > 0 && this.amount > 0; } add(): void { this.dialogRef.close({ partyCode: this.partyCode, days: Number(this.days), amount: this.amount, // Sent as days, not just an amount: the server recomputes what they come to and checks it // against this account, so the figure quoted here is the one that gets posted. advanceDays: this.isAdvance ? Number(this.days) : undefined, arrearsDays: this.isAdvance ? undefined : Number(this.days) }); } }