DDS: agent collection entry screen, per-agent GL account, maturity auto close
The Daily Transaction Entry screen no longer composes a Party Tran. An agent records their own round elsewhere; this screen reads back what they wrote down, shows what it adds up to, and settles the day once a clerk has counted the cash against it. Nothing is typed here and nothing is edited - what settles is what the entries say, to the rupee. Agent Master now asks which ledger account the agent's collections pass through, one agent to an account, and offers only the accounts that can carry them. The DDS scheme product is kept out of the agent's own savings list for the same reason the server refuses it: debits are blocked on those accounts, so commission paid into one would go in and never come out. The DDS product carries a Maturity Auto Close setting, asked as Yes/No to match the Auto Interest Post question directly above it, and Batch Processing offers the run that applies it. Also: the report viewer stops printing two money columns ungrouped and stops totalling a column that holds a word, and an agent's birth date cannot be picked later than eighteen years ago. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
57a61b3057
commit
e2eff9914f
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 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, 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 { MatRadioModule } from '@angular/material/radio';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
|
||||
/** Custom Services */
|
||||
import { OrganizationService } from 'app/organization/organization.service';
|
||||
|
||||
/** Custom Pipes */
|
||||
import { DateFormatPipe } from 'app/pipes/date-format.pipe';
|
||||
|
||||
/**
|
||||
* Where a matured DDS account's money should go.
|
||||
*
|
||||
* Two destinations, and the difference is whether the money leaves the bank. Another account of the
|
||||
* customer's here is a move across the books. Anywhere else means a transfer out, which clears later
|
||||
* or fails - so the money is parked in the matured-deposits payable account first and the branch
|
||||
* sends it on from there, rather than being launched into a gap where it has left one account and
|
||||
* arrived at none.
|
||||
*
|
||||
* The amount is not asked for. It is whatever the account holds, worked out by the server: a figure
|
||||
* typed here could pay out more than the customer has, or quietly leave some behind.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-payout-dialog',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
MatDialogModule,
|
||||
MatButtonModule,
|
||||
MatRadioModule,
|
||||
MatSelectModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatProgressBarModule,
|
||||
DateFormatPipe
|
||||
],
|
||||
templateUrl: './payout-dialog.component.html',
|
||||
styleUrls: ['./payout-dialog.component.scss']
|
||||
})
|
||||
export class PayoutDialogComponent implements OnInit {
|
||||
private organizationService = inject(OrganizationService);
|
||||
private dialogRef = inject(MatDialogRef<PayoutDialogComponent>);
|
||||
data = inject<any>(MAT_DIALOG_DATA);
|
||||
|
||||
/** 'own' moves it to another account here; 'other' parks it for a transfer to another bank. */
|
||||
destination: 'own' | 'other' = 'own';
|
||||
|
||||
/**
|
||||
* The customer's accounts this maturity can be paid into.
|
||||
*
|
||||
* Worked out by the server, which applies the same conditions the payout enforces: an active
|
||||
* savings account of theirs, not a fixed or recurring deposit, and not one of their DDS scheme
|
||||
* accounts. Filtering here instead let the two drift - the list once offered a scheme account
|
||||
* belonging to a party that had already closed, which would have stranded the money.
|
||||
*/
|
||||
ownAccounts: any[] = [];
|
||||
selectedAccountNo = '';
|
||||
loading = true;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.organizationService.getCreditableAccounts(this.data.clientId).subscribe({
|
||||
next: (accounts: any) => {
|
||||
this.ownAccounts = accounts || [];
|
||||
|
||||
// Nothing here to pay into, so the only real choice is a transfer out - offered as the
|
||||
// default rather than leaving the officer on an option that cannot be completed.
|
||||
if (this.ownAccounts.length === 0) {
|
||||
this.destination = 'other';
|
||||
} else if (this.ownAccounts.length === 1) {
|
||||
this.selectedAccountNo = this.ownAccounts[0].accountNo;
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
error: () => {
|
||||
this.ownAccounts = [];
|
||||
this.destination = 'other';
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get canPayOut(): boolean {
|
||||
if (this.loading) {
|
||||
return false;
|
||||
}
|
||||
return this.destination === 'other' || !!this.selectedAccountNo;
|
||||
}
|
||||
|
||||
payOut(): void {
|
||||
this.dialogRef.close(this.destination === 'own' ? { toSavingsAccountNo: this.selectedAccountNo } : {});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user