/** * 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, TemplateRef, ElementRef, ViewChild, AfterViewInit, inject } from '@angular/core'; import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms'; import { Router, ActivatedRoute, RouterLink } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; /** Custom Services */ import { AccountingService } from '../../accounting.service'; import { AlertService } from 'app/core/alert/alert.service'; import { PopoverService } from '../../../configuration-wizard/popover/popover.service'; import { ConfigurationWizardService } from '../../../configuration-wizard/configuration-wizard.service'; /** Custom Dialog Component */ import { ContinueSetupDialogComponent } from '../../../configuration-wizard/continue-setup-dialog/continue-setup-dialog.component'; import { GLAccount } from 'app/shared/models/general.model'; import { GlAccountSelectorComponent } from '../../../shared/accounting/gl-account-selector/gl-account-selector.component'; import { MatCheckbox } from '@angular/material/checkbox'; import { CdkTextareaAutosize } from '@angular/cdk/text-field'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; /** * Create gl account component. */ @Component({ selector: 'mifosx-create-gl-account', templateUrl: './create-gl-account.component.html', styleUrls: ['./create-gl-account.component.scss'], imports: [ ...STANDALONE_SHARED_IMPORTS, GlAccountSelectorComponent, MatCheckbox, CdkTextareaAutosize ] }) export class CreateGlAccountComponent implements OnInit, AfterViewInit { private formBuilder = inject(UntypedFormBuilder); private accountingService = inject(AccountingService); private alertService = inject(AlertService); private route = inject(ActivatedRoute); private router = inject(Router); private configurationWizardService = inject(ConfigurationWizardService); private popoverService = inject(PopoverService); dialog = inject(MatDialog); /** GL account form. */ glAccountForm: UntypedFormGroup; /** Submitting state to prevent duplicate submissions. */ submitting = false; /** Chart of accounts data. */ chartOfAccountsData: any; /** Account type data. */ accountTypeData: any; /** Account usage data. */ accountUsageData: any; /** Parent data. */ parentData: GLAccount[] = []; /** Tag data. */ tagData: any; /** Account type id. (for creation of sub-ledger account) */ accountTypeId: number; /** Parent id. (for creation of sub-ledger account) */ parentId: number; /** Cancel route. (depending on creation of gl account or sub-ledger account) */ cancelRoute = '../../'; /* Reference of accounts form */ @ViewChild('accountFormRef') accountFormRef: ElementRef; /* Template for popover on accounts form */ @ViewChild('templateAccountFormRef') templateAccountFormRef: TemplateRef; /** * Retrieves the chart of accounts data from `resolve`. * @param {FormBuilder} formBuilder Form Builder. * @param {AccountingService} accountingService Accounting Service. * @param {ActivatedRoute} route Activated Route. * @param {Router} router Router for navigation. * @param {ConfigurationWizardService} configurationWizardService ConfigurationWizard Service. * @param {PopoverService} popoverService PopoverService. * @param {Matdialog} dialog Matdialog. */ constructor() { this.route.queryParamMap.subscribe((params) => { this.accountTypeId = Number(params.get('accountType')); this.parentId = Number(params.get('parent')); if (this.parentId) { this.cancelRoute = `../view/${this.parentId}`; } }); this.route.data.subscribe((data: { chartOfAccountsTemplate: any }) => { this.chartOfAccountsData = data.chartOfAccountsTemplate; this.accountTypeData = data.chartOfAccountsTemplate.accountTypeOptions; this.accountUsageData = data.chartOfAccountsTemplate.usageOptions; }); } /** * Creates and sets gl account form. */ ngOnInit() { this.createGlAccountForm(); this.setGLAccountForm(); } /** * Creates gl account form. */ createGlAccountForm() { this.glAccountForm = this.formBuilder.group({ type: [ '', Validators.required ], name: [ '', Validators.required ], usage: [ '', Validators.required ], glCode: [ '', Validators.required ], parentId: [this.parentId || undefined], tagId: [''], manualEntriesAllowed: [true], description: [''] }); } /** * Sets gl account form for selected account type. */ setGLAccountForm() { this.glAccountForm.get('type').valueChanges.subscribe((accountTypeId) => { switch (accountTypeId) { case 1: this.parentData = this.chartOfAccountsData.assetHeaderAccountOptions; this.tagData = this.chartOfAccountsData.allowedAssetsTagOptions; break; case 2: this.parentData = this.chartOfAccountsData.liabilityHeaderAccountOptions; this.tagData = this.chartOfAccountsData.allowedLiabilitiesTagOptions; break; case 3: this.parentData = this.chartOfAccountsData.equityHeaderAccountOptions; this.tagData = this.chartOfAccountsData.allowedEquityTagOptions; break; case 4: this.parentData = this.chartOfAccountsData.incomeHeaderAccountOptions; this.tagData = this.chartOfAccountsData.allowedIncomeTagOptions; break; case 5: this.parentData = this.chartOfAccountsData.expenseHeaderAccountOptions; this.tagData = this.chartOfAccountsData.allowedExpensesTagOptions; break; } }); } /** * Submits the gl account form and creates gl account, * if successful redirects to view created account or back to list if awaiting approval. */ submit() { if (this.glAccountForm.invalid || this.submitting) { return; } this.submitting = true; this.accountingService.createGlAccount(this.glAccountForm.value).subscribe({ next: (response: any) => { if (response?.resourceId) { if (this.configurationWizardService.showChartofAccounts) { this.configurationWizardService.showChartofAccounts = false; this.openDialog(); } else { this.router.navigate( [ '../view', response.resourceId ], { relativeTo: this.route } ); } } else if (response?.rollbackTransaction) { this.alertService.alert({ type: 'Success', message: 'GL Account submitted successfully for approval.' }); this.router.navigate([this.cancelRoute], { relativeTo: this.route }); } else { this.router.navigate([this.cancelRoute], { relativeTo: this.route }); } }, error: () => { this.submitting = false; } }); } /** * Popover function * @param template TemplateRef. * @param target HTMLElement | ElementRef. * @param position String. * @param backdrop Boolean. */ showPopover( template: TemplateRef, target: HTMLElement | ElementRef, position: string, backdrop: boolean ): void { setTimeout(() => this.popoverService.open(template, target, position, backdrop, {}), 200); } /** * To show popover. */ ngAfterViewInit() { if (this.configurationWizardService.showChartofAccountsForm) { setTimeout(() => { this.showPopover(this.templateAccountFormRef, this.accountFormRef.nativeElement, 'bottom', true); }); } } /** * Next Step (Accounts Linked Accounting Page) Configuration Wizard. */ nextStep() { this.configurationWizardService.showChartofAccountsForm = false; this.configurationWizardService.showAccountsLinked = true; this.router.navigate(['/accounting']); } /** * Previous Step (Charts of Accounts Page) Configuration Wizard. */ previousStep() { this.configurationWizardService.showChartofAccountsForm = false; this.configurationWizardService.showChartofAccountsList = true; this.router.navigate(['/accounting/chart-of-accounts']); } /** * Opens dialog if the user wants to create more accounts. */ openDialog() { const continueSetupDialogRef = this.dialog.open(ContinueSetupDialogComponent, { data: { stepName: 'GL account' } }); continueSetupDialogRef.afterClosed().subscribe((response: { step: number }) => { if (response.step === 1) { this.configurationWizardService.showChartofAccountsForm = false; this.router.navigate(['../'], { relativeTo: this.route }); } else if (response.step === 2) { this.configurationWizardService.showChartofAccountsForm = true; this.router.routeReuseStrategy.shouldReuseRoute = () => false; this.router.onSameUrlNavigation = 'reload'; this.router.navigate(['/accounting/chart-of-accounts/gl-accounts/create']); } else if (response.step === 3) { this.configurationWizardService.showChartofAccountsForm = false; this.configurationWizardService.showAccountsLinked = true; this.router.navigate(['/accounting']); } }); } }