Mi Equipo
Resumen
Sección titulada «Resumen»El módulo cubre el flujo de lectura de un supervisor sobre su equipo: listar los colaboradores que le reportan (directos, indirectos o todos) y consultar el perfil de cada uno en pestañas de solo lectura — datos personales, estructura familiar, contactos de emergencia, RRHH, cargo, salud, información profesional (cargo y perfil de carrera), vacaciones/permisos, capacitación y datos de la empresa. No incluye edición: todos los endpoints de este módulo son de consulta.
Acciones cubiertas:
- Listar mi equipo con tres alcances: directo, indirecto y todos (directo + indirecto).
- Ver la ficha resumen de un colaborador (nombre, cargo, avatar, cumplimiento de perfil).
- Ver datos personales, estructura familiar, contactos de emergencia, información de RRHH, datos de cargo/nómina y salud.
- Ver información profesional: objetivo y funciones del cargo, educación/formación/competencias requeridas, y el perfil de carrera (experiencia, estudios académicos, formación).
- Ver historial de vacaciones, historial de permisos y un resumen de saldo/kardex de vacaciones.
- Ver cursos activos, malla curricular e historial de capacitaciones (evaluaciones, presenciales, virtuales) del colaborador.
- Ver datos generales de la empresa del colaborador y las competencias/valores organizacionales.
Prerrequisitos:
- El módulo (
MEN_EQUIPO) debe estar habilitado para el tenant y el usuario debe tenerlo en su menú — construye la disponibilidad a partir deGET /me/tenancy/products(ver Convenciones → Permisos y visibilidad). - El usuario debe tener al menos un colaborador a cargo (directo o indirecto). Si no tiene reportes, los tres listados (
direct/indirect/all) devuelvendata: []— no es un error, es el estado vacío normal del módulo. - Varias secciones del perfil del colaborador están condicionadas por perfil de seguridad (acciones
PUESTO_TRABAJO*,TALENTO_HUMANO,SALUD*,DATOS_GENERALES_EMPLEADO_PORTAL,ESTRUCTURA_FAMILIAR_PORTAL,CONTACTO_EMERGENCIA_1,MI_CARGO_*,MI_PERFIL_*, entre otras). La app debe ocultar la pestaña o sección correspondiente cuando el usuario no tiene el permiso, en vez de mostrarla vacía o fallar la llamada.
sequenceDiagram
participant App as App móvil
participant API as th-core-api
Note over App,API: Pantalla de listado, alcance por defecto es directo
App->>API: GET /v2/my-team/hierarchy/direct
API-->>App: colaboradores directos, paginado
Note over App: El usuario cambia el filtro a indirecto o todos
App->>API: GET /v2/my-team/hierarchy/indirect
API-->>App: colaboradores indirectos, paginado
App->>API: GET /v2/my-team/hierarchy/all
API-->>App: directos + indirectos, paginado
Note over App,API: El usuario abre el detalle de un colaborador
App->>API: GET /my-team/:id
API-->>App: ficha resumen, usada en el encabezado de todas las pestañas
Note over App,API: Pestaña Personal, sub-pestaña Datos personales por defecto
App->>API: GET /my-team/:id/personal-data
API-->>App: datos personales, dirección, contacto
Note over App: familia, contacto de emergencia, RRHH, cargo y salud<br/>se cargan al abrir cada sub-pestaña, no todas de una vez
App->>API: GET /my-team/:id/family-structure
App->>API: GET /my-team/:id/emergency-contact
App->>API: GET /my-team/:id/human-resources
App->>API: GET /my-team/:id/job-position
App->>API: GET /my-team/:id/health-care
Note over App,API: Pestaña Profesional, sub-pestaña Cargo por defecto
App->>API: GET /my-team/professional/:id/position
API-->>App: objetivo, funciones, educación/formación/competencias requeridas
Note over App: sub-pestaña Perfil, bajo demanda
App->>API: GET /my-team/professional/:id/profile
API-->>App: experiencia, estudios académicos, formación del colaborador
Note over App,API: Pestaña Vacaciones, sub-pestaña Solicitudes por defecto
App->>API: GET /my-team/:id/timeoff-summary
API-->>App: contadores de estado y saldo
App->>API: GET /my-team/:id/kardex
API-->>App: movimientos de saldo
Note over App: sub-pestañas Historial de vacaciones e Historial de permisos, bajo demanda
App->>API: GET /my-team/:id/vacation-history
App->>API: GET /my-team/:id/permission-history
Note over App,API: Pestaña Capacitación, sub-pestaña Cursos activos por defecto
App->>API: GET /my-team/:id/active-courses
Note over App: sub-pestañas Malla curricular e Historial, bajo demanda
App->>API: GET /my-team/:id/curricular-mesh
App->>API: GET /my-team/:id/training-history/evaluations
Note over App: el selector de tipo repite la llamada con<br/>real-training o virtual-training
Note over App,API: Panel Empresa, accesible desde cualquier pestaña
App->>API: GET /companies/:companyId
API-->>App: propósito y prioridades del negocio
App->>API: GET /competency/organizational
API-->>App: competencias y valores organizacionales del tenant
Endpoints
Sección titulada «Endpoints»GET /v2/my-team/hierarchy/{direct|indirect|all}
Sección titulada «GET /v2/my-team/hierarchy/{direct|indirect|all}»Lista paginada de colaboradores del usuario autenticado, según el alcance indicado en el path. Es el endpoint que alimenta la pantalla principal del módulo; sigue la paginación estándar de nestjs-paginate (ver Convenciones).
direct: colaboradores cuyosupervisores el usuario autenticado.indirect: descendientes del usuario que no son reportes directos (se calcula recorriendo la cadena de supervisores).all: directos + indirectos.
Query params: los estándar de paginación (page, limit, sortBy, search, filter.<columna>).
Response — data: array de:
| Campo | Tipo | Descripción |
|---|---|---|
userId |
string | Username del colaborador. |
avatar |
string | Ruta/URL del avatar. |
firstName |
string | Nombres. |
lastName |
string | Apellidos. |
position |
string | Nombre del cargo. |
companyName |
string | Nombre de la empresa del colaborador. |
memberFrom |
date | null | Fecha de ingreso (entryDate). |
performance |
number (1|2|3) | null |
Nivel de desempeño, ver tabla de enum abajo. null si no hay evaluación consolidada suficiente. |
lastSalaryChange |
date | null | Fecha del último incremento salarial. null si el colaborador solo tiene el registro de sueldo inicial (nunca tuvo un cambio real). |
upcomingVacation |
{ from, to } | null |
Próxima vacación aprobada que inicia dentro de los siguientes 14 días. null si no hay ninguna. |
{ "data": [ { "userId": "jperez", "avatar": "jperez.png", "firstName": "Juan", "lastName": "Pérez", "position": "Analista de Nómina", "companyName": "Twiins Ecuador", "memberFrom": "2023-03-01T00:00:00.000Z", "performance": 3, "lastSalaryChange": "2026-01-15T00:00:00.000Z", "upcomingVacation": { "from": "2026-07-20T00:00:00.000Z", "to": "2026-07-24T00:00:00.000Z" } } ], "meta": { "itemsPerPage": 20, "totalItems": 8, "currentPage": 1, "totalPages": 1, "sortBy": [["username", "ASC"]] }, "links": { "current": "...?page=1&limit=20" }}Sin errores específicos adicionales a los comunes. Si el usuario no tiene reportes en el alcance pedido, data viene vacío (200, no error).
GET /my-team/{id}
Sección titulada «GET /my-team/{id}»Ficha resumen de un colaborador del equipo, usada como encabezado persistente en el detalle (nombre, cargo, avatar, porcentajes de cumplimiento de perfil). id es el username del colaborador.
Response:
| Campo | Tipo | Descripción |
|---|---|---|
userId |
string | Username. |
avatar |
string | URL del avatar. |
firstName |
string | Nombres. |
lastName |
string | Apellidos. |
position |
string | Nombre del cargo. |
alias |
string | Apodo/alias del colaborador. |
identificationNumber |
string | Número de identificación. |
companyId |
number | Id de la empresa, usado para pedir el detalle de empresa (GET /companies/:companyId). |
education |
number | Porcentaje de cumplimiento de educación requerida para el cargo (0-100). |
formation |
number | Porcentaje de cumplimiento de formación requerida para el cargo (0-100). |
experience |
number | Porcentaje de cumplimiento de experiencia requerida para el cargo (0-100). |
{ "userId": "jperez", "avatar": "https://tenant.twiinshrm.com/talento_upload/usuarios/jperez.png", "firstName": "Juan", "lastName": "Pérez", "position": "Analista de Nómina", "alias": "Juanpe", "identificationNumber": "1712345678", "companyId": 4, "education": 100, "formation": 75, "experience": 50}Errores específicos: 404 si el username no existe o no está activo (status = ACTIVE).
GET /my-team/{id}/personal-data
Sección titulada «GET /my-team/{id}/personal-data»Datos personales, de residencia y de contacto del colaborador.
Response:
| Campo | Tipo | Descripción |
|---|---|---|
personalInfo.birthCountry / birthProvince / birthCity |
string | Lugar de nacimiento, nombres resueltos de catálogo. |
personalInfo.maritalStatus |
string | Estado civil, ya traducido (Casado/a, Soltero/a, Divorciado/a, Unión libre, Viudo/a). |
personalInfo.secondaryNationalityCountry |
string | Segunda nacionalidad, si aplica. |
addressInfo.residenceCountry / residenceProvince / residenceCity / residenceCanton / residenceParish |
string | Ubicación de residencia. |
addressInfo.housingType |
string | Tipo de vivienda, traducido (Casa, Departamento, Habitación, Media agua). |
addressInfo.housingStatus |
string | Tenencia, traducido (Propia, Arrendada, Prestada). |
addressInfo.housingLocation |
string | Traducido (Independiente, Conjunto habitacional, Urbanización). |
addressInfo.mainStreet / secondaryStreet / addressNumber / floor / reference / neighborhood / sector / postalCode |
string | Detalle de dirección. |
addressInfo.latitude / longitude |
number | null | Coordenadas de residencia, si están registradas. |
contactInfo.personalEmail / landlinePhone / mobilePhone |
string | Contacto personal. |
{ "personalInfo": { "birthCountry": "Ecuador", "birthProvince": "Pichincha", "birthCity": "Quito", "maritalStatus": "Casado/a", "secondaryNationalityCountry": "" }, "addressInfo": { "residenceCountry": "Ecuador", "residenceProvince": "Pichincha", "residenceCity": "Quito", "residenceCanton": "Quito", "residenceParish": "Iñaquito", "housingType": "Departamento", "housingStatus": "Arrendada", "housingLocation": "Conjunto habitacional", "mainStreet": "Av. Amazonas", "secondaryStreet": "Naciones Unidas", "addressNumber": "N34-120", "floor": "3", "reference": "Frente al parque", "neighborhood": "La Carolina", "sector": "Norte", "postalCode": "170135", "latitude": null, "longitude": null }, "contactInfo": { "personalEmail": "jperez@gmail.com", "landlinePhone": "022345678", "mobilePhone": "0991234567" }}Errores específicos: 404 si el colaborador no tiene un registro de detalles (user.details).
GET /my-team/{id}/family-structure
Sección titulada «GET /my-team/{id}/family-structure»Lista de integrantes de la estructura familiar del colaborador.
Response — array de:
| Campo | Tipo | Descripción |
|---|---|---|
firstName / lastName |
string | Nombre del familiar. |
relationship |
string | Parentesco, ya traducido (Padre, Madre, Cónyuge, Hijo, Hermano, Tío, Sobrino, Primo, Abuelo, Nieto, Unión libre legalizada, Unión libre no legalizada, Yerno/Nuera, Otro). |
identificationNumber |
string | Identificación del familiar. |
gender |
'Male' | 'Female' | '' |
Género. |
birthDate |
date | Fecha de nacimiento. |
isForeign |
boolean | Si es de nacionalidad extranjera. |
isFamilyCharge |
boolean | Si es carga familiar. |
hasDisability |
boolean | Si tiene discapacidad registrada. |
[ { "firstName": "María", "lastName": "Pérez", "relationship": "Cónyuge", "identificationNumber": "1798765430", "gender": "Female", "birthDate": "15-04-1990", "isForeign": false, "isFamilyCharge": true, "hasDisability": false }]Si no tiene familiares registrados, la respuesta es [] (200, no error).
GET /my-team/{id}/emergency-contact
Sección titulada «GET /my-team/{id}/emergency-contact»Contactos de emergencia del colaborador (primario y secundario, si están registrados).
Response — array de hasta 2 elementos:
| Campo | Tipo | Descripción |
|---|---|---|
firstName / lastName |
string | Nombre del contacto. |
personalEmail |
string | Correo del contacto. |
relationship |
string | Parentesco, mismo mapeo que family-structure. |
primaryAddress / secondaryAddress / addressNumber |
string | Dirección del contacto. |
homePhone / cellPhone |
string | Teléfonos del contacto. |
[ { "firstName": "María", "lastName": "Pérez Ruiz", "personalEmail": "mperez@gmail.com", "relationship": "Cónyuge", "primaryAddress": "Av. Amazonas N34-120", "secondaryAddress": "", "addressNumber": "N34-120", "homePhone": "022345678", "cellPhone": "0991234567" }]Un contacto solo se incluye si tiene al menos nombre, correo o algún teléfono cargado. Si no hay ninguno, la respuesta es [] (200, no error).
GET /my-team/{id}/human-resources
Sección titulada «GET /my-team/{id}/human-resources»Datos de situación laboral del colaborador en RRHH.
Response:
| Campo | Tipo | Descripción |
|---|---|---|
entryDate |
date | null | Fecha de ingreso. |
seniorityDate |
date | null | Fecha para cómputo de antigüedad. |
firstEntryDate |
date | null | Primera fecha de ingreso (si tuvo reingresos). |
contractType |
string | Nombre del tipo de contrato. |
workHours |
number | Cantidad de horas de jornada. |
workHoursType |
string | Traducido (Mensuales, Diarias, Semanales). |
until |
date | null | Fecha de salida, si aplica. |
status |
'Activo' | 'Inactivo' |
Estado del colaborador. |
{ "entryDate": "2023-03-01T00:00:00.000Z", "seniorityDate": "2023-03-01T00:00:00.000Z", "firstEntryDate": "2023-03-01T00:00:00.000Z", "contractType": "Indefinido", "workHours": 40, "workHoursType": "Semanales", "until": null, "status": "Activo"}Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/job-position
Sección titulada «GET /my-team/{id}/job-position»Datos de cargo, sindicato y pago del colaborador.
Response:
| Campo | Tipo | Descripción |
|---|---|---|
jobPosition.hierarchy |
string | Nombre del cargo. |
jobPosition.baseSalary |
string | Sueldo base vigente (del incremento salarial activo más reciente). |
jobPosition.isInPayroll |
'Si' | 'No' |
Si el colaborador está integrado a nómina. |
jobPosition.healthSystem |
string | Sistema de salud asociado. |
jobPosition.hasPrivateHealthInsurance |
'Si' | 'No' |
Si tiene aporte privado de salud. |
unions.belongsToUnion |
'Si' | 'No' |
Si pertenece a un sindicato. |
unions.reason |
string | Motivo de no afiliación, si aplica. |
unions.name / category / section / affiliation |
string | Datos del sindicato; caen a un texto descriptivo ('No pertenece a ningún sindicato', etc.) cuando no hay valor. |
payrollData.paymentMethod |
string | Traducido (Transferencia, Cheque, Efectivo). |
payrollData.bank / accountType / accountNumber / bankKey / alias |
string | Datos de la cuenta de pago. accountType traducido (Corriente, Ahorros). |
{ "jobPosition": { "hierarchy": "Analista de Nómina", "baseSalary": "850", "isInPayroll": "Si", "healthSystem": "IESS", "hasPrivateHealthInsurance": "No" }, "unions": { "belongsToUnion": "No", "reason": "No aplica por tipo de contrato", "name": "No pertenece a ningún sindicato", "category": "No pertenece a ninguna categoría", "section": "No pertenece a ninguna sección", "affiliation": "No pertenece a ninguna afiliación" }, "payrollData": { "paymentMethod": "Transferencia", "bank": "Banco Pichincha", "accountType": "Ahorros", "accountNumber": "2200123456", "bankKey": "", "alias": "" }}Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/health-care
Sección titulada «GET /my-team/{id}/health-care»Datos médicos y de discapacidad del colaborador.
Response:
| Campo | Tipo | Descripción |
|---|---|---|
medicalData.bloodType |
string | Tipo de sangre. |
medicalData.medicalAlerts |
'Si' | 'No' |
Si tiene alertas médicas/alergias registradas. |
medicalData.disabilities |
'Si' | 'No' |
Si tiene alguna discapacidad registrada. |
medicalData.disabilityPercentage |
string | Porcentaje con formato ('30%'), vacío si no aplica. |
medicalData.disabilityGrade |
string | Grado de discapacidad. |
disabilities |
array de { name, percentage } |
Detalle de discapacidad primaria; [] si no tiene. |
disabilityDetails |
string | Texto combinado de discapacidad + grado. |
{ "medicalData": { "bloodType": "O+", "medicalAlerts": "No", "disabilities": "No", "disabilityPercentage": "", "disabilityGrade": "" }, "disabilities": [], "disabilityDetails": ""}Sin errores específicos adicionales a los comunes.
GET /my-team/professional/{id}/position
Sección titulada «GET /my-team/professional/{id}/position»Objetivo, funciones y requisitos (educación/formación/competencias/condiciones) del cargo del colaborador.
Response:
| Campo | Tipo | Descripción |
|---|---|---|
AboutThePosition.objectives |
string | Objetivo del cargo. |
AboutThePosition.functions |
array de { name, weight } |
Funciones del cargo y su peso porcentual. |
education |
array de { topic, area, level } |
Educación requerida por el cargo. |
training |
array de { topic, area, hours } |
Formación requerida por el cargo. |
competencies |
array de { name, description, level } |
Competencias requeridas. |
conditions |
array de { name } |
Condiciones especiales del cargo (p. ej. viaja, maneja caja chica). |
{ "AboutThePosition": { "objectives": "Procesar la nómina mensual y atender consultas de colaboradores.", "functions": [ { "name": "Procesar rol de pagos", "weight": 40 }, { "name": "Atender consultas de nómina", "weight": 30 } ] }, "education": [ { "topic": "Contabilidad", "area": "Finanzas", "level": "Superior" } ], "training": [ { "topic": "Legislación laboral", "area": "Talento Humano", "hours": "16" } ], "competencies": [ { "name": "Atención al detalle", "description": "Precisión en cálculos", "level": "Alto" } ], "conditions": []}Errores específicos:
| Código | Cuándo ocurre |
|---|---|
404 |
El colaborador no tiene un cargo asignado. |
GET /my-team/professional/{id}/profile
Sección titulada «GET /my-team/professional/{id}/profile»Perfil de carrera del colaborador: experiencia laboral, estudios académicos y formación registrados en su hoja de vida.
Response:
| Campo | Tipo | Descripción |
|---|---|---|
experience |
array de { area, company, position, period } |
Experiencia laboral. period viene formateado ('3 años 2 meses'). |
AcademicStudies |
array de { area, institution, level, status, startDate, certificateFile } |
Estudios académicos. certificateFile es URL de descarga, vacío si no hay archivo. |
training |
array de { topic, area, observations, duration, certificateFile } |
Formación/cursos registrados en el perfil. |
{ "experience": [ { "area": "Recursos Humanos", "company": "Empresa Anterior S.A.", "position": "Asistente de Nómina", "period": "2 años" } ], "AcademicStudies": [ { "area": "Contabilidad y Auditoría", "institution": "Universidad Central", "level": "Tercer nivel", "status": "Graduado", "startDate": "01-09-2015", "certificateFile": "https://tenant.twiinshrm.com/talento_upload/usuarios/titulo_jperez.pdf" } ], "training": [ { "topic": "Excel avanzado", "area": "Ofimática", "observations": "Curso online", "duration": "20", "certificateFile": "" } ]}Errores específicos: 404 si el username no existe.
GET /my-team/{id}/timeoff-summary
Sección titulada «GET /my-team/{id}/timeoff-summary»Resumen de solicitudes de vacaciones/permisos y saldo del colaborador.
Response:
| Campo | Tipo | Descripción |
|---|---|---|
total |
number | Total de solicitudes (aprobadas + rechazadas + pendientes + canceladas). |
approved / rejected / pending / cancelled |
number | Contadores por estado. |
available |
number | Días disponibles. |
adjusted |
number | Días netos ajustados (incrementos - decrementos). |
used |
number | Días usados/aprobados. |
paid |
number | Días liquidados/pagados. |
upcomming.from / upcomming.to |
date | Rango de la próxima solicitud aprobada futura. |
upcomming.approvedBy |
string | Nombre de quien aprobó. |
{ "total": 6, "approved": 4, "rejected": 0, "pending": 1, "cancelled": 1, "available": 8, "adjusted": 2, "used": 15, "paid": 0, "upcomming": { "from": "20-07-2026", "to": "24-07-2026", "approvedBy": "Laura Gómez" }}Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/kardex
Sección titulada «GET /my-team/{id}/kardex»Kardex de movimientos de saldo de vacaciones del colaborador.
Response — array de:
| Campo | Tipo | Descripción |
|---|---|---|
date |
date | Fecha del movimiento. |
type |
string | Tipo de movimiento crudo (ver enum en Lógica de cliente). |
description |
string | En este endpoint viene igual a type (sin traducir); la app debe mapear type a un texto propio. |
days |
number | Días del movimiento (negativo = descuento). |
balance |
number | Saldo acumulado tras el movimiento. |
requestId |
string | Solo si type = APPROVED_REQUEST. |
startDate / endDate / incorporationDate |
date | Solo si type = APPROVED_REQUEST. |
observation |
string | Observación del movimiento (ajustes). |
[ { "date": "01-01-2026", "type": "VACATION_YEAR", "description": "VACATION_YEAR", "days": 15, "balance": 15 }, { "date": "20-07-2026", "type": "APPROVED_REQUEST", "description": "APPROVED_REQUEST", "days": 5, "balance": 10, "requestId": "8931", "startDate": "2026-07-20T00:00:00.000Z", "endDate": "2026-07-24T00:00:00.000Z", "incorporationDate": "2026-07-27T00:00:00.000Z" }]Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/vacation-history
Sección titulada «GET /my-team/{id}/vacation-history»Historial de solicitudes de vacaciones del colaborador.
Response — array de:
| Campo | Tipo | Descripción |
|---|---|---|
solicitationDate |
date | Fecha en que se creó la solicitud. |
period.from / period.to |
date | Rango de la solicitud. |
returnDate |
date | Fecha de reincorporación. |
usedDays |
number | Días descontados por la solicitud. |
status |
enum | Ver tabla de estados en Lógica de cliente. |
[ { "solicitationDate": "10-07-2026", "period": { "from": "20-07-2026", "to": "24-07-2026" }, "returnDate": "27-07-2026", "usedDays": 5, "status": "A" }]Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/permission-history
Sección titulada «GET /my-team/{id}/permission-history»Historial de solicitudes de permisos del colaborador.
Response — array de:
| Campo | Tipo | Descripción |
|---|---|---|
period.from / period.to |
date | Rango del permiso. |
returnDate |
date | Igual a period.to. |
duration |
string | Duración formateada ('1 días 2 horas', '3 horas 30 min'). |
type |
string | Motivo del permiso. |
comment |
string | Observación ingresada por el solicitante. |
status |
enum | Ver tabla de estados en Lógica de cliente. |
[ { "period": { "from": "05-07-2026T08:00:00.000Z", "to": "05-07-2026T12:00:00.000Z" }, "returnDate": "05-07-2026T12:00:00.000Z", "duration": "4 horas", "type": "Cita médica", "comment": "Control médico programado", "status": "A" }]Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/active-courses
Sección titulada «GET /my-team/{id}/active-courses»Cursos/evaluaciones virtuales activas asignadas al colaborador. Paginado.
Query params: page (default 1), limit (default 5).
Response: { items: [...], meta: { totalItems, ... } }. Cada item incluye virtualTraining.name, virtualTraining.description, finalValidityPeriod ('S' presencial / 'N' online) y userEvaluations[] (si el primer elemento tiene approval, el curso se considera terminado; si no, está en curso).
Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/curricular-mesh
Sección titulada «GET /my-team/{id}/curricular-mesh»Malla curricular (cursos asignados por posición/perfil) del colaborador. Paginado.
Query params: page (default 1), limit (default 5).
Response: { items: [...], meta: { totalItems, ... } }. Cada item incluye name, modality ('E' e-learning / 'P' presencial), subcategory.category.name, subcategory.category.type.name y trainingDetails.approvalStatus.
Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/training-history/{evaluations|real-training|virtual-training}
Sección titulada «GET /my-team/{id}/training-history/{evaluations|real-training|virtual-training}»Historial de capacitaciones del colaborador, separado en tres categorías por el segmento del path. Paginado.
Query params: page (default 1), limit (default 5).
Response: { items: [...], meta: { totalItems, ... } }. Cada item incluye name, registrationDate, type, score (number | null) y approvalStatus.
Sin errores específicos adicionales a los comunes.
GET /my-team/{id}/training-certificates
Sección titulada «GET /my-team/{id}/training-certificates»Certificados de capacitación con archivo adjunto del colaborador.
GET /v2/my-team/employee-profile/{username}/tabs/{tabCode}
Sección titulada «GET /v2/my-team/employee-profile/{username}/tabs/{tabCode}»Endpoint genérico de campos configurables usado por el portal de referencia para las pestañas Datos personales (tabCode = P), RRHH (R), Cargo (N) y Salud (S). Filtra los campos por el flag showInMyTeam de la configuración de campos del tenant — el conjunto de secciones/campos puede variar entre tenants.
Response — array de secciones:
| Campo | Tipo | Descripción |
|---|---|---|
code |
string | Código de la sección. |
name |
string | Nombre de la sección (clave de traducción). |
fields |
EpField[] |
Campos de la sección. |
EpField (campos relevantes para mostrar valor):
| Campo | Tipo | Descripción |
|---|---|---|
code |
string | Código del campo. |
label |
string | Etiqueta del campo. |
fieldType |
string | Tipo de campo (texto, fecha, selección, etc.). |
storageColumn |
string | null | Si es null y el campo no es calculado/autocompletado/de datos personalizados, el portal de referencia lo excluye de la UI. |
value |
— | Valor actual del campo (no tipado de forma fija; puede ser string, number, boolean o null). |
[ { "code": "DATOS_GENERALES", "name": "Datos generales", "fields": [ { "code": "NOMBRE_COMPLETO", "label": "Nombre completo", "fieldType": "text", "storageColumn": "name", "value": "Juan Pérez" }, { "code": "FECHA_NACIMIENTO", "label": "Fecha de nacimiento", "fieldType": "date", "storageColumn": "birthDate", "value": "1990-04-15" } ] }]Sin errores específicos adicionales a los comunes. Si el tenant no configuró ningún campo visible para ese tabCode, la respuesta es [] (200, no error) — muestra el estado vacío, no un error.
GET /companies/{companyId}
Sección titulada «GET /companies/{companyId}»Detalle de la empresa del colaborador (accesible como panel “Empresa” desde cualquier pestaña del detalle). companyId sale de GET /my-team/{id}.
Query param opcional: userId (username, contexto adicional para el detalle).
Response relevante para este módulo:
| Campo | Tipo | Descripción |
|---|---|---|
purpose |
string | Propósito/misión de la empresa. |
businessPriorities |
string | Prioridades de negocio. |
El resto de campos de la respuesta pertenecen a la administración de empresas y no son relevantes para este panel de solo lectura.
GET /competency/organizational
Sección titulada «GET /competency/organizational»Competencias y valores organizacionales del tenant (no varían por colaborador).
Response:
{ "competencies": [ { "name": "Trabajo en equipo", "description": "Colabora activamente con otros para lograr objetivos comunes." } ], "values": [ { "name": "Integridad", "description": "Actúa con honestidad y coherencia entre lo que dice y hace." } ]}Sin errores específicos adicionales a los comunes.
Lógica de cliente
Sección titulada «Lógica de cliente»Alcances del listado (hierarchy)
Sección titulada «Alcances del listado (hierarchy)»| Valor | Significado | Texto sugerido |
|---|---|---|
direct |
Reportan directamente al usuario. | Directo |
indirect |
Reportan a través de otro supervisor dentro de la cadena del usuario. | Indirecto |
all |
Directo + indirecto. | Todos |
El filtro por defecto al abrir la pantalla es direct. Cambiar de alcance reinicia la paginación (vuelve a page = 1).
Nivel de desempeño (performance)
Sección titulada «Nivel de desempeño (performance)»| Valor | Significado | Color sugerido |
|---|---|---|
1 |
Bajo | error / rojo |
2 |
Medio | warning / amarillo |
3 |
Alto | success / verde |
null |
Sin evaluación consolidada suficiente | neutral, mostrar “No evaluado” |
Estados de solicitudes de vacaciones/permisos (status)
Sección titulada «Estados de solicitudes de vacaciones/permisos (status)»| Valor | Significado backend | Texto sugerido | Color sugerido |
|---|---|---|---|
P |
Pendiente | Pendiente | warning / amarillo |
A |
Aprobado | Aprobada | success / verde |
N |
No aprobado | Rechazada | error / rojo |
H |
Histórico | Histórico | info / azul |
Tipos de movimiento de kardex (type)
Sección titulada «Tipos de movimiento de kardex (type)»| Valor | Descripción |
|---|---|
INITIAL_BALANCE |
Saldo inicial cargado para el usuario. |
VACATION_YEAR |
Asignación anual de días (apertura de período). |
APPROVED_REQUEST |
Descuento por una solicitud aprobada. |
ADJUSTMENT |
Ajuste manual de saldo. |
VACATION_CHARGE_ADJUSTMENT |
Ajuste de cargo de vacaciones. |
PROPORTION_DAYS |
Días proporcionales. |
PAYMENT |
Pago/liquidación de días. |
El signo de days decide el color: negativo se muestra en rojo (descuento), positivo sin color especial.
Modalidad de capacitación
Sección titulada «Modalidad de capacitación»| Endpoint | Valor | Significado |
|---|---|---|
active-courses (finalValidityPeriod) |
S |
Presencial |
active-courses (finalValidityPeriod) |
N |
Online |
curricular-mesh (modality) |
E |
E-learning |
curricular-mesh (modality) |
P |
Presencial |
Qué mostrar/ocultar según permisos y datos
Sección titulada «Qué mostrar/ocultar según permisos y datos»- Listado principal: si
dataviene vacío en los tres alcances, mostrar el estado vacío del módulo (“Aún no tienes colaboradores a cargo”) en vez de una tabla vacía — es el caso normal para un usuario sin reportes. - Pestañas del detalle (Personal, Profesional, Vacaciones, Capacitación): filtrar el menú de pestañas contra los productos/menú disponibles del tenant (mismo mecanismo que
GET /me/tenancy/products), igual que en el resto de la app. - Sub-pestañas de Personal (Datos personales, Estructura familiar, Contactos de emergencia, RRHH, Cargo, Salud): cada una se muestra solo si el usuario tiene el permiso de perfil de seguridad correspondiente. Estructura familiar y Contactos de emergencia son visibles por defecto salvo que el perfil las desactive explícitamente; RRHH, Cargo y Salud requieren activación explícita del perfil.
- Sub-pestaña Perfil (dentro de Profesional): mostrarla solo si el usuario tiene permiso para al menos una de sus tres secciones (Experiencia, Estudios, Formación) — si no tiene ninguna, ocultar la sub-pestaña completa en vez de mostrarla vacía.
- Botón “Empresa”: mostrarlo solo si el usuario tiene permiso de ubicación organizacional o física; si no, el panel de empresa no debe ofrecerse desde ninguna pestaña.
- Bloque “Próxima ausencia” en el resumen de vacaciones: mostrar solo si
timeoffSummary.upcomming.fromy.tovienen con valor; si no hay próxima solicitud, ocultar el bloque en vez de mostrar fechas vacías. - Condiciones especiales del cargo (
conditionsenprofessional/:id/position): mostrar la sección solo si el array no está vacío.
Validaciones y casos borde
Sección titulada «Validaciones y casos borde»lastSalaryChangevienenullcuando el colaborador solo tiene su registro de sueldo inicial (nunca tuvo un incremento real) — mostrarlo como “Sin cambios” en vez de una fecha vacía.upcomingVacationen el listado solo contempla vacaciones que inician dentro de los próximos 14 días; no es el próximo evento aprobado en términos absolutos. No lo uses como fuente de “próxima ausencia” fuera de esa ventana.- Los campos de texto largos (observaciones, nombres de cursos/temas de formación) deben truncarse en tablas y ofrecer el texto completo en un popover o modal — es el patrón usado en todas las tablas del portal de referencia.
- Para
training-historyycurricular-mesh, el selector de tipo de historial reinicia siempre la página a1al cambiar de categoría. - El endpoint genérico de perfil (
employee-profile/:username/tabs/:tabCode) puede devolver secciones con cero campos visibles (todos constorageColumn: nully sin ser calculados/autocompletados/de datos personalizados) — filtra esas secciones antes de renderizar tarjetas vacías.