From ff5cf080e73d519cfafdf5699566f29ff96de97b Mon Sep 17 00:00:00 2001 From: enlineawork Date: Mon, 7 Sep 2026 14:13:43 -0300 Subject: [PATCH] F3.1: persistir perfil personal y exigir email al Inspector --- .../src/administration/users/users.service.ts | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/api-v3/src/administration/users/users.service.ts b/api-v3/src/administration/users/users.service.ts index 16dfd5b..6ab6099 100644 --- a/api-v3/src/administration/users/users.service.ts +++ b/api-v3/src/administration/users/users.service.ts @@ -41,6 +41,10 @@ export interface AdministrativeUserView { id: string; username: string; email: string | null; + dni: string | null; + phone: string | null; + jobTitle: string | null; + employeeNumber: string | null; firstName: string; lastName: string; status: UserStatus; @@ -72,6 +76,13 @@ function roleSelectionInvalid(): BadRequestException { }); } +function inspectorEmailRequired(): BadRequestException { + return new BadRequestException({ + code: 'INSPECTOR_EMAIL_REQUIRED', + message: 'Los usuarios con rol Inspector deben tener un email válido para recibir la documentación de sus inspecciones', + }); +} + @Injectable() export class UsersService { constructor( @@ -96,6 +107,10 @@ export class UsersService { OR user_account.email ILIKE $${parameters.length} OR user_account.first_name ILIKE $${parameters.length} OR user_account.last_name ILIKE $${parameters.length} + OR user_account.dni ILIKE $${parameters.length} + OR user_account.phone ILIKE $${parameters.length} + OR user_account.job_title ILIKE $${parameters.length} + OR user_account.employee_number ILIKE $${parameters.length} ) `); } @@ -115,6 +130,10 @@ export class UsersService { user_account.id, user_account.username, user_account.email, + user_account.dni, + user_account.phone, + user_account.job_title AS "jobTitle", + user_account.employee_number AS "employeeNumber", user_account.first_name AS "firstName", user_account.last_name AS "lastName", user_account.status, @@ -176,9 +195,14 @@ export class UsersService { try { return await this.dataSource.transaction(async (manager) => { const roles = await this.resolveRoles(manager, dto.roleIds); + this.assertInspectorHasEmail(roles, dto.email ?? null); const user = manager.getRepository(User).create({ username: dto.username.trim().toLowerCase(), email: dto.email?.trim().toLowerCase() || null, + dni: dto.dni ?? null, + phone: dto.phone ?? null, + jobTitle: dto.jobTitle ?? null, + employeeNumber: dto.employeeNumber ?? null, passwordHash, firstName: dto.firstName.trim(), lastName: dto.lastName.trim(), @@ -227,6 +251,10 @@ export class UsersService { if ( dto.username === undefined && dto.email === undefined && + dto.dni === undefined && + dto.phone === undefined && + dto.jobTitle === undefined && + dto.employeeNumber === undefined && dto.firstName === undefined && dto.lastName === undefined ) { @@ -240,6 +268,9 @@ export class UsersService { return await this.dataSource.transaction(async (manager) => { const user = await this.lockUser(manager, id); const before = await this.loadUserView(manager, id); + if (dto.email !== undefined && !dto.email && before.roles.some((role) => role.code === 'inspector')) { + throw inspectorEmailRequired(); + } if (dto.username !== undefined) { user.username = dto.username.trim().toLowerCase(); @@ -247,6 +278,10 @@ export class UsersService { if (dto.email !== undefined) { user.email = dto.email?.trim().toLowerCase() || null; } + if (dto.dni !== undefined) user.dni = dto.dni ?? null; + if (dto.phone !== undefined) user.phone = dto.phone ?? null; + if (dto.jobTitle !== undefined) user.jobTitle = dto.jobTitle ?? null; + if (dto.employeeNumber !== undefined) user.employeeNumber = dto.employeeNumber ?? null; if (dto.firstName !== undefined) user.firstName = dto.firstName.trim(); if (dto.lastName !== undefined) user.lastName = dto.lastName.trim(); user.updatedBy = principal.userId; @@ -379,6 +414,7 @@ export class UsersService { await this.lockUser(manager, id); const roles = await this.resolveRoles(manager, dto.roleIds); const before = await this.loadUserView(manager, id); + this.assertInspectorHasEmail(roles, before.email); const beforeIds = before.roles.map((role) => role.id).sort(); const afterIds = roles.map((role) => role.id).sort(); if (beforeIds.join(',') === afterIds.join(',')) return before; @@ -417,6 +453,12 @@ export class UsersService { return roles; } + private assertInspectorHasEmail(roles: Role[], email: string | null | undefined): void { + if (roles.some((role) => role.code === 'inspector') && !email?.trim()) { + throw inspectorEmailRequired(); + } + } + private async insertUserRoles( manager: EntityManager, userId: string, @@ -455,6 +497,10 @@ export class UsersService { user_account.id, user_account.username, user_account.email, + user_account.dni, + user_account.phone, + user_account.job_title AS "jobTitle", + user_account.employee_number AS "employeeNumber", user_account.first_name AS "firstName", user_account.last_name AS "lastName", user_account.status, @@ -491,7 +537,7 @@ export class UsersService { private userConflict(): ConflictException { return new ConflictException({ code: 'USER_ALREADY_EXISTS', - message: 'El usuario o email ya está registrado', + message: 'El usuario, email o DNI ya está registrado', }); } }