import { Injectable } from "@nestjs/common"; import { PrismaPostgresService } from "prisma/postgres/prisma-postgres.service"; import { module_list, Modules } from "src/common/mappers/module-access.mapper"; import { EmailToIdResolver } from "src/common/mappers/email-id.mapper"; import { toStringFromDate } from "src/common/utils/date-utils"; import { Result } from "src/common/errors/result-error.factory"; import { toStringFromCompanyCode } from "src/identity-and-account/employees/employee.utils"; import { EmployeeDetailedDto, EmployeeWithDetails } from "src/identity-and-account/employees/employee-detailed.dto"; @Injectable() export class EmployeesGetService { constructor( private readonly prisma: PrismaPostgresService, private readonly emailResolver: EmailToIdResolver, ) { } async findListEmployees(): Promise[], string>> { const employee_list = await this.prisma.employees.findMany({ select: { user: { select: { first_name: true, last_name: true, email: true, phone_number: true, }, }, supervisor: { select: { user: { select: { first_name: true, last_name: true, }, }, }, }, contracts: { select: { daily_expected_hours: true, applicable_overtime: true, on_call_allocation: true, weekend_on_call_allocation: true, phone_allocation: true, }, }, is_supervisor: true, job_title: true, company_code: true, external_payroll_id: true, first_work_day: true, last_work_day: true, schedule_preset_id: true, } }); const employeeDetailedList = employee_list.map(r => { return { first_name: r.user.first_name, last_name: r.user.last_name, email: r.user.email, phone_number: r.user.phone_number, company_name: toStringFromCompanyCode(r.company_code), job_title: r.job_title ?? '', contract: { daily_expected_hours: r.contracts?.daily_expected_hours ?? 24, applicable_overtime: r.contracts?.applicable_overtime ?? [], phone_allocation: Number(r.contracts?.phone_allocation), on_call_allocation: Number(r.contracts?.on_call_allocation), weekend_on_call_allocation: Number(r.contracts?.weekend_on_call_allocation), }, external_payroll_id: r.external_payroll_id, employee_full_name: `${r.user.first_name} ${r.user.last_name}`, is_supervisor: r.is_supervisor, supervisor_full_name: `${r.supervisor?.user.first_name} ${r.supervisor?.user.last_name}`, first_work_day: toStringFromDate(r.first_work_day), last_work_day: r.last_work_day ? toStringFromDate(r.last_work_day) : null, preset_id: r.schedule_preset_id ?? undefined, } }); return { success: true, data: employeeDetailedList }; }; async findOwnProfile(email: string): Promise, string>> { const user_id = await this.emailResolver.resolveUserIdWithEmail(email); if (!user_id.success) return { success: false, error: 'INVALID_USER' }; const existing_profile = await this.prisma.employees.findUnique({ where: { user_id: user_id.data }, select: { user: { select: { first_name: true, last_name: true, email: true, phone_number: true, residence: true, }, }, first_work_day: true, company_code: true, job_title: true, external_payroll_id: true, paid_time_off: true, is_supervisor: true, schedule_preset_id: true, contracts: { select: { daily_expected_hours: true, }, }, supervisor: { select: { id: true, user: { select: { first_name: true, last_name: true, }, }, }, }, }, }); if (!existing_profile) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }; if (!existing_profile.contracts) return { success: false, error: 'CONTRACT_NOT_FOUND' }; const company_name = toStringFromCompanyCode(existing_profile.company_code); return { success: true, data: { first_name: existing_profile.user.first_name, last_name: existing_profile.user.last_name, email: existing_profile.user.email, supervisor_full_name: `${existing_profile.supervisor?.user.first_name} ${existing_profile.supervisor?.user.last_name}`, company_name: company_name, contract: { daily_expected_hours: existing_profile.contracts?.daily_expected_hours ?? 24, }, job_title: existing_profile.job_title ?? '', external_payroll_id: existing_profile.external_payroll_id, paid_time_off: { vacation_hours: existing_profile.paid_time_off?.vacation_hours.toNumber() ?? 0, banked_hours: existing_profile.paid_time_off?.banked_hours.toNumber() ?? 0, last_updated: existing_profile.paid_time_off?.last_updated?.toISOString() ?? null, }, is_supervisor: existing_profile.is_supervisor, phone_number: existing_profile.user.phone_number, residence: existing_profile.user.phone_number, first_work_day: toStringFromDate(existing_profile.first_work_day), preset_id: existing_profile.schedule_preset_id ?? undefined, }, }; }; async findOneDetailedProfile(email: string, employee_email?: string): Promise> { const account_email = employee_email ?? email; const user_id = await this.emailResolver.resolveUserIdWithEmail(account_email); if (!user_id.success) return { success: false, error: 'INVALID_USER' }; const employee = await this.prisma.employees.findUnique({ where: { user_id: user_id.data }, select: { user: { select: { first_name: true, last_name: true, email: true, phone_number: true, residence: true, user_module_access: { select: { dashboard: true, employee_list: true, employee_management: true, personal_profile: true, timesheets: true, timesheets_approval: true, ticket: true, ticket_management: true, chatbot: true, }, }, }, }, supervisor: { select: { user: { select: { first_name: true, last_name: true, }, }, }, }, contracts: { select: { daily_expected_hours: true, } }, job_title: true, company_code: true, first_work_day: true, last_work_day: true, external_payroll_id: true, paid_time_off: true, is_supervisor: true, schedule_preset_id: true, schedule_preset: { select: { id: true, } } } }) as EmployeeWithDetails | null; // added a cast to removed unsafe typing **Eslint** if (!employee) return { success: false, error: `EMPLOYEE_NOT_FOUND` }; if (!employee.user) return { success: false, error: 'USER_NOT_FOUND' }; let module_access_array: Modules[] = []; if (employee.user.user_module_access) { module_access_array = toStringFromBoolean(employee.user.user_module_access); } const company_name = toStringFromCompanyCode(employee.company_code); const detailed_employee: EmployeeDetailedDto = { first_name: employee.user.first_name, last_name: employee.user.last_name, email: employee.user.email, residence: employee.user.residence ?? '', phone_number: employee.user.phone_number, company_name: company_name, is_supervisor: employee.is_supervisor ?? false, job_title: employee.job_title ?? '', external_payroll_id: employee.external_payroll_id, paid_time_off: { id: employee.paid_time_off?.id ?? -1, employee_id: employee.paid_time_off?.employee_id ?? -1, sick_hours: employee.paid_time_off?.sick_hours.toNumber() ?? 0, vacation_hours: employee.paid_time_off?.vacation_hours.toNumber() ?? 0, banked_hours: employee.paid_time_off?.banked_hours.toNumber() ?? 0, last_updated: employee.paid_time_off?.last_updated?.toISOString() ?? null, }, employee_full_name: `${employee.user.first_name} ${employee.user.last_name}`, first_work_day: toStringFromDate(employee.first_work_day), last_work_day: employee.last_work_day ? toStringFromDate(employee.last_work_day) : undefined, supervisor_full_name: employee.supervisor ? `${employee.supervisor?.user.first_name} ${employee.supervisor?.user.last_name}` : '', user_module_access: module_access_array, contract: { daily_expected_hours: employee.contracts?.daily_expected_hours ?? 24, }, preset_id: employee.schedule_preset_id ? employee.schedule_preset_id : undefined, } return { success: true, data: detailed_employee }; }; } const createDefaultModuleAccess = (): Record => module_list.reduce((acc, mod) => { acc[mod] = false; return acc; }, {} as Record); export const toBooleanFromString = (arr?: readonly string[] | null): Record => { const result = createDefaultModuleAccess(); if (!arr || !Array.isArray(arr)) return result; for (const item of arr) { if (typeof item !== 'string') continue; const trimmed = item.trim(); if ((module_list as readonly string[]).includes(trimmed)) { result[trimmed as Modules] = true; } } return result; } export const toStringFromBoolean = (boolean_module_access: Record): Modules[] => { const access_array = Object.entries(boolean_module_access); // eslint-disable-next-line @typescript-eslint/no-unused-vars const allowed_accesses = access_array.filter(([_key, value]) => value === true); return allowed_accesses.map(([key]) => key as Modules); }