DDS: Agent settlement (Agent Tran), Close Party account UI, reports UI, Party-Savings link field
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/** Custom Services */
|
||||
import { OrganizationService } from 'app/organization/organization.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/**
|
||||
* DDS Interest & Commission Batch Processing component.
|
||||
*
|
||||
* Six batch job types, each following the same deliberate two-step
|
||||
* pattern from the legacy system: Calculate first (a dry-run preview),
|
||||
* then Post as a separate, explicit confirmation — so a wrong calculation
|
||||
* is never applied by accident. Modelled on the legacy Interest
|
||||
* Calculation screen this replaces.
|
||||
*
|
||||
* Backed by the DDS Batch Run API (`/dds/batchruns`). Only the three
|
||||
* "Calculation" job types can actually be generated - the three "Posting"
|
||||
* entries exist in the dropdown for parity with the legacy menu, but Post
|
||||
* always applies whatever run was most recently generated in this session,
|
||||
* regardless of which dropdown entry is currently selected (matching how
|
||||
* the Post button here is only ever gated on hasGenerated, not on jobType).
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-dds-batch-processing',
|
||||
templateUrl: './dds-batch-processing.component.html',
|
||||
styleUrls: ['./dds-batch-processing.component.scss'],
|
||||
imports: [...STANDALONE_SHARED_IMPORTS]
|
||||
})
|
||||
export class DdsBatchProcessingComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private router = inject(Router);
|
||||
private organizationService = inject(OrganizationService);
|
||||
private settingsService = inject(SettingsService);
|
||||
private dateUtils = inject(Dates);
|
||||
|
||||
private static readonly JOB_TYPE_CODES: Record<string, string> = {
|
||||
'Interest Calculation': 'INTEREST_CALCULATION',
|
||||
'OD Interest Calculation': 'OD_INTEREST_CALCULATION',
|
||||
'Commission Calculation': 'COMMISSION_CALCULATION'
|
||||
};
|
||||
|
||||
private currentBatchRunId: number | null = null;
|
||||
|
||||
offices: any[] = [];
|
||||
selectedOfficeNames = new Set<string>();
|
||||
|
||||
jobTypes = [
|
||||
'Interest Calculation',
|
||||
'Interest Posting',
|
||||
'OD Interest Calculation',
|
||||
'OD Interest Posting',
|
||||
'Commission Calculation',
|
||||
'Commission Posting'
|
||||
];
|
||||
|
||||
branchScopes = [
|
||||
'All',
|
||||
'Selected'
|
||||
];
|
||||
|
||||
hasGenerated = false;
|
||||
previewRows: Array<{ agent: string; party: string; amount: number }> = [];
|
||||
|
||||
batchForm: UntypedFormGroup = this.formBuilder.group({
|
||||
jobType: [
|
||||
'Interest Calculation',
|
||||
Validators.required
|
||||
],
|
||||
branchScope: [
|
||||
'All',
|
||||
Validators.required
|
||||
],
|
||||
jobDate: [
|
||||
new Date(),
|
||||
Validators.required
|
||||
],
|
||||
agentFrom: [
|
||||
1,
|
||||
Validators.required
|
||||
],
|
||||
agentTo: [
|
||||
99999,
|
||||
Validators.required
|
||||
],
|
||||
partyFrom: [
|
||||
1,
|
||||
Validators.required
|
||||
],
|
||||
partyTo: [
|
||||
99999999,
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
|
||||
get isPostingJob(): boolean {
|
||||
return (this.batchForm.get('jobType').value as string).includes('Posting');
|
||||
}
|
||||
|
||||
get isBranchSelected(): boolean {
|
||||
return this.batchForm.get('branchScope')?.value === 'Selected';
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.organizationService.getOffices().subscribe((offices: any[]) => {
|
||||
this.offices = offices || [];
|
||||
});
|
||||
}
|
||||
|
||||
toggleOffice(officeName: string): void {
|
||||
if (this.selectedOfficeNames.has(officeName)) {
|
||||
this.selectedOfficeNames.delete(officeName);
|
||||
} else {
|
||||
this.selectedOfficeNames.add(officeName);
|
||||
}
|
||||
}
|
||||
|
||||
generate(): void {
|
||||
const raw = this.batchForm.getRawValue();
|
||||
const jobType = DdsBatchProcessingComponent.JOB_TYPE_CODES[raw.jobType];
|
||||
|
||||
if (!jobType) {
|
||||
// A "Posting" entry was selected - there is nothing to calculate for
|
||||
// it, only to post (see class-level note on how Post is wired).
|
||||
this.hasGenerated = true;
|
||||
this.previewRows = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const payload: any = {
|
||||
jobType,
|
||||
branchScope: raw.branchScope,
|
||||
jobDate: this.dateUtils.formatDate(raw.jobDate, dateFormat),
|
||||
agentFrom: raw.agentFrom,
|
||||
agentTo: raw.agentTo,
|
||||
partyFrom: raw.partyFrom,
|
||||
partyTo: raw.partyTo,
|
||||
dateFormat,
|
||||
locale: this.settingsService.language.code
|
||||
};
|
||||
|
||||
if (raw.branchScope === 'Selected') {
|
||||
payload.officeNames = Array.from(this.selectedOfficeNames);
|
||||
}
|
||||
|
||||
this.organizationService.generateDdsBatchRun(payload).subscribe((result: any) => {
|
||||
this.currentBatchRunId = result.resourceId;
|
||||
this.organizationService.getDdsBatchRun(this.currentBatchRunId).subscribe((batchRun: any) => {
|
||||
this.previewRows = (batchRun.rows || []).map((row: any) => ({
|
||||
agent: row.agentCode,
|
||||
party: row.partyCode || '—',
|
||||
amount: row.amount
|
||||
}));
|
||||
this.hasGenerated = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
post(): void {
|
||||
if (!this.currentBatchRunId) {
|
||||
return;
|
||||
}
|
||||
this.organizationService.postDdsBatchRun(this.currentBatchRunId).subscribe(() => {
|
||||
this.currentBatchRunId = null;
|
||||
this.hasGenerated = false;
|
||||
this.previewRows = [];
|
||||
});
|
||||
}
|
||||
|
||||
exit(): void {
|
||||
this.router.navigate(['/organization']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user