feat(userModuleAccess): added ticket, ticket_management and chatbot to the employee services and module-access services

This commit is contained in:
Matthieu Haineault 2026-03-16 09:11:30 -04:00
parent 043e517a83
commit 8949b8a4fa
10 changed files with 91 additions and 10 deletions

View File

@ -47,6 +47,8 @@ export const Modules = {
employee_management: 'employee_management',
personal_profile: 'personal_profile',
dashboard: 'dashboard',
ticket: 'ticket',
ticket_management: 'ticket_management',
chatbot: 'chatbot'
} as const

View File

@ -5,6 +5,8 @@ export type Modules =
| 'employee_management'
| 'personal_profile'
| 'dashboard'
| 'ticket'
| 'ticket_management'
| 'chatbot';
export const module_list = [
@ -14,5 +16,7 @@ export const module_list = [
'employee_management',
'personal_profile',
'dashboard',
'ticket',
'ticket_management',
'chatbot',
] as const;

View File

@ -1,6 +1,7 @@
import { IsArray, IsBoolean, IsDateString, IsEmail, IsInt, IsNotEmpty, IsOptional, IsPositive, IsString } from 'class-validator';
import { Type } from 'class-transformer';
import { PaidTimeOffDto } from 'src/time-and-attendance/paid-time-off/paid-time-off.dto';
import { Prisma } from 'prisma/postgres/generated/prisma/client/postgres/client';
export class EmployeeDetailedDto {
@IsString() @IsNotEmpty() first_name: string;
@ -41,3 +42,42 @@ export class EmployeeDetailedUpsertDto {
@IsArray() @IsString({ each: true }) user_module_access: string[];
@IsInt() @IsOptional() preset_id?: number;
}
export type EmployeeWithDetails = Prisma.EmployeesGetPayload<{
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 } } } },
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,
daily_expected_hours: true,
schedule_preset_id: true,
schedule_preset: { select: { id: true } }
}
}>;

View File

@ -33,7 +33,9 @@ export class EmployeesCreateService {
personal_profile: normalized_access.personal_profile,
timesheets: normalized_access.timesheets,
timesheets_approval: normalized_access.timesheets_approval,
ticket: normalized_access.ticket,
ticket_management: normalized_access.ticket_management,
chatbot: normalized_access.chatbot,
},
},
},

View File

@ -7,7 +7,7 @@ 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 } from "src/identity-and-account/employees/employee-detailed.dto";
import { EmployeeDetailedDto, EmployeeWithDetails } from "src/identity-and-account/employees/employee-detailed.dto";
@Injectable()
export class EmployeesGetService {
@ -153,6 +153,8 @@ export class EmployeesGetService {
personal_profile: true,
timesheets: true,
timesheets_approval: true,
ticket: true,
ticket_management: true,
chatbot: true,
},
},
@ -183,7 +185,7 @@ export class EmployeesGetService {
}
}
}
});
}) 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' };
@ -248,6 +250,8 @@ export const toBooleanFromString = (arr?: readonly string[] | null): Record<Modu
export const toStringFromBoolean = (boolean_module_access: Record<Modules, boolean>): 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);
}

View File

@ -20,14 +20,14 @@ export class EmployeesUpdateService {
async updateEmployee(dto: EmployeeDetailedUpsertDto): Promise<Result<boolean, string>> {
const user_id = await this.emailResolver.resolveUserIdWithEmail(dto.email);
if (!user_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND'}
if (!user_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }
const employee = await this.prisma.employees.findFirst({
where: { user_id: user_id.data },
select: { id: true },
})
if (!employee) return { success: false, error: 'EMPLOYEE_NOT_FOUND'};
if (!employee) return { success: false, error: 'EMPLOYEE_NOT_FOUND' };
const company_code = toCompanyCodeFromString(dto.company_name);
const supervisor_id = await this.toIdFromFullName(dto.supervisor_full_name);
@ -55,6 +55,8 @@ export class EmployeesUpdateService {
personal_profile: normalized_access.personal_profile,
timesheets: normalized_access.timesheets,
timesheets_approval: normalized_access.timesheets_approval,
ticket: normalized_access.ticket,
ticket_management: normalized_access.ticket_management,
chatbot: normalized_access.chatbot,
},
create: {
@ -65,6 +67,8 @@ export class EmployeesUpdateService {
personal_profile: normalized_access.personal_profile,
timesheets: normalized_access.timesheets,
timesheets_approval: normalized_access.timesheets_approval,
ticket: normalized_access.ticket,
ticket_management: normalized_access.ticket_management,
chatbot: normalized_access.chatbot,
},
});

View File

@ -7,4 +7,7 @@ export class ModuleAccess {
@IsBoolean() employee_management: boolean;
@IsBoolean() personal_profile: boolean;
@IsBoolean() dashboard: boolean;
@IsBoolean() ticket: boolean;
@IsBoolean() ticket_management: boolean;
@IsBoolean() chatbot: boolean;
}

View File

@ -29,8 +29,11 @@ export class AccessGetService {
employee_management: true,
personal_profile: true,
dashboard: true,
ticket: true,
ticket_management: true,
chatbot: true,
},
});
}) as ModuleAccess;
if (!access) return { success: false, error: 'MODULE_ACCESS_NOT_FOUND' };
const granted_access: ModuleAccess = {
@ -40,6 +43,9 @@ export class AccessGetService {
employee_management: access.employee_management,
personal_profile: access.personal_profile,
dashboard: access.dashboard,
ticket: access.ticket,
ticket_management: access.ticket_management,
chatbot: access.chatbot,
};
return { success: true, data: granted_access }
};

View File

@ -23,19 +23,21 @@ export class AccessUpdateService {
const orignal_access = await this.prisma.userModuleAccess.findUnique({
where: { user_id: user_id.data },
select: {
id: true,
timesheets: true,
timesheets_approval: true,
employee_list: true,
employee_management: true,
personal_profile: true,
dashboard: true,
ticket: true,
ticket_management: true,
chatbot: true,
},
});
}) as ModuleAccess | null;
if (!orignal_access) return { success: false, error: 'MODULE_ACCESS_NOT_FOUND' };
const updated_access:ModuleAccess = await this.prisma.userModuleAccess.update({
where: { id: orignal_access.id },
where: { user_id: user_id.data },
data: {
timesheets: dto.timesheets,
timesheets_approval: dto.timesheets_approval,
@ -43,6 +45,9 @@ export class AccessUpdateService {
employee_management: dto.employee_management,
personal_profile: dto.personal_profile,
dashboard: dto.dashboard,
ticket: dto.ticket,
ticket_management: dto.ticket_management,
chatbot: dto.chatbot
},
select: {
timesheets: true,
@ -51,6 +56,9 @@ export class AccessUpdateService {
employee_management: true,
personal_profile: true,
dashboard: true,
ticket: true,
ticket_management: true,
chatbot: true,
}
})
return { success: true, data: updated_access };
@ -79,6 +87,9 @@ export class AccessUpdateService {
employee_management: false,
personal_profile: false,
dashboard: false,
ticket: false,
ticket_management: false,
chatbot: false,
},
select: {
timesheets: true,
@ -87,6 +98,9 @@ export class AccessUpdateService {
employee_management: true,
personal_profile: true,
dashboard: true,
ticket: true,
ticket_management: true,
chatbot: true,
}
});

View File

@ -21,6 +21,8 @@ export abstract class AbstractUserService {
personal_profile: true,
timesheets: true,
timesheets_approval: true,
ticket: true,
ticket_management: true,
chatbot: true,
},
},