@softdin/portal-admin 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +95 -2
  2. package/dist-lib/chunks/AppLayout-COCPfLWo.js +303 -0
  3. package/dist-lib/chunks/AuditoriaView-Bcf_kOqI.js +643 -0
  4. package/dist-lib/chunks/CarnetView-BsdUtYeu.js +450 -0
  5. package/dist-lib/chunks/CarteleraView-CRnVjt-S.js +996 -0
  6. package/dist-lib/chunks/CertificadosView-DvHDflcN.js +549 -0
  7. package/dist-lib/chunks/ChatBandejaView-HqhdSw7G.js +274 -0
  8. package/dist-lib/chunks/ChatConfiguracionView-BdH5gDdR.js +716 -0
  9. package/dist-lib/chunks/ChatConocimientoView-nKTAKxFa.js +263 -0
  10. package/dist-lib/chunks/ChatConversacionView-Do74V09l.js +477 -0
  11. package/dist-lib/chunks/ChatInformeView-BIiAH9L_.js +280 -0
  12. package/dist-lib/chunks/ChatRespuestasView-QFXbyg8U.js +183 -0
  13. package/dist-lib/chunks/EmpleadosView-BtqrO5-8.js +311 -0
  14. package/dist-lib/chunks/HomologacionView-UCZk4u6R.js +949 -0
  15. package/dist-lib/chunks/IngresoSsoView-BKkcnrYO.js +98 -0
  16. package/dist-lib/chunks/SolicitudesView-CYPD2A1s.js +900 -0
  17. package/dist-lib/chunks/TiposSolicitudView-CrWTVizl.js +168 -0
  18. package/dist-lib/chunks/ToggleSwitch-BYrIyheq.js +55 -0
  19. package/dist-lib/chunks/_plugin-vue_export-helper-BOaGB7Aw.js +8 -0
  20. package/dist-lib/chunks/api-M7D1c3IT.js +97 -0
  21. package/dist-lib/chunks/apiError-BHGbwz97.js +15 -0
  22. package/dist-lib/chunks/auth.store-BrGKZg-7.js +220 -0
  23. package/dist-lib/chunks/chat.service-C7ZQf4w3.js +241 -0
  24. package/dist-lib/chunks/cliente-interno.store-De39VsEE.js +203 -0
  25. package/dist-lib/chunks/homologacion-CoeHD7cB.js +131 -0
  26. package/dist-lib/chunks/portal-empleado-6KQrnsQJ.js +120 -0
  27. package/dist-lib/chunks/tipos-D93bLfFC.js +22 -0
  28. package/dist-lib/portal-admin.js +196 -0
  29. package/dist-lib/style.css +4813 -0
  30. package/dist-lib/types/App.vue.d.ts +3 -0
  31. package/dist-lib/types/components/AppLayout.vue.d.ts +3 -0
  32. package/dist-lib/types/components/CarnetClientesInternos.vue.d.ts +11 -0
  33. package/dist-lib/types/components/InvitacionPortalModal.vue.d.ts +20 -0
  34. package/dist-lib/types/components/MenuUsuario.vue.d.ts +3 -0
  35. package/dist-lib/types/components/VistoBuenoPortalModal.vue.d.ts +23 -0
  36. package/dist-lib/types/components/auditoria/AuditoriaFila.vue.d.ts +16 -0
  37. package/dist-lib/types/components/auditoria/AuditoriaFiltros.vue.d.ts +30 -0
  38. package/dist-lib/types/components/auditoria/AuditoriaPaginador.vue.d.ts +14 -0
  39. package/dist-lib/types/components/cartelera/PaginaCarteleraImagen.vue.d.ts +14 -0
  40. package/dist-lib/types/components/cartelera/PublicacionFormModal.vue.d.ts +27 -0
  41. package/dist-lib/types/components/cartelera/VistaCelularCartelera.vue.d.ts +34 -0
  42. package/dist-lib/types/components/certificados/AtenderCertificadoModal.vue.d.ts +22 -0
  43. package/dist-lib/types/components/certificados/RechazarCertificadoModal.vue.d.ts +18 -0
  44. package/dist-lib/types/components/certificados/ResumenSolicitudCertificado.vue.d.ts +8 -0
  45. package/dist-lib/types/components/chat/ChatClientesInternos.vue.d.ts +21 -0
  46. package/dist-lib/types/components/chat/ChatHorarioCampos.vue.d.ts +21 -0
  47. package/dist-lib/types/components/forms/ExportExcelButton.vue.d.ts +30 -0
  48. package/dist-lib/types/components/forms/ToggleSwitch.vue.d.ts +17 -0
  49. package/dist-lib/types/components/homologacion/HomologacionFila.vue.d.ts +30 -0
  50. package/dist-lib/types/components/homologacion/TipoPermisoFormModal.vue.d.ts +26 -0
  51. package/dist-lib/types/components/homologacion/TipoSolicitudFormModal.vue.d.ts +27 -0
  52. package/dist-lib/types/lib/auditoria.d.ts +25 -0
  53. package/dist-lib/types/lib/cartelera-paginas.d.ts +26 -0
  54. package/dist-lib/types/lib/cartelera-vigencia.d.ts +3 -0
  55. package/dist-lib/types/lib/export-excel-csv.d.ts +4 -0
  56. package/dist-lib/types/lib/export-excel.d.ts +9 -0
  57. package/dist-lib/types/lib/exportar-listado.d.ts +68 -0
  58. package/dist-lib/types/lib/homologacion.d.ts +41 -0
  59. package/dist-lib/types/lib/portal-empleado.d.ts +32 -0
  60. package/dist-lib/types/modulo.d.ts +31 -0
  61. package/dist-lib/types/portal-admin/config.d.ts +17 -0
  62. package/dist-lib/types/portal-admin/rutas.d.ts +17 -0
  63. package/dist-lib/types/portal-admin/tipos.d.ts +68 -0
  64. package/dist-lib/types/router/index.d.ts +7 -0
  65. package/dist-lib/types/services/api.d.ts +29 -0
  66. package/dist-lib/types/services/auditoria.service.d.ts +63 -0
  67. package/dist-lib/types/services/auth.service.d.ts +61 -0
  68. package/dist-lib/types/services/carnet.service.d.ts +56 -0
  69. package/dist-lib/types/services/cartelera.service.d.ts +69 -0
  70. package/dist-lib/types/services/chat.service.d.ts +279 -0
  71. package/dist-lib/types/services/configuracion-cliente-interno.service.d.ts +23 -0
  72. package/dist-lib/types/services/homologacion.service.d.ts +105 -0
  73. package/dist-lib/types/services/portal-empleado.service.d.ts +112 -0
  74. package/dist-lib/types/services/solicitudes-certificado.service.d.ts +59 -0
  75. package/dist-lib/types/stores/auth.store.d.ts +125 -0
  76. package/dist-lib/types/stores/cliente-interno.store.d.ts +65 -0
  77. package/dist-lib/types/utils/apiError.d.ts +4 -0
  78. package/dist-lib/types/views/AuditoriaView.vue.d.ts +3 -0
  79. package/dist-lib/types/views/CarnetView.vue.d.ts +3 -0
  80. package/dist-lib/types/views/CarteleraView.vue.d.ts +3 -0
  81. package/dist-lib/types/views/CertificadosView.vue.d.ts +3 -0
  82. package/dist-lib/types/views/EmpleadosView.vue.d.ts +3 -0
  83. package/dist-lib/types/views/HomologacionView.vue.d.ts +4 -0
  84. package/dist-lib/types/views/IngresoSsoView.vue.d.ts +3 -0
  85. package/dist-lib/types/views/LoginView.vue.d.ts +3 -0
  86. package/dist-lib/types/views/OlvideView.vue.d.ts +3 -0
  87. package/dist-lib/types/views/RestablecerView.vue.d.ts +3 -0
  88. package/dist-lib/types/views/SolicitudesView.vue.d.ts +3 -0
  89. package/dist-lib/types/views/TiposSolicitudView.vue.d.ts +3 -0
  90. package/dist-lib/types/views/chat/ChatBandejaView.vue.d.ts +3 -0
  91. package/dist-lib/types/views/chat/ChatConfiguracionView.vue.d.ts +3 -0
  92. package/dist-lib/types/views/chat/ChatConocimientoView.vue.d.ts +3 -0
  93. package/dist-lib/types/views/chat/ChatConversacionView.vue.d.ts +11 -0
  94. package/dist-lib/types/views/chat/ChatInformeView.vue.d.ts +3 -0
  95. package/dist-lib/types/views/chat/ChatRespuestasView.vue.d.ts +3 -0
  96. package/package.json +66 -4
@@ -0,0 +1,32 @@
1
+ import type { EstadoSolicitudPortal, SolicitudPortal } from '../services/portal-empleado.service';
2
+ /** Estado de una solicitud del portal, como lo ve nómina. */
3
+ export declare const ESTADOS_SOLICITUD_PORTAL: Record<EstadoSolicitudPortal, {
4
+ texto: string;
5
+ clase: string;
6
+ }>;
7
+ /** `2026-11-10` o `2026-11-10 00:00:00` → `10/11/2026`. */
8
+ export declare function fechaCorta(valor: string | null): string;
9
+ /**
10
+ * Novedad que SoftDIN crea al aprobar, por tipo. Es informativo: el empleado
11
+ * elige el concepto entre los que SoftDIN tiene configurados para su grupo de
12
+ * nómina, y la configuración vive allá.
13
+ */
14
+ export declare function conceptoDeTipo(tipo: string): string;
15
+ /** Nombre legible del tipo (el que trae el portal en minúsculas y con guion bajo). */
16
+ export declare const NOMBRES_TIPO_SOLICITUD: Record<string, string>;
17
+ export declare function nombreTipoSolicitud(tipo: string): string;
18
+ /** Incapacidad y licencias: llevan soporte (certificado médico, registro civil) que nómina revisa en SoftDIN. */
19
+ export declare const TIPOS_CON_SOPORTE: readonly ["incapacidad", "licencia_maternidad", "licencia_paternidad"];
20
+ export declare function esTipoConSoporte(tipo: string): boolean;
21
+ /** Cuándo pide soporte el tipo, para la tabla de tipos (la regla vive en SoftDIN). */
22
+ export declare function soporteDeTipo(tipo: string): string | null;
23
+ /**
24
+ * Estado del soporte de una solicitud. El documento (dato de salud) está solo en SoftDIN, reservado en el
25
+ * expediente del empleado: aquí no se muestra ni se descarga.
26
+ */
27
+ export declare function estadoSoporte(s: Pick<SolicitudPortal, 'tipo' | 'tiene_soporte' | 'soporte_pendiente' | 'soporte_en_envio'>): {
28
+ texto: string;
29
+ pendiente: boolean;
30
+ } | null;
31
+ /** Datos no clínicos de la incapacidad o licencia, en una línea. */
32
+ export declare function datosNoClinicos(s: Pick<SolicitudPortal, 'origen' | 'es_prorroga' | 'fecha_parto'>): string | null;
@@ -0,0 +1,31 @@
1
+ import type { RouteRecordRaw, Router } from 'vue-router';
2
+ import { type OpcionesPortalAdmin } from './portal-admin/tipos';
3
+ /**
4
+ * Punto de entrada de `@softdin/portal-admin`: el portal administrativo (Gestión del Portal)
5
+ * como módulo que se monta en una app Vue con su router y su Pinia. Lo usan la app
6
+ * independiente (gestionportal.dinsoft.online, ingreso con usuario y contraseña) y
7
+ * softdin-central (ingreso por SSO de superusuarios).
8
+ */
9
+ export type { AsercionSso, NombreRutaPortal, OpcionesPortalAdmin, ProveedorSesionSso, } from './portal-admin/tipos';
10
+ export { RUTAS_PORTAL } from './portal-admin/tipos';
11
+ export { crearRutasPortalAdmin, guardiaPortalAdmin } from './portal-admin/rutas';
12
+ export type { OpcionesRutas } from './portal-admin/rutas';
13
+ /** Store de la sesión del portal (id `portal-auth`), aparte del `auth` de la app anfitriona. */
14
+ export { useAuthStore as usePortalAuthStore } from './stores/auth.store';
15
+ /** Cliente interno elegido en la barra (id `portal-cliente-interno`). */
16
+ export { useClienteInternoStore as usePortalClienteInternoStore } from './stores/cliente-interno.store';
17
+ export type { ClienteRrhh, DatosSesion, RespuestaLogin, Sesion, UsuarioRrhh } from './services/auth.service';
18
+ /** Cliente axios del portal (base `${apiUrl}/rrhh`), separado del de la app anfitriona. */
19
+ export { api as portalApi } from './services/api';
20
+ export interface PortalAdminInstalado {
21
+ /** Rutas registradas (por si la app quiere listarlas o enlazarlas). */
22
+ rutas: RouteRecordRaw[];
23
+ /** Cierra la sesión del portal (`rrhh/auth/logout`) si hay una; nunca falla. */
24
+ cerrarSesion(): Promise<void>;
25
+ }
26
+ /**
27
+ * Configura el cliente HTTP del portal, registra sus rutas bajo `basePath` (y bajo
28
+ * `rutaPadre`, si se da) y su guardia. Debe llamarse con Pinia ya instalada y antes de
29
+ * `app.use(router)` para que la primera navegación ya encuentre las rutas.
30
+ */
31
+ export declare function instalarPortalAdmin(router: Router, opciones?: OpcionesPortalAdmin): PortalAdminInstalado;
@@ -0,0 +1,17 @@
1
+ import type { ProveedorSesionSso } from './tipos';
2
+ /**
3
+ * Configuración en curso del módulo. Una app monta un solo portal administrativo, así que es
4
+ * un objeto del módulo (como el cliente axios) y `instalarPortalAdmin` lo llena.
5
+ */
6
+ export interface ConfigPortalAdmin {
7
+ basePath: string;
8
+ sesion: ProveedorSesionSso | null;
9
+ alSalir: (() => void) | null;
10
+ /** Ver `OpcionesPortalAdmin.cambioDeTenant`. */
11
+ cambioDeTenant: boolean;
12
+ }
13
+ export declare const configPortal: ConfigPortalAdmin;
14
+ /** `'/central/portal/'` → `'/central/portal'`; `''` o `'/'` → `'/'`. */
15
+ export declare function normalizarBasePath(base: string | undefined): string;
16
+ /** Une la base con un tramo: `('/', 'ingreso')` → `'/ingreso'`. */
17
+ export declare function unirRuta(base: string, tramo: string): string;
@@ -0,0 +1,17 @@
1
+ import type { RouteLocationNormalized, RouteLocationRaw, RouteRecordRaw } from 'vue-router';
2
+ export interface OpcionesRutas {
3
+ basePath?: string;
4
+ /** Con SSO se registra además la pantalla de ingreso (`portal-ingreso`). */
5
+ conSso?: boolean;
6
+ metaRutas?: Record<string, unknown>;
7
+ }
8
+ /**
9
+ * Rutas del portal administrativo. Todas llevan `meta.portalAdmin` (así la guardia sabe que
10
+ * son suyas) y nombres con prefijo `portal-` para no chocar con los de la app que las monta.
11
+ */
12
+ export declare function crearRutasPortalAdmin(opciones?: OpcionesRutas): RouteRecordRaw[];
13
+ /**
14
+ * Guardia de las rutas del módulo (las demás pasan sin tocarlas): sin sesión al ingreso, una
15
+ * verificación de `rrhh/me` por carga y las pantallas de solo administradores.
16
+ */
17
+ export declare function guardiaPortalAdmin(to: RouteLocationNormalized): Promise<true | RouteLocationRaw>;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Tipos públicos de `@softdin/portal-admin`. Este archivo no importa nada con el alias `@/`
3
+ * a propósito: es lo que ven las apps que consumen el paquete (sus `.d.ts`).
4
+ */
5
+ /** Lo que entrega softdin-api en `POST /api/v1/admin/portal/sso`. */
6
+ export interface AsercionSso {
7
+ asercion: string;
8
+ /** Segundos de vigencia (hoy 60). */
9
+ expira_en?: number;
10
+ /** Base del API del portal (`…/api/v1`) o `null` si softdin-api no la tiene configurada. */
11
+ portal_api_url?: string | null;
12
+ }
13
+ /**
14
+ * Proveedor de sesión por SSO (softdin-central). El módulo le pide una aserción NUEVA cada vez
15
+ * que necesita un token: al entrar, al elegir cliente y al renovar tras un 401. Las aserciones
16
+ * son de un solo uso y duran 60 s, así que nunca se reutilizan.
17
+ */
18
+ export interface ProveedorSesionSso {
19
+ obtenerAsercion(): Promise<AsercionSso>;
20
+ }
21
+ export interface OpcionesPortalAdmin {
22
+ /**
23
+ * Base del API del portal, p. ej. `https://apiportal.dinsoft.shop/api/v1` (el módulo agrega
24
+ * `/rrhh`). Con SSO puede omitirse: se usa `portal_api_url` de la primera aserción.
25
+ */
26
+ apiUrl?: string | null;
27
+ /** Dónde cuelgan las pantallas: `'/'` en la app independiente, `'/central/portal'` en central. */
28
+ basePath?: string;
29
+ /** Nombre de una ruta existente bajo la que se registran (p. ej. el layout de central). */
30
+ rutaPadre?: string;
31
+ /** Meta que se agrega a cada ruta del módulo (p. ej. `{ module: 'Portal de autogestión' }`). */
32
+ metaRutas?: Record<string, unknown>;
33
+ /** Con SSO: el token del portal se obtiene con aserciones y se renueva en silencio en un 401. */
34
+ sesion?: ProveedorSesionSso | null;
35
+ /**
36
+ * La sesión del portal terminó y no se pudo renovar (401/403). Por defecto: limpiar la sesión
37
+ * y llevar al ingreso (SSO) o a la ruta `login` (app independiente).
38
+ */
39
+ alExpirar?: (() => void) | null;
40
+ /** Tras «Salir» en el menú de usuario. Por defecto, la ruta `login`. */
41
+ alSalir?: (() => void) | null;
42
+ /**
43
+ * Si la barra ofrece cambiar de tenant cuando el usuario tiene varios (por defecto, sí).
44
+ * `false` en softdin-tenant: el SSO de ámbito tenant entrega una sesión solo del tenant de
45
+ * la app, y cambiarlo desde el portal la sacaría de ese ámbito.
46
+ */
47
+ cambioDeTenant?: boolean;
48
+ }
49
+ /** Nombres de las rutas del módulo: siempre con el prefijo `portal-`. */
50
+ export declare const RUTAS_PORTAL: {
51
+ readonly inicio: "portal-inicio";
52
+ readonly ingreso: "portal-ingreso";
53
+ readonly solicitudes: "portal-solicitudes";
54
+ readonly certificados: "portal-certificados";
55
+ readonly empleados: "portal-empleados";
56
+ readonly tiposSolicitud: "portal-tipos-solicitud";
57
+ readonly homologacion: "portal-homologacion";
58
+ readonly carnet: "portal-carnet";
59
+ readonly cartelera: "portal-cartelera";
60
+ readonly chat: "portal-chat";
61
+ readonly chatConfiguracion: "portal-chat-configuracion";
62
+ readonly chatRespuestas: "portal-chat-respuestas";
63
+ readonly chatInforme: "portal-chat-informe";
64
+ readonly chatConocimiento: "portal-chat-conocimiento";
65
+ readonly chatConversacion: "portal-chat-conversacion";
66
+ readonly auditoria: "portal-auditoria";
67
+ };
68
+ export type NombreRutaPortal = (typeof RUTAS_PORTAL)[keyof typeof RUTAS_PORTAL];
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Router de la app independiente (gestionportal): aquí solo viven el ingreso con usuario y
3
+ * contraseña y sus pantallas públicas. Las del portal (`portal-*`) las registra
4
+ * `instalarPortalAdmin` en `main.ts`, igual que en softdin-central.
5
+ */
6
+ declare const router: import("vue-router")._RouterClassic;
7
+ export default router;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Cliente HTTP de Gestión del Portal (softdin-portal-api, rutas `/rrhh`). Esta
3
+ * app ya no habla con softdin-api: el usuario, el token y el cliente son del
4
+ * portal.
5
+ *
6
+ * La base no sale de `import.meta.env` aquí: este archivo también se publica en
7
+ * `@softdin/portal-admin` y Vite congelaría en el paquete la URL con la que se compiló.
8
+ * La pone quien instala el módulo (`configurarApiUrl`).
9
+ */
10
+ export declare const api: import("axios").AxiosInstance;
11
+ /** `https://apiportal…/api/v1` → base `…/api/v1/rrhh`. */
12
+ export declare function configurarApiUrl(apiUrl: string): void;
13
+ /**
14
+ * Con SSO la base puede venir en la aserción (`portal_api_url`) y no en la configuración de
15
+ * la app: se recuerda para que, al recargar con el token guardado, las peticiones no salgan
16
+ * contra el propio origen antes de la siguiente aserción.
17
+ */
18
+ export declare function recordarApiUrl(apiUrl: string): void;
19
+ export declare function apiUrlRecordada(): string | null;
20
+ export declare function apiUrlConfigurada(): boolean;
21
+ /** Mensaje del 403 de softdin-portal-api cuando la escritura es de un cliente interno no permitido. */
22
+ export declare const MENSAJE_FUERA_DE_ALCANCE = "No tiene acceso a ese cliente.";
23
+ /**
24
+ * `token`: el de la sesión. `alExpirar`: 401 con sesión abierta (token vencido,
25
+ * usuario desactivado). Un 403 (cliente desactivado o sin acceso) también cierra.
26
+ * `renovar` (SSO): ante un 401 se pide un token nuevo una sola vez y se repite la petición;
27
+ * si no se puede, entonces sí `alExpirar`. Llamarla otra vez reemplaza los interceptores.
28
+ */
29
+ export declare function setupApiInterceptors(token: () => string | null, alExpirar: () => void, renovar?: (() => Promise<boolean>) | null): void;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Auditoría del portal (softdin-portal-api, grupo `rrhh`, `auditoria` y `auditoria/exportar`).
3
+ * Solo la ve un administrador del cliente de la sesión; a los demás el servidor responde 403.
4
+ * Los registros son solo del cliente (tenant) de la sesión.
5
+ */
6
+ export type ActorTipo = 'empleado' | 'rrhh' | 'conductor' | 'softdin' | 'anonimo';
7
+ export type ResultadoAuditoria = 'exito' | 'fallo' | 'rechazado';
8
+ export interface RegistroAuditoria {
9
+ id: number;
10
+ /** Hora de Colombia, como la guarda el servidor (`YYYY-MM-DD HH:MM:SS(.mmm)` o ISO). */
11
+ ocurrido_en: string;
12
+ actor: {
13
+ tipo: ActorTipo;
14
+ id: number | string | null;
15
+ nombre: string | null;
16
+ identificacion: string | null;
17
+ };
18
+ cliente_interno: {
19
+ id: number;
20
+ nombre: string;
21
+ } | null;
22
+ accion: string;
23
+ etiqueta: string | null;
24
+ recurso: {
25
+ tipo: string | null;
26
+ id: string | number | null;
27
+ } | null;
28
+ resultado: ResultadoAuditoria;
29
+ estado_http: number | null;
30
+ ip: string | null;
31
+ user_agent: string | null;
32
+ /** Parámetros ya saneados por el servidor (sin secretos, PII enmascarada). */
33
+ detalle: Record<string, unknown> | unknown[] | null;
34
+ }
35
+ export interface AccionAuditoria {
36
+ clave: string;
37
+ etiqueta: string;
38
+ }
39
+ export interface FiltrosAuditoria {
40
+ cliente_interno_id?: number | null;
41
+ actor_tipo?: ActorTipo | '';
42
+ accion?: string;
43
+ resultado?: ResultadoAuditoria | '';
44
+ desde?: string;
45
+ hasta?: string;
46
+ q?: string;
47
+ }
48
+ export interface PaginaAuditoria {
49
+ data: RegistroAuditoria[];
50
+ meta: {
51
+ pagina: number;
52
+ por_pagina: number;
53
+ total: number;
54
+ };
55
+ acciones: AccionAuditoria[];
56
+ }
57
+ /** Solo los filtros con valor: el servidor no recibe `accion=` vacíos. */
58
+ export declare function parametrosAuditoria(f: FiltrosAuditoria): Record<string, string | number>;
59
+ export declare const auditoriaService: {
60
+ listar(filtros: FiltrosAuditoria, pagina?: number, porPagina?: number): Promise<PaginaAuditoria>;
61
+ /** CSV UTF-8 con BOM (abre bien en Excel), con los mismos filtros del listado. */
62
+ exportar(filtros: FiltrosAuditoria): Promise<Blob>;
63
+ };
@@ -0,0 +1,61 @@
1
+ /** Ingreso de RRHH (softdin-portal-api `AuthRrhhController`). */
2
+ export interface UsuarioRrhh {
3
+ id: number;
4
+ nombre: string;
5
+ email: string;
6
+ }
7
+ export interface ClienteRrhh {
8
+ id: number;
9
+ nombre: string;
10
+ logo_url: string | null;
11
+ }
12
+ export interface DatosSesion {
13
+ usuario: UsuarioRrhh;
14
+ cliente: ClienteRrhh;
15
+ clientes: ClienteRrhh[];
16
+ /**
17
+ * Rol del usuario en el cliente de la sesión (pivote `cliente_usuario`, p. ej. `admin`) y si
18
+ * lo administra. Los manda `GET rrhh/me`; un servidor anterior no los manda: entonces no se sabe
19
+ * y lo que es solo de administradores (Auditoría) queda oculto.
20
+ */
21
+ rol?: string | null;
22
+ es_admin?: boolean;
23
+ /**
24
+ * Clientes internos en los que puede escribir (SSO de ámbito tenant con alcance por cliente).
25
+ * `null` = sin restricción; ausente = el servidor no lo dijo (versión anterior): sin restricción.
26
+ */
27
+ clientes_internos?: number[] | null;
28
+ /**
29
+ * De dónde vino la sesión: `tenant` (SSO desde softdin-tenant: solo el cliente de la sesión,
30
+ * sin cambio de cliente) o `central`. Ausente en servidores anteriores.
31
+ */
32
+ ambito?: 'tenant' | 'central' | null;
33
+ }
34
+ export interface Sesion extends DatosSesion {
35
+ token: string;
36
+ }
37
+ /** Con varios clientes y sin `cliente_id`, el servidor pide elegir (sin token). */
38
+ export type RespuestaLogin = Sesion | {
39
+ requiere_cliente: true;
40
+ clientes: ClienteRrhh[];
41
+ };
42
+ export declare const authService: {
43
+ login(email: string, password: string, clienteId?: number): Promise<RespuestaLogin>;
44
+ /**
45
+ * Ingreso desde softdin-central (`rrhh/auth/sso`): misma respuesta que `login`. La aserción
46
+ * se gasta solo cuando entrega token.
47
+ */
48
+ sso(asercion: string, clienteId?: number): Promise<RespuestaLogin>;
49
+ me(): Promise<DatosSesion>;
50
+ /** Token nuevo ligado al otro cliente; el actual queda anulado. */
51
+ cambiarCliente(clienteId: number): Promise<Sesion>;
52
+ logout(): Promise<void>;
53
+ /** Siempre la misma respuesta, exista o no el correo. */
54
+ olvide(email: string): Promise<string>;
55
+ restablecer(datos: {
56
+ email: string;
57
+ token: string;
58
+ password: string;
59
+ password_confirmation: string;
60
+ }): Promise<string>;
61
+ };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Carnet digital del cliente de la sesión (softdin-portal-api, `routes/api.php`, grupo
3
+ * `rrhh`, `carnet/*`). Diseño en softdin-portal-api/docs/carnet-digital.md.
4
+ */
5
+ /**
6
+ * Envío a SoftDIN de la foto aprobada (reemplaza la foto del tercero): `pendiente` = se
7
+ * reintenta sola; `fallida` = agotó los intentos o SoftDIN la rechazó, se reintenta a mano;
8
+ * null = no aplica (la foto vino de SoftDIN o ya no es la del carnet).
9
+ */
10
+ export type SincronizacionFoto = 'pendiente' | 'sincronizada' | 'fallida' | null;
11
+ export interface FotoCarnet {
12
+ id: number;
13
+ estado: 'pendiente' | 'aprobada' | 'rechazada' | 'reemplazada';
14
+ /** `portal` = la tomó el empleado; `softdin` = la que el tercero ya tenía en SoftDIN. */
15
+ origen: 'portal' | 'softdin';
16
+ empleado: string;
17
+ cargo: string | null;
18
+ enviada_en: string | null;
19
+ motivo_rechazo: string | null;
20
+ /** Ya tiene una foto aprobada en el carnet: esta la reemplazaría. */
21
+ tiene_aprobada: boolean;
22
+ sincronizacion: SincronizacionFoto;
23
+ sincronizacion_error: string | null;
24
+ sincronizacion_intentos: number;
25
+ sincronizada_en: string | null;
26
+ }
27
+ export interface ResultadoSincronizacion {
28
+ id: number;
29
+ estado: FotoCarnet['estado'];
30
+ sincronizacion: SincronizacionFoto;
31
+ sincronizacion_error: string | null;
32
+ sincronizada_en: string | null;
33
+ }
34
+ export interface CarnetActivo {
35
+ id: string;
36
+ empleado: string;
37
+ cargo: string | null;
38
+ emitido_en: string;
39
+ vence_en: string;
40
+ }
41
+ export declare const carnetService: {
42
+ config(): Promise<boolean>;
43
+ activar(activo: boolean): Promise<boolean>;
44
+ /** Con `clienteInterno`, solo las de los empleados de ese cliente interno. */
45
+ fotos(estado?: FotoCarnet["estado"], clienteInterno?: number | null): Promise<FotoCarnet[]>;
46
+ /** La imagen va con el token de la sesión: se pide como blob y se muestra con una URL local. */
47
+ imagen(id: number): Promise<Blob>;
48
+ /** Aprueba la foto y la envía a SoftDIN; responde cómo quedó ese envío. */
49
+ aprobar(id: number): Promise<ResultadoSincronizacion>;
50
+ /** Reintenta a mano el envío a SoftDIN de una foto aprobada. */
51
+ sincronizar(id: number): Promise<ResultadoSincronizacion>;
52
+ rechazar(id: number, motivo: string): Promise<void>;
53
+ /** Con `clienteInterno`, solo los de los empleados de ese cliente interno. */
54
+ carnets(clienteInterno?: number | null): Promise<CarnetActivo[]>;
55
+ revocar(id: string): Promise<void>;
56
+ };
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Cartelera de la app del empleado (softdin-portal-api, `routes/api.php`, grupo `rrhh`,
3
+ * `cartelera/*`). Desde el 2026-10-09 la administra el portal; antes se armaba en SoftDIN
4
+ * (Gestión portal → Cartelera) y llegaba por sincronización: esas siguen aquí con
5
+ * `desde_softdin`, sin el archivo original.
6
+ */
7
+ export type EstadoPublicacion = 'borrador' | 'publicada' | 'retirada';
8
+ export interface PaginaPublicacion {
9
+ /** Desde 1. */
10
+ n: number;
11
+ ancho: number;
12
+ alto: number;
13
+ }
14
+ export interface PublicacionCartelera {
15
+ id: number;
16
+ /** Cliente interno; null = todo el tenant. */
17
+ cliente_interno_id: number | null;
18
+ titulo: string;
19
+ resumen: string | null;
20
+ tipo_archivo: 'imagen' | 'pdf' | null;
21
+ archivo_nombre: string | null;
22
+ /** Hay archivo original para descargar (las que vinieron de SoftDIN no lo traen). */
23
+ tiene_original: boolean;
24
+ paginas: PaginaPublicacion[];
25
+ fecha_desde: string;
26
+ fecha_hasta: string | null;
27
+ orden: number;
28
+ destacada: boolean;
29
+ estado: EstadoPublicacion;
30
+ publicada_en: string | null;
31
+ /** Se armó en SoftDIN antes de que la cartelera pasara al portal. */
32
+ desde_softdin: boolean;
33
+ /** Marca de tiempo del último cambio: sirve para volver a pedir las imágenes. */
34
+ actualizada: number;
35
+ }
36
+ export interface PublicacionCarteleraPayload {
37
+ /** Cliente interno; null = todo el tenant. `undefined` en una edición = se conserva. */
38
+ cliente_interno_id?: number | null;
39
+ titulo: string;
40
+ resumen: string;
41
+ fecha_desde: string;
42
+ fecha_hasta: string | null;
43
+ orden: number;
44
+ destacada: boolean;
45
+ /** Solo si se cambia el archivo: el original y sus páginas ya convertidas. */
46
+ archivo?: File;
47
+ paginas?: Blob[];
48
+ }
49
+ export interface FiltroCartelera {
50
+ estado?: EstadoPublicacion | null;
51
+ cliente_interno_id?: number | null;
52
+ }
53
+ export declare function formularioPublicacion(p: PublicacionCarteleraPayload): FormData;
54
+ export declare const carteleraService: {
55
+ listar(filtro?: FiltroCartelera): Promise<PublicacionCartelera[]>;
56
+ ver(id: number): Promise<PublicacionCartelera>;
57
+ /** Nace en borrador. */
58
+ crear(p: PublicacionCarteleraPayload): Promise<PublicacionCartelera>;
59
+ /** Multipart: PHP no lo lee en un PATCH, así que va como POST con `_method=PATCH`. Sin archivo conserva las páginas. */
60
+ actualizar(id: number, p: PublicacionCarteleraPayload): Promise<PublicacionCartelera>;
61
+ eliminar(id: number): Promise<void>;
62
+ /** 422 si la vigencia ya terminó o no tiene páginas. */
63
+ publicar(id: number): Promise<PublicacionCartelera>;
64
+ retirar(id: number): Promise<PublicacionCartelera>;
65
+ /** Imagen de una página (`n` desde 1). Va con el token de la sesión: se pide como blob. */
66
+ pagina(id: number, n: number): Promise<Blob>;
67
+ /** Archivo original tal como se subió (404 si no lo tiene). */
68
+ archivo(id: number): Promise<Blob>;
69
+ };