Módulo Departments
src/app/modules/departments/
Gestiona los departamentos del tenant (equipos de atención) y la pertenencia de usuarios a cada uno. Cada departamento define su mensaje de bienvenida, la política de asignación automática, si se exige motivo de contacto y su propia regla de auto-resolución de tickets.
Modelos
Department (colección departments)
| Campo | Tipo | Descripción |
|---|---|---|
tenantId | ObjectId → Tenant | Tenant propietario |
name | string | Nombre |
color | string | Color hexadecimal (por defecto #000000) |
greetingMessage | string | Mensaje de bienvenida (por defecto vacío) |
autoAssignment | boolean | Asignación automática de chats (por defecto false) |
assignOfflineUsers | boolean | Permite asignar a usuarios desconectados (por defecto false) |
redistributeChats | boolean | Redistribuye chats (por defecto false) |
contactReasonRequirement | enum | none, optional o required (por defecto none) |
overrideGlobalResolution | boolean | Si es true, usa autoResolution en lugar de la configuración global (por defecto false) |
autoResolution | subdocumento | Ver a continuación |
Subdocumento autoResolution (sin _id):
| Campo | Por defecto | Descripción |
|---|---|---|
enabled | false | Activa la auto-resolución |
sendFarewellMessage | true | Envía mensaje de despedida al resolver |
resolveInMinutes | 5 | Minutos de inactividad hasta resolver |
notifyInMinutes | 1 | Minutos de aviso previo |
notificationMessage | vacío | Texto del aviso |
DepartmentUser (colección department_users)
Relación usuario-departamento, sin timestamps.
| Campo | Tipo | Descripción |
|---|---|---|
tenantId | ObjectId → Tenant | — |
departmentId | ObjectId → Department | — |
userId | ObjectId → User | — |
assignToDepartment | boolean | El usuario es miembro del departamento |
autoAssign | boolean | El usuario participa en la asignación automática |
Índices: (departmentId, tenantId) y (userId, tenantId).
Endpoints
Base: /api/v1/departments. Controlador con @Auth() y PermissionsGuard; todo se filtra por el tenantId del usuario autenticado.
| Método | Ruta | Permiso | Descripción |
|---|---|---|---|
POST | /departments/create | DEPARTMENT_CREATE | Crea un departamento |
GET | /departments/get-all | DEPARTMENT_READ | Lista; paginada si se envían page y limit |
GET | /departments/get-one/:id | DEPARTMENT_READ | Obtiene uno por _id |
PATCH | /departments/update/:id | DEPARTMENT_UPDATE | Actualiza |
DELETE | /departments/remove/:id | DEPARTMENT_DELETE | Elimina el departamento y sus relaciones |
GET | /departments/:id/users | DEPARTMENT_READ | Usuarios del tenant con su estado en el departamento |
PATCH | /departments/:id/users | DEPARTMENT_UPDATE | Reemplaza o actualiza la pertenencia de usuarios |
get-all acepta name (regex insensible a mayúsculas), userId (restringe a los departamentos donde ese usuario tiene assignToDepartment) y page/limit. Con paginación devuelve data.meta { total, page, limit }.
DTOs
Las validaciones corresponden a class-validator (ValidationPipe global). "Opcional" significa que el campo lleva @IsOptional().
Parámetros de ruta
| Parámetro | Tipo | Obligatorio | Validación | Usado en |
|---|---|---|---|---|
id | string | Sí | Ninguna; se convierte con new Types.ObjectId(id) | get-one/:id, update/:id, remove/:id, :id/users (GET y PATCH) |
CreateDepartmentDto (body de POST /departments/create)
| Campo | Tipo | Obligatorio | Validaciones | Descripción |
|---|---|---|---|---|
name | string | Sí | @IsString, @IsNotEmpty | Nombre del departamento |
color | string | No | @IsHexColor | Color hexadecimal; por defecto #000000 en el modelo |
greetingMessage | string | No | @IsString | Mensaje de bienvenida |
autoAssignment | boolean | No | @IsBoolean | Asignación automática |
assignOfflineUsers | boolean | No | @IsBoolean | Asignar a usuarios desconectados |
redistributeChats | boolean | No | @IsBoolean | Redistribuir chats |
contactReasonRequirement | string | No | @IsEnum: none, optional, required | Exigencia de motivo de contacto |
overrideGlobalResolution | boolean | No | @IsBoolean | Usar la auto-resolución propia en lugar de la global |
autoResolution | AutoResolutionDto | No | @ValidateNested, @Type | Configuración de auto-resolución |
AutoResolutionDto (anidado en autoResolution)
| Campo | Tipo | Obligatorio | Validaciones | Descripción |
|---|---|---|---|---|
enabled | boolean | No | @IsBoolean | Activa la auto-resolución |
sendFarewellMessage | boolean | No | @IsBoolean | Enviar despedida al resolver |
resolveInMinutes | number | No | @IsInt, @Min(1) | Minutos hasta resolver |
notifyInMinutes | number | No | @IsInt, @Min(1) | Minutos de aviso previo |
notificationMessage | string | No | @IsString | Texto del aviso |
UpdateDepartmentDto (body de PATCH /departments/update/:id)
PartialType(CreateDepartmentDto): mismos campos y validaciones, todos opcionales (incluido name).
QueryDepartmentDto (query de GET /departments/get-all)
Combina paginación y filtros con IntersectionType.
| Campo | Tipo | Obligatorio | Validaciones | Descripción |
|---|---|---|---|---|
page | number | No | @IsInt, @Min(1), @Type(() => Number) | Página; la paginación solo se aplica si llegan page y limit |
limit | number | No | @IsInt, @Min(1), @Type(() => Number) | Tamaño de página |
name | string | No | @IsString | Filtro por nombre (regex insensible a mayúsculas) |
userId | string | No | @IsMongoId | Restringe a departamentos donde el usuario tiene assignToDepartment |
UpdateDepartmentUsersDto (body de PATCH /departments/:id/users)
| Campo | Tipo | Obligatorio | Validaciones | Descripción |
|---|---|---|---|---|
users | DepartmentUserEntryDto[] | Sí | @IsArray, @ValidateNested({ each: true }), @Type | Entradas a actualizar |
DepartmentUserEntryDto:
| Campo | Tipo | Obligatorio | Validaciones | Descripción |
|---|---|---|---|---|
userId | string | Sí | @IsMongoId | Usuario |
assignToDepartment | boolean | No | @IsBoolean | Miembro del departamento; si se omite se guarda false |
autoAssign | boolean | No | @IsBoolean | Participa en la asignación automática; si se omite se guarda false |
Servicios
DepartmentService: CRUD por tenant. Si llegauserIden el filtro, primero resuelve los departamentos del usuario enDepartmentUserRepositoryy luego restringe el listado.removeborra el departamento y después sus registrosDepartmentUser.DepartmentUserService:getUsersForDepartmentcombina todos los usuarios del tenant con las asignaciones del departamento (los flags faltantes quedan enfalse) y devuelveuserId,username,email,assignToDepartmentyautoAssign.updateUsersForDepartmenthaceupsertpor cada entrada recibida y devuelve la lista actualizada.
Gotchas
- El
:idde las rutas es el_idde MongoDB y se convierte connew Types.ObjectId(id)sin validar antes: un id mal formado produce un error no controlado en lugar de un404. PATCH /:id/usershaceupsertsolo de las entradas enviadas; no elimina a los usuarios ausentes del arreglo, y un flag omitido se sobrescribe confalse.- El
DepartmentsModuleexporta repositorios y servicios y otros módulos lo importan (por ejemplointernal-chat,quick-response,metay el job de inactividad de tickets).