Files
ever-gauzy/apps/gauzy/src/app/pages/dashboard/human-resources/human-resources.component.ts
T
Rahul R. e6b86f4c9d [Chore] Support Angular v19 (Nx v20.8.0) (#8610)
* chore(nx): migrate @nx/workspace to version 20.3.0

* chore(material): run migration-v19 for Angular Material update

* chore(packages): run explicit-standalone-flag migration for Angular v19

* chore(deps): downgrade TypeScript to 5.5.4 for Angular compatibility

* chore(deps): bump Angular ESLint dependencies to version 19

* chore(deps): bump @ng-select/ng-select to version 14.1.0

* chore(deps): bump @commitlint packages to latest versions

* fix(cspell): typo spelling :-)

* chore(packages): migrate initializers to new provider functions

* chore(deps): update the @angular/cli package version to ~19.0.0

* chore(deps): update packages to support Angular v19

* chore(packages): migrate initializers to new provider functions

* fix: correct Sentry.TraceService injection in AppInitializer

* Update yarn.lock

* Update yarn.lock

* fix: update yarn.lock

* fix(cspell): typo spelling :-)

* fix: update yarn.lock

* chore(deps): bump @angular/common to version 19.0.0

* chore(nx): migrate @nx/workspace to version 20.4.2

* chore(deps): update yarn.lock

* chore(nx): migrate @nx/workspace to version 20.4.4

* chore(deps): bump @angular/core from 19.1.5 to 19.1.6

* chore(deps): upgrade @nebular/auth and @nebular/theme to v15

- Upgrade @nebular/auth from ^14.0.2 to ^15.0.0
- Upgrade @nebular/theme from ^14.0.2 to ^15.0.0

* chore(deps): bump @angular-slider/ngx-slider from ^18.0.0 to ^19.0.0

* chore(deps): bump ngx-page-scroll and ngx-page-scroll-core to v14

- Bump ngx-page-scroll from ^13.0.0 to ^14.0.0
- Bump ngx-page-scroll-core from ^13.0.0 to ^14.0.0

* chore(deps): bump ngx-permissions from ^17.1.0 to ^19.0.0

* chore(deps): bump @ng-select/ng-select from ^14.1.0 to ^14.2.2

* chore(deps): bump @fortawesome/angular-fontawesome from 0.15.0 to 1.0.0

* fix: desktop build (make component standalone disabled)

* chore(deps): bump @angular/core from 18.2.12 to 19.1.6

* chore(nx): migrate @nx/workspace to version 20.8.0

* chore(deps): bump ng2-file-upload to version ^8.0.0

* chore(deps): bump @angular/core from 19.1.6 to 19.2.7

* chore(deps): bump @fullcalendar/core from ^6.1.15 to ^6.1.17

* chore(deps): bump @angular-eslint packages to v19.3.0

* fix: add `standalone: false` to angular components

* chore(deps): downgrade @angular-builders/custom-webpack from v19.0.1 to v18.0.0

* chore(deps): bump angular2-smart-table from ^3.5.0 to ^3.6.1

* refactor(styles): replace @import with @use for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* chore(deps): bump @angular/core from 19.0.0 to 19.2.0

* chore(deps): updated dependencies for `@fullcalendar/angular`

* fix(cspell): typo spelling :-)

* Revert "chore(deps): updated dependencies for `@fullcalendar/angular`"

This reverts commit 4b34d72071.

* chore(deps): switch @angular/* to ^19.2.7

* fix: revert nx migrations.json

* Revert "chore(deps): switch @angular/* to ^19.2.7"

This reverts commit edd9105c51.

* fix: align @angular/cdk version with @angular/core version

* chore(deps): bump @angular-builders/custom-webpack from 18.0.0 to 19.0.1

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* refactor(styles): replace `@import` with `@use` for SCSS module

* chore(deps): bump typescript from 5.5.4 to ^5.8.3

* fix(server-dashboard): remove redundant nullish coalescing from autoStart check

* fix: add suggestions from greptile-apps bot review

* fix: add suggestions from greptile-apps bot review
2025-04-26 15:47:55 +05:30

232 lines
6.6 KiB
TypeScript

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import {
BonusTypeEnum,
EmployeeStatisticsHistoryEnum,
IDateRangePicker,
IMonthAggregatedEmployeeStatistics,
IOrganization,
ISelectedEmployee
} from '@gauzy/contracts';
import { NbDialogService } from '@nebular/theme';
import { combineLatest } from 'rxjs';
import { debounceTime, filter, tap } from 'rxjs/operators';
import { Subject } from 'rxjs/internal/Subject';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { distinctUntilChange, toUTC } from '@gauzy/ui-core/common';
import { DateRangePickerBuilderService, EmployeeStatisticsService, Store } from '@gauzy/ui-core/core';
import { ProfitHistoryComponent, RecordsHistoryComponent } from '@gauzy/ui-core/shared';
@UntilDestroy({ checkProperties: true })
@Component({
selector: 'ga-human-resources',
templateUrl: './human-resources.component.html',
styleUrls: ['./human-resources.component.scss'],
standalone: false
})
export class HumanResourcesComponent implements OnInit, OnDestroy {
loading: boolean;
selectedDate: Date;
selectedEmployee: ISelectedEmployee;
selectedOrganization: IOrganization;
selectedDateRange: IDateRangePicker;
defaultCurrency: string;
incomePermissionsError = false;
expensePermissionError = false;
employeeStatistics: IMonthAggregatedEmployeeStatistics[];
expense = 0;
expenseWithoutSalary: number;
income: number;
nonBonusIncome: number;
profit: number;
directIncomeBonus: number;
bonus: number;
calculatedBonus: number;
bonusType: BonusTypeEnum;
bonusPercentage: number;
salary: number;
averageBonus: number;
statistics$: Subject<any> = new Subject();
constructor(
private readonly store: Store,
private readonly dialogService: NbDialogService,
private readonly router: Router,
private readonly employeeStatisticsService: EmployeeStatisticsService,
private readonly dateRangePickerBuilderService: DateRangePickerBuilderService
) {}
async ngOnInit() {
this.statistics$
.pipe(
debounceTime(300),
tap(() => this.getEmployeeStatistics()),
untilDestroyed(this)
)
.subscribe();
const storeOrganization$ = this.store.selectedOrganization$;
const selectedDateRange$ = this.dateRangePickerBuilderService.selectedDateRange$;
const selectedEmployee$ = this.store.selectedEmployee$;
combineLatest([storeOrganization$, selectedDateRange$, selectedEmployee$])
.pipe(
debounceTime(300),
distinctUntilChange(),
filter(([organization, dateRange, employee]) => !!organization && !!dateRange && !!employee),
tap(([organization, dateRange, employee]) => {
this.selectedOrganization = organization;
this.selectedDateRange = dateRange;
this.selectedEmployee = employee;
}),
tap(() => {
if (!this.selectedEmployee || !this.selectedEmployee.id) {
this.navigateToAccounting();
return;
}
}),
tap(([organization]) => {
this.bonusType = organization.bonusType as BonusTypeEnum;
this.bonusPercentage = organization.bonusPercentage;
this.defaultCurrency = organization.currency;
}),
tap(() => this.statistics$.next(true)),
untilDestroyed(this)
)
.subscribe();
}
async getEmployeeStatistics() {
if (!this.selectedOrganization) {
return;
}
const { tenantId } = this.store.user;
const { id: organizationId } = this.selectedOrganization;
const { startDate, endDate } = this.selectedDateRange;
this.loading = true;
this.employeeStatistics = await this.employeeStatisticsService.getAggregatedStatisticsByEmployeeId({
employeeId: this.selectedEmployee.id,
startDate: toUTC(startDate).format('YYYY-MM-DD HH:mm:ss'),
endDate: toUTC(endDate).format('YYYY-MM-DD HH:mm:ss'),
organizationId,
tenantId
});
this.income = this._statsSum(this.employeeStatistics, 'income');
this.expenseWithoutSalary = this._statsSum(this.employeeStatistics, 'expenseWithoutSalary');
this.expense = this._statsSum(this.employeeStatistics, 'expense');
this.directIncomeBonus = this._statsSum(this.employeeStatistics, 'directIncomeBonus');
this.nonBonusIncome = this.income - this.directIncomeBonus;
this.profit = this._statsSum(this.employeeStatistics, 'profit');
this.bonus = this._statsSum(this.employeeStatistics, 'bonus');
this.calculatedBonus = +(this.bonus - this.directIncomeBonus).toFixed(2);
this.salary = +(this.expense - this.expenseWithoutSalary).toFixed(2);
this.loading = false;
}
async openHistoryDialog(type: EmployeeStatisticsHistoryEnum) {
if (!this.selectedOrganization) {
return;
}
const { id: organizationId, tenantId } = this.selectedOrganization;
const { startDate, endDate } = this.selectedDateRange;
this.dialogService.open(RecordsHistoryComponent, {
context: {
type,
records: await this.employeeStatisticsService.getEmployeeStatisticsHistory({
employeeId: this.selectedEmployee.id,
startDate,
endDate,
type,
organizationId,
tenantId
})
}
});
}
/**
*
* @returns
*/
async openProfitDialog() {
if (!this.selectedOrganization) {
return;
}
const { id: organizationId, tenantId } = this.selectedOrganization;
const { startDate, endDate } = this.selectedDateRange;
const incomes = await this.employeeStatisticsService.getEmployeeStatisticsHistory({
employeeId: this.selectedEmployee.id,
startDate,
endDate,
type: EmployeeStatisticsHistoryEnum.INCOME,
organizationId,
tenantId
});
const expenses = await this.employeeStatisticsService.getEmployeeStatisticsHistory({
employeeId: this.selectedEmployee.id,
startDate,
endDate,
type: EmployeeStatisticsHistoryEnum.EXPENSES,
organizationId,
tenantId
});
this.dialogService.open(ProfitHistoryComponent, {
context: {
records: {
incomes,
expenses,
incomeTotal: this.income,
expenseTotal: this.expense,
profit: this.profit
}
}
});
}
/**
*
* @param employeeStatistics
* @param key
* @returns
*/
private _statsSum = (employeeStatistics: IMonthAggregatedEmployeeStatistics[], key: string): number => {
return Number(employeeStatistics.reduce((a, b) => a + b[key], 0).toFixed(2));
};
/**
*
*/
navigateToAccounting() {
this.router.navigate(['/pages/dashboard/accounting']);
}
/**
*
*/
edit() {
this.router.navigate(['/pages/employees/edit/' + this.selectedEmployee.id]);
}
/**
* GET Employee Position Accessor
*/
get employeePosition() {
if (!this.selectedEmployee) {
return;
}
const { shortDescription, employeeLevel } = this.selectedEmployee;
return [shortDescription, employeeLevel].filter(Boolean).join(' | ');
}
ngOnDestroy() {}
}