Ir al contenido

Mis Datos

El módulo cubre el autoservicio de datos del empleado autenticado: consultar su propia ficha (organizada en pestañas configurables por tenant), su estructura familiar (cargas familiares), sus contactos de emergencia, y cambiar su contraseña. El portal web también permite editar varios de estos datos por pestaña/sección; este documento la trata como acción secundaria (la app puede implementarla o dejar la pantalla en solo lectura).

Acciones cubiertas:

  • Ver el catálogo de pestañas de la ficha personal disponibles para el tenant.
  • Ver los campos y valores de cada pestaña (nombre, tipo de dato, si es editable/obligatorio, catálogo de opciones si aplica).
  • Editar los campos de una pestaña (PATCH), acción secundaria del portal.
  • Ver, crear, editar y eliminar cargas familiares (estructura familiar).
  • Ver y editar los dos contactos de emergencia del usuario.
  • Cambiar la contraseña propia.

Prerrequisitos:

  • GET /v2/me/employee-profile/tabs devuelve el catálogo completo de pestañas de la ficha del empleado — el mismo catálogo que usa la pantalla de administración (incluye pestañas como “Puesto de Trabajo”, “Salud” o “Rubros Nómina” que no tienen por qué tener contenido de autoservicio). La app debe filtrar qué pestañas mostrar en “Mis Datos” verificando que traigan contenido real — ver Lógica de cliente.
  • Los endpoints de estructura familiar y contactos de emergencia (/me/users/*) y el de cambio de contraseña (/auth/password) son de la generación legacy (v1, sin prefijo /v2); los de la ficha por pestañas son API v2. Ver Convenciones → Dos generaciones de rutas.
sequenceDiagram
    participant App as App móvil
    participant API as th-core-api

    Note over App,API: Carga inicial de Mis Datos — ficha por pestañas
    App->>API: GET /v2/me/employee-profile/tabs
    API-->>App: catálogo completo de pestañas del tenant
    Note over App: descarta pestañas sin sentido de autoservicio,<br/>ver Lógica de cliente
    loop por cada pestaña candidata
        App->>API: GET /v2/me/employee-profile/tabs/:tabCode
        API-->>App: secciones + campos + valores, o arreglo vacío si no aplica
    end
    Note over App: solo se muestran las pestañas que devolvieron secciones

    Note over App,API: Usuario entra a editar un campo tipo SELECT
    App->>API: GET /v2/employee-profile/dropdown-options?source=...
    API-->>App: opciones value/label del campo (o del hijo de una cascada)

    Note over App,API: Usuario guarda cambios de una pestaña
    App->>API: PATCH /v2/me/employee-profile/tabs/:tabCode
    API-->>App: cantidad de campos guardados
    App->>API: GET /v2/me/employee-profile/tabs/:tabCode
    API-->>App: refresco de valores de la pestaña

    Note over App,API: Pantalla Estructura familiar
    App->>API: GET /me/users/family-structure
    API-->>App: lista de cargas familiares
    App->>API: POST /me/users/family-structure
    API-->>App: carga familiar creada
    App->>API: PATCH /me/users/family-structure
    API-->>App: carga familiar actualizada
    App->>API: DELETE /me/users/family-structure/:id
    API-->>App: confirmación de borrado

    Note over App,API: Pantalla Contactos de emergencia
    App->>API: GET /me/users/details
    API-->>App: ficha completa del usuario, incluye los 2 contactos de emergencia
    App->>API: PATCH /me/users/details
    API-->>App: ficha actualizada

    Note over App,API: Pantalla Cambiar contraseña
    App->>API: POST /auth/password
    API-->>App: confirmación

Catálogo completo de pestañas de la ficha de empleado configuradas para el tenant. No está filtrado por contexto de autoservicio — es el mismo catálogo que usa la ficha de administración.

No recibe query params.

Response — array de:

Campo Tipo Descripción
id number Id de la pestaña (ep_tab.id).
code string Código de la pestaña (p. ej. P, F, CE, R, N, S…). Se usa como :tabCode en el resto de endpoints.
name string Nombre a mostrar, editable desde el admin del tenant.
visible boolean Si la pestaña debe listarse.
enabled boolean Si la pestaña es interactiva (una pestaña puede ser visible pero no enabled, es decir, mostrarse deshabilitada).
icon string | null Ícono sugerido (convención del design system del portal, p. ej. i-heroicons-user).
renderArea string Área de renderizado configurada en el admin (p. ej. record). No tiene un significado especial para mobile más allá de agrupar.
[
{
"id": 4,
"code": "P",
"name": "Datos Personales",
"visible": true,
"enabled": true,
"icon": "i-heroicons-user",
"renderArea": "record"
},
{
"id": 5,
"code": "F",
"name": "Datos Familiares",
"visible": true,
"enabled": true,
"icon": "i-heroicons-users",
"renderArea": "record"
},
{
"id": 8,
"code": "N",
"name": "Puesto de Trabajo",
"visible": true,
"enabled": true,
"icon": "i-heroicons-building-office",
"renderArea": "record"
}
]

Sin errores específicos adicionales a los comunes.

Secciones, definición de campos y valores actuales del usuario autenticado para una pestaña. Ya filtrado por showInMyData — solo trae los campos habilitados para autoservicio en ese tenant.

Path param: tabCode (string).

Response — array de secciones:

Campo Tipo Descripción
code string Código de la sección.
name string Nombre de la sección.
fields array Campos de la sección, ver tabla siguiente.

Cada campo (EpFieldDto + valores):

Campo Tipo Descripción
id number Id del campo.
code string Código del campo — clave a usar en el PATCH.
label string Etiqueta a mostrar.
fieldType enum TEXT | SELECT | DATE | CHECK | MULTI | FILE | TEXTAREA | RADIO | NUMBER | EMAIL | PHONE. Ver widget sugerido en Lógica de cliente.
storageTarget string Destino de almacenamiento interno del backend (user, user_detail, etc.). Informativo, la app no necesita usarlo.
dropdownSource string | null Solo si fieldType = SELECT. Prefijo indica el origen: static:* (catálogo fijo), catalog:* (tabla de catálogos del tenant) o entity:* (entidad real, p. ej. supervisores). Se pasa tal cual como source a dropdown-options.
cascadeParent string | null Código del campo padre cuando esta opción depende de otra (p. ej. provincia depende de país). Al cambiar el padre, resetear este campo y volver a pedir opciones con parentValue.
isRequired boolean Obligatorio al guardar (si se envía).
isReadonly boolean Solo lectura — no incluir en el PATCH.
maxLength / minLength number | null Límite de caracteres, solo aplica a campos tipo texto.
validationPattern string | null Regex de validación adicional.
defaultValue string | null Valor por defecto sugerido.
sortOrder number Orden dentro de la sección.
gridCol number Ancho sugerido en la grilla del formulario (columnas).
config object | null Configuración avanzada del campo (overrides de etiqueta, mapeo de columnas, etc.). La app no necesita interpretarlo, es de uso interno del backend.
isCustom boolean Si es un campo custom del tenant (no del catálogo base).
[
{
"code": "info_basica",
"name": "Información básica",
"fields": [
{
"id": 101,
"code": "txt_primer_nombre",
"label": "Primer nombre",
"fieldType": "TEXT",
"storageTarget": "user",
"storageColumn": "nom_usuario",
"dropdownSource": null,
"cascadeParent": null,
"isRequired": true,
"isReadonly": false,
"maxLength": 60,
"minLength": null,
"validationPattern": null,
"defaultValue": null,
"sortOrder": 1,
"gridCol": 6,
"config": null,
"isCustom": false,
"value": "JUAN",
"rawValue": "JUAN"
},
{
"id": 108,
"code": "sel_estado_civil",
"label": "Estado civil",
"fieldType": "SELECT",
"storageTarget": "user_detail",
"storageColumn": "est_civil",
"dropdownSource": "static:estado_civil",
"cascadeParent": null,
"isRequired": false,
"isReadonly": false,
"maxLength": null,
"minLength": null,
"validationPattern": null,
"defaultValue": null,
"sortOrder": 2,
"gridCol": 6,
"config": null,
"isCustom": false,
"value": "Soltero",
"rawValue": "S"
},
{
"id": 112,
"code": "txt_email",
"label": "Correo personal",
"fieldType": "EMAIL",
"storageTarget": "user_detail",
"storageColumn": "correo_externo",
"dropdownSource": null,
"cascadeParent": null,
"isRequired": false,
"isReadonly": false,
"maxLength": 120,
"minLength": null,
"validationPattern": null,
"defaultValue": null,
"sortOrder": 3,
"gridCol": 12,
"config": null,
"isCustom": false,
"value": "jperez@twiinshrm.com",
"rawValue": "jperez@twiinshrm.com"
}
]
}
]

Si la pestaña no tiene campos configurados con showInMyData para el tenant, la respuesta es [] (200, no error) — ver “Qué pestañas mostrar en Mis Datos” en Lógica de cliente.

Sin errores específicos adicionales a los comunes.

GET /v2/me/employee-profile/tabs/{tabCode}/fields

Sección titulada «GET /v2/me/employee-profile/tabs/{tabCode}/fields»

Solo la definición de campos de la pestaña (misma forma que el arreglo anterior, pero sin value/rawValue). El flujo de referencia de “Mis Datos” no la usa — GET tabs/{tabCode} ya trae definición + valores en una sola llamada. Se documenta por completitud (existe en el controller y puede ser útil para prellenar un formulario de creación en otro flujo).

Path param: tabCode (string). Response: igual estructura de secciones/campos que arriba, sin value/rawValue.

Devuelve las opciones (value/label) para un campo SELECT. Necesario para renderizar el combo y para resolver cascadas.

Query params:

Param Tipo Obligatorio Descripción
source string Valor de field.dropdownSource tal cual vino en la definición del campo.
parentValue string No Valor actual del campo padre, solo si field.cascadeParent está definido.
search string No Filtro de texto libre, para fuentes entity:* con muchos registros (p. ej. buscar un supervisor por nombre).
limit number No Máximo de resultados a devolver (relevante sobre todo con search).

Response — array de:

Campo Tipo Descripción
value string | number Valor a enviar en el PATCH si se selecciona esta opción.
label string Texto a mostrar.
[
{ "value": "S", "label": "Soltero" },
{ "value": "C", "label": "Casado" },
{ "value": "D", "label": "Divorciado" },
{ "value": "V", "label": "Viudo" },
{ "value": "U", "label": "Unión libre" }
]

Si source no tiene un catálogo asociado (fuente inválida o mal configurada), devuelve [] (200, no error) — mostrar el combo sin opciones, no un error.

PATCH /v2/me/employee-profile/tabs/{tabCode}

Sección titulada «PATCH /v2/me/employee-profile/tabs/{tabCode}»

Guarda cambios de campos de una pestaña del usuario autenticado. Acción secundaria del portal (el alcance funcional principal de este módulo es lectura).

Path param: tabCode (string).

Body (SaveTabFieldsDto):

Campo Tipo Obligatorio Descripción
fields Record<string, any> Mapa código de campo → valor. Enviar solo los campos que cambiaron, con el valor crudo (rawValue), nunca el value ya resuelto para mostrar.
{
"fields": {
"txt_primer_nombre": "JUAN",
"sel_estado_civil": "C",
"txt_email": "juan.perez@gmail.com"
}
}

Response:

{ "saved": 3 }

Errores específicos:

Código Cuándo ocurre
400 tabCode no existe o no tiene campos activos ("Tab '{tabCode}' not found or has no fields").
400 Errores de validación por campo — { "message": "Errores de validación", "errors": [{ "field": "...", "message": "..." }] }. message por campo puede ser: Campo no permitido (código no pertenece a la pestaña o no es visible para el usuario), Campo de solo lectura, Campo requerido (se envió vacío/null siendo obligatorio), Máximo N caracteres, Mínimo N caracteres, Formato inválido (no matchea validationPattern).

Lista las cargas familiares del usuario autenticado.

Query params:

Param Tipo Obligatorio Descripción
onlyDependants string ('true'|'1') No Si viene, devuelve solo los miembros marcados como carga familiar (isResponsible = 'S'). Cualquier otro valor (u omitirlo) devuelve todos.

Response — array de:

Campo Tipo Descripción
id number Id del registro.
userId string Username del titular (siempre el usuario autenticado en este endpoint).
foreign enum 'S'|'N' Si el familiar es extranjero.
idNumber string Número de identificación del familiar.
firstName / lastName string Nombre y apellido del familiar.
familyRelationship enum Ver tabla de parentescos en Lógica de cliente.
gender enum 'F'|'M' Género del familiar.
birthDate date | null Fecha de nacimiento.
isResponsible enum 'S'|'N' Si es carga familiar del empleado (usado por onlyDependants).
hasDisability enum 'S'|'N' Si tiene discapacidad.
otherOption string Campo libre de una sola letra, uso interno del formulario del tenant.
disabilityPercentage number | null Porcentaje de discapacidad (0-100).
disabilityDegree enum | null Ver tabla de grados en Lógica de cliente. Solo relevante si hasDisability = 'S'.
disabilityList string | null Lista de discapacidades en texto libre.
maritalStatus string | null Estado civil del familiar (código de un carácter).
educationLevel string | null Nivel educativo (código de un carácter).
hasJob string | null Si el familiar trabaja ('Y'/'N', texto libre).
occupationObservation string | null Observación sobre la ocupación.
healthObservation string | null Observación de salud.
document / disabilityDocument string | null URL o path de documentos adjuntos.
status enum 'A'|'T' A activo, T temporal.
[
{
"id": 41,
"userId": "jperez",
"foreign": "N",
"idNumber": "1712345678",
"firstName": "María",
"lastName": "Pérez",
"familyRelationship": "C",
"gender": "F",
"birthDate": "1990-04-12T00:00:00.000Z",
"isResponsible": "S",
"hasDisability": "N",
"otherOption": "",
"disabilityPercentage": null,
"disabilityDegree": null,
"disabilityList": null,
"maritalStatus": "C",
"educationLevel": "S",
"hasJob": "Y",
"occupationObservation": "Docente",
"healthObservation": null,
"document": null,
"disabilityDocument": null,
"status": "A"
}
]

Sin cargas familiares, la respuesta es [] (200, no error). Sin errores específicos adicionales a los comunes.

Crea una carga familiar para el usuario autenticado.

Body (MeCreateUserFamilyStructureDto) — mismos campos que la respuesta de arriba, sin id/userId/status (los asigna el backend):

Campo Tipo Enum Descripción
firstName string Nombre del familiar (máx. 60).
lastName string Apellido del familiar (máx. 60).
familyRelationship string ver tabla de parentescos Parentesco.
gender string F | M Género.
isResponsible string S | N Si es carga familiar.
hasDisability string S | N Si tiene discapacidad.
otherOption string Campo de 1 carácter, uso del tenant.
foreign string S | N Default N.
idNumber string Default ''.
birthDate date Opcional.
disabilityPercentage number 0-100 Opcional.
disabilityDegree string ver tabla de grados Default X (sin especificar).
disabilityList, maritalStatus, educationLevel, hasJob, occupationObservation, healthObservation, document, disabilityDocument string Todos opcionales.
{
"firstName": "María",
"lastName": "Pérez",
"familyRelationship": "C",
"gender": "F",
"isResponsible": "S",
"hasDisability": "N",
"otherOption": "",
"birthDate": "1990-04-12"
}

Response: el registro creado, misma forma que un ítem de GET (incluye id, userId y status asignados por el backend).

Sin errores específicos adicionales a los comunes.

Actualiza una carga familiar del usuario autenticado. El id va en el body, no en la URL.

Body (MeUpdateUserFamilyStructureDto): mismos campos opcionales del POST, más:

Campo Tipo Obligatorio Descripción
id number Sí en la práctica Id del registro a actualizar.
{
"id": 41,
"occupationObservation": "Docente de secundaria"
}

Response: el registro actualizado (misma forma que un ítem de GET).

Elimina una carga familiar del usuario autenticado.

Path param: id (number).

Response: sin cuerpo relevante.

Ficha completa del usuario autenticado. Es un endpoint grande y compartido entre módulos (más de 150 campos: dirección, nómina, salud, contactos de emergencia, etc.). Dentro de “Mis Datos”, la pantalla de referencia solo lo usa para leer/escribir los contactos de emergencia (dos contactos, ver tabla abajo); el resto de campos de la respuesta pertenece a otros módulos y debe ignorarse en esta pantalla.

No recibe query params.

Response — subconjunto relevante a este módulo (contactos de emergencia):

Campo Tipo Descripción
familyFirstName / familySecondName string Nombre(s) del contacto de emergencia 1.
familyLastName1 / familyLastName2 string Apellido(s) del contacto de emergencia 1.
familyRelationship string Parentesco del contacto 1 (catálogo RELATIONSHIP del tenant, ver Lógica de cliente).
familyEmail string Correo del contacto 1.
familyPrimaryAddress / familySecondaryAddress / familyAddressNumber string Dirección del contacto 1.
familyPhoneNumber1 / familyPhoneNumber2 string Teléfonos del contacto 1.
secondaryFamilyFirstName / secondaryFamilyLastName1 string Nombre y apellido del contacto de emergencia 2.
secondaryFamilyRelationship string Parentesco del contacto 2.
secondaryFamilyEmail string Correo del contacto 2.
secondaryFamilyPrimaryAddress / secondaryFamilySecondaryAddress / secondaryFamilyAddressNumber string Dirección del contacto 2.
secondaryFamilyPhoneNumber1 / secondaryFamilyPhoneNumber2 string Teléfonos del contacto 2.
{
"familyFirstName": "Ana",
"familySecondName": "",
"familyLastName1": "Torres",
"familyLastName2": "",
"familyRelationship": "C",
"familyEmail": "ana.torres@gmail.com",
"familyPrimaryAddress": "Av. Amazonas",
"familySecondaryAddress": "N34-123",
"familyAddressNumber": "34-123",
"familyPhoneNumber1": "022345678",
"familyPhoneNumber2": "0991234567",
"secondaryFamilyFirstName": "Luis",
"secondaryFamilyLastName1": "Pérez",
"secondaryFamilyRelationship": "P",
"secondaryFamilyEmail": "luis.perez@gmail.com",
"secondaryFamilyPrimaryAddress": "Av. 6 de Diciembre",
"secondaryFamilySecondaryAddress": "N45-67",
"secondaryFamilyAddressNumber": "45-67",
"secondaryFamilyPhoneNumber1": "022987654",
"secondaryFamilyPhoneNumber2": "0987654321"
}

Sin errores específicos adicionales a los comunes.

Actualiza campos del usuario autenticado. Solo documentamos aquí el uso que hace la pantalla de Contactos de emergencia.

Body (MeUpdateUserDetailDto, subconjunto de contactos de emergencia) — todos opcionales, mismos 18 campos que la tabla de arriba salvo familySecondName/familyLastName2 (no forman parte del DTO de edición, son de solo lectura):

{
"familyFirstName": "Ana",
"familyLastName1": "Torres",
"familyRelationship": "C",
"familyEmail": "ana.torres@gmail.com",
"familyPrimaryAddress": "Av. Amazonas",
"familySecondaryAddress": "N34-123",
"familyAddressNumber": "34-123",
"familyPhoneNumber1": "022345678",
"familyPhoneNumber2": "0991234567"
}

Response: la ficha actualizada, misma forma que el GET.

Sin errores específicos adicionales a los comunes (validaciones de maxLength/tipo por campo, formato estándar de error de DTO).

Cambia la contraseña del usuario autenticado.

Body (UpdatePasswordDto):

Campo Tipo Obligatorio Reglas
currentPassword string Entre 3 y 35 caracteres.
newPassword string Entre 8 y 35 caracteres; al menos una mayúscula, una minúscula, un número y un carácter especial (!@#$%^&*(),.?":{}|<>).
{
"currentPassword": "Anterior123!",
"newPassword": "NuevaClave456!"
}

Response: sin cuerpo relevante (200 = éxito).

Errores específicos:

Código Cuándo ocurre
401 currentPassword no coincide con la contraseña actual del usuario.
400 newPassword es igual a la contraseña actual.
400 newPassword/currentPassword no cumplen las reglas de formato (mensajes de class-validator en español, uno por regla incumplida).

GET /tabs devuelve el catálogo completo del tenant, compartido con la ficha de administración — no es una lista pre-filtrada para autoservicio. Para decidir qué pestañas mostrar en la app:

  1. Pedir GET /tabs una sola vez al entrar al módulo.
  2. Para cada pestaña con visible = true, pedir GET /tabs/:tabCode.
  3. Mostrar la pestaña solo si la respuesta trae al menos una sección con campos. Un arreglo vacío significa que esa pestaña no tiene contenido configurado para autoservicio en este tenant — ocultarla, no es un error.
  4. Si enabled = false para una pestaña que sí tiene contenido, mostrarla deshabilitada (solo lectura) en vez de ocultarla.

La pantalla de referencia del portal web hoy simplifica esto mostrando una sola pestaña fija (P, Datos Personales) en vez de iterar el catálogo — es una limitación conocida de esa pantalla, no el contrato de la API. La app móvil debe seguir el comportamiento dinámico descrito arriba.

fieldType Widget sugerido
TEXT Input de texto simple.
EMAIL Input de texto con teclado/validación de email.
PHONE Input de texto con teclado numérico/telefónico.
NUMBER Input numérico.
DATE Selector de fecha (usar rawValue, formato YYYY-MM-DD).
TEXTAREA Input multilínea, respetar maxLength.
CHECK Switch/checkbox — el valor persistido es 'S'/'N', no true/false.
SELECT Combo cargado con GET dropdown-options.
MULTI, FILE, RADIO Sin manejo específico en el portal de referencia (cae al input de texto genérico). Antes de construirlos en mobile, confirmar con backend el formato esperado — no hay contrato observado para estos tres tipos.

Al entrar en modo edición, inicializar cada input con field.rawValue (si viene) y solo usar field.value como fallback para tipos no-SELECT cuando no hay rawValue. Para SELECT, si no hay rawValue, dejar el campo vacío — nunca precargar con el texto de value (es el label resuelto, no un value válido de opción). Al guardar, enviar solo los campos que cambiaron respecto al valor cargado (diff), no la pestaña completa.

Si field.cascadeParent está definido, las opciones de ese campo dependen del valor actual del campo padre:

  • Pedir dropdown-options con parentValue = valor actual del campo padre.
  • Si el campo padre cambia, limpiar el valor del campo hijo y volver a pedir sus opciones.
  • Si el padre no tiene valor, no pedir opciones del hijo (mostrarlo vacío/deshabilitado).

Parentescos (UserFamilyStructureRelationshipEnum) — estructura familiar

Sección titulada «Parentescos (UserFamilyStructureRelationshipEnum) — estructura familiar»
Valor Significado
B Abuelo/a
A Amigo/a
C Cónyuge
E Hermano/a
J Hijastro/a
H Hijo/a
M Madre
I Nieto/a
O Otro
P Padre
R Primo/a
S Sobrino/a
G Suegro/a
T Tío/a
U Unión libre legalizada
N Unión libre no legalizada
Y Yerno/Nuera

Grado de discapacidad (UserFamilyStructureDisabilityDegreeEnum)

Sección titulada «Grado de discapacidad (UserFamilyStructureDisabilityDegreeEnum)»
Valor Significado
X Sin especificar (default)
L Leve
M Moderada
S Severa
R Grave
G Muy grave

Mostrar el selector de grado solo si hasDisability = 'S'.

Estado del registro de estructura familiar (status)

Sección titulada «Estado del registro de estructura familiar (status)»
Valor Significado
A Activo
T Temporal
  • Pestaña sin contenido de autoservicio: GET tabs/:tabCode devuelve [] — ocultar la pestaña del menú, no mostrar error (ver “Qué pestañas mostrar en Mis Datos”).
  • SELECT sin opciones disponibles: dropdown-options devuelve [] — mostrar el combo deshabilitado con placeholder tipo “No hay opciones disponibles”, no bloquear el resto del formulario.
  • Sin cargas familiares: GET /me/users/family-structure devuelve [] — mostrar estado vacío invitando a agregar una carga familiar.
  • Borrado/edición de una carga familiar ajena o inexistente: no lanza error (ver cautions de PATCH/DELETE arriba) — siempre refrescar la lista tras la operación en vez de confiar en el código de estado.
  • Contactos de emergencia vacíos: los campos vienen como string vacío (""), no null — tratarlos como “sin dato” para mostrar el estado vacío del formulario.
  • Cambio de contraseña con la misma clave: 400 explícito ("New password cannot be the same as the current password") — mostrarlo como error de validación del campo newPassword, no como error genérico del servidor.