Ir al contenido

Mi Equipo

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 de GET /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) devuelven data: [] — 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

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 cuyo supervisor es 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>).

Responsedata: 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).

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).

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).

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).

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).

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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).

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
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.

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 data viene 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.from y .to vienen con valor; si no hay próxima solicitud, ocultar el bloque en vez de mostrar fechas vacías.
  • Condiciones especiales del cargo (conditions en professional/:id/position): mostrar la sección solo si el array no está vacío.
  • lastSalaryChange viene null cuando 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.
  • upcomingVacation en 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-history y curricular-mesh, el selector de tipo de historial reinicia siempre la página a 1 al cambiar de categoría.
  • El endpoint genérico de perfil (employee-profile/:username/tabs/:tabCode) puede devolver secciones con cero campos visibles (todos con storageColumn: null y sin ser calculados/autocompletados/de datos personalizados) — filtra esas secciones antes de renderizar tarjetas vacías.