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 {BehaviorSubject, Observable, of as observableOf} from 'rxjs'; import {EmployeeBenefitsDataSource} from './employee-benefits-datasource'; import {VoucherService} from '../core/voucher.service'; import {EmployeeBenefit, Voucher} from '../core/voucher'; import * as moment from 'moment'; import {AuthService} from '../auth/auth.service'; import {ConfirmDialogComponent} from '../shared/confirm-dialog/confirm-dialog.component'; import {ToasterService} from '../core/toaster.service'; import {debounceTime, distinctUntilChanged, map, startWith, switchMap} from 'rxjs/operators'; import {Employee} from '../employee/employee'; import {EmployeeService} from '../employee/employee.service'; @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, private auth: AuthService, private ser: VoucherService, private employeeSer: EmployeeService ) { this.createForm(); this.setupEmployeeAutocomplete(); } ngOnInit() { this.route.data .subscribe((data: { voucher: Voucher }) => { this.voucher = data.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); }); } ngAfterViewInit() { setTimeout(() => { this.employeeElement.nativeElement.focus(); }, 0); } createForm() { this.form = this.fb.group({ date: '', addRow: this.fb.group({ employee: '', grossSalary: '', daysWorked: '' }), }); } 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)) ); } displayEmployeeName(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 = this.getEsi(grossSalary, daysWorked, daysInMonth); const pf = this.getPf(grossSalary, daysWorked, daysInMonth); this.voucher.employeeBenefits.push({ employee: this.employee, grossSalary: grossSalary, daysWorked: 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); } getEsi(grossSalary, daysWorked, daysInMonth) { const limit = 21000, employeeRate = 0.0175, employerRate = 0.0475, employee = (grossSalary > limit) ? 0 : Math.ceil(employeeRate * grossSalary * daysWorked / daysInMonth), employer = (grossSalary > limit) ? 0 : Math.ceil(employerRate * grossSalary * daysWorked / daysInMonth); return {ee: employee, er: employer, both: employee + employer}; } getPf(grossSalary, daysWorked, daysInMonth) { const limit = 15000, employeeRate = 0.12, employerRate = 0.12 + 0.011 + 0.005 + 0.0001, employee = (grossSalary > limit) ? 0 : Math.ceil(employeeRate * grossSalary * daysWorked / daysInMonth), employer = (grossSalary > limit) ? 0 : Math.ceil(employerRate * grossSalary * daysWorked / daysInMonth); return {ee: employee, er: employer, both: employee + employer}; } canSave() { if (!this.voucher.id) { return true; } else if (this.voucher.posted && this.auth.user.perms.indexOf('edit-posted-vouchers') !== -1) { return true; } else { 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.toaster.show('Success', 'Voucher Posted'); }, (error) => { this.toaster.show('Danger', error); } ); } save() { this.ser.saveOrUpdate(this.getVoucher()) .subscribe( (result) => { this.toaster.show('Success', ''); 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( (result) => { 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(); } }); } }