Files
cbsnexora/src/app/organization/branch-profile/branch-profile.component.ts
T

168 lines
5.8 KiB
TypeScript

/**
* 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 { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { catchError, of } from 'rxjs';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { OrganizationService } from '../organization.service';
const BRANCH_TYPES = [
{ value: 'HEAD_OFFICE', label: 'Head Office' },
{ value: 'BRANCH', label: 'Branch' },
{ value: 'REGIONAL_OFFICE', label: 'Regional Office' },
{ value: 'ZONAL_OFFICE', label: 'Zonal Office' }
];
/**
* The real-world operational fields behind a branch — code, address, contact, type and working
* hours — kept as their own screen on top of the stock Manage Offices flow, since m_office (the
* core Fineract entity) was deliberately left untouched. Pick an office, fill in what real-world
* UCB branch setup expects, save.
*/
@Component({
selector: 'mifosx-branch-profile',
templateUrl: './branch-profile.component.html',
styleUrls: ['./branch-profile.component.scss'],
imports: [...STANDALONE_SHARED_IMPORTS]
})
export class BranchProfileComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private organizationService = inject(OrganizationService);
branchTypes = BRANCH_TYPES;
offices: any[] = [];
selectedOfficeId: number | null = null;
form: UntypedFormGroup;
loadingOffices = true;
loadingProfile = false;
saving = false;
errorMsg = '';
successMsg = '';
lastUpdated: any = null;
ngOnInit(): void {
this.form = this.formBuilder.group({
branchCode: [''],
branchType: [null],
address: [''],
pincode: [''],
contactPhone: [''],
contactEmail: [''],
workingHoursStart: [''],
workingHoursEnd: [''],
workingDays: [''],
ifscCode: [''],
micrCode: [''],
latitude: [null],
longitude: [null]
});
this.organizationService
.getBranchProfiles()
.pipe(
catchError((err: any) => {
this.errorMsg = err?.error?.errors?.[0]?.defaultUserMessage ?? 'Could not load branches.';
return of([]);
})
)
.subscribe((res: any[]) => {
this.loadingOffices = false;
this.offices = res || [];
if (this.offices.length === 1) {
this.selectOffice(this.offices[0].officeId);
}
});
}
selectOffice(officeId: number): void {
this.selectedOfficeId = officeId;
this.loadingProfile = true;
this.errorMsg = '';
this.successMsg = '';
this.organizationService
.getBranchProfile(officeId)
.pipe(
catchError((err: any) => {
this.loadingProfile = false;
this.errorMsg = err?.error?.errors?.[0]?.defaultUserMessage ?? 'Could not load this branch.';
return of(null);
})
)
.subscribe((res: any) => {
this.loadingProfile = false;
if (!res) return;
this.form.patchValue({
branchCode: res.branchCode ?? '',
branchType: res.branchType ?? null,
address: res.address ?? '',
pincode: res.pincode ?? '',
contactPhone: res.contactPhone ?? '',
contactEmail: res.contactEmail ?? '',
workingHoursStart: res.workingHoursStart ?? '',
workingHoursEnd: res.workingHoursEnd ?? '',
workingDays: res.workingDays ?? '',
ifscCode: res.ifscCode ?? '',
micrCode: res.micrCode ?? '',
latitude: res.latitude ?? null,
longitude: res.longitude ?? null
});
this.lastUpdated = res.updatedByUsername ? { by: res.updatedByUsername, at: res.updatedAt } : null;
this.form.markAsPristine();
// Reflect the just-loaded office in the list so the selector stays accurate without a reload.
const idx = this.offices.findIndex((o) => o.officeId === officeId);
if (idx >= 0) this.offices[idx] = res;
});
}
officeLabel(o: any): string {
return o.branchCode ? `${o.officeName} (${o.branchCode})` : o.officeName;
}
submit(): void {
if (this.saving || !this.selectedOfficeId) return;
this.saving = true;
this.errorMsg = '';
this.successMsg = '';
this.organizationService
.updateBranchProfile(this.selectedOfficeId, this.form.value)
.pipe(
catchError((err: any) => {
this.saving = false;
this.errorMsg = err?.error?.errors?.[0]?.defaultUserMessage ?? 'Could not save this branch.';
return of(null);
})
)
.subscribe((res: any) => {
this.saving = false;
if (!res) return;
if (res.rollbackTransaction) {
// Parked for checker approval - the branch profile has not actually changed yet.
this.successMsg = 'Branch profile update has been submitted for approval.';
this.form.markAsPristine();
return;
}
this.successMsg = 'Branch profile saved.';
this.form.markAsPristine();
// The response is now a CommandProcessingResult, not the updated row (the write goes through
// the command pipeline) - reload the saved row from the server instead of patching state from
// this response.
this.organizationService.getBranchProfile(this.selectedOfficeId!).subscribe((updated: any) => {
if (!updated) return;
this.lastUpdated = updated.updatedByUsername
? { by: updated.updatedByUsername, at: updated.updatedAt }
: null;
const idx = this.offices.findIndex((o) => o.officeId === this.selectedOfficeId);
if (idx >= 0) this.offices[idx] = updated;
});
});
}
}