diff --git a/prisma/migrations/20251203192130_added_the_option_of_null_to_is_dark_mode/migration.sql b/prisma/migrations/20251203192130_added_the_option_of_null_to_is_dark_mode/migration.sql new file mode 100644 index 0000000..6bc061e --- /dev/null +++ b/prisma/migrations/20251203192130_added_the_option_of_null_to_is_dark_mode/migration.sql @@ -0,0 +1,5 @@ +-- CreateEnum +CREATE TYPE "modules" AS ENUM ('timesheets', 'timesheets_approval', 'employee_list', 'employee_management', 'personal_profile', 'dashboard'); + +-- AlterTable +ALTER TABLE "preferences" ALTER COLUMN "is_dark_mode" DROP NOT NULL; diff --git a/prisma/migrations/20251203210621_removed_autoincrements_from_external_payroll_id/migration.sql b/prisma/migrations/20251203210621_removed_autoincrements_from_external_payroll_id/migration.sql new file mode 100644 index 0000000..9f0050d --- /dev/null +++ b/prisma/migrations/20251203210621_removed_autoincrements_from_external_payroll_id/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "employees" ALTER COLUMN "external_payroll_id" DROP DEFAULT; +DROP SEQUENCE "employees_external_payroll_id_seq"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5dc2348..a016790 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -53,7 +53,7 @@ model Employees { supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id]) supervisor_id Int? - external_payroll_id Int @default(autoincrement()) + external_payroll_id Int company_code Int first_work_day DateTime @db.Date last_work_day DateTime? @db.Date @@ -347,12 +347,12 @@ model Preferences { user Users @relation("UserPreferences", fields: [user_id], references: [id]) user_id String @unique @db.Uuid - notifications Boolean @default(true) + notifications Boolean @default(true) is_dark_mode Boolean? @default(false) - display_language String @default("fr-FR") //'fr-FR' | 'en-CA'; - is_lefty_mode Boolean @default(false) - is_employee_list_grid Boolean @default(true) - is_timesheet_approval_grid Boolean @default(true) + display_language String @default("fr-FR") //'fr-FR' | 'en-CA'; + is_lefty_mode Boolean @default(false) + is_employee_list_grid Boolean @default(true) + is_timesheet_approval_grid Boolean @default(true) @@map("preferences") } diff --git a/src/identity-and-account/employees/controllers/employees.controller.ts b/src/identity-and-account/employees/controllers/employees.controller.ts index ef11eb9..6dba8bf 100644 --- a/src/identity-and-account/employees/controllers/employees.controller.ts +++ b/src/identity-and-account/employees/controllers/employees.controller.ts @@ -1,11 +1,11 @@ import { Controller, Get, Query, Body, Post, Patch } from "@nestjs/common"; +import { Modules as ModulesEnum } from ".prisma/client"; +import { ModuleAccessAllowed } from "src/common/decorators/modules-guard.decorators"; import { Access } from "src/common/decorators/module-access.decorators"; import { Result } from "src/common/errors/result-error.factory"; import { EmployeeDetailedDto } from "src/identity-and-account/employees/dtos/employee-detailed.dto"; import { EmployeeDto } from "src/identity-and-account/employees/dtos/employee.dto"; import { EmployeesGetService } from "src/identity-and-account/employees/services/employees-get.service"; -import { ModuleAccessAllowed } from "src/common/decorators/modules-guard.decorators"; -import { Modules as ModulesEnum } from ".prisma/client"; import { EmployeesCreateService } from "src/identity-and-account/employees/services/employees-create.service"; import { EmployeesUpdateService } from "src/identity-and-account/employees/services/employees-update.service"; diff --git a/src/identity-and-account/employees/dtos/employee-detailed.dto.ts b/src/identity-and-account/employees/dtos/employee-detailed.dto.ts index 2384a96..1a6769b 100644 --- a/src/identity-and-account/employees/dtos/employee-detailed.dto.ts +++ b/src/identity-and-account/employees/dtos/employee-detailed.dto.ts @@ -4,7 +4,7 @@ import { Type } from 'class-transformer'; export class EmployeeDetailedDto { @IsString() @IsNotEmpty() first_name: string; @IsString() @IsNotEmpty() last_name: string; - @IsString() employee_full_name: string; + @IsString() @IsOptional() employee_full_name: string; @IsString() @IsOptional() supervisor_full_name: string; @IsOptional() @IsBoolean() is_supervisor: boolean; @IsString() company_name: string; diff --git a/src/identity-and-account/employees/services/employees-create.service.ts b/src/identity-and-account/employees/services/employees-create.service.ts index 16d2d0d..ac388c7 100644 --- a/src/identity-and-account/employees/services/employees-create.service.ts +++ b/src/identity-and-account/employees/services/employees-create.service.ts @@ -14,6 +14,7 @@ export class EmployeesCreateService { const normalized_access = toBooleanFromString(dto.user_module_access); const supervisor_id = await this.toIdFromFullName(dto.supervisor_full_name); const company_code = toCompanyCodeFromString(dto.company_name) + await this.prisma.$transaction(async (tx) => { const user: Users = await tx.users.create({ data: { @@ -37,10 +38,10 @@ export class EmployeesCreateService { return tx.employees.create({ data: { user_id: user.id, + external_payroll_id: dto.external_payroll_id, company_code: company_code, job_title: dto.job_title, first_work_day: dto.first_work_day, - last_work_day: dto.last_work_day, is_supervisor: dto.is_supervisor, supervisor_id: supervisor_id, }, diff --git a/src/identity-and-account/employees/services/employees-update.service.ts b/src/identity-and-account/employees/services/employees-update.service.ts index aca67e7..1e0f280 100644 --- a/src/identity-and-account/employees/services/employees-update.service.ts +++ b/src/identity-and-account/employees/services/employees-update.service.ts @@ -2,6 +2,7 @@ import { Injectable } from "@nestjs/common"; import { Result } from "src/common/errors/result-error.factory"; import { EmailToIdResolver } from "src/common/mappers/email-id.mapper"; import { toBooleanFromString } from "src/common/mappers/module-access.mapper"; +import { toDateFromString } from "src/common/utils/date-utils"; import { EmployeeDetailedDto } from "src/identity-and-account/employees/dtos/employee-detailed.dto"; import { toCompanyCodeFromString } from "src/identity-and-account/employees/utils/employee.utils"; import { PrismaService } from "src/prisma/prisma.service"; @@ -13,8 +14,8 @@ export class EmployeesUpdateService { private readonly emailResolver: EmailToIdResolver, ) { } - async updateEmployee(email: string, dto: EmployeeDetailedDto, employee_email?: string): Promise> { - const account_email = employee_email ?? email; + async updateEmployee(email: string, dto: EmployeeDetailedDto): Promise> { + const account_email = dto.email ?? email; const user_id = await this.emailResolver.resolveUserIdWithEmail(account_email); if (!user_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND' } @@ -31,16 +32,26 @@ export class EmployeesUpdateService { email: dto.email, phone_number: dto.phone_number, residence: dto.residence, - user_module_access: { - update: { - dashboard: normalized_access.dashboard, - employee_list: normalized_access.employee_list, - employee_management: normalized_access.employee_management, - personal_profile: normalized_access.personal_profile, - timesheets: normalized_access.timesheets, - timesheets_approval: normalized_access.timesheets_approval, - }, - }, + }, + }); + await tx.userModuleAccess.upsert({ + where: { user_id: user_id.data }, + update: { + dashboard: normalized_access.dashboard, + employee_list: normalized_access.employee_list, + employee_management: normalized_access.employee_management, + personal_profile: normalized_access.personal_profile, + timesheets: normalized_access.timesheets, + timesheets_approval: normalized_access.timesheets_approval, + }, + create: { + user_id: user_id.data, + dashboard: normalized_access.dashboard, + employee_list: normalized_access.employee_list, + employee_management: normalized_access.employee_management, + personal_profile: normalized_access.personal_profile, + timesheets: normalized_access.timesheets, + timesheets_approval: normalized_access.timesheets_approval, }, }); return tx.employees.update({ @@ -48,7 +59,7 @@ export class EmployeesUpdateService { data: { company_code: company_code, job_title: dto.job_title, - first_work_day: dto.first_work_day, + first_work_day: toDateFromString(dto.first_work_day), last_work_day: dto.last_work_day, is_supervisor: dto.is_supervisor, supervisor_id: supervisor_id, diff --git a/src/identity-and-account/preferences/dtos/preferences.dto.ts b/src/identity-and-account/preferences/dtos/preferences.dto.ts index 81a8dd6..e470dad 100644 --- a/src/identity-and-account/preferences/dtos/preferences.dto.ts +++ b/src/identity-and-account/preferences/dtos/preferences.dto.ts @@ -8,7 +8,7 @@ export enum DisplayLanguage { export class PreferencesDto { @IsInt() id: number; @IsBoolean() notifications: boolean; - @IsOptional() @IsBoolean() is_dark_mode?: boolean; + @IsOptional() @IsBoolean() is_dark_mode?: boolean | null; @IsEnum(DisplayLanguage) display_language: string; @IsBoolean() is_lefty_mode: boolean; @IsBoolean() is_employee_list_grid: boolean;