import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; import { AuthService } from '../auth/auth.service'; import { EmployeeBenefit } from '../core/employee-benefit'; import { ToasterService } from '../core/toaster.service'; import { Voucher } from '../core/voucher'; import { VoucherService } from '../core/voucher.service'; import { Employee } from '../employee/employee'; import { EmployeeService } from '../employee/employee.service'; import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.component'; import { EmployeeBenefitsDataSource } from './employee-benefits-datasource'; @Component({ selector: 'app-employee-benefits', templateUrl: './employee-benefits.component.html', styleUrls: ['./employee-benefits.component.css'], }) export class EmployeeBenefitsComponent implements OnInit, AfterViewInit { @ViewChild('employeeElement', { static: true }) employeeElement?: ElementRef; public benefitsObservable = new BehaviorSubject([]); dataSource: EmployeeBenefitsDataSource; form: FormGroup; voucher: Voucher; employee: Employee; accBal: any; displayedColumns = [ 'name', 'designation', 'department', 'grossSalary', 'daysWorked', 'esiEmployee', 'pfEmployee', 'esiEmployer', 'pfEmployer', ]; employees: Observable; constructor( private route: ActivatedRoute, private router: Router, private fb: FormBuilder, private dialog: MatDialog, private toaster: ToasterService, public auth: AuthService, private ser: VoucherService, private employeeSer: EmployeeService, ) { this.form = this.fb.group({ date: '', addRow: this.fb.group({ employee: '', grossSalary: '', daysWorked: '', }), }); this.setupEmployeeAutocomplete(); } static getPf(grossSalary, daysWorked, daysInMonth) { const limit = 15000; const employeeRate = 0.12; const employerRate = 0.12 + 0.011 + 0.005 + 0.0001; const employee = grossSalary > limit ? 0 : Math.ceil((employeeRate * grossSalary * daysWorked) / daysInMonth); const employer = grossSalary > limit ? 0 : Math.ceil((employerRate * grossSalary * daysWorked) / daysInMonth); return { ee: employee, er: employer, both: employee + employer }; } static getEsi(grossSalary, daysWorked, daysInMonth) { const limit = 21000; const employeeRate = 0.0175; const employerRate = 0.0475; const employee = grossSalary > limit ? 0 : Math.ceil((employeeRate * grossSalary * daysWorked) / daysInMonth); const employer = grossSalary > limit ? 0 : Math.ceil((employerRate * grossSalary * daysWorked) / daysInMonth); return { ee: employee, er: employer, both: employee + employer }; } ngOnInit() { this.route.data.subscribe((value) => { const data = value as { voucher: Voucher }; this.loadVoucher(data.voucher); }); } ngAfterViewInit() { setTimeout(() => { this.employeeElement.nativeElement.focus(); }, 0); } loadVoucher(voucher) { this.voucher = voucher; this.form.setValue({ date: moment(this.voucher.date, 'DD-MMM-YYYY').toDate(), addRow: { employee: '1', grossSalary: '', daysWorked: '', }, }); this.dataSource = new EmployeeBenefitsDataSource(this.benefitsObservable); this.benefitsObservable.next(this.voucher.employeeBenefits); } setupEmployeeAutocomplete(): void { const control = this.form.get('addRow').get('employee'); this.employees = control.valueChanges.pipe( startWith(null), map((x) => (x !== null && x.length >= 1 ? x : null)), debounceTime(150), distinctUntilChanged(), switchMap((x) => (x === null ? observableOf([]) : this.employeeSer.autocomplete(x))), ); } displayFn(employee?: Employee): string | undefined { return employee ? employee.name : undefined; } employeeSelected(event: MatAutocompleteSelectedEvent): void { this.employee = event.option.value; } addRow() { const oldFiltered = this.voucher.employeeBenefits.filter( (x) => x.employee.id === this.employee.id, ); if (oldFiltered.length) { this.toaster.show('Danger', 'Employee has already been added'); return; } const formValue = this.form.get('addRow').value; const grossSalary = +formValue.grossSalary; const daysWorked = +formValue.daysWorked; const date = this.form.get('date').value; const daysInMonth = moment(date).daysInMonth(); const esi = EmployeeBenefitsComponent.getEsi(grossSalary, daysWorked, daysInMonth); const pf = EmployeeBenefitsComponent.getPf(grossSalary, daysWorked, daysInMonth); this.voucher.employeeBenefits.push({ employee: this.employee, grossSalary, daysWorked, esiEmployee: esi.ee, pfEmployee: pf.ee, esiEmployer: esi.er, pfEmployer: pf.er, }); this.benefitsObservable.next(this.voucher.employeeBenefits); this.resetAddRow(); } resetAddRow() { this.form.get('addRow').reset({ employee: '', grossSalary: null, daysWorked: null, }); this.employee = null; setTimeout(() => { this.employeeElement.nativeElement.focus(); }, 0); } deleteRow(row: EmployeeBenefit) { this.voucher.employeeBenefits.splice(this.voucher.employeeBenefits.indexOf(row), 1); this.benefitsObservable.next(this.voucher.employeeBenefits); } canSave() { if (!this.voucher.id) { return true; } if (this.voucher.posted && this.auth.user.perms.indexOf('edit-posted-vouchers') !== -1) { return true; } return ( this.voucher.user.id === this.auth.user.id || this.auth.user.perms.indexOf("edit-other-user's-vouchers") !== -1 ); } post() { this.ser.post(this.voucher.id).subscribe( (result) => { this.loadVoucher(result); this.toaster.show('Success', 'Voucher Posted'); }, (error) => { this.toaster.show('Danger', error); }, ); } save() { const voucher: Voucher = this.getVoucher(); this.ser.saveOrUpdate(voucher).subscribe( (result) => { this.toaster.show('Success', ''); if (voucher.id === result.id) { this.loadVoucher(result); } else { this.router.navigate(['/employee-benefits', result.id]); } }, (error) => { this.toaster.show('Danger', error); }, ); } getVoucher(): Voucher { const formModel = this.form.value; this.voucher.date = moment(formModel.date).format('DD-MMM-YYYY'); return this.voucher; } delete() { this.ser.delete(this.voucher.id).subscribe( () => { this.toaster.show('Success', ''); this.router.navigate(['/employee-benefits'], { replaceUrl: true }); }, (error) => { this.toaster.show('Danger', error); }, ); } confirmDelete(): void { const dialogRef = this.dialog.open(ConfirmDialogComponent, { width: '250px', data: { title: 'Delete Voucher?', content: 'Are you sure? This cannot be undone.' }, }); dialogRef.afterClosed().subscribe((result: boolean) => { if (result) { this.delete(); } }); } }