From 9b7a65d38e40e04d6416f207a4214b9433087b3b Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Tue, 28 Oct 2025 19:08:53 -0300 Subject: [PATCH 01/14] =?UTF-8?q?feat(IN-658):=20Sacar=20formulario=20esta?= =?UTF-8?q?d=C3=ADstico=20de=20coleccion-=20prestaciones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apps/rup/mapa-camas/mapa-camas.module.ts | 4 +- .../informe-estadistica.interface.ts | 121 ++++++++++++++++++ .../rup/interfaces/ocupacion.interface.ts | 79 ++++++++++++ .../services/informe-estadistica.service.ts | 46 +++++++ 4 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 src/app/modules/rup/interfaces/informe-estadistica.interface.ts create mode 100644 src/app/modules/rup/interfaces/ocupacion.interface.ts create mode 100644 src/app/modules/rup/services/informe-estadistica.service.ts diff --git a/src/app/apps/rup/mapa-camas/mapa-camas.module.ts b/src/app/apps/rup/mapa-camas/mapa-camas.module.ts index 9066429f6e..c051ff9291 100644 --- a/src/app/apps/rup/mapa-camas/mapa-camas.module.ts +++ b/src/app/apps/rup/mapa-camas/mapa-camas.module.ts @@ -70,6 +70,7 @@ import { IngresoPacienteService } from './sidebar/ingreso/ingreso-paciente-workf import { PeriodosCensablesComponent } from './sidebar/periodos-censables/periodos-censables.component'; import { ListadoMedicamentosCapasComponent } from './views/listado-internacion-capas/listado-medicamentos-capas.component'; import { CITASLibModule } from '../../../components/turnos/citas.module'; +import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; export const INTERNACION_COMPONENTS = [ MapaCamasMainComponent, @@ -128,7 +129,8 @@ export const INTERNACION_PROVIDERS = [ IntegridadService, PermisosMapaCamasService, PlanIndicacionesEventosServices, - IngresoPacienteService + IngresoPacienteService, + InformeEstadisticaService ]; @NgModule({ diff --git a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts new file mode 100644 index 0000000000..e82d0ab3b9 --- /dev/null +++ b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts @@ -0,0 +1,121 @@ +import { ISnomedConcept } from './snomed-concept.interface'; +import { IOrganizacion } from '../../../interfaces/IOrganizacion'; +import { IProfesional } from 'src/app/interfaces/IProfesional'; +import { IPaciente } from '../../../core/mpi/interfaces/IPaciente'; +import { IOcupacion } from './ocupacion.interface'; +export interface IInformeIngreso { + fechaIngreso: Date; + esCensable?: boolean; + esMovimiento?: boolean; + periodosCensables?: { + desde: Date; + hasta?: Date | null; + }[]; + origen?: { + tipo?: string; + organizacionOrigen?: IOrganizacion; + otraOrganizacion?: string; + }; + ocupacionHabitual?: IOcupacion | null; + situacionLaboral?: string; + nivelInstruccion?: string; + especialidades?: ISnomedConcept[]; + nroCarpeta?: string | null; + motivo?: string; + profesional?: IProfesional; + paseAunidadOrganizativa?: string; + cobertura?: { + tipo?: string; + obraSocial?: { + codigoPuco?: number; + nombre?: string; + financiador?: string; + }; + }; + createdAt?: Date; + createdBy?: { + id: string; + nombreCompleto: string; + nombre: string; + apellido: string; + username: string | number; + documento: string | number; + organizacion: IOrganizacion; + }; +} + +export interface IInformeEgreso { + fechaEgreso?: Date; + procedimientosQuirurgicos?: { + procedimiento?: ISnomedConcept; + fecha?: Date; + }[]; + causaExterna?: { + producidaPor?: string; + lugar?: string; + comoSeProdujo?: string; + }; + diasDeEstada?: number; + tipoEgreso?: { + tipo?: string; + OrganizacionDestino?: IOrganizacion; + otraOrganizacion?: string; + }; + diagnosticos?: { + principal?: ISnomedConcept; + secundarios?: ISnomedConcept[]; + otrasCircunstancias?: ISnomedConcept; + diasEstadaOtrasCircunstancias?: number; + diasDePermisoDeSalida?: number; + }; + createdAt?: Date; + createdBy?: { + id: string; + nombreCompleto: string; + nombre: string; + apellido: string; + username: string | number; + documento: string | number; + organizacion: IOrganizacion; + }; +} + +export interface IInternacionEstado { + tipo: 'anulada' | 'ejecucion' | 'validada'; + createdAt?: Date; + createdBy?: { + id: string; + nombreCompleto: string; + nombre: string; + apellido: string; + username: string | number; + documento: string | number; + organizacion: IOrganizacion; + }; +} + +export interface IInformeEstadistica { + _id?: string; + organizacion: { + id: string; + nombre: string; + [key: string]: any; // <-- esto permite campos faltantes + }; + unidadOrganizativa: ISnomedConcept; + paciente: IPaciente; + informeIngreso: IInformeIngreso; + informeEgreso?: IInformeEgreso; + periodosCensables?: { desde: Date; hasta: Date }[]; + estados?: IInternacionEstado[]; + estadoActual?: IInternacionEstado; + createdAt?: Date; + createdBy?: { + id: string; + nombreCompleto: string; + nombre: string; + apellido: string; + username: string | number; + documento: string | number; + organizacion: IOrganizacion; + }; +} diff --git a/src/app/modules/rup/interfaces/ocupacion.interface.ts b/src/app/modules/rup/interfaces/ocupacion.interface.ts new file mode 100644 index 0000000000..9a76fd901d --- /dev/null +++ b/src/app/modules/rup/interfaces/ocupacion.interface.ts @@ -0,0 +1,79 @@ +export interface IOcupacion { + _id?: string; + organizacion: IOrganizacion; + unidadOrganizativa: IUnidadOrganizativa; + paciente: IPaciente; + informeIngreso: IInformeIngreso; + estadoActual?: IEstadoActual; + estados?: IEstado[]; + periodosCensables?: any[]; + createdAt?: Date; + createdBy?: IUsuario; + updatedAt?: Date; + updatedBy?: IUsuario; +} + +export interface IOrganizacion { + _id: string; + nombre: string; + id?: string; +} + +export interface IUnidadOrganizativa { + _id: string; + conceptId: string; + term: string; + fsn: string; + semanticTag: string; +} + +export interface IPaciente { + id: string; + documento: string; + nombre: string; + apellido: string; + carpetaEfectores?: any[]; +} + +export interface IInformeIngreso { + id?: string; + fechaIngreso: Date; + motivo: string; + nivelInstruccion?: string; + profesional: IProfesional; + especialidades?: IEspecialidad[]; +} + +export interface IProfesional { + id: string; + nombre: string; + apellido: string; + documento?: string; +} + +export interface IEspecialidad { + term: string; + conceptId: string; +} + +export interface IEstadoActual { + _id?: string; + tipo: string; + createdAt: Date; + createdBy: IUsuario; + id?: string; +} + +export interface IEstado { + tipo: string; + fecha: Date; + createdBy?: IUsuario; +} + +export interface IUsuario { + id: string; + nombre: string; + apellido: string; + nombreCompleto?: string; + username?: string; +} diff --git a/src/app/modules/rup/services/informe-estadistica.service.ts b/src/app/modules/rup/services/informe-estadistica.service.ts new file mode 100644 index 0000000000..536220e268 --- /dev/null +++ b/src/app/modules/rup/services/informe-estadistica.service.ts @@ -0,0 +1,46 @@ +/* eslint-disable no-console */ +import { Injectable } from '@angular/core'; +import { ResourceBaseHttp, Server } from '@andes/shared'; +import { Observable, tap } from 'rxjs'; +import { IInformeEstadistica } from '../interfaces/informe-estadistica.interface'; // ruta según tu estructura + +@Injectable({ + providedIn: 'root' +}) +export class InformeEstadisticaService extends ResourceBaseHttp { + protected override url = '/modules/rup/internacion/informe-estadistica'; + + constructor(protected override server: Server) { + super(server); + } + + /** + * Crear un nuevo informe estadístico + */ + CreateInforme(data: IInformeEstadistica): Observable { + return this.server.post(this.url, data); + } + + /** + * Actualizar un informe existente + */ + updateInforme(id: string, data: Partial): Observable { + return this.server.patch(`${this.url}/${id}`, data); + } + /** + * Obtener un informe por su ID + */ + getById(id: string): Observable { + const url = `${this.url}/${id}`; + return this.server.get(url); + } + + get(params: any = {}, options: any = {}): Observable { + if (typeof options.showError === 'undefined') { + options.showError = true; + } + const opt = { params, options }; + + return this.server.get(this.url, opt); + } +} From 8f9f2ea8b2012666bc15400553df62c9f3e7ed19 Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Wed, 29 Oct 2025 08:22:32 -0300 Subject: [PATCH 02/14] feat(IN):"Nuevos metodos para squema InformeEstadistica" --- .../mapa-camas/services/mapa-camas.service.ts | 48 +++ .../ingreso/ingresar-paciente.component.ts | 384 ++++++++++-------- .../informe-estadistica.interface.ts | 3 +- .../services/informe-estadistica.service.ts | 45 +- 4 files changed, 272 insertions(+), 208 deletions(-) diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts index 7d8ef76131..5e0577b8aa 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts @@ -18,6 +18,8 @@ import { MapaCamasHTTP } from './mapa-camas.http'; import { MaquinaEstadosHTTP } from './maquina-estados.http'; import { InternacionResumenHTTP, IResumenInternacion } from './resumen-internacion.http'; import { PermisosMapaCamasService } from '../services/permisos-mapa-camas.service'; +import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; @Injectable() export class MapaCamasService { public timer$; @@ -45,6 +47,7 @@ export class MapaCamasService { public view = new BehaviorSubject<'mapa-camas' | 'listado-internacion' | 'mapa-recursos'>('mapa-camas'); public prestacion$: Observable; + public informeEstadistica$: Observable; public selectedPrestacion = new BehaviorSubject({ id: null } as any); public camaSelectedSegunView$: Observable; @@ -80,6 +83,7 @@ export class MapaCamasService { constructor( private camasHTTP: MapaCamasHTTP, private prestacionService: PrestacionesService, + private informeEstadisticaService: InformeEstadisticaService, private pacienteService: PacienteService, private maquinaEstadosHTTP: MaquinaEstadosHTTP, private salaComunService: SalaComunService, @@ -223,6 +227,50 @@ export class MapaCamasService { cache() ) as Observable; + this.informeEstadistica$ = combineLatest([ + this.selectedPrestacion, + this.selectedCama, + this.view, + this.capa2 + ]).pipe( + switchMap(([prestacion, cama, view, capa]) => { + if (view === 'listado-internacion') { + if (prestacion?.id) { + return this.informeEstadisticaService.get({ paciente: prestacion.paciente.id }).pipe( + map(informes => informes?.[0] || null) + ); + } + return of(null); + } + + if (!cama.idInternacion) { + return of(null); + } + + if (capa === 'estadistica') { + return this.informeEstadisticaService.get({ paciente: cama.paciente.id }).pipe( + map(informes => informes?.[0] || null) + ); + } + + if (capa === 'estadistica-v2') { + return this.internacionResumenHTTP.get(cama.idInternacion).pipe( + switchMap(internacionResumen => { + if (internacionResumen?.paciente?.id) { + return this.informeEstadisticaService.get({ paciente: internacionResumen.paciente.id }).pipe( + map(informes => informes?.[0] || null) + ); + } + return of(null); + }) + ); + } + + return of(null); + }), + catchError(() => of(null)), + cache() + ); this.camaSelectedSegunView$ = this.view.pipe( switchMap(view => { diff --git a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts index 3a849b1815..72bfe13665 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts @@ -25,7 +25,9 @@ import { cache } from '@andes/shared'; import { IMaquinaEstados } from '../../interfaces/IMaquinaEstados'; import { ListadoInternacionCapasService } from '../../views/listado-internacion-capas/listado-internacion-capas.service'; import { IObraSocial } from 'src/app/interfaces/IObraSocial'; - +import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; +import { debug } from 'console'; @Component({ selector: 'app-ingresar-paciente', templateUrl: './ingresar-paciente.component.html', @@ -48,12 +50,14 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { public snomedIngreso = snomedIngreso; public expr = SnomedExpression; public fechaMax = moment().toDate(); + estado: IMaquinaEstados;// 👈 agregá esta línea // VARIABLES public esPrepaga = false; public cama: ISnapshot; public snapshot: ISnapshot[]; public prestacion: IPrestacion; + public informeEstadistica: IInformeEstadistica; public resumen: IResumenInternacion; public capa: string; public fechaValida = true; @@ -106,6 +110,7 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { private ocupacionService: OcupacionService, private organizacionService: OrganizacionService, private servicioPrestacion: PrestacionesService, + private InformeEstadisticaService: InformeEstadisticaService, public mapaCamasService: MapaCamasService, private listadoInternacionService: ListadoInternacionService, private historialInternacionService: ListadoInternacionCapasService, @@ -184,91 +189,104 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { this.mapaCamasService.capa2, this.mapaCamasService.camaSelectedSegunView$, this.mapaCamasService.prestacion$, + this.mapaCamasService.informeEstadistica$, this.mapaCamasService.resumenInternacion$, pacienteID$.pipe( filter(pacID => !!pacID), - switchMap((pacID) => { - return this.mapaCamasService.getPaciente({ id: pacID }, false); - }) - )] - ).subscribe(([estado, view, capa, cama, prestacion, resumen, paciente]: [IMaquinaEstados, string, string, ISnapshot, IPrestacion, IResumenInternacion, IPaciente]) => { - this.capa = capa; - this.prestacion = prestacion; - this.paciente = paciente; - this.resumen = resumen; - // Puede suceder, por error, que el ingreso impacte pero no se cree el movimiento correspondiente - this.poseeMovimientos = !!(cama?.id); // si tiene cama, entonces registra al menos un movimiento - if (paciente && paciente.financiador && paciente.financiador.length > 0) { - const os = paciente.financiador[0]; - this.backupObraSocial = os; - } - - if (this.prestacion) { - this.informeIngreso = this.prestacion.ejecucion.registros[0].valor.informeIngreso; - if (this.origenExterno) { - this.check = typeof this.informeIngreso.organizacionOrigen === 'string'; + switchMap((pacID) => this.mapaCamasService.getPaciente({ id: pacID }, false)) + ) + ]) + .subscribe(([estado, view, capa, cama, prestacion, informeEstadistica, resumen, paciente]: [ + IMaquinaEstados, + string, + string, + ISnapshot, + IPrestacion, + IInformeEstadistica, + IResumenInternacion, + IPaciente + ]) => { + + this.estado = estado; + this.view = view; + this.capa = capa; + this.cama = cama; + this.prestacion = prestacion; + this.informeEstadistica = informeEstadistica; // 👈 ya no da error + this.resumen = resumen; + this.paciente = paciente; + this.poseeMovimientos = !!(cama?.id); + + if (paciente && paciente.financiador && paciente.financiador.length > 0) { + const os = paciente.financiador[0]; + this.backupObraSocial = os; } - this.fechaIngresoOriginal = new Date(this.informeIngreso.fechaIngreso); - this.paciente.obraSocial = this.prestacion.paciente.obraSocial; - this.changeTipoObraSocial(); - } else { - // capa medica/enfermeria, ingreso en estadistica o carga de prestacion en estadistica-v2 - if (paciente.id) { - const fechaIngresoInicial = resumen?.fechaIngreso || this.mapaCamasService.fecha; - this.informeIngreso.fechaIngreso = new Date(fechaIngresoInicial); - this.fechaIngresoOriginal = new Date(fechaIngresoInicial); - if (this.backupObraSocial) { - this.paciente.obraSocial = { - nombre: this.backupObraSocial.financiador, - financiador: this.backupObraSocial.financiador, - codigoPuco: this.backupObraSocial.codigoPuco - }; - this.informeIngreso.asociado = { - id: 'Plan o Seguro público', - nombre: 'Plan o Seguro público' - }; - this.esPrepaga = false; + + if (this.prestacion) { + this.informeIngreso = this.prestacion.ejecucion.registros[0].valor.informeIngreso; + if (this.origenExterno) { + this.check = typeof this.informeIngreso.organizacionOrigen === 'string'; } - let indiceCarpeta = -1; - if (paciente.carpetaEfectores && paciente.carpetaEfectores.length > 0) { - indiceCarpeta = paciente.carpetaEfectores.findIndex(x => (x.organizacion as any)._id === this.auth.organizacion.id); - if (indiceCarpeta > -1) { - this.informeIngreso.nroCarpeta = paciente.carpetaEfectores[indiceCarpeta].nroCarpeta; + this.fechaIngresoOriginal = new Date(this.informeIngreso.fechaIngreso); + this.paciente.obraSocial = this.prestacion.paciente.obraSocial; + this.changeTipoObraSocial(); + } else { + if (paciente.id) { + const fechaIngresoInicial = resumen?.fechaIngreso || this.mapaCamasService.fecha; + this.informeIngreso.fechaIngreso = new Date(fechaIngresoInicial); + this.fechaIngresoOriginal = new Date(fechaIngresoInicial); + if (this.backupObraSocial) { + this.paciente.obraSocial = { + nombre: this.backupObraSocial.financiador, + financiador: this.backupObraSocial.financiador, + codigoPuco: this.backupObraSocial.codigoPuco + }; + this.informeIngreso.asociado = { + id: 'Plan o Seguro público', + nombre: 'Plan o Seguro público' + }; + this.esPrepaga = false; + } + let indiceCarpeta = -1; + if (paciente.carpetaEfectores && paciente.carpetaEfectores.length > 0) { + indiceCarpeta = paciente.carpetaEfectores.findIndex(x => (x.organizacion as any)._id === this.auth.organizacion.id); + if (indiceCarpeta > -1) { + this.informeIngreso.nroCarpeta = paciente.carpetaEfectores[indiceCarpeta].nroCarpeta; + } } } + if (capa === 'estadistica') { + this.cargarUltimaInternacion(paciente); + } } - if (capa === 'estadistica') { - this.cargarUltimaInternacion(paciente); - } - } - if (cama && cama.id && cama.id !== ' ') { - this.cama = cama; - if (cama.estado === 'ocupada' && !cama.sala) { - this.paciente = cama.paciente; - } - if (this.informeIngreso.especialidades && this.informeIngreso.especialidades.length === 0) { - this.informeIngreso.especialidades = this.cama.especialidades; - } - this.createFormularioDinamico(cama, estado); - } else if (view === 'listado-internacion') { - if (this.subscription2) { - this.subscription2.unsubscribe(); - } - if (this.poseeMovimientos) { - const idInternacion = resumen?.id || prestacion.id; - this.subscription2 = this.mapaCamasService.snapshot(this.informeIngreso.fechaIngreso, idInternacion).pipe( - map(snapshot => this.cama = snapshot[0]) - ).subscribe(); + if (cama && cama.id && cama.id !== ' ') { + this.cama = cama; + if (cama.estado === 'ocupada' && !cama.sala) { + this.paciente = cama.paciente; + } + if (this.informeIngreso.especialidades && this.informeIngreso.especialidades.length === 0) { + this.informeIngreso.especialidades = this.cama.especialidades; + } + this.createFormularioDinamico(cama, estado); + } else if (view === 'listado-internacion') { + if (this.subscription2) { + this.subscription2.unsubscribe(); + } + if (this.poseeMovimientos) { + const idInternacion = resumen?.id || prestacion.id; + this.subscription2 = this.mapaCamasService.snapshot(this.informeIngreso.fechaIngreso, idInternacion).pipe( + map(snapshot => this.cama = snapshot[0]) + ).subscribe(); + } + } else { + this.cama = null; } - } else { - this.cama = null; - } - if (this.informeIngreso.asociado?.id === 'Plan de salud privado o Mutual') { - this.selectedOS = true; - } - }); + if (this.informeIngreso.asociado?.id === 'Plan de salud privado o Mutual') { + this.selectedOS = true; + } + }); this.camas$ = combineLatest([ this.mapaCamasService.snapshot$, @@ -411,7 +429,6 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { return flagValid; } - guardar(valid) { if (valid.formValid && this.validarRUP()) { if (this.cama.sala) { @@ -423,7 +440,6 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { map(resp => resp) ).subscribe(historial => { if (historial.length) { - // Verificamos si hay otra internacion mas adelante. Asi mismo un bloqueo de cama o cambio de UO if ((this.cama.idInternacion !== historial[0]?.idInternacion && historial[0].estado !== 'disponible') || historial[0].unidadOrganizativa.id !== this.cama.unidadOrganizativa.id) { const fechaEnConflicto = moment(historial[0].fecha); @@ -465,12 +481,9 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { this.completarIngreso(dtoPaciente); } else if (this.prestacion) { this.actualizarPrestacion(dtoPaciente); - } else { - this.ingresoSimplificado('ocupada', dtoPaciente, this.resumen?.id); } } - // Sincroniza las fechas editadas entre la cama y elresumen/prestacion private sincronizarCamaInternacion(idInternacion, fechaIngresoOriginal, fechaIngreso): Observable { return this.mapaCamasService.snapshot(this.fechaIngresoOriginal, idInternacion).pipe( switchMap(snapshot => { @@ -496,107 +509,73 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { } isCamaCensable(): boolean { - return !!this.prestacion?.id && !this.cama?.esCensable && (this.capa === 'estadistica' || this.capa === 'estadistica-v2'); + return (!this.cama?.esCensable) && ( + (this.capa === 'estadistica' && !!this.informeEstadistica) || + (this.capa === 'estadistica-v2' && !!this.prestacion?.id) + ); } ingresoSimplificado(estado, paciente, idInternacion = null, nuevaPrestacion = null) { - // si idInternacion === null es ingreso nuevo - // si nuevaPrestacion !== null estadistica-v2 esta ingresando un paciente - // Se modifica el estado de la cama this.cama.estado = estado; this.cama.paciente = paciente; this.cama.fechaIngreso = new Date(this.informeIngreso.fechaIngreso); + // Caso con movimientos previos if (this.prestacion && this.poseeMovimientos) { - // Se actualiza fecha y hora en camas this.cama.idInternacion = idInternacion; - if (this.informeIngreso.fechaIngreso.getTime() !== this.fechaIngresoOriginal.getTime()) { - // Recuperamos snapshot inicial, por si hay un cambio de cama - this.sincronizarCamaInternacion(idInternacion, this.fechaIngresoOriginal, this.informeIngreso.fechaIngreso).subscribe(() => { - this.plex.info('success', 'Los datos se actualizaron correctamente'); - this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); - this.listadoInternacionService.setFechaHasta(this.informeIngreso.fechaIngreso); - this.disableButton = false; - this.onSave.emit(); - }, () => { - this.plex.info('danger', 'Ocurrió un error actualizando los datos. Revise los movimientos e intente nuevamente.', 'Atención'); - this.disableButton = false; + this.sincronizarCamaInternacion(idInternacion, this.fechaIngresoOriginal, this.informeIngreso.fechaIngreso) + .subscribe({ + next: () => { + this.plex.info('success', 'Los datos se actualizaron correctamente'); + this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); + this.listadoInternacionService.setFechaHasta(this.informeIngreso.fechaIngreso); + this.disableButton = false; + this.onSave.emit(); + }, + error: (err) => { + this.plex.info('danger', 'Ocurrió un error actualizando los datos. Revise los movimientos e intente nuevamente.', 'Atención'); + this.disableButton = false; + } }); - } else { - this.plex.info('success', 'Los datos se actualizaron correctamente'); - this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); - this.listadoInternacionService.setFechaHasta(this.informeIngreso.fechaIngreso); - this.disableButton = false; - this.onSave.emit(); - } } else { if (nuevaPrestacion) { - // estadistica-v2 this.prestacion = nuevaPrestacion; } - if (this.cama.idInternacion) { - // Edición de internación existente por capa medica/enfermeria - this.sincronizarCamaInternacion(this.cama.idInternacion, this.fechaIngresoOriginal, this.informeIngreso.fechaIngreso).subscribe(() => { - this.onSave.emit(); - this.disableButton = false; - this.mapaCamasService.fecha2.next(this.informeIngreso.fechaIngreso); // para vista del mapa - this.mapaCamasService.select(this.cama); - this.historialInternacionService.refresh.next(null); // para vista del historial - this.plex.info('success', 'Los datos se actualizaron correctamente'); - }, () => { - this.plex.info('danger', 'Ocurrió un error actualizando los datos. Revise los movimientos e intente nuevamente.', 'Atención'); - this.disableButton = false; + + const createAction: Observable = idInternacion + ? of({ id: idInternacion }) + : this.internacionResumenService.create({ + ambito: this.mapaCamasService.ambito, + fechaIngreso: this.informeIngreso.fechaIngreso, + paciente: this.cama.paciente, + organizacion: { ...this.auth.organizacion }, + idInformeEstadistica: this.capa === 'estadistica' ? idInternacion : undefined, + idPrestacion: this.capa === 'estadistica-v2' ? nuevaPrestacion?.id : undefined }); - } else { - // Nueva internacion por capa medica/enfermería/estadistica-v2 - delete this.cama['sectorName']; - delete this.cama['diaEstada']; - delete this.cama['_key']; - this.cama.extras = { - ingreso: true - }; - const ingreso = this.elementoRUP ? { - elementoRUP: this.elementoRUP, - registros: this.prestacionFake.ejecucion.registros - } : null; - - const createAction: Observable = idInternacion ? of({ id: idInternacion }) : - - this.internacionResumenService.create({ - ambito: this.mapaCamasService.ambito, - fechaIngreso: this.informeIngreso.fechaIngreso, - paciente: this.cama.paciente, - organizacion: { ...this.auth.organizacion }, - ingreso, - idPrestacion: this.capa === 'estadistica-v2' ? nuevaPrestacion.id : undefined - }); - - createAction.pipe( - switchMap(internacion => { - if (!internacion.id) { - throw new Error(); - } - this.cama.idInternacion = internacion.id; - return this.mapaCamasService.save(this.cama, this.informeIngreso.fechaIngreso); - }) - ).subscribe(camaEstado => { - if (camaEstado?.id) { - this.plex.info('success', 'Paciente internado'); - this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); - this.selectCama(camaEstado); - this.onSave.emit(); - } else { - this.plex.info('warning', 'Ocurrió un error realizando el ingreso. Por favor revise los movimientos y de ser necesario anule la internación.', 'Atención'); - } + + createAction.pipe( + switchMap(internacion => { + if (!internacion.id) {throw new Error('⚠️ Internación sin ID');} + this.cama.idInternacion = internacion.id; + return this.mapaCamasService.save(this.cama, this.informeIngreso.fechaIngreso); + }) + ).subscribe({ + next: (camaEstado) => { + this.plex.info('success', 'Paciente internado'); + this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); + this.selectCama(camaEstado); + this.onSave.emit(); this.disableButton = false; - }, () => { - this.plex.info('warning', 'Ocurrió un error realizando el ingreso. Por favor revise los movimientos y de ser necesario anule la internación.', 'Atención'); + }, + error: (err) => { + this.plex.info('warning', 'Ocurrió un error realizando el ingreso.', 'Atención'); this.disableButton = false; - }); - } + } + }); } } + ingresoExtendido(paciente) { // construimos el informe de ingreso this.informeIngreso.situacionLaboral = (this.informeIngreso.situacionLaboral) ? this.informeIngreso.situacionLaboral.nombre : null; @@ -622,7 +601,9 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { if (this.paciente.fechaNacimiento) { this.informeIngreso.edadAlIngreso = this.mapaCamasService.calcularEdad(this.paciente.fechaNacimiento, this.informeIngreso.fechaIngreso); } - if (this.prestacion) { + if (this.capa === 'estadistica') { + this.crearInformeEstadistica(paciente);// 👈 Nuevo flujo + } else if (this.prestacion) { this.actualizarPrestacion(paciente); } else { this.crearPrestacion(paciente); @@ -668,6 +649,43 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { }); } + crearInformeEstadistica(paciente) { + const nuevoInforme: IInformeEstadistica = { + paciente, + unidadOrganizativa: this.cama?.unidadOrganizativa, + organizacion: this.auth.organizacion, + informeIngreso: this.informeIngreso, + estados: [{ tipo: 'ejecucion' }] + }; + + this.InformeEstadisticaService.post(nuevoInforme).subscribe({ + next: (informe) => { + // 🔗 Vinculamos el informe con un resumen de internación + this.internacionResumenService.create({ + ambito: 'internacion', + fechaIngreso: this.informeIngreso.fechaIngreso, + paciente: paciente, + organizacion: this.auth.organizacion, + idInformeEstadistica: informe._id + }).subscribe({ + next: (resumen) => { + if (this.cama) { + this.ingresoSimplificado('ocupada', paciente, resumen.id, informe); + } else { + console.warn('⚠️ Paciente ingresado en lista de espera (sin cama asignada)'); + this.plex.info('warning', 'Paciente ingresado en lista de espera (sin cama asignada)'); + } + }, + error: (err) => { + this.plex.info('danger', 'ERROR: No se pudo crear el resumen de internación'); + } + }); + }, + error: (err) => { + this.plex.info('danger', 'ERROR: El informe no pudo ser registrado'); + } + }); + } // Inicializa una prestación con todos sus datos básicos datosBasicosPrestacion() { // armamos el elemento data a agregar al array de registros @@ -790,32 +808,46 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { createFormularioDinamico(cama: ISnapshot, estado: any) { this.conceptObserverService.destroy(); + const molecula = estado.ingresos && estado.ingresos[cama.id as string]; if (!molecula) { this.elementoRUP = null; this.prestacionFake = null; return; } - this.elementoRUP = molecula; const elementoRUP = this.elementosRUPService.getById(molecula); - - this.prestacionFake = { - paciente: this.paciente, - solicitud: { - tipoPrestacion: {}, + if (this.capa === 'estadistica') { + this.prestacionFake = { + paciente: this.paciente, organizacion: { ...this.auth.organizacion }, - profesional: {} - }, - ejecucion: { - organizacion: { ...this.auth.organizacion }, - registros: [], - } - }; + unidadOrganizativa: this.cama.unidadOrganizativa, + informeIngreso: this.informeIngreso, + estados: [{ tipo: 'ejecucion' }], + ejecucion: { registros: [] } + }; + } else { + this.prestacionFake = { + paciente: this.paciente, + solicitud: { + tipoPrestacion: {}, + organizacion: { ...this.auth.organizacion }, + profesional: {} + }, + ejecucion: { + organizacion: { ...this.auth.organizacion }, + registros: [], + } + }; + } for (const elementoRequerido of elementoRUP.requeridos) { const elementoRUP_ = this.elementosRUPService.buscarElemento(elementoRequerido.concepto, false); - const nuevoRegistro = new IPrestacionRegistro(elementoRUP_, elementoRequerido.concepto, this.prestacionFake); + const nuevoRegistro = new IPrestacionRegistro( + elementoRUP_, + elementoRequerido.concepto, + this.prestacionFake + ); this.prestacionFake.ejecucion.registros.push(nuevoRegistro); } } diff --git a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts index e82d0ab3b9..b32b4474ed 100644 --- a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts +++ b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts @@ -99,7 +99,7 @@ export interface IInformeEstadistica { organizacion: { id: string; nombre: string; - [key: string]: any; // <-- esto permite campos faltantes + [key: string]: any; }; unidadOrganizativa: ISnomedConcept; paciente: IPaciente; @@ -108,6 +108,7 @@ export interface IInformeEstadistica { periodosCensables?: { desde: Date; hasta: Date }[]; estados?: IInternacionEstado[]; estadoActual?: IInternacionEstado; + estado?: IInternacionEstado | string; createdAt?: Date; createdBy?: { id: string; diff --git a/src/app/modules/rup/services/informe-estadistica.service.ts b/src/app/modules/rup/services/informe-estadistica.service.ts index 536220e268..5f98bea2ee 100644 --- a/src/app/modules/rup/services/informe-estadistica.service.ts +++ b/src/app/modules/rup/services/informe-estadistica.service.ts @@ -1,46 +1,29 @@ -/* eslint-disable no-console */ import { Injectable } from '@angular/core'; -import { ResourceBaseHttp, Server } from '@andes/shared'; -import { Observable, tap } from 'rxjs'; -import { IInformeEstadistica } from '../interfaces/informe-estadistica.interface'; // ruta según tu estructura +import { Server } from '@andes/shared'; +import { Observable } from 'rxjs'; +import { IInformeEstadistica } from '../interfaces/informe-estadistica.interface'; @Injectable({ providedIn: 'root' }) -export class InformeEstadisticaService extends ResourceBaseHttp { - protected override url = '/modules/rup/internacion/informe-estadistica'; +export class InformeEstadisticaService { + private baseUrl = '/modules/rup/internacion/informe-estadistica'; - constructor(protected override server: Server) { - super(server); - } + constructor(private server: Server) { } - /** - * Crear un nuevo informe estadístico - */ - CreateInforme(data: IInformeEstadistica): Observable { - return this.server.post(this.url, data); + get(params?: any): Observable { + return this.server.get(this.baseUrl, { params }); } - /** - * Actualizar un informe existente - */ - updateInforme(id: string, data: Partial): Observable { - return this.server.patch(`${this.url}/${id}`, data); - } - /** - * Obtener un informe por su ID - */ getById(id: string): Observable { - const url = `${this.url}/${id}`; - return this.server.get(url); + return this.server.get(`${this.baseUrl}/${id}`); } - get(params: any = {}, options: any = {}): Observable { - if (typeof options.showError === 'undefined') { - options.showError = true; - } - const opt = { params, options }; + post(data: IInformeEstadistica): Observable { + return this.server.post(this.baseUrl, data); + } - return this.server.get(this.url, opt); + put(id: string, data: IInformeEstadistica): Observable { + return this.server.put(`${this.baseUrl}/${id}`, data); } } From d355807680a89ee2681c34bdd40a241980da2573 Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:08:48 -0300 Subject: [PATCH 03/14] feat(IN):"Varios cambios en la app para la llamada de la api InformeEstadistica" --- .../mapa-camas/services/mapa-camas.service.ts | 58 +- .../cama-detalle/cama-detalle.component.ts | 9 +- .../internacion-detalle.component.ts | 10 + .../ingreso/informe-ingreso.component.html | 130 ++-- .../ingreso/informe-ingreso.component.ts | 48 +- .../ingreso/ingresar-paciente.component.html | 65 +- .../ingreso/ingresar-paciente.component.ts | 620 ++++++++++-------- .../informe-estadistica.interface.ts | 23 +- .../services/informe-estadistica.service.ts | 47 +- 9 files changed, 595 insertions(+), 415 deletions(-) diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts index 5e0577b8aa..b43ce39087 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts @@ -2,7 +2,7 @@ import { Auth } from '@andes/auth'; import { cache, notNull } from '@andes/shared'; import { Injectable } from '@angular/core'; import { BehaviorSubject, combineLatest, Observable, of, timer } from 'rxjs'; -import { catchError, map, multicast, pluck, startWith, switchMap } from 'rxjs/operators'; +import { catchError, map, multicast, pluck, startWith, switchMap, tap } from 'rxjs/operators'; import { IPaciente } from '../../../../core/mpi/interfaces/IPaciente'; import { PacienteService } from '../../../../core/mpi/services/paciente.service'; import { ISectores } from '../../../../interfaces/IOrganizacion'; @@ -48,7 +48,10 @@ export class MapaCamasService { public prestacion$: Observable; public informeEstadistica$: Observable; + public selectedPrestacion = new BehaviorSubject({ id: null } as any); + public selectedInformeEstadistica = new BehaviorSubject({ id: null } as any); + public camaSelectedSegunView$: Observable; public maquinaDeEstado$: Observable; @@ -139,6 +142,11 @@ export class MapaCamasService { snap.diaEstada = 0; } }); + // 👉 Aquí detectamos los casos sin sectores + const sinSectores = snapshot.filter(s => !s.sectores || s.sectores.length === 0); + if (sinSectores.length > 0) { + console.warn('⚠️ Snapshots sin sectores:', sinSectores.map(s => s.id)); + } return snapshot.sort((a, b) => (a.unidadOrganizativa.term.localeCompare(b.unidadOrganizativa.term)) || (a.sectores[a.sectores.length - 1].nombre.localeCompare(b.sectores[b.sectores.length - 1].nombre + '')) || (a.nombre.localeCompare('' + b.nombre))); @@ -191,7 +199,7 @@ export class MapaCamasService { if (!cama.idInternacion) { return of(null); } - if (capa === 'estadistica') { + if (capa !== 'estadistica') { return this.prestacionService.getById(cama.idInternacion, { showError: false }); } return this.internacionResumenHTTP.get(cama.idInternacion).pipe( @@ -228,47 +236,41 @@ export class MapaCamasService { ) as Observable; this.informeEstadistica$ = combineLatest([ - this.selectedPrestacion, + this.selectedInformeEstadistica, this.selectedCama, this.view, this.capa2 ]).pipe( - switchMap(([prestacion, cama, view, capa]) => { + switchMap(([informe, cama, view, capa]) => { + if (view === 'listado-internacion') { - if (prestacion?.id) { - return this.informeEstadisticaService.get({ paciente: prestacion.paciente.id }).pipe( + const pacienteId = informe?.paciente?.id || cama?.paciente?.id; + if (pacienteId) { + return this.informeEstadisticaService.get({ paciente: pacienteId }).pipe( map(informes => informes?.[0] || null) ); } return of(null); } - if (!cama.idInternacion) { + if (!cama?.idInternacion) { return of(null); } if (capa === 'estadistica') { - return this.informeEstadisticaService.get({ paciente: cama.paciente.id }).pipe( - map(informes => informes?.[0] || null) - ); - } - - if (capa === 'estadistica-v2') { - return this.internacionResumenHTTP.get(cama.idInternacion).pipe( - switchMap(internacionResumen => { - if (internacionResumen?.paciente?.id) { - return this.informeEstadisticaService.get({ paciente: internacionResumen.paciente.id }).pipe( - map(informes => informes?.[0] || null) - ); - } - return of(null); - }) - ); + const id = informe?.id || cama?.idInternacion; + if (!id) { + console.warn('⚠️ No hay ID válido para obtener el informe estadístico'); + return of(null); + } + return this.informeEstadisticaService.getById(id, { showError: false }); } return of(null); }), - catchError(() => of(null)), + catchError(err => { + return of(null); + }), cache() ); @@ -427,6 +429,14 @@ export class MapaCamasService { this.selectedPrestacion.next(prestacion); } + selectInformeEstadistica(informe: IInformeEstadistica) { + if (!informe) { + return this.selectedInformeEstadistica.next({ id: null } as any); + } + + this.selectedInformeEstadistica.next(informe); + } + selectResumen(resumen: IResumenInternacion) { if (!resumen) { return this.selectedResumen.next({ id: null } as any); diff --git a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/cama-detalle.component.ts b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/cama-detalle.component.ts index 5ffe1e66b6..59d857f115 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/cama-detalle.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/cama-detalle.component.ts @@ -15,8 +15,8 @@ import { PermisosMapaCamasService } from '../../services/permisos-mapa-camas.ser import { InternacionResumenHTTP } from '../../services/resumen-internacion.http'; import { OrganizacionService } from 'src/app/services/organizacion.service'; import { Auth } from '@andes/auth'; - - +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; +import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; @Component({ selector: 'app-cama-detalle', templateUrl: 'cama-detalle.component.html' @@ -69,6 +69,7 @@ export class CamaDetalleComponent implements OnInit, AfterViewChecked, OnDestroy public unicoMovimiento = false; public subscripcion: Subscription; public prestacion; + public InformeEstadistica; items = [ { @@ -93,6 +94,7 @@ export class CamaDetalleComponent implements OnInit, AfterViewChecked, OnDestroy private mapaCamasService: MapaCamasService, private mapaCamasHTTP: MapaCamasHTTP, private prestacionesService: PrestacionesService, + public InformeEstadisticaService: InformeEstadisticaService, public permisosMapaCamasService: PermisosMapaCamasService, private turneroService: TurneroService, private motivoAccesoService: ModalMotivoAccesoHudsService, @@ -115,8 +117,7 @@ export class CamaDetalleComponent implements OnInit, AfterViewChecked, OnDestroy this.relaciones$ = this.cama$.pipe(switchMap(cama => this.mapaCamasService.getRelacionesPosibles(cama))); this.accionesEstado$ = this.mapaCamasService.prestacionesPermitidas(this.mapaCamasService.selectedCama); this.organizacionV2$ = this.organizacionService.usaCapasUnificadas(this.auth.organizacion.id); - this.subscripcion = this.mapaCamasService.prestacion$.subscribe(p => this.prestacion = p); - + this.subscripcion = this.mapaCamasService.informeEstadistica$.subscribe(p => this.InformeEstadistica = p); this.paciente$ = this.cama$.pipe( filter(cama => !!cama.paciente), switchMap(cama => cama.paciente ? this.mapaCamasService.getPaciente(cama.paciente) : of(null)) diff --git a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts index 26cdec5a75..a109eed8b7 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts @@ -108,6 +108,16 @@ export class InternacionDetalleComponent implements OnInit, AfterViewChecked { this.mapaCamasService.isLoading(false); }); + // Nueva capa estadística (internacionFormEstadistica) + this.mapaCamasService.informeEstadistica$.subscribe(informe => { + if (informe?.paciente?.id) { + this.ingresoPacienteService.selectPaciente(informe.paciente.id); + this.existeIngreso = !!informe.informeIngreso; + this.estadoPrestacion = informe.estadoActual?.tipo || 'ejecucion'; + this.editarEgreso = !informe.informeEgreso; + } + }); + // Configura los tabs a mostrar según capa y vista this.mapaCamasService.resumenInternacion$.pipe( map(resumen => { diff --git a/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.html b/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.html index 3d2968cea9..ccee2b3ca4 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.html +++ b/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.html @@ -1,65 +1,85 @@ - + - - + + + + + - - - + + + + + + + + + + + +
+ + Censable + + + + NUEVO REGISTRO + + + + + + - + + - + + - -
- - - Censable - - - - - - - - - - - - + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ - +
+
+ - -
- -
- - -
-
- - -
- - - -
- - -
-
- + +
\ No newline at end of file diff --git a/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.ts b/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.ts index ef350c1ca5..1481b854a7 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.ts @@ -1,10 +1,10 @@ import { Component, OnInit, Output, EventEmitter } from '@angular/core'; import { MapaCamasService } from '../../services/mapa-camas.service'; import { IPrestacion } from '../../../../../modules/rup/interfaces/prestacion.interface'; -import { Observable } from 'rxjs'; +import { combineLatest, Observable } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; import { notNull } from '@andes/shared'; - +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; @Component({ selector: 'app-informe-ingreso', templateUrl: './informe-ingreso.component.html', @@ -15,7 +15,7 @@ export class InformeIngresoComponent implements OnInit { informeIngreso$: Observable; paciente$: Observable; pacienteFields = ['sexo', 'fechaNacimiento', 'edad', 'cuil', 'financiador', 'numeroAfiliado', 'direccion', 'telefono']; - + informeEstadistica$: Observable; // EVENTOS @Output() toggleEditar = new EventEmitter(); @@ -24,14 +24,46 @@ export class InformeIngresoComponent implements OnInit { ) { } ngOnInit() { + this.informeEstadistica$ = this.mapaCamasService.informeEstadistica$; this.prestacion$ = this.mapaCamasService.prestacion$; - this.informeIngreso$ = this.prestacion$.pipe( - notNull(), - map((prestacion) => prestacion.ejecucion.registros[0].valor.informeIngreso) + + this.informeIngreso$ = combineLatest([ + this.informeEstadistica$, + this.prestacion$ + ]).pipe( + map(([informeEstadistica, prestacion]) => { + if (informeEstadistica?.informeIngreso) { + return informeEstadistica.informeIngreso; + } + + if (prestacion?.ejecucion?.registros?.[0]?.valor?.informeIngreso) { + return prestacion.ejecucion.registros[0].valor.informeIngreso; + } + + return null; + }), + notNull() ); - this.paciente$ = this.prestacion$.pipe( + + this.paciente$ = combineLatest([ + this.informeEstadistica$, + this.prestacion$ + ]).pipe( + map(([informeEstadistica, prestacion]) => { + if (informeEstadistica?.paciente) { + return informeEstadistica.paciente; + } + + if (prestacion?.paciente) { + return prestacion.paciente; + } + + console.warn('⚠️ No se encontró paciente ni en informeEstadistica ni en prestación'); + return null; + }), notNull(), - switchMap(prestacion => this.mapaCamasService.getPaciente(prestacion.paciente)) + switchMap(paciente => this.mapaCamasService.getPaciente(paciente)) ); } + } diff --git a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.html b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.html index 1a6e83d55a..c14f16f23d 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.html +++ b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.html @@ -2,7 +2,7 @@
+ (click)="guardar($event)" [disabled]="formIngreso.invalid || disableButton || inProgress"> @@ -10,13 +10,13 @@ + (guardarCarpetaEmit)="afterComponenteCarpeta($event)"> + (click)="togglePrestacionCensable()"> @@ -26,7 +26,7 @@ + (click)="togglePrestacionNoCensable()"> No Censable @@ -37,42 +37,43 @@ + name=" fechaIngreso" [max]="mapaCamasService.fechaActual$ | async" required [debounce]="600" + (change)="setFecha()" grow="full" (typing)="onType()"> + [(ngModel)]="cama" name="cama" [data]="camas" placeholder="Elija cama" label="Cama" + idField="id" labelField="nombre + '(' + sectorName + ')'" (change)="selectCama(cama)" + grow="full"> + name="cama" [(ngModel)]="cama.nombre"> - + + (getData)="loadProfesionales($event)" [required]="true" labelField="apellido+' '+nombre"> + (change)="onchange($event)"> + (getData)="loadOrganizacion($event)" label="Organización origen" + placeholder="Seleccione la organización" labelField="nombre" [required]="true"> + [(ngModel)]="informeIngreso.organizacionOrigen" [required]="true"> @@ -81,8 +82,7 @@ + [(ngModel)]="informeIngreso.especialidades" [multiple]="true" label="Especialidad/es"> @@ -104,15 +104,16 @@ + [data]="pacienteAsociado" placeholder="Seleccione..." label="Cobertura" idField="id" + labelField="nombre">
+ *ngIf="(informeIngreso?.asociado?.id === 'Plan de salud privado o Mutual') || (informeIngreso?.asociado === 'Plan de salud privado o Mutual')"> + (ngModelChange)="onFinanciadorChange($event)" name="financiador" + [data]="selectorFinanciadores" label="Financiador" idField="nombre" labelField="nombre" + [required]="true">

@@ -121,19 +122,19 @@ + name="situacionLaboral" [data]="situacionesLaborales" placeholder="Seleccione... " + labelField="nombre"> + name="ocupacionHabitual" (getData)="getOcupaciones($event)" + placeholder="Seleccione... " labelField="'(' + codigo + ') ' + nombre"> + [data]="nivelesInstruccion" placeholder="Seleccione..." label="Nivel instrucción" + idField="nombre" labelField="nombre">
@@ -142,8 +143,8 @@ + [paciente]="paciente" [registro]="registro" [soloValores]="false" + [params]="elementosRUPService.getParams(registro)"> \ No newline at end of file diff --git a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts index 72bfe13665..eb4fcff76c 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts @@ -27,7 +27,7 @@ import { ListadoInternacionCapasService } from '../../views/listado-internacion- import { IObraSocial } from 'src/app/interfaces/IObraSocial'; import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; -import { debug } from 'console'; +import { IOrganizacion } from 'src/app/interfaces/IOrganizacion'; @Component({ selector: 'app-ingresar-paciente', templateUrl: './ingresar-paciente.component.html', @@ -50,7 +50,6 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { public snomedIngreso = snomedIngreso; public expr = SnomedExpression; public fechaMax = moment().toDate(); - estado: IMaquinaEstados;// 👈 agregá esta línea // VARIABLES public esPrepaga = false; @@ -69,29 +68,39 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { public inProgress = false; public prepagas$: Observable; private backupObraSocial; - public registrosIngresoResumen$: Observable;; + public registrosIngresoResumen$: Observable; public get origenExterno() { - return this.informeIngreso?.origen?.id === 'traslado' || this.informeIngreso.origen === 'Traslado'; + return this.informeIngreso?.origen?.tipo === 'Traslado'; } public check = false; - public informeIngreso = { + public informeIngreso: any = { fechaIngreso: new Date(), horaNacimiento: new Date(), edadAlIngreso: null, - origen: null, + origen: { + tipo: null, + organizacionOrigen: null, + otraOrganizacion: null + }, ocupacionHabitual: null, situacionLaboral: null, nivelInstruccion: null, especialidades: [], asociado: null, - obraSocial: null, + cobertura: { + tipo: null, + obraSocial: { + nombre: '' as string, + financiador: '' as string, + codigoPuco: undefined as number | undefined + } + }, nroCarpeta: null, motivo: null, organizacionOrigen: null, profesional: null, financiador: null, - - PaseAunidadOrganizativa: null + paseAunidadOrganizativa: null }; public poseeMovimientos: Boolean; private subscription: Subscription; @@ -110,7 +119,6 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { private ocupacionService: OcupacionService, private organizacionService: OrganizacionService, private servicioPrestacion: PrestacionesService, - private InformeEstadisticaService: InformeEstadisticaService, public mapaCamasService: MapaCamasService, private listadoInternacionService: ListadoInternacionService, private historialInternacionService: ListadoInternacionCapasService, @@ -119,7 +127,8 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { public elementosRUPService: ElementosRUPService, public internacionResumenService: InternacionResumenHTTP, private conceptObserverService: ConceptObserverService, - private obraSocialService: ObraSocialService + private obraSocialService: ObraSocialService, + private informeEstadisticaService: InformeEstadisticaService ) { } ngOnDestroy() { @@ -193,100 +202,87 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { this.mapaCamasService.resumenInternacion$, pacienteID$.pipe( filter(pacID => !!pacID), - switchMap((pacID) => this.mapaCamasService.getPaciente({ id: pacID }, false)) - ) - ]) - .subscribe(([estado, view, capa, cama, prestacion, informeEstadistica, resumen, paciente]: [ - IMaquinaEstados, - string, - string, - ISnapshot, - IPrestacion, - IInformeEstadistica, - IResumenInternacion, - IPaciente - ]) => { - - this.estado = estado; - this.view = view; - this.capa = capa; - this.cama = cama; - this.prestacion = prestacion; - this.informeEstadistica = informeEstadistica; // 👈 ya no da error - this.resumen = resumen; - this.paciente = paciente; - this.poseeMovimientos = !!(cama?.id); - - if (paciente && paciente.financiador && paciente.financiador.length > 0) { - const os = paciente.financiador[0]; - this.backupObraSocial = os; - } + switchMap((pacID) => { + return this.mapaCamasService.getPaciente({ id: pacID }, false); + }) + )] + ).subscribe(([estado, view, capa, cama, prestacion, informeEstadistica, resumen, paciente]: [IMaquinaEstados, string, string, ISnapshot, IPrestacion, IInformeEstadistica, IResumenInternacion, IPaciente]) => { + this.capa = capa; + this.prestacion = prestacion; + this.informeEstadistica = informeEstadistica; + this.paciente = paciente; + this.resumen = resumen; + this.poseeMovimientos = !!(cama?.id); + if (paciente && paciente.financiador && paciente.financiador.length > 0) { + const os = paciente.financiador[0]; + this.backupObraSocial = os; + } - if (this.prestacion) { - this.informeIngreso = this.prestacion.ejecucion.registros[0].valor.informeIngreso; - if (this.origenExterno) { - this.check = typeof this.informeIngreso.organizacionOrigen === 'string'; + if (this.prestacion) { + this.informeIngreso = this.prestacion.ejecucion.registros[0].valor.informeIngreso; + if (this.origenExterno) { + this.check = typeof this.informeIngreso.organizacionOrigen === 'string'; + } + this.fechaIngresoOriginal = new Date(this.informeIngreso.fechaIngreso); + this.paciente.obraSocial = this.prestacion.paciente.obraSocial; + this.changeTipoObraSocial(); + } else { + if (paciente.id) { + const fechaIngresoInicial = resumen?.fechaIngreso || this.mapaCamasService.fecha; + this.informeIngreso.fechaIngreso = new Date(fechaIngresoInicial); + this.fechaIngresoOriginal = new Date(fechaIngresoInicial); + if (this.backupObraSocial) { + this.paciente.obraSocial = { + nombre: this.backupObraSocial.financiador, + financiador: this.backupObraSocial.financiador, + codigoPuco: this.backupObraSocial.codigoPuco + }; + this.informeIngreso.asociado = { + id: 'Plan o Seguro público', + nombre: 'Plan o Seguro público' + }; + this.esPrepaga = false; } - this.fechaIngresoOriginal = new Date(this.informeIngreso.fechaIngreso); - this.paciente.obraSocial = this.prestacion.paciente.obraSocial; - this.changeTipoObraSocial(); - } else { - if (paciente.id) { - const fechaIngresoInicial = resumen?.fechaIngreso || this.mapaCamasService.fecha; - this.informeIngreso.fechaIngreso = new Date(fechaIngresoInicial); - this.fechaIngresoOriginal = new Date(fechaIngresoInicial); - if (this.backupObraSocial) { - this.paciente.obraSocial = { - nombre: this.backupObraSocial.financiador, - financiador: this.backupObraSocial.financiador, - codigoPuco: this.backupObraSocial.codigoPuco - }; - this.informeIngreso.asociado = { - id: 'Plan o Seguro público', - nombre: 'Plan o Seguro público' - }; - this.esPrepaga = false; - } - let indiceCarpeta = -1; - if (paciente.carpetaEfectores && paciente.carpetaEfectores.length > 0) { - indiceCarpeta = paciente.carpetaEfectores.findIndex(x => (x.organizacion as any)._id === this.auth.organizacion.id); - if (indiceCarpeta > -1) { - this.informeIngreso.nroCarpeta = paciente.carpetaEfectores[indiceCarpeta].nroCarpeta; - } + let indiceCarpeta = -1; + if (paciente.carpetaEfectores && paciente.carpetaEfectores.length > 0) { + indiceCarpeta = paciente.carpetaEfectores.findIndex(x => (x.organizacion as any)._id === this.auth.organizacion.id); + if (indiceCarpeta > -1) { + this.informeIngreso.nroCarpeta = paciente.carpetaEfectores[indiceCarpeta].nroCarpeta; } } - if (capa === 'estadistica') { - this.cargarUltimaInternacion(paciente); - } } - - if (cama && cama.id && cama.id !== ' ') { - this.cama = cama; - if (cama.estado === 'ocupada' && !cama.sala) { - this.paciente = cama.paciente; - } - if (this.informeIngreso.especialidades && this.informeIngreso.especialidades.length === 0) { - this.informeIngreso.especialidades = this.cama.especialidades; - } - this.createFormularioDinamico(cama, estado); - } else if (view === 'listado-internacion') { - if (this.subscription2) { - this.subscription2.unsubscribe(); - } - if (this.poseeMovimientos) { - const idInternacion = resumen?.id || prestacion.id; - this.subscription2 = this.mapaCamasService.snapshot(this.informeIngreso.fechaIngreso, idInternacion).pipe( - map(snapshot => this.cama = snapshot[0]) - ).subscribe(); - } - } else { - this.cama = null; + if (capa === 'estadistica') { + this.cargarUltimaInternacion(paciente); } + } - if (this.informeIngreso.asociado?.id === 'Plan de salud privado o Mutual') { - this.selectedOS = true; + if (cama && cama.id && cama.id !== ' ') { + this.cama = cama; + if (cama.estado === 'ocupada' && !cama.sala) { + this.paciente = cama.paciente; } - }); + if (this.informeIngreso.especialidades && this.informeIngreso.especialidades.length === 0) { + this.informeIngreso.especialidades = this.cama.especialidades; + } + this.createFormularioDinamico(cama, estado); + } else if (view === 'listado-internacion') { + if (this.subscription2) { + this.subscription2.unsubscribe(); + } + if (this.poseeMovimientos) { + const idInternacion = resumen?.id || prestacion.id; + this.subscription2 = this.mapaCamasService.snapshot(this.informeIngreso.fechaIngreso, idInternacion).pipe( + map(snapshot => this.cama = snapshot[0]) + ).subscribe(); + } + } else { + this.cama = null; + } + + if (this.informeIngreso.asociado?.id === 'Plan de salud privado o Mutual') { + this.selectedOS = true; + } + }); this.camas$ = combineLatest([ this.mapaCamasService.snapshot$, @@ -301,53 +297,55 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { }) ); this.obraSocialService.getListado({}).subscribe(listado => this.selectorFinanciadores = listado.filter(financiador => this.obrasSociales.every(os => os.nombre !== financiador.nombre))); - if (this.informeIngreso.obraSocial) { + if (this.informeIngreso.cobertura?.obraSocial) { this.financiador = this.selectorFinanciadores.find( - f => f.codigoPuco === this.informeIngreso.obraSocial.codigoPuco + f => f.codigoPuco === this.informeIngreso.cobertura.obraSocial.codigoPuco ); } } - cargarUltimaInternacion(paciente: IPaciente) { const conceptIdIngresoInternacion = '721915006'; - this.servicioPrestacion.getRegistrosHuds(paciente.id, conceptIdIngresoInternacion).subscribe(ingreso => { - if (ingreso.length > 0) { - ingreso = ingreso.sort((a, b) => b.fecha.getTime() - a.fecha.getTime()); - const ultimoIngreso = ingreso[0].registro.valor.informeIngreso; + this.informeEstadisticaService.getRegistrosHuds(paciente.id, conceptIdIngresoInternacion).subscribe((ingreso: any[]) => { + if (ingreso && ingreso.length > 0) { + const ultimoIngreso = ingreso[0].informeIngreso; this.informeIngreso.situacionLaboral = this.situacionesLaborales?.find(item => item.nombre === ultimoIngreso.situacionLaboral) || null; this.informeIngreso.nivelInstruccion = this.nivelesInstruccion?.find(item => item.nombre === ultimoIngreso.nivelInstruccion) || null; this.informeIngreso.ocupacionHabitual = ultimoIngreso.ocupacionHabitual; this.informeIngreso.asociado = ultimoIngreso.asociado; - this.informeIngreso.obraSocial = ultimoIngreso.obraSocial; + this.informeIngreso.cobertura.obraSocial = (ultimoIngreso as any).obraSocial; + + this.informeIngreso.cobertura.tipo = (ultimoIngreso as any).asociado; this.paciente.obraSocial = ultimoIngreso.obraSocial; this.esPrepaga = this.informeIngreso.asociado?.id === 'Plan de salud privado o Mutual'; + } }); } changeTipoObraSocial() { - this.selectedOS = false; - this.esPrepaga = false; - this.financiador = null; - const asociadoId = typeof this.informeIngreso.asociado === 'string' - ? this.informeIngreso.asociado - : this.informeIngreso.asociado?.id; - if (asociadoId === 'Plan de salud privado o Mutual') { - this.selectedOS = true; - this.esPrepaga = true; - if (this.informeIngreso.obraSocial) { - const financiadorParaSelect = this.selectorFinanciadores.find( - f => f.nombre === this.informeIngreso.obraSocial.nombre - ); - - if (financiadorParaSelect) { - this.financiador = financiadorParaSelect; - } else { - this.financiador = this.informeIngreso.obraSocial; - } - } + if (!this.informeIngreso.cobertura) { + this.informeIngreso.cobertura = { tipo: null, obraSocial: null }; + } + + const asociado = this.informeIngreso.asociado?.id || this.informeIngreso.asociado; + + if (asociado === 'Plan de salud privado o Mutual') { + this.informeIngreso.cobertura.tipo = 'Plan de salud privado o Mutual'; + + this.informeIngreso.cobertura.obraSocial = this.financiador || null; + + } else if (asociado === 'Plan o Seguro público' || asociado === 'Hospital Público') { + this.informeIngreso.cobertura.tipo = 'Plan o Seguro público'; + this.informeIngreso.cobertura.obraSocial = null; + } else if (asociado === 'Sin cobertura' || asociado === 'Ninguno') { + this.informeIngreso.cobertura.tipo = 'sinCobertura'; + this.informeIngreso.cobertura.obraSocial = null; + } else { + this.informeIngreso.cobertura.tipo = null; + this.informeIngreso.cobertura.obraSocial = null; } + } @@ -429,6 +427,7 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { return flagValid; } + guardar(valid) { if (valid.formValid && this.validarRUP()) { if (this.cama.sala) { @@ -440,6 +439,7 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { map(resp => resp) ).subscribe(historial => { if (historial.length) { + // Verificamos si hay otra internacion mas adelante. Asi mismo un bloqueo de cama o cambio de UO if ((this.cama.idInternacion !== historial[0]?.idInternacion && historial[0].estado !== 'disponible') || historial[0].unidadOrganizativa.id !== this.cama.unidadOrganizativa.id) { const fechaEnConflicto = moment(historial[0].fecha); @@ -481,9 +481,12 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { this.completarIngreso(dtoPaciente); } else if (this.prestacion) { this.actualizarPrestacion(dtoPaciente); + } else { + this.ingresoSimplificado('ocupada', dtoPaciente, this.resumen?.id); } } + // Sincroniza las fechas editadas entre la cama y elresumen/prestacion private sincronizarCamaInternacion(idInternacion, fechaIngresoOriginal, fechaIngreso): Observable { return this.mapaCamasService.snapshot(this.fechaIngresoOriginal, idInternacion).pipe( switchMap(snapshot => { @@ -509,105 +512,191 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { } isCamaCensable(): boolean { - return (!this.cama?.esCensable) && ( - (this.capa === 'estadistica' && !!this.informeEstadistica) || - (this.capa === 'estadistica-v2' && !!this.prestacion?.id) - ); + return !!this.prestacion?.id && !this.cama?.esCensable && (this.capa === 'estadistica' || this.capa === 'estadistica-v2'); } - ingresoSimplificado(estado, paciente, idInternacion = null, nuevaPrestacion = null) { + + ingresoSimplificado(estado, paciente, idInternacion = null, nuevoInforme = null) { + // si idInternacion === null es ingreso nuevo + // si nuevaPrestacion !== null estadistica-v2 esta ingresando un paciente + // Se modifica el estado de la cama this.cama.estado = estado; this.cama.paciente = paciente; this.cama.fechaIngreso = new Date(this.informeIngreso.fechaIngreso); - - // Caso con movimientos previos - if (this.prestacion && this.poseeMovimientos) { + this.informeEstadistica = this.informeEstadistica; + if (this.informeEstadistica && this.poseeMovimientos) { this.cama.idInternacion = idInternacion; - this.sincronizarCamaInternacion(idInternacion, this.fechaIngresoOriginal, this.informeIngreso.fechaIngreso) - .subscribe({ - next: () => { - this.plex.info('success', 'Los datos se actualizaron correctamente'); - this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); - this.listadoInternacionService.setFechaHasta(this.informeIngreso.fechaIngreso); - this.disableButton = false; - this.onSave.emit(); - }, - error: (err) => { - this.plex.info('danger', 'Ocurrió un error actualizando los datos. Revise los movimientos e intente nuevamente.', 'Atención'); - this.disableButton = false; - } + if (this.informeIngreso.fechaIngreso.getTime() !== this.fechaIngresoOriginal.getTime()) { + this.sincronizarCamaInternacion(idInternacion, this.fechaIngresoOriginal, this.informeIngreso.fechaIngreso).subscribe(() => { + this.plex.info('success', 'Los datos se actualizaron correctamente'); + this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); + this.listadoInternacionService.setFechaHasta(this.informeIngreso.fechaIngreso); + this.disableButton = false; + this.onSave.emit(); + }, () => { + this.plex.info('danger', 'Ocurrió un error actualizando los datos. Revise los movimientos e intente nuevamente.', 'Atención'); + this.disableButton = false; }); + } else { + this.plex.info('success', 'Los datos se actualizaron correctamente'); + this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); + this.listadoInternacionService.setFechaHasta(this.informeIngreso.fechaIngreso); + this.disableButton = false; + this.onSave.emit(); + } } else { - if (nuevaPrestacion) { - this.prestacion = nuevaPrestacion; + if (nuevoInforme) { + this.informeEstadistica = nuevoInforme; } - - const createAction: Observable = idInternacion - ? of({ id: idInternacion }) - : this.internacionResumenService.create({ - ambito: this.mapaCamasService.ambito, - fechaIngreso: this.informeIngreso.fechaIngreso, - paciente: this.cama.paciente, - organizacion: { ...this.auth.organizacion }, - idInformeEstadistica: this.capa === 'estadistica' ? idInternacion : undefined, - idPrestacion: this.capa === 'estadistica-v2' ? nuevaPrestacion?.id : undefined - }); - - createAction.pipe( - switchMap(internacion => { - if (!internacion.id) {throw new Error('⚠️ Internación sin ID');} - this.cama.idInternacion = internacion.id; - return this.mapaCamasService.save(this.cama, this.informeIngreso.fechaIngreso); - }) - ).subscribe({ - next: (camaEstado) => { - this.plex.info('success', 'Paciente internado'); - this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); - this.selectCama(camaEstado); + if (this.cama.idInternacion) { + this.sincronizarCamaInternacion(this.cama.idInternacion, this.fechaIngresoOriginal, this.informeIngreso.fechaIngreso).subscribe(() => { this.onSave.emit(); this.disableButton = false; - }, - error: (err) => { - this.plex.info('warning', 'Ocurrió un error realizando el ingreso.', 'Atención'); + this.mapaCamasService.fecha2.next(this.informeIngreso.fechaIngreso); // para vista del mapa + this.mapaCamasService.select(this.cama); + this.historialInternacionService.refresh.next(null); // para vista del historial + this.plex.info('success', 'Los datos se actualizaron correctamente'); + }, () => { + this.plex.info('danger', 'Ocurrió un error actualizando los datos. Revise los movimientos e intente nuevamente.', 'Atención'); this.disableButton = false; - } - }); + }); + } else { + // Nueva internacion por capa medica/enfermería/estadistica-v2 + delete this.cama['sectorName']; + delete this.cama['diaEstada']; + delete this.cama['_key']; + this.cama.extras = { + ingreso: true + }; + const ingreso = this.elementoRUP ? { + elementoRUP: this.elementoRUP, + registros: this.prestacionFake.ejecucion.registros + } : null; + + const createAction: Observable = idInternacion ? of({ id: idInternacion }) : + + this.internacionResumenService.create({ + ambito: this.mapaCamasService.ambito, + fechaIngreso: this.informeIngreso.fechaIngreso, + paciente: this.cama.paciente, + organizacion: { ...this.auth.organizacion }, + ingreso, + idPrestacion: this.capa === 'estadistica-v2' ? this.informeEstadistica.id : undefined + }); + + createAction.pipe( + switchMap(internacion => { + if (!internacion.id) { + throw new Error(); + } + this.cama.idInternacion = internacion.id; + return this.mapaCamasService.save(this.cama, this.informeIngreso.fechaIngreso); + }) + ).subscribe(camaEstado => { + if (camaEstado?.id) { + this.plex.info('success', 'Paciente internado'); + this.mapaCamasService.setFecha(this.informeIngreso.fechaIngreso); + this.selectCama(camaEstado); + this.onSave.emit(); + } else { + this.plex.info('warning', 'Ocurrió un error realizando el ingreso. Por favor revise los movimientos y de ser necesario anule la internación.', 'Atención'); + } + this.disableButton = false; + }, () => { + this.plex.info('warning', 'Ocurrió un error realizando el ingreso. Por favor revise los movimientos y de ser necesario anule la internación.', 'Atención'); + this.disableButton = false; + }); + } } } - ingresoExtendido(paciente) { // construimos el informe de ingreso this.informeIngreso.situacionLaboral = (this.informeIngreso.situacionLaboral) ? this.informeIngreso.situacionLaboral.nombre : null; this.informeIngreso.nivelInstruccion = ((typeof this.informeIngreso.nivelInstruccion === 'string')) ? this.informeIngreso.nivelInstruccion : (Object(this.informeIngreso.nivelInstruccion).nombre); this.informeIngreso.asociado = ((typeof this.informeIngreso.asociado === 'string')) ? this.informeIngreso.asociado : (Object(this.informeIngreso.asociado).nombre); - this.informeIngreso.origen = ((typeof this.informeIngreso.origen === 'string')) ? this.informeIngreso.origen : (Object(this.informeIngreso.origen).nombre); - // Verificamos si es de origen externo + const origenAntiguo: string | { [key: string]: any } = (this.informeIngreso as any).origen; + + if (origenAntiguo) { + if (typeof origenAntiguo === 'string') { + this.informeIngreso.origen = { + tipo: null, + organizacionOrigen: null, + otraOrganizacion: origenAntiguo + }; + } else { + this.informeIngreso.origen = { + tipo: origenAntiguo.tipo || null, + organizacionOrigen: origenAntiguo.organizacionOrigen || null, + otraOrganizacion: origenAntiguo.otraOrganizacion || null + }; + } + } else { + this.informeIngreso.origen = { + tipo: null, + organizacionOrigen: null, + otraOrganizacion: null + }; + } if (this.origenExterno && !this.check) { - this.informeIngreso.organizacionOrigen = { - id: this.informeIngreso.organizacionOrigen.id, - nombre: this.informeIngreso.organizacionOrigen.nombre + this.informeIngreso.origen = this.informeIngreso.origen || { + tipo: null, + organizacionOrigen: null, + otraOrganizacion: null + }; + + this.informeIngreso.origen.organizacionOrigen = { + id: this.informeIngreso.organizacionOrigen?.id || this.informeIngreso.origen.organizacionOrigen?.id, + nombre: this.informeIngreso.organizacionOrigen?.nombre || this.informeIngreso.origen.organizacionOrigen?.nombre }; } - this.informeIngreso.PaseAunidadOrganizativa = this.informeIngreso.PaseAunidadOrganizativa; - if (!this.informeIngreso.asociado && this.informeIngreso.obraSocial) { - delete this.informeIngreso.obraSocial; - } if (this.informeIngreso.asociado === 'Plan o Seguro público') { - this.informeIngreso.obraSocial = null; + + if (this.informeIngreso.origen?.tipo && typeof this.informeIngreso.origen.tipo !== 'string') { + this.informeIngreso.origen.tipo = this.informeIngreso.origen.tipo.nombre || null; + } + this.informeIngreso.paseAunidadOrganizativa = this.informeIngreso.paseAunidadOrganizativa; + + if (!this.informeIngreso.cobertura?.tipo && this.informeIngreso.cobertura?.obraSocial) { + this.informeIngreso.cobertura.obraSocial = null; + } + + if (this.informeIngreso.cobertura?.tipo === 'Plan o Seguro público') { + this.informeIngreso.cobertura.obraSocial = null; } else { - this.informeIngreso.obraSocial = this.paciente.obraSocial || this.financiador; + this.informeIngreso.cobertura.obraSocial = this.paciente.obraSocial || this.financiador; } if (this.paciente.fechaNacimiento) { this.informeIngreso.edadAlIngreso = this.mapaCamasService.calcularEdad(this.paciente.fechaNacimiento, this.informeIngreso.fechaIngreso); } - if (this.capa === 'estadistica') { - this.crearInformeEstadistica(paciente);// 👈 Nuevo flujo - } else if (this.prestacion) { - this.actualizarPrestacion(paciente); + if (this.informeEstadistica) { + // Si ya existe un informe estadístico, lo actualiza + this.actualizarInformeEstadistica(paciente); } else { - this.crearPrestacion(paciente); + // Si no existe ni informe ni prestación, crea una nueva prestación + this.crearInformeEstadistico(paciente); } + + + } + + actualizarInformeEstadistica(paciente) { + const cambios = { + op: 'update', + paciente: this.paciente, + informeIngreso: this.informeIngreso, + }; + + this.informeEstadisticaService.patch(this.informeEstadistica.id, cambios).subscribe({ + next: (informeActualizado: any) => { + this.informeIngreso = informeActualizado.informeIngreso; + this.mapaCamasService.selectInformeEstadistica(informeActualizado); + this.ingresoSimplificado('ocupada', paciente, informeActualizado._id); + }, + error: (err) => { + this.plex.info('danger', 'Error al actualizar informe estadístico'); + } + }); } actualizarPrestacion(paciente) { @@ -629,16 +718,17 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { }); } - crearPrestacion(paciente) { - const nuevaPrestacion = this.datosBasicosPrestacion(); - this.servicioPrestacion.post(nuevaPrestacion).subscribe(prestacion => { + crearInformeEstadistico(paciente) { + const nuevoInforme = this.datosBasicosInformeEstad(); + + this.informeEstadisticaService.post(nuevoInforme).subscribe(informeEstadistica => { if (this.cama) { if (this.capa === 'estadistica') { - this.ingresoSimplificado('ocupada', paciente, prestacion.id); + this.ingresoSimplificado('ocupada', paciente, informeEstadistica.id); } else { // capa estadistica-v2 usa como idInternacion el id del resumen, por tanto primero hay que crearlo - this.ingresoSimplificado('ocupada', paciente, null, prestacion); + this.ingresoSimplificado('ocupada', paciente, null, informeEstadistica); } } else if (this.capa === 'estadistica') { this.plex.info('warning', 'Paciente ingresado a lista de espera'); @@ -648,44 +738,6 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { this.plex.info('danger', 'ERROR: La prestación no pudo ser registrada'); }); } - - crearInformeEstadistica(paciente) { - const nuevoInforme: IInformeEstadistica = { - paciente, - unidadOrganizativa: this.cama?.unidadOrganizativa, - organizacion: this.auth.organizacion, - informeIngreso: this.informeIngreso, - estados: [{ tipo: 'ejecucion' }] - }; - - this.InformeEstadisticaService.post(nuevoInforme).subscribe({ - next: (informe) => { - // 🔗 Vinculamos el informe con un resumen de internación - this.internacionResumenService.create({ - ambito: 'internacion', - fechaIngreso: this.informeIngreso.fechaIngreso, - paciente: paciente, - organizacion: this.auth.organizacion, - idInformeEstadistica: informe._id - }).subscribe({ - next: (resumen) => { - if (this.cama) { - this.ingresoSimplificado('ocupada', paciente, resumen.id, informe); - } else { - console.warn('⚠️ Paciente ingresado en lista de espera (sin cama asignada)'); - this.plex.info('warning', 'Paciente ingresado en lista de espera (sin cama asignada)'); - } - }, - error: (err) => { - this.plex.info('danger', 'ERROR: No se pudo crear el resumen de internación'); - } - }); - }, - error: (err) => { - this.plex.info('danger', 'ERROR: El informe no pudo ser registrado'); - } - }); - } // Inicializa una prestación con todos sus datos básicos datosBasicosPrestacion() { // armamos el elemento data a agregar al array de registros @@ -709,6 +761,35 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { return nuevaPrestacion; } + datosBasicosInformeEstad(): IInformeEstadistica { + const nuevoInforme: IInformeEstadistica = { + id: null as any, + organizacion: this.auth.organizacion, + unidadOrganizativa: this.cama.unidadOrganizativa, + paciente: this.paciente, + informeIngreso: this.informeIngreso, + estados: [{ + tipo: 'ejecucion', + createdAt: new Date(), + createdBy: this.informeIngreso.profesional + }], + createdAt: new Date(), + createdBy: { + id: this.informeIngreso.profesional.id, + nombreCompleto: this.informeIngreso.profesional.nombre + ' ' + this.informeIngreso.profesional.apellido, + nombre: this.informeIngreso.profesional.nombre, + apellido: this.informeIngreso.profesional.apellido, + username: this.informeIngreso.profesional.documento, + documento: this.informeIngreso.profesional.documento, + organizacion: this.auth.organizacion as unknown as IOrganizacion + + } + }; + + return nuevoInforme; + } + + // Crea o actualiza una prestación de internación completarIngreso(paciente) { if (!this.prestacion) { @@ -808,46 +889,32 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { createFormularioDinamico(cama: ISnapshot, estado: any) { this.conceptObserverService.destroy(); - const molecula = estado.ingresos && estado.ingresos[cama.id as string]; if (!molecula) { this.elementoRUP = null; this.prestacionFake = null; return; } + this.elementoRUP = molecula; const elementoRUP = this.elementosRUPService.getById(molecula); - if (this.capa === 'estadistica') { - this.prestacionFake = { - paciente: this.paciente, + + this.prestacionFake = { + paciente: this.paciente, + solicitud: { + tipoPrestacion: {}, organizacion: { ...this.auth.organizacion }, - unidadOrganizativa: this.cama.unidadOrganizativa, - informeIngreso: this.informeIngreso, - estados: [{ tipo: 'ejecucion' }], - ejecucion: { registros: [] } - }; - } else { - this.prestacionFake = { - paciente: this.paciente, - solicitud: { - tipoPrestacion: {}, - organizacion: { ...this.auth.organizacion }, - profesional: {} - }, - ejecucion: { - organizacion: { ...this.auth.organizacion }, - registros: [], - } - }; - } + profesional: {} + }, + ejecucion: { + organizacion: { ...this.auth.organizacion }, + registros: [], + } + }; for (const elementoRequerido of elementoRUP.requeridos) { const elementoRUP_ = this.elementosRUPService.buscarElemento(elementoRequerido.concepto, false); - const nuevoRegistro = new IPrestacionRegistro( - elementoRUP_, - elementoRequerido.concepto, - this.prestacionFake - ); + const nuevoRegistro = new IPrestacionRegistro(elementoRUP_, elementoRequerido.concepto, this.prestacionFake); this.prestacionFake.ejecucion.registros.push(nuevoRegistro); } } @@ -909,23 +976,22 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { public setFinanciador(financiador) { this.financiador = financiador; } - onAsociadoChange(asociado) { + onAsociadoChange(asociado: any) { this.informeIngreso.asociado = asociado; this.changeTipoObraSocial(); + if (asociado?.id === 'Plan de salud privado o Mutual' || asociado === 'Plan de salud privado o Mutual') { + this.selectedOS = true; + } else { + this.selectedOS = false; + } } - onFinanciadorChange(financiadorSeleccionado) { - this.financiador = financiadorSeleccionado; - if (this.paciente.obraSocial) { - this.paciente.obraSocial.financiador = financiadorSeleccionado.financiador; - this.paciente.obraSocial.codigoPuco = financiadorSeleccionado.codigoPuco; - this.paciente.obraSocial.nombre = financiadorSeleccionado.nombre; - } else { - this.paciente.obraSocial = { - codigoPuco: financiadorSeleccionado.codigoPuco, - nombre: financiadorSeleccionado.nombre, - financiador: financiadorSeleccionado.financiador - }; + + onFinanciadorChange(financiador: any) { + this.financiador = financiador; + if (!this.informeIngreso.cobertura) { + this.informeIngreso.cobertura = { tipo: null, obraSocial: null }; } + this.informeIngreso.cobertura.obraSocial = financiador; } } diff --git a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts index b32b4474ed..d4c14d7587 100644 --- a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts +++ b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts @@ -26,11 +26,7 @@ export interface IInformeIngreso { paseAunidadOrganizativa?: string; cobertura?: { tipo?: string; - obraSocial?: { - codigoPuco?: number; - nombre?: string; - financiador?: string; - }; + obraSocial?: IObraSocial; }; createdAt?: Date; createdBy?: { @@ -44,6 +40,12 @@ export interface IInformeIngreso { }; } +export interface IObraSocial { + nombre: string; + financiador: string; + codigoPuco?: number; // Nota: ES OPCIONAL +} + export interface IInformeEgreso { fechaEgreso?: Date; procedimientosQuirurgicos?: { @@ -95,12 +97,8 @@ export interface IInternacionEstado { } export interface IInformeEstadistica { - _id?: string; - organizacion: { - id: string; - nombre: string; - [key: string]: any; - }; + id: string; + organizacion: Partial; unidadOrganizativa: ISnomedConcept; paciente: IPaciente; informeIngreso: IInformeIngreso; @@ -117,6 +115,7 @@ export interface IInformeEstadistica { apellido: string; username: string | number; documento: string | number; - organizacion: IOrganizacion; + organizacion: Partial; }; } + diff --git a/src/app/modules/rup/services/informe-estadistica.service.ts b/src/app/modules/rup/services/informe-estadistica.service.ts index 5f98bea2ee..b1682358cf 100644 --- a/src/app/modules/rup/services/informe-estadistica.service.ts +++ b/src/app/modules/rup/services/informe-estadistica.service.ts @@ -2,28 +2,69 @@ import { Injectable } from '@angular/core'; import { Server } from '@andes/shared'; import { Observable } from 'rxjs'; import { IInformeEstadistica } from '../interfaces/informe-estadistica.interface'; +import { HUDSService } from './huds.service'; @Injectable({ providedIn: 'root' }) export class InformeEstadisticaService { + // URL base para el servicio de informe estadístico private baseUrl = '/modules/rup/internacion/informe-estadistica'; + // Añadimos la URL base del servicio de Prestaciones, donde residen los endpoints de HUDS (Historial Único de Salud). + private prestacionesBaseUrl = '/modules/rup/prestaciones'; - constructor(private server: Server) { } + constructor(private server: Server, + private hudsService: HUDSService + ) { } + // Obtiene una lista de informes estadísticos con filtros opcionales get(params?: any): Observable { return this.server.get(this.baseUrl, { params }); } - getById(id: string): Observable { - return this.server.get(`${this.baseUrl}/${id}`); + // Obtiene un informe estadístico por su ID + getById(id: string, options: any = {}): Observable { + if (typeof options.showError === 'undefined') { + options.showError = true; + } + const url = `${this.baseUrl}/${id}`; + return this.server.get(url, options); } post(data: IInformeEstadistica): Observable { return this.server.post(this.baseUrl, data); } + patch(id: string, data: Partial): Observable { + return this.server.patch(`${this.baseUrl}/${id}`, data); + } + put(id: string, data: IInformeEstadistica): Observable { return this.server.put(`${this.baseUrl}/${id}`, data); } + + // Este método está corregido para usar la URL de Prestaciones. + getRegistrosHuds(idPaciente: string, expresion, deadLine = null, valor = null, searchTerm = null, form = null) { + const hudsToken = this.hudsService.getHudsToken(); + const urlPeticion = this.prestacionesBaseUrl + '/huds/' + idPaciente; + + const opt = { + params: { + valor, + expresion, + searchTerm, + form, + deadLine, + hudsToken: hudsToken + }, + options: { + } + }; + // IMPORTANTE: Usamos la URL base de Prestaciones para acceder a los registros HUDS + return this.server.get(urlPeticion, opt); + } + + search(params?: any): Observable { + return this.server.get(this.baseUrl, { params }); + } } From 236f99e753fd3c76e11e9ba7b0bc32b3c2e3d6ee Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Mon, 3 Nov 2025 13:38:20 -0300 Subject: [PATCH 04/14] feat(IN-665)="Modificar listado de internacion en base al nuevo squema y la nueva api" --- .../mapa-camas/services/mapa-camas.http.ts | 5 +- .../mapa-camas/services/mapa-camas.service.ts | 50 ++- .../listado-internacion.component.html | 221 +++++++------ .../listado-internacion.component.ts | 295 ++++++------------ .../listado-internacion.service.ts | 82 ++++- 5 files changed, 328 insertions(+), 325 deletions(-) diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.http.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.http.ts index e1590ddb4c..e698cccdd3 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.http.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.http.ts @@ -1,6 +1,7 @@ +/* eslint-disable no-console */ import { Injectable } from '@angular/core'; import { Server } from '@andes/shared'; -import { Observable } from 'rxjs'; +import { Observable, tap } from 'rxjs'; import { ISnapshot } from '../interfaces/ISnapshot'; import { ICama } from '../interfaces/ICama'; @@ -135,6 +136,6 @@ export class MapaCamasHTTP { } getPrestacionesInternacion(params: any): Observable { - return this.server.get(`${this.url}/prestaciones`, { params: params, showError: true }); + return this.server.get(`${this.url}/informe-estadistica`, { params: params, showError: true }); } } diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts index b43ce39087..d883ca1f52 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts @@ -181,7 +181,7 @@ export class MapaCamasService { // Devuelve la prestación que contiene el informe de ingreso this.prestacion$ = combineLatest([ - this.selectedPrestacion, + this.selectedInformeEstadistica, this.selectedCama, this.view, this.capa2 @@ -281,7 +281,7 @@ export class MapaCamasService { } // Para conseguir la cama de la internación desde el listado return combineLatest([ - this.selectedPrestacion, + this.selectedInformeEstadistica, this.selectedResumen ]).pipe( switchMap(([prestacion, resumen]) => { @@ -584,6 +584,38 @@ export class MapaCamasService { return listaInternacionFiltrada; } + filtrarInformesEstadistica( + listaInformes: IInformeEstadistica[], + documento?: string, + apellido?: string, + estado?: string + ): IInformeEstadistica[] { + let listaFiltrada = listaInformes; + + if (documento) { + const doc = documento.toLowerCase(); + listaFiltrada = listaFiltrada.filter((informe: IInformeEstadistica) => + informe.paciente?.documento?.toLowerCase().includes(doc) || + informe.paciente?.numeroIdentificacion?.toLowerCase().includes(doc) + ); + } + + if (apellido) { + const ape = apellido.toLowerCase(); + listaFiltrada = listaFiltrada.filter((informe: IInformeEstadistica) => + informe.paciente?.apellido?.toLowerCase().includes(ape) + ); + } + + if (estado) { + listaFiltrada = listaFiltrada.filter((informe: IInformeEstadistica) => + informe.estadoActual?.tipo === estado + ); + } + + return listaFiltrada; + } + snapshot(fecha, idInternacion = null, ambito: string = null, capa: string = null, estado: string = null): Observable { ambito = ambito || this.ambito; capa = capa || this.capa; @@ -599,11 +631,11 @@ export class MapaCamasService { this.ambito2, this.capa2, this.selectedCama, - this.selectedPrestacion, + this.selectedInformeEstadistica, this.selectedResumen, this.view ]).pipe( - switchMap(([ambito, capa, selectedCama, selectedPrestacion, selectedResumen, view]) => { + switchMap(([ambito, capa, selectedCama, selectedInformeEstadistica, selectedResumen, view]) => { hasta = hasta || new Date(); if (type === 'cama') { return this.camasHTTP.historial(ambito, capa, desde, hasta, { idCama: cama ? cama.idCama : selectedCama.idCama }); @@ -614,11 +646,13 @@ export class MapaCamasService { } else if (view === 'listado-internacion') { if (!desde) { - desde = selectedPrestacion ? selectedPrestacion.solicitud.fecha : selectedResumen.fechaIngreso; + desde = selectedInformeEstadistica ? selectedInformeEstadistica.informeIngreso.fechaIngreso : selectedResumen.fechaIngreso; + } - if (this.capa === 'estadistica' && selectedPrestacion.id) { - desde = [desde, selectedPrestacion.solicitud.fecha].sort((a, b) => moment(a).diff(moment(b)))[0]; - return this.camasHTTP.historialInternacion(ambito, capa, desde, hasta, selectedPrestacion.id); + if (this.capa === 'estadistica' && selectedInformeEstadistica.id) { + desde = [desde, selectedInformeEstadistica.informeIngreso.fechaIngreso].sort((a, b) => moment(a).diff(moment(b)))[0]; + + return this.camasHTTP.historialInternacion(ambito, capa, desde, hasta, selectedInformeEstadistica.id); } if (selectedResumen._id) { desde = [desde, selectedResumen.fechaIngreso].sort((a, b) => moment(a).diff(moment(b)))[0]; diff --git a/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.html b/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.html index f5c0b2b82f..15a81cde84 100644 --- a/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.html +++ b/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.html @@ -1,110 +1,125 @@ - - - -
- - - -
+ + - - + -
- - - -
+
+ + + +
-
- - -
+ - -
- - -
- - - - - - {{ internacion.paciente | nombre }} - - - {{ internacion.paciente | documento }} - - - - {{internacion.ejecucion?.registros[0]?.valor?.informeIngreso?.motivo}} - - - - {{ devuelveFecha(internacion,"ingreso") | fecha }} - {{ devuelveFecha(internacion,"ingreso") | hora }} - - - - {{ fechaEgreso | fecha }} - {{ fechaEgreso | hora }} - - - - {{ internacion.paciente.obraSocial?.nombre }} - - - {{ internacion.unidadOrganizativa?.term }} - - - {{internacion.estadoActual.tipo }} - - - -
-
+ - - - - - - +
+ + + +
-
+
+ + +
- - - - - - - - - - - - - - - - - - -
-
\ No newline at end of file + +
+ + +
+ + + + + + {{ internacion.paciente | nombre }} + {{ internacion.paciente | documento }} + + + {{ internacion.informeIngreso.motivo }} + + + + {{ devuelveFecha(internacion, 'ingreso') | fecha }} + {{ devuelveFecha(internacion, 'ingreso') | hora }} + + + + {{ fechaEgreso | fecha }} + {{ fechaEgreso | hora }} + + + + {{ internacion.paciente.obraSocial?.nombre }} + + + {{ internacion.unidadOrganizativa?.term }} + + + {{ internacion.estadoActual?.tipo }} + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.ts b/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.ts index ecc0cd51c6..98931f84f6 100644 --- a/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.ts +++ b/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.ts @@ -2,136 +2,101 @@ import { Component, OnInit } from '@angular/core'; import { Location } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; import { Plex } from '@andes/plex'; -import { snomedIngreso, snomedEgreso } from '../../constantes-internacion'; -import { PrestacionesService } from '../../../../../modules/rup/services/prestaciones.service'; -import { MapaCamasService } from '../../services/mapa-camas.service'; -import { IPrestacion } from '../../../../../modules/rup/interfaces/prestacion.interface'; +import { map } from 'rxjs/operators'; import { Observable } from 'rxjs'; +import { Auth } from '@andes/auth'; + +import { MapaCamasService } from '../../services/mapa-camas.service'; import { ListadoInternacionService } from './listado-internacion.service'; import { IngresoPacienteService } from '../../sidebar/ingreso/ingreso-paciente-workflow/ingreso-paciente-workflow.service'; -import { map } from 'rxjs/operators'; import { PermisosMapaCamasService } from '../../services/permisos-mapa-camas.service'; -import { Auth } from '@andes/auth'; +import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; @Component({ selector: 'app-internacion-listado', templateUrl: './listado-internacion.component.html', }) - export class InternacionListadoComponent implements OnInit { - listaInternacion$: Observable; - selectedPrestacion$: Observable; + listaInternacion$: Observable; + selectedInforme$: Observable; + + + fechaIngresoHasta$ = this.listadoInternacionService.fechaIngresoHasta; mainView$ = this.mapaCamasService.mainView; - // VARIABLES public mostrar = 'datosInternacion'; public cambiarUO = false; public puedeValidar = false; public puedeRomper = false; public editando = false; public estaBuscando = false; + public columns = [ - { // prioriza nombre autopercibido en caso de tener + { key: 'apellido-nombre', label: 'Apellido y nombre', sorteable: true, opcional: false, - sort: (a, b) => { - const aNombre = a.paciente.alias || a.paciente.nombre; - const bNombre = b.paciente.alias || b.paciente.nombre; - return (a.paciente.apellido + aNombre).localeCompare(b.paciente.apellido + bNombre); - } + sort: (a, b) => (a.paciente.apellido + a.paciente.nombre).localeCompare(b.paciente.apellido + b.paciente.nombre) }, { key: 'documento', label: 'Documento', sorteable: true, opcional: false, - sort: (a, b) => { - const aDocumento = a.paciente.documento || a.paciente.numeroIdentificacion; - const bDocumento = b.paciente.documento || b.paciente.numeroIdentificacion; - return aDocumento.localeCompare(bDocumento); - } + sort: (a, b) => (a.paciente.documento || '').localeCompare(b.paciente.documento || '') }, { key: 'diagnostico', - label: 'Motivo Ingreso', + label: 'Motivo ingreso', sorteable: true, opcional: true, - sort: (a: any, b: any) => { - const nameA = a.ejecucion?.registros[0]?.valor?.informeIngreso?.motivo || ''; - const nameB = b.ejecucion?.registros[0]?.valor?.informeIngreso?.motivo || ''; - return nameA.localeCompare(nameB); - } + sort: (a, b) => (a.informeIngreso?.motivo || '').localeCompare(b.informeIngreso?.motivo || '') }, { key: 'fechaIngreso', label: 'Fecha de ingreso', sorteable: true, opcional: false, - sort: (a, b) => { - const fecha1 = moment(this.devuelveFecha(a, 'ingreso')); - const fecha2 = moment(this.devuelveFecha(b, 'ingreso')); - return fecha1.diff(fecha2); - } + sort: (a, b) => moment(a.informeIngreso?.fechaIngreso).diff(moment(b.informeIngreso?.fechaIngreso)) }, { key: 'fechaEgreso', label: 'Fecha de egreso', sorteable: true, opcional: false, - sort: (a, b) => { - let fecha1 = this.devuelveFecha(a, 'egreso'); - let fecha2 = this.devuelveFecha(b, 'egreso'); - if (fecha1) { - fecha1 = moment(fecha1); - if (fecha2) { - fecha2 = moment(fecha2); - return fecha1.diff(fecha2); - } else { - return 1; - } - } - return -1; - } + sort: (a, b) => moment(a.informeEgreso?.fechaEgreso).diff(moment(b.informeEgreso?.fechaEgreso)) }, { key: 'obraSocial', label: 'Obra social', sorteable: true, opcional: false, - sort: (a, b) => { - const p1 = a.paciente.obraSocial?.nombre || ''; - const p2 = b.paciente.obraSocial?.nombre || ''; - return p1.localeCompare(p2); - } + sort: (a, b) => (a.obraSocial?.nombre || '').localeCompare(b.obraSocial?.nombre || '') }, { key: 'unidadOrganizativa', label: 'Unidad organizativa', sorteable: true, opcional: false, - sort: (a, b) => { - return a.unidadOrganizativa.term.localeCompare(b.unidadOrganizativa.term); - } + sort: (a, b) => (a.unidadOrganizativa?.term || '').localeCompare(b.unidadOrganizativa?.term || '') }, { key: 'estado', label: 'Estado', sorteable: true, opcional: false, - sort: (a, b) => { - return a.estadoActual.tipo.localeCompare(b.estadoActual.tipo); - } + sort: (a, b) => (a.estadoActual?.tipo || '').localeCompare(b.estadoActual?.tipo || '') } ]; constructor( private plex: Plex, private location: Location, - private prestacionService: PrestacionesService, - public mapaCamasService: MapaCamasService, + private informeEstadisticaService: InformeEstadisticaService, + private mapaCamasService: MapaCamasService, private listadoInternacionService: ListadoInternacionService, private ingresoPacienteService: IngresoPacienteService, private permisosMapaCamasService: PermisosMapaCamasService, @@ -141,99 +106,92 @@ export class InternacionListadoComponent implements OnInit { ) { } ngOnInit() { - // verificamos permisos + const capa = this.route.snapshot.paramMap.get('capa'); const permisosInternacion = this.auth.getPermissions('internacion:rol:?'); - if (permisosInternacion.length >= 1 && (permisosInternacion.indexOf(capa) !== -1 || permisosInternacion[0] === '*')) { + + if (permisosInternacion.length >= 1 && (permisosInternacion.includes(capa) || permisosInternacion[0] === '*')) { this.mapaCamasService.setCapa(capa); } else { this.router.navigate(['/inicio']); } + this.mapaCamasService.setAmbito('internacion'); this.permisosMapaCamasService.setAmbito('internacion'); this.mapaCamasService.setView('listado-internacion'); - this.mapaCamasService.select({ id: ' ' } as any); // Pequeño HACK - this.plex.updateTitle([{ - route: '/inicio', - name: 'Andes' - }, { - name: 'Internacion' - }, { - name: 'Listado de Internacion' - }]); + this.mapaCamasService.select({ id: ' ' } as any); + + this.plex.updateTitle([ + { route: '/inicio', name: 'Andes' }, + { name: 'Internación' }, + { name: 'Listado de Internación' } + ]); + + this.listaInternacion$ = this.listadoInternacionService.listaInternacionFiltrada$.pipe( + map((res: any) => { + // Si res es un objeto, intentamos extraer el array + if (Array.isArray(res)) { + return res; + } else if (Array.isArray(res?.data)) { + return res.data; + } else if (Array.isArray(res?.listaInternacion)) { + return res.listaInternacion; + } else { + console.warn('⚠️ listaInternacionFiltrada$ no devolvió un array. Valor recibido:', res); + return []; + } + }) + ); - this.selectedPrestacion$ = this.mapaCamasService.selectedPrestacion.pipe( - map(prestacion => { - this.puedeValidar = false; - this.puedeRomper = false; - if (prestacion?.ejecucion?.registros[1] && prestacion.ejecucion.registros[1].valor?.InformeEgreso) { - const informeEgreso = prestacion.ejecucion.registros[1].valor.InformeEgreso; - this.puedeValidar = prestacion.estados[prestacion.estados.length - 1].tipo !== 'validada' && - informeEgreso.fechaEgreso && - informeEgreso.tipoEgreso && - informeEgreso.diagnosticoPrincipal; - this.puedeRomper = (prestacion.ejecucion && prestacion.ejecucion.registros[1] && prestacion.estados[prestacion.estados.length - 1].tipo === 'validada'); + this.selectedInforme$ = this.mapaCamasService.selectedInformeEstadistica.pipe( + map((prestacion: any) => { + const informe = prestacion as IInformeEstadistica; + + if (informe) { + this.puedeValidar = !!( + informe.informeEgreso?.fechaEgreso && + informe.informeEgreso?.tipoEgreso && + informe.informeEgreso?.diagnosticos?.principal + ); + this.puedeRomper = informe.estadoActual?.tipo === 'validada'; } - return prestacion; + return informe; }) ); - this.listaInternacion$ = this.listadoInternacionService.listaInternacionFiltrada$; } - devuelveFecha(internacion, tipo) { - const informe = this.verRegistro(internacion, tipo); - if (tipo === 'ingreso') { - return informe.informeIngreso.fechaIngreso; - } else { - return informe ? informe.InformeEgreso.fechaEgreso : null; - - } + devuelveFecha(internacion: IInformeEstadistica, tipo: 'ingreso' | 'egreso') { + return tipo === 'ingreso' ? internacion.informeIngreso?.fechaIngreso : internacion.informeEgreso?.fechaEgreso || null; } - verRegistro(prestacion, tipoRegistro) { - let registro = null; - if (tipoRegistro === 'ingreso') { - registro = prestacion.ejecucion.registros.find(r => r.concepto.conceptId === snomedIngreso.conceptId); - } - if (tipoRegistro === 'egreso') { - registro = prestacion.ejecucion.registros.find(r => r.concepto.conceptId === snomedEgreso.conceptId); - } - - if (registro) { - return registro.valor; + seleccionarInforme(informe: IInformeEstadistica, selected: IInformeEstadistica) { + if (this.mostrar === 'datosInternacion') { + if (selected?.id === informe.id) { + this.mapaCamasService.selectInformeEstadistica(null); + this.mapaCamasService.select(null); + } else { + this.mapaCamasService.selectInformeEstadistica(informe); + this.mapaCamasService.setFecha(informe.informeIngreso?.fechaIngreso); + this.ingresoPacienteService.selectPaciente(informe.paciente.id); + this.mapaCamasService.isLoading(true); + } } - return null; } - seleccionarPrestacion(prestacion, selectedPrestacion) { + seleccionarPrestacion(informe: IInformeEstadistica, selected: IInformeEstadistica) { if (this.mostrar === 'datosInternacion') { - if (selectedPrestacion._id === prestacion._id) { - this.mapaCamasService.selectPrestacion(null); + if (selected?.id === informe.id) { + this.mapaCamasService.selectInformeEstadistica(null); this.mapaCamasService.select(null); } else { - this.mapaCamasService.selectPrestacion(prestacion); - this.mapaCamasService.setFecha(prestacion.ejecucion.registros[0].valor.informeIngreso.fechaIngreso); - this.ingresoPacienteService.selectPaciente(prestacion.paciente.id); - this.verificarPrestacion(prestacion); + this.mapaCamasService.selectInformeEstadistica(informe); + this.mapaCamasService.setFecha(informe.informeIngreso?.fechaIngreso); + this.ingresoPacienteService.selectPaciente(informe.paciente.id); this.mapaCamasService.isLoading(true); } } } - cancelar() { - this.mapaCamasService.selectPrestacion(null); - this.mostrar = 'datosInternacion'; - } - - volver() { - this.mapaCamasService.selectPrestacion(null); - this.location.back(); - } - - cambiarCama() { - this.mostrar = 'desocuparCama'; - } - refresh() { this.listadoInternacionService.refresh.next(true); this.volverADetalle(); @@ -243,83 +201,28 @@ export class InternacionListadoComponent implements OnInit { this.mostrar = 'datosInternacion'; } - accionDesocupar(accion) { - this.mostrar = 'cambiarCama'; - this.cambiarUO = accion.cambiarUO; - } - - verificarPrestacion(prestacion: IPrestacion) { - this.puedeValidar = false; - this.puedeRomper = false; - if (prestacion.ejecucion) { - if (prestacion.ejecucion.registros[1]) { - if (prestacion.estados[prestacion.estados.length - 1].tipo !== 'validada') { - const informeEgreso = prestacion.ejecucion.registros[1].valor.InformeEgreso; - if (informeEgreso) { - if (informeEgreso.fechaEgreso && informeEgreso.tipoEgreso && informeEgreso.diagnosticoPrincipal) { - this.puedeValidar = true; - } - } - } else { - this.puedeRomper = true; - } - } - } - } - - onAccion($event) { - this.editando = $event?.accion === 'editando'; + volver() { + this.mapaCamasService.selectInformeEstadistica(null); + this.location.back(); } - validar(selectedPrestacion: IPrestacion) { - this.plex.confirm('Luego de validar la prestación ya no podrá editarse.
¿Desea continuar?', 'Confirmar validación').then(validar => { - if (validar) { - if (selectedPrestacion.ejecucion.registros[1]) { - const egresoExiste = selectedPrestacion.ejecucion.registros[1].valor; - if (egresoExiste && selectedPrestacion.estados[selectedPrestacion.estados.length - 1].tipo !== 'validada') { - if (egresoExiste.InformeEgreso.fechaEgreso && egresoExiste.InformeEgreso.tipoEgreso && - egresoExiste.InformeEgreso.diagnosticoPrincipal) { - this.prestacionService.validarPrestacion(selectedPrestacion).subscribe({ - next: prestacion => { - this.mapaCamasService.selectPrestacion(prestacion); - this.verificarPrestacion(prestacion); - this.listadoInternacionService.refresh.next(true); - }, - error: () => this.plex.info('danger', 'ERROR: No es posible validar la prestación') - }); - } else { - this.plex.info('danger', 'ERROR: Faltan datos'); - } - } else { - this.plex.info('danger', 'ERROR: Debe completar los datos mínimos de egreso para validar la internación'); - } - } - } - }); - } + buscando(valor: any) { + this.estaBuscando = true; - romperValidacion(selectedPrestacion: IPrestacion,) { - this.plex.confirm('Esta acción puede traer consecuencias
¿Desea continuar?', 'Romper validación').then(validar => { - if (validar) { - // hacemos el patch y luego creamos los planes - const cambioEstado: any = { - op: 'romperValidacion', - desdeInternacion: true - }; - // En api el estado de la prestación cambia a ejecucion - this.prestacionService.patch(selectedPrestacion.id, cambioEstado).subscribe({ - next: prestacion => { - this.mapaCamasService.selectPrestacion(prestacion); - this.verificarPrestacion(prestacion); - this.listadoInternacionService.refresh.next(true); - }, - error: () => this.plex.toast('danger', 'ERROR: No es posible romper la validación de la prestación') - }); + if (typeof valor !== 'object') { + console.warn('⚠️ Valor no válido para el filtrado:', valor); + this.estaBuscando = false; + return; + } + this.listadoInternacionService.listaInternacion$.subscribe({ + next: (data) => { + const filtrados = this.listadoInternacionService.filtrarInformesEstadistica(data, valor); + this.estaBuscando = false; + }, + error: (err) => { + this.estaBuscando = false; } }); } - buscando(valor) { - this.estaBuscando = valor; - } } diff --git a/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.service.ts b/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.service.ts index 3459b4d4c1..499cee2e07 100644 --- a/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.service.ts +++ b/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.service.ts @@ -1,15 +1,15 @@ import { Injectable } from '@angular/core'; -import { IPrestacion } from '../../../../../modules/rup/interfaces/prestacion.interface'; -import { Observable, BehaviorSubject, combineLatest, of } from 'rxjs'; +import { Observable, BehaviorSubject, combineLatest } from 'rxjs'; import { switchMap, map, auditTime } from 'rxjs/operators'; import { MapaCamasHTTP } from '../../services/mapa-camas.http'; import { cache } from '@andes/shared'; +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; @Injectable() export class ListadoInternacionService { - public listaInternacion$: Observable; - public listaInternacionFiltrada$: Observable; + public listaInternacion$: Observable; + public listaInternacionFiltrada$: Observable; public pacienteText = new BehaviorSubject(null); public fechaIngresoDesde = new BehaviorSubject(moment().subtract(1, 'months').toDate()); public fechaIngresoHasta = new BehaviorSubject(moment().toDate()); @@ -41,7 +41,6 @@ export class ListadoInternacionService { fechaEgresoHasta, }; return this.mapaHTTP.getPrestacionesInternacion(filtros); - }), cache() ); @@ -54,7 +53,7 @@ export class ListadoInternacionService { this.unidadOrganizativa ]).pipe( map(([listaInternacion, paciente, estado, obraSocial, unidad]) => - this.filtrarListaInternacion(listaInternacion, paciente, estado, obraSocial, unidad) + this.filtrarInformesEstadistica(listaInternacion, { paciente, estado, obraSocial, unidad }) ) ); @@ -64,8 +63,7 @@ export class ListadoInternacionService { this.fechaEgresoDesde, this.fechaEgresoHasta ]).pipe( - map(([ - ingresoDesde, ingresoHasta, egresoDesde, egresoHasta]) => { + map(([ingresoDesde, ingresoHasta, egresoDesde, egresoHasta]) => { return !( (moment(ingresoDesde).isValid() && moment(ingresoHasta).isValid()) || (moment(egresoDesde).isValid() && moment(egresoHasta).isValid()) @@ -86,39 +84,46 @@ export class ListadoInternacionService { ); } - filtrarListaInternacion(listaInternacion: IPrestacion[], paciente: string, estado: string, obraSocial: any, unidad: any) { + // Método viejo + filtrarListaInternacion(listaInternacion: IInformeEstadistica[], paciente: string, estado: string, obraSocial: any, unidad: any) { let listaInternacionFiltrada = listaInternacion; if (paciente) { const esNumero = Number.isInteger(Number(paciente)); if (esNumero) { - listaInternacionFiltrada = listaInternacionFiltrada.filter((internacion: IPrestacion) => + listaInternacionFiltrada = listaInternacionFiltrada.filter((internacion: IInformeEstadistica) => (internacion.paciente.documento?.includes(paciente) || internacion.paciente?.numeroIdentificacion?.includes(paciente))); } else { - listaInternacionFiltrada = listaInternacionFiltrada.filter((internacion: IPrestacion) => (internacion.paciente.nombre.toLowerCase().includes(paciente.toLowerCase()) || + listaInternacionFiltrada = listaInternacionFiltrada.filter((internacion: IInformeEstadistica) => + (internacion.paciente.nombre.toLowerCase().includes(paciente.toLowerCase()) || internacion.paciente.alias?.toLowerCase().includes(paciente.toLowerCase()) || internacion.paciente.apellido.toLowerCase().includes(paciente.toLowerCase())) ); } } + if (estado) { - listaInternacionFiltrada = listaInternacionFiltrada.filter((internacion: IPrestacion) => + listaInternacionFiltrada = listaInternacionFiltrada.filter((internacion: IInformeEstadistica) => internacion.estados[internacion.estados.length - 1].tipo === estado ); } + if (obraSocial) { listaInternacionFiltrada = listaInternacionFiltrada.filter( - (internacion: IPrestacion) => { + (internacion: IInformeEstadistica) => { + const cobertura = internacion.informeIngreso?.cobertura; + const obra = cobertura?.obraSocial; + if (obraSocial._id === 'sin-obra-social') { - return !internacion.paciente.obraSocial; + return !obra; } - return internacion.paciente.obraSocial?.nombre === obraSocial.nombre; + return obra?.nombre === obraSocial.nombre; } ); } if (unidad) { - listaInternacionFiltrada = listaInternacionFiltrada.filter((internacion: IPrestacion) => + listaInternacionFiltrada = listaInternacionFiltrada.filter((internacion: IInformeEstadistica) => internacion.unidadOrganizativa?.term === unidad.term ); } @@ -126,6 +131,51 @@ export class ListadoInternacionService { return listaInternacionFiltrada; } + filtrarInformesEstadistica(informes: any[], filtros: any) { + const { paciente, estado, obraSocial, unidad } = filtros || {}; + + let listaFiltrada = informes; + + if (paciente) { + const esNumero = Number.isInteger(Number(paciente)); + if (esNumero) { + listaFiltrada = listaFiltrada.filter((i) => + i.paciente?.documento?.includes(paciente) || + i.paciente?.numeroIdentificacion?.includes(paciente) + ); + } else { + const valor = paciente.toLowerCase(); + listaFiltrada = listaFiltrada.filter((i) => + i.paciente?.nombre?.toLowerCase().includes(valor) || + i.paciente?.apellido?.toLowerCase().includes(valor) || + i.paciente?.alias?.toLowerCase().includes(valor) + ); + } + } + + if (estado) { + listaFiltrada = listaFiltrada.filter((i) => + i.estados?.[i.estados.length - 1]?.tipo === estado + ); + } + + if (obraSocial) { + listaFiltrada = listaFiltrada.filter((i) => { + if (obraSocial._id === 'sin-obra-social') { + return !i.paciente?.obraSocial; + } + return i.paciente?.obraSocial?.nombre === obraSocial.nombre; + }); + } + if (unidad) { + listaFiltrada = listaFiltrada.filter((i) => + i.unidadOrganizativa?.term === unidad.term + ); + } + return listaFiltrada; + } + + setFechaHasta(fecha: Date) { this.fechaIngresoHasta.next(fecha); } From 73a3335e68d4adbf8ec0a3b9ab19d10a7a64d1cb Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Thu, 6 Nov 2025 10:12:26 -0300 Subject: [PATCH 05/14] feat(IN-663):"Modificar egreso estadistico en base al nuevo esquema utilizando las rutas de informeEstadistico" --- .../mapa-camas/services/mapa-camas.service.ts | 2 +- .../internacion-detalle.component.ts | 37 ++- .../egreso/egresar-paciente.component.html | 154 ++++++------ .../egreso/egresar-paciente.component.ts | 227 ++++++++++++------ .../informe-estadistica.interface.ts | 11 +- 5 files changed, 263 insertions(+), 168 deletions(-) diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts index d883ca1f52..1d572b18af 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts @@ -274,6 +274,7 @@ export class MapaCamasService { cache() ); + this.camaSelectedSegunView$ = this.view.pipe( switchMap(view => { if (view === 'mapa-camas') { @@ -433,7 +434,6 @@ export class MapaCamasService { if (!informe) { return this.selectedInformeEstadistica.next({ id: null } as any); } - this.selectedInformeEstadistica.next(informe); } diff --git a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts index a109eed8b7..58ee95bead 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts @@ -9,7 +9,7 @@ import { PermisosMapaCamasService } from '../../../services/permisos-mapa-camas. import { ListadoInternacionCapasService } from '../../../views/listado-internacion-capas/listado-internacion-capas.service'; import { ListadoInternacionService } from '../../../views/listado-internacion/listado-internacion.service'; import { IngresoPacienteService } from '../../ingreso/ingreso-paciente-workflow/ingreso-paciente-workflow.service'; - +import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; @Component({ selector: 'app-internacion-detalle', templateUrl: './internacion-detalle.component.html', @@ -51,7 +51,8 @@ export class InternacionDetalleComponent implements OnInit, AfterViewChecked { private listadoInternacionCapasService: ListadoInternacionCapasService, private listadoInternacion: ListadoInternacionService, private cdr: ChangeDetectorRef, - private ingresoPacienteService: IngresoPacienteService + private ingresoPacienteService: IngresoPacienteService, + private informeEstadisticaService: InformeEstadisticaService ) { } ngAfterViewChecked() { @@ -91,24 +92,23 @@ export class InternacionDetalleComponent implements OnInit, AfterViewChecked { } ); - this.mapaCamasService.prestacion$.subscribe(prestacion => { - this.estadoPrestacion = ''; - this.existeIngreso = false; + // this.mapaCamasService.prestacion$.subscribe(prestacion => { + // this.estadoPrestacion = ''; + // this.existeIngreso = false; - if (prestacion) { - this.estadoPrestacion = prestacion.estadoActual.tipo; - if (prestacion.ejecucion.registros[0].valor.informeIngreso) { - this.existeIngreso = true; - } - this.existeEgreso = !!prestacion.ejecucion.registros[1]?.valor?.InformeEgreso; - this.editarEgreso = !this.existeEgreso; - this.ingresoPacienteService.selectPaciente(prestacion.paciente?.id); - } - // loading se setea en true desde el listado de internacion - this.mapaCamasService.isLoading(false); - }); + // if (prestacion) { + // this.estadoPrestacion = prestacion.estadoActual.tipo; + // if (prestacion.ejecucion.registros[0].valor.informeIngreso) { + // this.existeIngreso = true; + // } + // this.existeEgreso = !!prestacion.ejecucion.registros[1]?.valor?.InformeEgreso; + // this.editarEgreso = !this.existeEgreso; + // this.ingresoPacienteService.selectPaciente(prestacion.paciente?.id); + // } + // // loading se setea en true desde el listado de internacion + // this.mapaCamasService.isLoading(false); + // }); - // Nueva capa estadística (internacionFormEstadistica) this.mapaCamasService.informeEstadistica$.subscribe(informe => { if (informe?.paciente?.id) { this.ingresoPacienteService.selectPaciente(informe.paciente.id); @@ -117,7 +117,6 @@ export class InternacionDetalleComponent implements OnInit, AfterViewChecked { this.editarEgreso = !informe.informeEgreso; } }); - // Configura los tabs a mostrar según capa y vista this.mapaCamasService.resumenInternacion$.pipe( map(resumen => { diff --git a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html index f939882dd9..6bfef442ab 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html +++ b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html @@ -1,6 +1,6 @@ - @@ -9,15 +9,15 @@ + - - + @@ -52,62 +52,65 @@ - - - - - + - - - - + + + + + + - - - - - - - - - - + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts index a8253a493b..554e0994ef 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts @@ -19,6 +19,8 @@ import { InternacionResumenHTTP } from '../../services/resumen-internacion.http' import { ListadoInternacionService } from '../../views/listado-internacion/listado-internacion.service'; import { ListadoInternacionCapasService } from '../../views/listado-internacion-capas/listado-internacion-capas.service'; import { NgForm } from '@angular/forms'; +import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; @Component({ selector: 'app-egresar-paciente', templateUrl: './egresar-paciente.component.html', @@ -46,6 +48,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { public capa: string; public cama: ISnapshot; public prestacion: IPrestacion; + public informe: IInformeEstadistica; public maquinaEstados: IMaquinaEstados; public estadoDestino; public checkTraslado = false; @@ -67,6 +70,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { valor: { InformeEgreso: { fechaEgreso: null, + diasDeEstada: null, nacimientos: [ { pesoAlNacer: null, @@ -80,11 +84,24 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { producidaPor: null, lugar: null, comoSeProdujo: null + }, + tipoEgreso: { + tipo: null, + OrganizacionDestino: null, + otraOrganizacion: null + }, + diagnosticos: { + principal: null, + secundarios: [], + otrasCircunstancias: null, + diasEstadaOtrasCircunstancias: null, + diasDePermisoDeSalida: null } } } }; + public procedimientosObstetricos = false; public procedimientosObstetricosNoReq = false; public existeCausaExterna = false; @@ -108,6 +125,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { public cie10Service: Cie10Service, private organizacionService: OrganizacionService, private servicioPrestacion: PrestacionesService, + private informeEstadisticaService: InformeEstadisticaService, public mapaCamasService: MapaCamasService, public procedimientosQuirurgicosService: ProcedimientosQuirurgicosService, private listadoInternacionService: ListadoInternacionService, @@ -153,6 +171,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { // else: this.cama tiene valor, el form de egreso es valido y de ser capa estadistica la prestacion no esta validada const condicion = camaActual?.estado === 'disponible' || (camaActual?.estado === 'ocupada' && camaActual?.idInternacion === this.cama?.idInternacion) + || this.informe || this.prestacion; return !condicion; @@ -161,17 +180,20 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { this.registrosEgresoResumen$ = combineLatest([ this.mapaCamasService.capa2, - this.mapaCamasService.prestacion$ + this.mapaCamasService.prestacion$, + this.mapaCamasService.informeEstadistica$ ]).pipe( first(), - switchMap(([capa, prestacion]) => { + switchMap(([capa, prestacion, informe]) => { if (capa === 'estadistica' || (capa === 'estadistica-v2' && this.view === 'mapa-camas')) { - /* Si es capa estadistica va a existir la prestacion pero no el resumen. - Si es capa medica la que realiza el egreso, puede que estadistica-v2 aun no haya cargado el informe de ingreso. - En este caso particular, permitimos el egreso y obtenemos la fecha de ingreso desde el resumen. - */ - const fechaIngreso = prestacion?.ejecucion.registros[0].valor.informeIngreso.fechaIngreso || this.resumen?.fechaIngreso; - const paciente = prestacion?.paciente.id || this.resumen?.paciente.id; + const fechaIngreso = informe?.informeIngreso?.fechaIngreso; + const paciente = informe?.paciente?.id; + + if (!fechaIngreso || !paciente) { + console.warn('⚠️ No hay datos de ingreso en el informe estadístico'); + return of(null); + } + const desde = moment(fechaIngreso).subtract(12, 'hours').toDate(); const hasta = moment(fechaIngreso).add(12, 'hours').toDate(); @@ -186,7 +208,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { ), this.internacionResumenService.search({ organizacion: this.auth.organizacion.id, - paciente: paciente, + paciente, ingreso: this.internacionResumenService.queryDateParams(desde, hasta) }) ]).pipe( @@ -206,45 +228,98 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { cache() ); + this.subscription = combineLatest([ this.mapaCamasService.view, this.mapaCamasService.capa2, this.mapaCamasService.ambito2, this.mapaCamasService.selectedCama, this.mapaCamasService.prestacion$, + this.mapaCamasService.informeEstadistica$, this.mapaCamasService.resumenInternacion$ - ]).subscribe(([view, capa, ambito, cama, prestacion, resumen]) => { + ]).subscribe(([view, capa, ambito, cama, prestacion, informe, resumen]) => { this.inProgress = false; this.resumen = resumen; - let fecha = moment(resumen?.fechaEgreso || this.mapaCamasService.fecha).toDate(); + this.capa = capa; + this.prestacion = prestacion; + + this.informe = informe || { + id: null, + organizacion: null, + unidadOrganizativa: null, + paciente: null, + informeIngreso: null, + informeEgreso: null + }; + this.informe.informeEgreso = this.informe.informeEgreso || { + fechaEgreso: null, + diasDeEstada: null, + nacimientos: [{ + pesoAlNacer: null, + condicionAlNacer: null, + terminacion: null, + sexo: null + }], + procedimientosQuirurgicos: [], + causaExterna: { + producidaPor: null, + lugar: null, + comoSeProdujo: null + }, + tipoEgreso: { + tipo: null, + OrganizacionDestino: null, + otraOrganizacion: null + }, + diagnosticos: { + principal: null, + secundarios: [], + otrasCircunstancias: null, + diasEstadaOtrasCircunstancias: null, + diasDePermisoDeSalida: null + } + }; + this.registro.valor.InformeEgreso = Object.assign( + {}, + this.registro.valor.InformeEgreso, + this.informe.informeEgreso + ); + let fecha: Date; if (view === 'listado-internacion' && prestacion) { - // DESDE EL LISTADO FECHA VIENE CON LA DEL INGRESO. PUES NO! fecha = moment(resumen?.fechaEgreso).toDate() || moment().toDate(); this.prestacionValidada = prestacion.estados[prestacion.estados.length - 1].tipo === 'validada'; + } else { + fecha = moment().toDate(); } - + this.informe.informeEgreso.fechaEgreso = moment(fecha).toDate(); this.registro.valor.InformeEgreso.fechaEgreso = moment(fecha).toDate(); - this.fechaMaxProcedimiento = moment(this.registro.valor.InformeEgreso.fechaEgreso).endOf('day').toDate(); - this.fechaEgresoOriginal = null; + this.fecha = this.registro.valor.InformeEgreso.fechaEgreso; // Sincroniza la variable 'fecha' usada en el datetime. + + this.fechaMaxProcedimiento = moment(fecha).endOf('day').toDate(); + + if (this.hayEgreso && this.prestacion?.ejecucion?.registros?.[1]) { + this.registro.valor.InformeEgreso = Object.assign( + {}, + this.prestacion.ejecucion.registros[1].valor.InformeEgreso + ); + const informeEgreso = this.registro.valor.InformeEgreso; + this.fechaEgresoOriginal = moment(informeEgreso.fechaEgreso).toDate(); + this.checkTraslado = informeEgreso.tipoEgreso?.tipo === 'Traslado' && + !informeEgreso.tipoEgreso?.OrganizacionDestino?.id; + this.fecha = moment(informeEgreso.fechaEgreso).toDate(); + this.fechaMaxProcedimiento = moment(this.fecha).endOf('day').toDate(); + } this.view = view; this.capa = capa; + if (capa === 'estadistica' || capa === 'estadistica-v2') { - if (!prestacion) { + if (!informe) { return; } - this.prestacion = prestacion; - this.informeIngreso = this.prestacion.ejecucion.registros[0].valor.informeIngreso; - if (this.hayEgreso) { - this.registro.valor.InformeEgreso = Object.assign({}, this.prestacion.ejecucion.registros[1].valor.InformeEgreso); - fecha = moment(this.registro.valor.InformeEgreso.fechaEgreso).toDate(); - this.fechaEgresoOriginal = moment(this.registro.valor.InformeEgreso.fechaEgreso).toDate(); - - const informeEgreso = this.registro.valor.InformeEgreso; - this.checkTraslado = informeEgreso.tipoEgreso.id === 'Traslado' && !informeEgreso.UnidadOrganizativaDestino?.id; - this.fechaMaxProcedimiento = moment(this.registro.valor.InformeEgreso.fechaEgreso).endOf('day').toDate(); - } + this.informe = informe; + this.informeIngreso = this.informe?.informeIngreso; if (this.view === 'listado-internacion') { if (this.subscription2) { @@ -273,38 +348,35 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { this.setEstadoDestino(); } } else if (this.resumen?.id) { - // asistencial (no sala) - if (this.resumen.fechaEgreso) { - this.fechaEgresoOriginal = moment(this.resumen.fechaEgreso).toDate(); - this.registro.valor.InformeEgreso.tipoEgreso = this.listaTipoEgreso.find(tipo => tipo.nombre === this.resumen.tipo_egreso); + const fechaABuscarMin = moment(this.informeIngreso.fechaIngreso).add(-1, 's').toDate(); + const fechaABuscarMax = this.hayEgreso ? moment(this.registro.valor.InformeEgreso.fechaEgreso).add(-10, 's').toDate() : moment().toDate(); // para excluir el egreso + const idInternacion = resumen?.id || prestacion.id; + if (this.subscription2) { + this.subscription2.unsubscribe(); } - const fechaABuscarMax = resumen.fechaEgreso ? moment(resumen.fechaEgreso).add(-10, 's').toDate() : moment().toDate(); // para excluir el egreso this.subscription2 = this.camasHTTP.historialInternacion(ambito, capa, resumen.fechaIngreso, fechaABuscarMax, resumen.id) .subscribe(movimientos => { - movimientos.sort((a, b) => new Date(b.fecha).getTime() - new Date(a.fecha).getTime()); - const ultimoMovimiento = movimientos[0]; - this.cama = ultimoMovimiento; - this.refreshSaveButton.next({}); - this.fechaMin = moment(ultimoMovimiento.fecha).add(1, 'm').toDate(); - this.checkHistorial(fecha); - this.setEstadoDestino(); }); - } else if (cama.sala) { + } else if (cama?.sala) { this.cama = cama; + } else { + this.cama = cama; + this.setEstadoDestino(); } - - this.fecha = moment(fecha).toDate(); this.setDiasEstada(); }); - } - /* Calcula cual seria el siguiente estado correcto que corresponderia partir del movimiento actual - en base a la maquina de estados y se lo asigna a la variable 'estadoDestino' - */ + } private setEstadoDestino() { - this.subscription3 = this.mapaCamasService.getRelacionesPosibles(this.cama).subscribe((relacionesPosibles) => { - this.estadoDestino = relacionesPosibles[0]?.destino; + if (!this.cama) { + return; + } + if (this.subscription3) { + this.subscription3.unsubscribe(); + } + this.subscription3 = this.mapaCamasService.getRelacionesPosibles(this.cama).pipe(first()).subscribe((relacionesPosibles) => { + this.estadoDestino = relacionesPosibles.find(r => r.destino.nombre === 'Disponible' || r.destino.nombre === 'Limpieza' || r.destino.nombre === 'Mantenimiento')?.destino || relacionesPosibles[0]?.destino; }); } @@ -313,7 +385,11 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { } get hayEgreso() { - return this.prestacion && this.prestacion.ejecucion.registros[1] && this.prestacion.ejecucion.registros[1].valor; + return !!this.informe?.informeEgreso && ( + this.informe.informeEgreso.fechaEgreso || + this.informe.informeEgreso.diagnosticos?.principal || + this.informe.informeEgreso.procedimientosQuirurgicos?.length + ); } setFecha() { @@ -347,7 +423,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { // actualiza el listado this.listadoInternacionService.setFechaHasta(fechaHasta); this.listadoInternacionCapasService.setFechaHasta(fechaHasta); - this.mapaCamasService.selectPrestacion(null); + this.mapaCamasService.selectInformeEstadistica(null); this.mapaCamasService.selectResumen(null); } else if (this.view === 'mapa-camas') { this.mapaCamasService.setFecha(this.registro.valor.InformeEgreso.fechaEgreso); @@ -441,10 +517,10 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { op: 'registros', registros: registros }; - return this.servicioPrestacion.patch(this.prestacion.id, params).pipe( - switchMap(prestacion => { + return this.informeEstadisticaService.patch(this.informe.id, params).pipe( + switchMap(informe => { if (this.view === 'listado-internacion' || this.capa === 'estadistica') { - this.mapaCamasService.selectPrestacion(prestacion); + this.mapaCamasService.selectInformeEstadistica(informe); } if (this.capa === 'estadistica-v2' && this.resumen?.fechaEgreso) { const idInternacion = this.view === 'listado-internacion' ? this.resumen.id : this.cama.idInternacion; @@ -468,37 +544,46 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { } controlRegistrosGuardar() { - const registros = JSON.parse(JSON.stringify(this.prestacion.ejecucion.registros)); - if (this.registro.valor.InformeEgreso.diagnosticoPrincipal) { + const registros: any[] = []; + + if (this.informe.informeEgreso?.diagnosticos?.principal) { this.registro.esDiagnosticoPrincipal = true; } - if (this.registro.valor.InformeEgreso.UnidadOrganizativaDestino) { - const datosOrganizacionDestino = { - id: this.registro.valor.InformeEgreso.UnidadOrganizativaDestino.id, - nombre: this.registro.valor.InformeEgreso.UnidadOrganizativaDestino.nombre + if (this.informe.informeEgreso?.tipoEgreso?.OrganizacionDestino) { + this.informe.informeEgreso.tipoEgreso.OrganizacionDestino = { + ...this.informe.informeEgreso.tipoEgreso.OrganizacionDestino, + id: this.informe.informeEgreso.tipoEgreso.OrganizacionDestino.id, + nombre: this.informe.informeEgreso.tipoEgreso.OrganizacionDestino.nombre }; - this.registro.valor.InformeEgreso.UnidadOrganizativaDestino = datosOrganizacionDestino; } - const existeEgreso = this.prestacion.ejecucion.registros.find(r => r.concepto.conceptId === '58000006'); + const registroEgreso = { + concepto: { conceptId: '58000006' }, + valor: this.informe.informeEgreso + }; - if (!existeEgreso) { - registros.push(this.registro); + const indexEgreso = registros.findIndex(r => r.concepto.conceptId === '58000006'); + if (indexEgreso >= 0) { + registros[indexEgreso] = registroEgreso; } else { - const indexRegistro = registros.findIndex(registro => registro.concepto.conceptId === '58000006'); - registros[indexRegistro] = this.registro; + registros.push(registroEgreso); } return registros; } - - setDiasEstada() { if (this.capa === 'estadistica' || this.capa === 'estadistica-v2') { - const fechaIngreso = this.informeIngreso.fechaIngreso || this.resumen.fechaIngreso; - const fechaEgreso = this.registro.valor.InformeEgreso.fechaEgreso; - this.registro.valor.InformeEgreso['diasDeEstada'] = this.mapaCamasService.calcularDiasEstada(fechaIngreso, fechaEgreso); + const fechaIngreso = this.informe.informeIngreso?.fechaIngreso || this.resumen?.fechaIngreso; + const fechaEgreso = this.registro.valor.InformeEgreso?.fechaEgreso; + + if (fechaIngreso && fechaEgreso) { + this.registro.valor.InformeEgreso.diasDeEstada = + this.mapaCamasService.calcularDiasEstada(fechaIngreso, fechaEgreso); + } else { + console.warn('⚠️ No se puede calcular días de estadía: faltan fechas', + { fechaIngreso, fechaEgreso }); + } } } @@ -526,6 +611,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { } + codigoCIE10(event, tipo) { const filtro = [{ desde: 'A00', @@ -564,6 +650,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { } } + showProcedimientos_causas() { this.procedimientosObstetricos = false; this.procedimientosObstetricosNoReq = false; diff --git a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts index d4c14d7587..46931b7b9f 100644 --- a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts +++ b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts @@ -70,6 +70,12 @@ export interface IInformeEgreso { diasEstadaOtrasCircunstancias?: number; diasDePermisoDeSalida?: number; }; + nacimientos?: { + pesoAlNacer?: number; + condicionAlNacer?: string; + terminacion?: string; + sexo?: string; + }[]; createdAt?: Date; createdBy?: { id: string; @@ -98,7 +104,8 @@ export interface IInternacionEstado { export interface IInformeEstadistica { id: string; - organizacion: Partial; + organizacion: Partial; + unidadOrganizativa: ISnomedConcept; paciente: IPaciente; informeIngreso: IInformeIngreso; @@ -115,7 +122,7 @@ export interface IInformeEstadistica { apellido: string; username: string | number; documento: string | number; - organizacion: Partial; + organizacion: Partial; }; } From cb9742fbec6758a197daf69d77da9b0936c0f8f7 Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:32:24 -0300 Subject: [PATCH 06/14] =?UTF-8?q?feat(IN-666):"Corregir=20test=20de=20capa?= =?UTF-8?q?=20estad=C3=ADstica"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapa-camas/services/mapa-camas.service.ts | 4 +- .../egreso/egresar-paciente.component.ts | 359 +++++++++--------- .../informe-estadistica.interface.ts | 1 + .../services/informe-estadistica.service.ts | 15 +- 4 files changed, 184 insertions(+), 195 deletions(-) diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts index 1d572b18af..a57d4ab852 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts @@ -454,8 +454,8 @@ export class MapaCamasService { camasFiltradas = camasFiltradas.filter((snap: ISnapshot) => snap.paciente.documento.includes(paciente) || snap.paciente.numeroIdentificacion?.includes(paciente)); } else { - camasFiltradas = camasFiltradas.filter((snap: ISnapshot) => - (snap.paciente.nombre.toLowerCase().includes(paciente.toLowerCase()) || + camasFiltradas = camasFiltradas.filter((snap: ISnapshot) => ( + snap.paciente.nombre.toLowerCase().includes(paciente.toLowerCase()) || snap.paciente.alias?.toLowerCase().includes(paciente.toLowerCase()) || snap.paciente.apellido.toLowerCase().includes(paciente.toLowerCase())) ); diff --git a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts index 554e0994ef..e2869b2616 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts @@ -4,7 +4,7 @@ import { Plex } from '@andes/plex'; import { cache } from '@andes/shared'; import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { BehaviorSubject, combineLatest, Observable, of, Subscription } from 'rxjs'; -import { catchError, first, map, switchMap } from 'rxjs/operators'; +import { catchError, debounceTime, first, map, switchMap, tap } from 'rxjs/operators'; import { IPrestacion } from '../../../../../modules/rup/interfaces/prestacion.interface'; import { PrestacionesService } from '../../../../../modules/rup/services/prestaciones.service'; import { OrganizacionService } from '../../../../../services/organizacion.service'; @@ -21,6 +21,8 @@ import { ListadoInternacionCapasService } from '../../views/listado-internacion- import { NgForm } from '@angular/forms'; import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; +import { debug } from 'console'; +import { debugOutputAstAsTypeScript } from '@angular/compiler'; @Component({ selector: 'app-egresar-paciente', templateUrl: './egresar-paciente.component.html', @@ -85,11 +87,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { lugar: null, comoSeProdujo: null }, - tipoEgreso: { - tipo: null, - OrganizacionDestino: null, - otraOrganizacion: null - }, + tipoEgreso: null, diagnosticos: { principal: null, secundarios: [], @@ -178,37 +176,31 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { }) ); + this.registrosEgresoResumen$ = combineLatest([ this.mapaCamasService.capa2, - this.mapaCamasService.prestacion$, - this.mapaCamasService.informeEstadistica$ + this.mapaCamasService.informeEstadistica$, + this.mapaCamasService.prestacion$ ]).pipe( first(), - switchMap(([capa, prestacion, informe]) => { + switchMap(([capa, informe, prestacion]) => { if (capa === 'estadistica' || (capa === 'estadistica-v2' && this.view === 'mapa-camas')) { - const fechaIngreso = informe?.informeIngreso?.fechaIngreso; - const paciente = informe?.paciente?.id; - - if (!fechaIngreso || !paciente) { - console.warn('⚠️ No hay datos de ingreso en el informe estadístico'); - return of(null); - } - + const fechaIngreso = informe?.informeIngreso?.fechaIngreso || this.resumen?.fechaIngreso; + const paciente = informe?.paciente?.id || this.resumen?.paciente.id; const desde = moment(fechaIngreso).subtract(12, 'hours').toDate(); const hasta = moment(fechaIngreso).add(12, 'hours').toDate(); - - // Combinar el historial de cama con la búsqueda del resumen return combineLatest([ this.camasHTTP.historialInternacion( 'internacion', capa, this.informeIngreso.fechaIngreso, moment().toDate(), - prestacion.id + informe.id + // prestacion.id ), this.internacionResumenService.search({ organizacion: this.auth.organizacion.id, - paciente, + paciente: paciente, ingreso: this.internacionResumenService.queryDateParams(desde, hasta) }) ]).pipe( @@ -228,106 +220,66 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { cache() ); - this.subscription = combineLatest([ this.mapaCamasService.view, this.mapaCamasService.capa2, this.mapaCamasService.ambito2, this.mapaCamasService.selectedCama, - this.mapaCamasService.prestacion$, this.mapaCamasService.informeEstadistica$, + this.mapaCamasService.prestacion$, this.mapaCamasService.resumenInternacion$ - ]).subscribe(([view, capa, ambito, cama, prestacion, informe, resumen]) => { + ]).subscribe(([view, capa, ambito, cama, informe, prestacion, resumen]) => { this.inProgress = false; this.resumen = resumen; - this.capa = capa; - this.prestacion = prestacion; - this.informe = informe || { - id: null, - organizacion: null, - unidadOrganizativa: null, - paciente: null, - informeIngreso: null, - informeEgreso: null - }; - this.informe.informeEgreso = this.informe.informeEgreso || { - fechaEgreso: null, - diasDeEstada: null, - nacimientos: [{ - pesoAlNacer: null, - condicionAlNacer: null, - terminacion: null, - sexo: null - }], - procedimientosQuirurgicos: [], - causaExterna: { - producidaPor: null, - lugar: null, - comoSeProdujo: null - }, - tipoEgreso: { - tipo: null, - OrganizacionDestino: null, - otraOrganizacion: null - }, - diagnosticos: { - principal: null, - secundarios: [], - otrasCircunstancias: null, - diasEstadaOtrasCircunstancias: null, - diasDePermisoDeSalida: null - } - }; - this.registro.valor.InformeEgreso = Object.assign( - {}, - this.registro.valor.InformeEgreso, - this.informe.informeEgreso - ); - let fecha: Date; - if (view === 'listado-internacion' && prestacion) { + let fecha = moment(resumen?.fechaEgreso || this.mapaCamasService.fecha).toDate(); + if (view === 'listado-internacion' && (informe || prestacion)) { fecha = moment(resumen?.fechaEgreso).toDate() || moment().toDate(); - this.prestacionValidada = prestacion.estados[prestacion.estados.length - 1].tipo === 'validada'; - } else { - fecha = moment().toDate(); + const objetoConEstados = informe || prestacion; + + const estados = objetoConEstados?.estados; + if (estados && estados.length > 0) { + this.prestacionValidada = estados[estados.length - 1].tipo === 'validada'; + } else { + this.prestacionValidada = false; + } + } - this.informe.informeEgreso.fechaEgreso = moment(fecha).toDate(); this.registro.valor.InformeEgreso.fechaEgreso = moment(fecha).toDate(); - this.fecha = this.registro.valor.InformeEgreso.fechaEgreso; // Sincroniza la variable 'fecha' usada en el datetime. + this.fechaMaxProcedimiento = moment(this.registro.valor.InformeEgreso.fechaEgreso).endOf('day').toDate(); + this.fechaEgresoOriginal = null; - this.fechaMaxProcedimiento = moment(fecha).endOf('day').toDate(); - if (this.hayEgreso && this.prestacion?.ejecucion?.registros?.[1]) { - this.registro.valor.InformeEgreso = Object.assign( - {}, - this.prestacion.ejecucion.registros[1].valor.InformeEgreso - ); - const informeEgreso = this.registro.valor.InformeEgreso; - this.fechaEgresoOriginal = moment(informeEgreso.fechaEgreso).toDate(); - this.checkTraslado = informeEgreso.tipoEgreso?.tipo === 'Traslado' && - !informeEgreso.tipoEgreso?.OrganizacionDestino?.id; - this.fecha = moment(informeEgreso.fechaEgreso).toDate(); - this.fechaMaxProcedimiento = moment(this.fecha).endOf('day').toDate(); - } this.view = view; this.capa = capa; + if (capa === 'estadistica' || capa === 'estadistica-v2') { if (!informe) { return; } this.informe = informe; this.informeIngreso = this.informe?.informeIngreso; + if (this.hayEgreso) { + this.registro.valor.InformeEgreso = Object.assign({}, this.informe.informeEgreso); + fecha = moment(this.registro.valor.InformeEgreso.fechaEgreso).toDate(); + this.fechaEgresoOriginal = moment(this.registro.valor.InformeEgreso.fechaEgreso).toDate(); + + const informeEgreso = this.registro.valor.InformeEgreso; + this.checkTraslado = informeEgreso.tipoEgreso.id === 'Traslado' && !informeEgreso.UnidadOrganizativaDestino?.id; + this.fechaMaxProcedimiento = moment(this.registro.valor.InformeEgreso.fechaEgreso).endOf('day').toDate(); + } if (this.view === 'listado-internacion') { if (this.subscription2) { this.subscription2.unsubscribe(); } + const fechaABuscarMin = moment(this.informeIngreso.fechaIngreso).add(-1, 's').toDate(); const fechaABuscarMax = this.hayEgreso ? moment(this.registro.valor.InformeEgreso.fechaEgreso).add(-10, 's').toDate() : moment().toDate(); // para excluir el egreso - const idInternacion = resumen?.id || prestacion.id; + const idInternacion = resumen?.id || informe?.id || prestacion.id; this.subscription2 = this.camasHTTP.historialInternacion(ambito, capa, fechaABuscarMin, fechaABuscarMax, idInternacion) .subscribe(movimientos => { movimientos.sort((a, b) => new Date(b.fecha).getTime() - new Date(a.fecha).getTime()); @@ -343,31 +295,42 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { this.setEstadoDestino(); } }); + } else { this.cama = cama; this.setEstadoDestino(); } } else if (this.resumen?.id) { - const fechaABuscarMin = moment(this.informeIngreso.fechaIngreso).add(-1, 's').toDate(); - const fechaABuscarMax = this.hayEgreso ? moment(this.registro.valor.InformeEgreso.fechaEgreso).add(-10, 's').toDate() : moment().toDate(); // para excluir el egreso - const idInternacion = resumen?.id || prestacion.id; - if (this.subscription2) { - this.subscription2.unsubscribe(); + const esCapaAsistencial = this.capa === 'medica' || this.capa === 'enfermeria'; + + if (this.resumen.fechaEgreso && (esCapaAsistencial || this.view === 'listado-internacion')) { + this.fechaEgresoOriginal = moment(this.resumen.fechaEgreso).toDate(); + this.registro.valor.InformeEgreso.tipoEgreso = this.listaTipoEgreso.find(tipo => tipo.nombre === this.resumen.tipo_egreso); } + + const fechaABuscarMax = resumen.fechaEgreso ? moment(resumen.fechaEgreso).add(-10, 's').toDate() : moment().toDate(); // para excluir el egreso this.subscription2 = this.camasHTTP.historialInternacion(ambito, capa, resumen.fechaIngreso, fechaABuscarMax, resumen.id) .subscribe(movimientos => { + movimientos.sort((a, b) => new Date(b.fecha).getTime() - new Date(a.fecha).getTime()); + const ultimoMovimiento = movimientos[0]; + this.cama = ultimoMovimiento; + this.refreshSaveButton.next({}); + this.fechaMin = moment(ultimoMovimiento.fecha).add(1, 'm').toDate(); + this.checkHistorial(fecha); + this.setEstadoDestino(); }); + } else if (cama?.sala) { this.cama = cama; - } else { - this.cama = cama; - this.setEstadoDestino(); } + + this.fecha = moment(fecha).toDate(); this.setDiasEstada(); }); } + private setEstadoDestino() { if (!this.cama) { return; @@ -383,13 +346,8 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { onType() { this.inProgress = true; } - - get hayEgreso() { - return !!this.informe?.informeEgreso && ( - this.informe.informeEgreso.fechaEgreso || - this.informe.informeEgreso.diagnosticos?.principal || - this.informe.informeEgreso.procedimientosQuirurgicos?.length - ); + get hayEgreso(): boolean { + return !!(this.informe && this.informe.informeEgreso); } setFecha() { @@ -400,7 +358,6 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { this.mapaCamasService.setFecha(nuevaFecha); this.registro.valor.InformeEgreso.fechaEgreso = nuevaFecha; if (this.capa === 'estadistica' || this.capa === 'estadistica-v2') { - // si se está egresando con fusion de capas puede que estadistica-v2 aun no haya cargado el informe if (this.capa === 'estadistica-v2' && !this.informeIngreso?.fechaIngreso) { this.plex.info('warning', 'Antes de egresar al paciente debe cargar el informe de ingreso.'); return; @@ -410,7 +367,6 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { this.fechaMaxProcedimiento = moment(this.registro.valor.InformeEgreso.fechaEgreso).endOf('day').toDate(); } } - guardar(valid) { if (valid.formValid) { this.inProgress = true; @@ -420,11 +376,14 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { this.plex.info('success', 'Los datos se actualizaron correctamente'); if (this.view === 'listado-internacion') { const fechaHasta = moment(this.registro.valor.InformeEgreso.fechaEgreso).add(1, 'm').toDate(); - // actualiza el listado this.listadoInternacionService.setFechaHasta(fechaHasta); this.listadoInternacionCapasService.setFechaHasta(fechaHasta); + this.mapaCamasService.selectResumen(null); this.mapaCamasService.selectInformeEstadistica(null); + this.mapaCamasService.selectPrestacion(null); this.mapaCamasService.selectResumen(null); + + } else if (this.view === 'mapa-camas') { this.mapaCamasService.setFecha(this.registro.valor.InformeEgreso.fechaEgreso); } @@ -447,15 +406,16 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { } } - /* Para las capas estadistica-v2, medica y enfermeria actualiza el resumen. Luego actualiza el estado de la cama cualquiera sea la capa. */ + + // Setea valores de la prestacion (estadistica y estadistica-v2) antes de llamar al egreso simplificado + egresoSimplificado(estado): Observable { // Se configura nuevo estado con datos del egreso let estadoPatch = {}; if (this.cama.sala) { - // sala comun this.cama.estado = estado; this.cama.extras = { egreso: true, @@ -464,7 +424,6 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { }; estadoPatch = this.cama; } else { - // cama estadoPatch = { _id: this.cama.id || this.cama._id, estado: estado, @@ -479,6 +438,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { } }; } + const saveInternacion = () => { if (this.capa !== 'estadistica' && !this.cama.sala) { // estadistica-v2, medica, enfermeria (exceptuando salas) @@ -496,93 +456,107 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { this.inProgress = false; if (this.capa !== 'estadistica' && !this.cama.sala && !resumenSaved) { - /* si hubo algun error actualizando el resumen, no debería actualizar el estado de la cama para + /* si hubo algun error actualizando el resumen, no debería actualizar el estado de la cama para no generar datos inconsistentes entre internacion y movimientos */ - throw new Error(); + throw new Error('Error al actualizar el resumen de internación.'); } + if (this.fechaEgresoOriginal) { - return this.mapaCamasService.changeTime(this.cama, this.fechaEgresoOriginal, this.registro.valor.InformeEgreso.fechaEgreso, this.cama.idInternacion); + const fechaOriginalString = moment(this.fechaEgresoOriginal).toISOString(); + const nuevaFechaString = moment(this.registro.valor.InformeEgreso.fechaEgreso).toISOString(); + + if (fechaOriginalString !== nuevaFechaString) { + return this.mapaCamasService.changeTime(this.cama, this.fechaEgresoOriginal, this.registro.valor.InformeEgreso.fechaEgreso, this.cama.idInternacion); + } + this.plex.info('success', 'Datos de egreso actualizados. Liberando/actualizando la cama.', 'Actualización Completa'); + return this.mapaCamasService.save(estadoPatch, this.registro.valor.InformeEgreso.fechaEgreso); + } else { + // Caso 3: PRIMER EGRESO (fechaEgresoOriginal es null) return this.mapaCamasService.save(estadoPatch, this.registro.valor.InformeEgreso.fechaEgreso); } }) ); } - // Setea valores de la prestacion (estadistica y estadistica-v2) antes de llamar al egreso simplificado egresoExtendido(): Observable { const registros = this.controlRegistrosGuardar(); - if (registros) { - const params: any = { - op: 'registros', - registros: registros - }; - return this.informeEstadisticaService.patch(this.informe.id, params).pipe( - switchMap(informe => { - if (this.view === 'listado-internacion' || this.capa === 'estadistica') { - this.mapaCamasService.selectInformeEstadistica(informe); - } - if (this.capa === 'estadistica-v2' && this.resumen?.fechaEgreso) { - const idInternacion = this.view === 'listado-internacion' ? this.resumen.id : this.cama.idInternacion; - // actualiza fecha y tipo de egreso en el resumen para mantener la sincronización - return this.internacionResumenService.update(idInternacion, { - tipo_egreso: this.registro.valor.InformeEgreso.tipoEgreso.id, - fechaEgreso: this.registro.valor.InformeEgreso.fechaEgreso - }); - } else { - // estadistica o medica - return this.egresoSimplificado(this.estadoDestino); - } - }), - catchError(error => { - this.plex.info('warning', `${error} ${moment(registros[0].valor.informeIngreso.fechaIngreso).format('YYYY-MM-DD HH:mm:ss').bold()}`, 'Error'); - return of(null); - }) - ); + + if (!registros) { + return of(null); } - return of(null); - } - controlRegistrosGuardar() { - const registros: any[] = []; + const informeId = this.informe._id || this.informe.id; + const body = { informeEgreso: this.registro.valor.InformeEgreso }; - if (this.informe.informeEgreso?.diagnosticos?.principal) { - this.registro.esDiagnosticoPrincipal = true; - } + return this.informeEstadisticaService.patchRegistros(informeId, body).pipe( + switchMap(informes => { - if (this.informe.informeEgreso?.tipoEgreso?.OrganizacionDestino) { - this.informe.informeEgreso.tipoEgreso.OrganizacionDestino = { - ...this.informe.informeEgreso.tipoEgreso.OrganizacionDestino, - id: this.informe.informeEgreso.tipoEgreso.OrganizacionDestino.id, - nombre: this.informe.informeEgreso.tipoEgreso.OrganizacionDestino.nombre - }; - } + if (this.view === 'listado-internacion' || this.capa === 'estadistica') { + this.mapaCamasService.selectInformeEstadistica(informes); + } - const registroEgreso = { - concepto: { conceptId: '58000006' }, - valor: this.informe.informeEgreso - }; + if (this.capa === 'estadistica-v2' && this.resumen?.fechaEgreso) { + const idInternacion = this.resumen.id; + this.internacionResumenService.update(idInternacion, { + tipo_egreso: this.registro.valor.InformeEgreso.tipoEgreso?.id, + fechaEgreso: this.registro.valor.InformeEgreso.fechaEgreso + }).subscribe(); + } - const indexEgreso = registros.findIndex(r => r.concepto.conceptId === '58000006'); - if (indexEgreso >= 0) { - registros[indexEgreso] = registroEgreso; - } else { - registros.push(registroEgreso); - } + return this.egresoSimplificado(this.estadoDestino); + }), - return registros; + catchError(error => { + this.plex.info( + 'warning', + `${error} ${moment(this.registro.valor.InformeEgreso.fechaEgreso).format('YYYY-MM-DD HH:mm:ss').bold()}`, + 'Error' + ); + return of(null); + }) + ); + } + controlRegistrosGuardar() { + const egreso = this.registro.valor.InformeEgreso; + + return { + fechaEgreso: egreso.fechaEgreso, + diasDeEstada: egreso.diasDeEstada, + tipoEgreso: { + id: egreso.tipoEgreso?.id, + nombre: egreso.tipoEgreso?.nombre, + OrganizacionDestino: egreso.UnidadOrganizativaDestino + ? { + id: egreso.UnidadOrganizativaDestino.id, + nombre: egreso.UnidadOrganizativaDestino.nombre + } + : undefined + }, + diagnosticos: { + principal: egreso.diagnosticoPrincipal, + secundarios: egreso.otrosDiagnosticos, + otrasCircunstancias: egreso.otrasCircunstancias, + diasEstadaOtrasCircunstancias: egreso.diasEstadaOtrasCircunstancias, + diasDePermisoDeSalida: egreso.diasDePermisoDeSalida + } + }; } + setDiasEstada() { if (this.capa === 'estadistica' || this.capa === 'estadistica-v2') { const fechaIngreso = this.informe.informeIngreso?.fechaIngreso || this.resumen?.fechaIngreso; const fechaEgreso = this.registro.valor.InformeEgreso?.fechaEgreso; - if (fechaIngreso && fechaEgreso) { - this.registro.valor.InformeEgreso.diasDeEstada = - this.mapaCamasService.calcularDiasEstada(fechaIngreso, fechaEgreso); + const dias = this.mapaCamasService.calcularDiasEstada(fechaIngreso, fechaEgreso); + + this.registro.valor.InformeEgreso.diasDeEstada = dias; + } else { - console.warn('⚠️ No se puede calcular días de estadía: faltan fechas', - { fechaIngreso, fechaEgreso }); + console.warn('⚠️ No se puede calcular días de estadía: faltan fechas', { + fechaIngreso, + fechaEgreso + }); } } } @@ -602,13 +576,15 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { } } - onChangeTraslado(event) { + + public onChangeTraslado(event: { value: boolean }) { if (event.value) { - this.registro.valor.InformeEgreso.UnidadOrganizativaDestino = { id: null, nombre: '' }; + this.registro.valor.InformeEgreso.tipoEgreso.OrganizacionDestino = null; } else { - this.registro.valor.InformeEgreso.UnidadOrganizativaDestino = null; + this.registro.valor.InformeEgreso.tipoEgreso.otraOrganizacion = null; + this.registro.valor.InformeEgreso.tipoEgreso.OrganizacionDestino = { id: null, nombre: null }; } - + this.refreshSaveButton.next({}); } @@ -635,17 +611,20 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { }); } else { const callback = []; - if (this.registro.valor.InformeEgreso.diagnosticoPrincipal) { - callback.push(this.registro.valor.InformeEgreso.diagnosticoPrincipal); - } - if (this.registro.valor.InformeEgreso.otrosDiagnosticos) { - callback.push(this.registro.valor.InformeEgreso.otrosDiagnosticos); + const principal = this.registro.valor.InformeEgreso.diagnosticos?.principal; + if (principal) { + callback.push(principal); + } + if (this.registro.valor.InformeEgreso.otrosDiagnosticos) { + callback.push(...this.registro.valor.InformeEgreso.otrosDiagnosticos); } - if (this.registro.valor.InformeEgreso.causaExterna && this.registro.valor.InformeEgreso.causaExterna.comoSeProdujo) { + + if (this.registro.valor.InformeEgreso.causaExterna?.comoSeProdujo) { callback.push(this.registro.valor.InformeEgreso.causaExterna.comoSeProdujo); } + event.callback(callback); } } @@ -667,8 +646,11 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { const regexCIEProcedimientosObstetricos = new RegExp('^O8[0-4].[0-9]|O60.1|O60.2'); const regexCIEProcedimientosObstetricosNoReq = new RegExp('^O0[0-6].[0-9]'); - if (this.registro.valor.InformeEgreso.diagnosticoPrincipal) { - this.existeCausaExterna = regexCIECausasExternas.test(this.registro.valor.InformeEgreso.diagnosticoPrincipal.codigo); + + if (this.registro.valor.InformeEgreso.diagnosticos?.principal) { + this.existeCausaExterna = regexCIECausasExternas.test( + this.registro.valor.InformeEgreso.diagnosticos.principal.codigo + ); } if (this.registro.valor.InformeEgreso.otrosDiagnosticos) { @@ -678,11 +660,11 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { } } - if (this.registro.valor.InformeEgreso.diagnosticoPrincipal) { - this.procedimientosObstetricos = regexCIEProcedimientosObstetricos.test(this.registro.valor.InformeEgreso.diagnosticoPrincipal.codigo); - this.procedimientosObstetricosNoReq = regexCIEProcedimientosObstetricosNoReq.test(this.registro.valor.InformeEgreso.diagnosticoPrincipal.codigo); + if (this.registro.valor.InformeEgreso.diagnosticos?.principal) { + const principal = this.registro.valor.InformeEgreso.diagnosticos.principal; + this.procedimientosObstetricos = regexCIEProcedimientosObstetricos.test(principal.codigo); + this.procedimientosObstetricosNoReq = regexCIEProcedimientosObstetricosNoReq.test(principal.codigo); } - if (this.registro.valor.InformeEgreso.otrosDiagnosticos) { const diagObstetitricos = this.registro.valor.InformeEgreso.otrosDiagnosticos.filter(d => regexCIEProcedimientosObstetricosNoReq.test(d.codigo)); if (diagObstetitricos && diagObstetitricos.length > 0) { @@ -794,7 +776,7 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { checkEstadoCama() { this.mapaCamasService.get(this.fecha, this.cama?.id).subscribe((cama) => { if (cama && cama.estado !== 'disponible') { - if (!cama.idInternacion || (cama.idInternacion && cama.idInternacion !== this.prestacion.id) && this.capa !== 'estadistica-v2') { + if (!cama.idInternacion || (cama.idInternacion && cama.idInternacion !== this.informe.id) && this.capa !== 'estadistica-v2') { this.registro.valor.InformeEgreso.fechaEgreso = this.fechaEgresoOriginal; this.fecha = this.fechaEgresoOriginal; this.plex.info('warning', `No es posible realizar el cambio de fecha porque la cama ${this.cama.nombre.bold()} no se encuentra disponible`, @@ -811,10 +793,11 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { Define las fechas minima y maxima para el egreso actual según corresponda. */ checkHistorial(fecha: Date) { + if (this.subscription4) { this.subscription4.unsubscribe(); } - this.subscription4 = this.mapaCamasService.historial('cama', this.cama.fecha, moment().toDate(), this.cama).subscribe( + this.subscription4 = this.mapaCamasService.historial('cama', this.cama?.fecha, moment().toDate(), this.cama).subscribe( historialCama => { this.fechaMax = null; for (const historial of historialCama) { diff --git a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts index 46931b7b9f..0c7fcc731e 100644 --- a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts +++ b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts @@ -104,6 +104,7 @@ export interface IInternacionEstado { export interface IInformeEstadistica { id: string; + _id?: string; organizacion: Partial; unidadOrganizativa: ISnomedConcept; diff --git a/src/app/modules/rup/services/informe-estadistica.service.ts b/src/app/modules/rup/services/informe-estadistica.service.ts index b1682358cf..3a4622263c 100644 --- a/src/app/modules/rup/services/informe-estadistica.service.ts +++ b/src/app/modules/rup/services/informe-estadistica.service.ts @@ -8,16 +8,15 @@ import { HUDSService } from './huds.service'; providedIn: 'root' }) export class InformeEstadisticaService { - // URL base para el servicio de informe estadístico private baseUrl = '/modules/rup/internacion/informe-estadistica'; // Añadimos la URL base del servicio de Prestaciones, donde residen los endpoints de HUDS (Historial Único de Salud). private prestacionesBaseUrl = '/modules/rup/prestaciones'; - constructor(private server: Server, - private hudsService: HUDSService + constructor( + private server: Server, + private hudsService: HUDSService ) { } - // Obtiene una lista de informes estadísticos con filtros opcionales get(params?: any): Observable { return this.server.get(this.baseUrl, { params }); } @@ -35,10 +34,16 @@ export class InformeEstadisticaService { return this.server.post(this.baseUrl, data); } + patch(id: string, data: Partial): Observable { - return this.server.patch(`${this.baseUrl}/${id}`, data); + const url = `${this.baseUrl}/${id}`; + return this.server.patch(url, data); } + patchRegistros(id: string, body: any): Observable { + const url = `${this.baseUrl}/${id}`; + return this.server.patch(url, body); + } put(id: string, data: IInformeEstadistica): Observable { return this.server.put(`${this.baseUrl}/${id}`, data); } From ca7d556ff264ce04f64a8ea7f182b7bc144b4b49 Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:39:44 -0300 Subject: [PATCH 07/14] feat(IN-667)Modificar censos diario y mensual" --- .../mapa-camas/services/mapa-camas.http.ts | 6 + .../mapa-camas/services/mapa-camas.service.ts | 3 + .../egreso/egresar-paciente.component.html | 156 +++++++++--------- .../egreso/egresar-paciente.component.ts | 102 +++++++++--- .../ingreso/informe-ingreso.component.html | 10 +- .../ingreso/ingresar-paciente.component.ts | 23 ++- .../censo-diario/censo-diario.component.html | 51 ++++-- .../censo-diario/censo-diario.component.ts | 7 + .../informe-estadistica.interface.ts | 4 +- 9 files changed, 231 insertions(+), 131 deletions(-) diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.http.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.http.ts index e698cccdd3..6b0be4196b 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.http.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.http.ts @@ -118,6 +118,12 @@ export class MapaCamasHTTP { } censoDiario(fecha: Date, unidadOrganizativa: string): Observable { + console.log('🌐 [MapaCamasHTTP] Request a censo-diario →', { + url: `${this.url}/censo-diario`, + fecha, + unidadOrganizativa + }); + return this.server.get(`${this.url}/censo-diario`, { params: { fecha, unidadOrganizativa }, showError: true diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts index a57d4ab852..ea9b373717 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { Auth } from '@andes/auth'; import { cache, notNull } from '@andes/shared'; import { Injectable } from '@angular/core'; @@ -690,6 +691,8 @@ export class MapaCamasService { } censoDiario(fecha, unidadOrganizativa): Observable { + console.log('📞 Llamando a censoDiario con:', fecha, unidadOrganizativa); + return this.camasHTTP.censoDiario(fecha, unidadOrganizativa); } diff --git a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html index 6bfef442ab..5bd2babec3 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html +++ b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html @@ -12,26 +12,25 @@ [max]="fechaMax || (mapaCamasService.fechaActual$ | async)" [min]="fechaMin" (change)="setFecha()" [debounce]="600" grow="full" (typing)="onType()"> - - + - + + + [(ngModel)]="registro.valor.InformeEgreso.tipoEgreso.otraOrganizacion" [required]="true"> @@ -53,64 +52,65 @@ - + - - - - - - + + + - + + + - - - - - - - - - - - - - - + - - - + - - - + + + - - + + + - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - \ No newline at end of file diff --git a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts index e2869b2616..bf73e0f773 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.ts @@ -486,36 +486,88 @@ export class EgresarPacienteComponent implements OnInit, OnDestroy { return of(null); } - const informeId = this.informe._id || this.informe.id; - const body = { informeEgreso: this.registro.valor.InformeEgreso }; + if (this.informe) { + const informeEgresoNormalizado = JSON.parse(JSON.stringify(this.informe.informeEgreso)); + const tipoEgreso = informeEgresoNormalizado?.tipoEgreso; - return this.informeEstadisticaService.patchRegistros(informeId, body).pipe( - switchMap(informes => { + if (tipoEgreso && tipoEgreso.tipo && typeof tipoEgreso.tipo === 'object') { + const tipo: any = tipoEgreso.tipo; + informeEgresoNormalizado.tipoEgreso.tipo = tipo.id ?? null; + } - if (this.view === 'listado-internacion' || this.capa === 'estadistica') { - this.mapaCamasService.selectInformeEstadistica(informes); - } + if (informeEgresoNormalizado.tipoEgreso?.OrganizacionDestino && + typeof informeEgresoNormalizado.tipoEgreso.OrganizacionDestino === 'object') { - if (this.capa === 'estadistica-v2' && this.resumen?.fechaEgreso) { - const idInternacion = this.resumen.id; - this.internacionResumenService.update(idInternacion, { - tipo_egreso: this.registro.valor.InformeEgreso.tipoEgreso?.id, - fechaEgreso: this.registro.valor.InformeEgreso.fechaEgreso - }).subscribe(); - } + const org = informeEgresoNormalizado.tipoEgreso.OrganizacionDestino; + informeEgresoNormalizado.tipoEgreso.OrganizacionDestino = { + id: org.id || null, + nombre: org.nombre || null + }; + } - return this.egresoSimplificado(this.estadoDestino); - }), + const body = { + registros, + informeEgreso: informeEgresoNormalizado + }; - catchError(error => { - this.plex.info( - 'warning', - `${error} ${moment(this.registro.valor.InformeEgreso.fechaEgreso).format('YYYY-MM-DD HH:mm:ss').bold()}`, - 'Error' - ); - return of(null); - }) - ); + return this.informeEstadisticaService.patchRegistros( + this.informe._id || this.informe.id, + body + ).pipe( + switchMap(informes => { + if (this.view === 'listado-internacion' || this.capa === 'estadistica') { + this.mapaCamasService.selectInformeEstadistica(informes); + } + + if (this.capa === 'estadistica-v2' && this.resumen?.fechaEgreso) { + const idInternacion = this.view === 'listado-internacion' + ? this.resumen.id + : this.cama.idInternacion; + return this.internacionResumenService.update(idInternacion, { + tipo_egreso: informeEgresoNormalizado.tipoEgreso.id, + fechaEgreso: informeEgresoNormalizado.fechaEgreso + }); + } else { + return this.egresoSimplificado(this.estadoDestino); + } + }), + catchError(error => { + this.plex.info( + 'warning', + `${error} ${moment(this.registro.valor.InformeEgreso.fechaEgreso).format('YYYY-MM-DD HH:mm:ss').bold()}`, + 'Error' + ); + return of(null); + }) + ); + } else if (this.prestacion) { + const params: any = { + op: 'registros', + registros: registros + }; + return this.servicioPrestacion.patch(this.prestacion.id, params).pipe( + switchMap(prestacion => { + if (this.view === 'listado-internacion' || this.capa === 'estadistica') { + this.mapaCamasService.selectPrestacion(prestacion); + } + if (this.capa === 'estadistica-v2' && this.resumen?.fechaEgreso) { + const idInternacion = this.view === 'listado-internacion' ? this.resumen.id : this.cama.idInternacion; + return this.internacionResumenService.update(idInternacion, { + tipo_egreso: this.registro.valor.InformeEgreso.tipoEgreso.id, + fechaEgreso: this.registro.valor.InformeEgreso.fechaEgreso + }); + } else { + return this.egresoSimplificado(this.estadoDestino); + } + }), + catchError(error => { + this.plex.info('warning', `${error} ${moment(registros[0].valor.informeIngreso.fechaIngreso).format('YYYY-MM-DD HH:mm:ss').bold()}`, 'Error'); + return of(null); + }) + ); + } + + return of(null); } controlRegistrosGuardar() { const egreso = this.registro.valor.InformeEgreso; diff --git a/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.html b/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.html index ccee2b3ca4..ddf8ae0b43 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.html +++ b/src/app/apps/rup/mapa-camas/sidebar/ingreso/informe-ingreso.component.html @@ -8,6 +8,7 @@ + + + + - -
diff --git a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts index eb4fcff76c..d4b4bbb291 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts @@ -687,13 +687,15 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { informeIngreso: this.informeIngreso, }; - this.informeEstadisticaService.patch(this.informeEstadistica.id, cambios).subscribe({ + this.informeEstadisticaService.patch(this.informeEstadistica._id, cambios).subscribe({ next: (informeActualizado: any) => { this.informeIngreso = informeActualizado.informeIngreso; this.mapaCamasService.selectInformeEstadistica(informeActualizado); + + // acá sí está perfecto usar el _id del actualizado this.ingresoSimplificado('ocupada', paciente, informeActualizado._id); }, - error: (err) => { + error: () => { this.plex.info('danger', 'Error al actualizar informe estadístico'); } }); @@ -725,7 +727,7 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { this.informeEstadisticaService.post(nuevoInforme).subscribe(informeEstadistica => { if (this.cama) { if (this.capa === 'estadistica') { - this.ingresoSimplificado('ocupada', paciente, informeEstadistica.id); + this.ingresoSimplificado('ocupada', paciente, informeEstadistica._id); } else { // capa estadistica-v2 usa como idInternacion el id del resumen, por tanto primero hay que crearlo this.ingresoSimplificado('ocupada', paciente, null, informeEstadistica); @@ -767,7 +769,19 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { organizacion: this.auth.organizacion, unidadOrganizativa: this.cama.unidadOrganizativa, paciente: this.paciente, - informeIngreso: this.informeIngreso, + informeIngreso: { + ...this.informeIngreso, + situacionLaboral: (typeof this.informeIngreso.situacionLaboral === 'string') + ? this.informeIngreso.situacionLaboral + : this.informeIngreso.situacionLaboral?.nombre || null, + nivelInstruccion: (typeof this.informeIngreso.nivelInstruccion === 'string') + ? this.informeIngreso.nivelInstruccion + : this.informeIngreso.nivelInstruccion?.nombre || null, + ocupacionHabitual: this.informeIngreso.ocupacionHabitual, + asociado: (typeof this.informeIngreso.asociado === 'string') + ? this.informeIngreso.asociado + : this.informeIngreso.asociado?.nombre || null, + } as any, estados: [{ tipo: 'ejecucion', createdAt: new Date(), @@ -782,7 +796,6 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { username: this.informeIngreso.profesional.documento, documento: this.informeIngreso.profesional.documento, organizacion: this.auth.organizacion as unknown as IOrganizacion - } }; diff --git a/src/app/apps/rup/mapa-camas/views/censos/censo-diario/censo-diario.component.html b/src/app/apps/rup/mapa-camas/views/censos/censo-diario/censo-diario.component.html index 168e366c1d..d0aa8aefa9 100644 --- a/src/app/apps/rup/mapa-camas/views/censos/censo-diario/censo-diario.component.html +++ b/src/app/apps/rup/mapa-camas/views/censos/censo-diario/censo-diario.component.html @@ -6,20 +6,23 @@ + [debounce]="600"> - +
- + + [tooltip]="(!censo) ? 'Debe generar el censo para descargarlo' : 'Descargar censo diario'" + type="warning" (click)="descargarCenso()"> - +
@@ -40,19 +43,31 @@ - {{censoP.datos.paciente | nombre}} | - {{censoP.datos.paciente | documento}} - {{censoP.datos.cama.nombre}}, - {{censoP.datos.cama.sectores[censoP.datos.cama.sectores.length -1].nombre}} + + {{ censoP?.datos?.paciente | nombre }} | + {{ censoP?.datos?.paciente | documento }} - {{censoP.ingreso}} - {{censoP.paseDe}} - {{censoP.egreso}} - {{censoP.paseA}} + - {{ censoP.fechaIngreso | fecha }} + {{ censoP?.datos?.cama?.nombre || '-' }}, + {{ + censoP?.datos?.cama?.sectores?.length + ? censoP.datos.cama.sectores[censoP.datos.cama.sectores.length - 1]?.nombre + : '-' + }} - {{censoP.diasEstada}} + + {{ censoP?.ingreso || '-' }} + {{ censoP?.paseDe || '-' }} + {{ censoP?.egreso || '-' }} + {{ censoP?.paseA || '-' }} + + + {{ censoP.fechaIngreso | fecha }} + - + + + {{ censoP?.diasEstada || 0 }} diff --git a/src/app/apps/rup/mapa-camas/views/censos/censo-diario/censo-diario.component.ts b/src/app/apps/rup/mapa-camas/views/censos/censo-diario/censo-diario.component.ts index 03eb0e41ee..ac3233fb58 100644 --- a/src/app/apps/rup/mapa-camas/views/censos/censo-diario/censo-diario.component.ts +++ b/src/app/apps/rup/mapa-camas/views/censos/censo-diario/censo-diario.component.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { Component, OnInit } from '@angular/core'; import { Auth } from '@andes/auth'; import { OrganizacionService } from '../../../../../../services/organizacion.service'; @@ -53,11 +54,14 @@ export class CensosDiariosComponent implements OnInit { }); } + generarCensoDiario() { this.censoPacientes = []; this.censo = {}; this.mapaCamasService.censoDiario(moment(this.fecha).toDate(), this.selectedUnidadOranizativa.conceptId) .subscribe((censoDiario: any) => { + console.log('--- RESPUESTA COMPLETA DE LA API ---', censoDiario); + console.log('--- censoDiario.censo ES ---', censoDiario.censo); this.censo = { existencia0: censoDiario.censo.existenciaALas0, ingresos: censoDiario.censo.ingresos, @@ -71,11 +75,14 @@ export class CensosDiariosComponent implements OnInit { diasEstada: censoDiario.censo.diasEstada, disponibles24: censoDiario.censo.disponibles, }; + console.log('📦 CENSO DIARIO:', censoDiario); Object.keys(censoDiario.pacientes).map(p => { let delDiaAnterior = false; let ingresoAServicio = false; const censoPaciente = censoDiario.pacientes[p]; + console.log('🧩 PACIENTE:', p, censoPaciente); + censoPaciente.actividad.forEach((actividad: any, index) => { const movimiento = { datos: { diff --git a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts index 0c7fcc731e..db27d98302 100644 --- a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts +++ b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts @@ -60,7 +60,7 @@ export interface IInformeEgreso { diasDeEstada?: number; tipoEgreso?: { tipo?: string; - OrganizacionDestino?: IOrganizacion; + OrganizacionDestino?: Partial; otraOrganizacion?: string; }; diagnosticos?: { @@ -103,7 +103,7 @@ export interface IInternacionEstado { } export interface IInformeEstadistica { - id: string; + id: any; _id?: string; organizacion: Partial; From c6fbcffe2644d47b495f46e1f637ca330db650bb Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:59:05 -0300 Subject: [PATCH 08/14] =?UTF-8?q?IN(671)"Cambiar=20visualizaci=C3=B3n=20de?= =?UTF-8?q?=20huds=20de=20la=20internaci=C3=B3n=20estad=C3=ADstica=20y=20m?= =?UTF-8?q?ejores=20en=20egreso"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapa-camas/services/mapa-camas.service.ts | 20 +- .../internacion-detalle.component.html | 10 +- .../internacion-detalle.component.ts | 54 ++--- .../egreso/egresar-paciente.component.html | 11 +- .../egreso/egresar-paciente.component.ts | 3 +- .../egreso/informe-egreso.component.html | 15 +- .../egreso/informe-egreso.component.ts | 34 ++- .../ingreso/ingresar-paciente.component.ts | 14 +- .../listado-internacion.component.ts | 133 +++++++++-- .../ejecucion/hudsBusqueda.component.ts | 117 ++++++++-- .../components/ejecucion/hudsBusqueda.html | 206 +++++++++--------- .../ejecucion/vistaHuds.component.ts | 10 + .../elementos/internacionEgreso.component.ts | 16 +- .../listado-internacion-huds.component.ts | 30 ++- .../huds/listado-internacion-huds.html | 18 +- .../informe-estadistica.interface.ts | 8 +- .../services/informe-estadistica.service.ts | 72 +++++- .../rup/services/prestaciones.service.ts | 12 +- 18 files changed, 545 insertions(+), 238 deletions(-) diff --git a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts index ea9b373717..6faac64ec9 100644 --- a/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts +++ b/src/app/apps/rup/mapa-camas/services/mapa-camas.service.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ import { Auth } from '@andes/auth'; import { cache, notNull } from '@andes/shared'; import { Injectable } from '@angular/core'; @@ -182,7 +181,7 @@ export class MapaCamasService { // Devuelve la prestación que contiene el informe de ingreso this.prestacion$ = combineLatest([ - this.selectedInformeEstadistica, + this.selectedPrestacion, this.selectedCama, this.view, this.capa2 @@ -200,8 +199,8 @@ export class MapaCamasService { if (!cama.idInternacion) { return of(null); } - if (capa !== 'estadistica') { - return this.prestacionService.getById(cama.idInternacion, { showError: false }); + if (capa === 'estadistica') { + return of(null); } return this.internacionResumenHTTP.get(cama.idInternacion).pipe( switchMap(internacionResumen => { @@ -216,6 +215,7 @@ export class MapaCamasService { cache() ); + this.resumenInternacion$ = combineLatest([ this.selectedCama, this.ambito2, @@ -245,12 +245,17 @@ export class MapaCamasService { switchMap(([informe, cama, view, capa]) => { if (view === 'listado-internacion') { - const pacienteId = informe?.paciente?.id || cama?.paciente?.id; + if (informe?.id) { + return of(informe); + } + + const pacienteId = cama?.paciente?.id; if (pacienteId) { return this.informeEstadisticaService.get({ paciente: pacienteId }).pipe( map(informes => informes?.[0] || null) ); } + return of(null); } @@ -435,9 +440,12 @@ export class MapaCamasService { if (!informe) { return this.selectedInformeEstadistica.next({ id: null } as any); } + this.selectedInformeEstadistica.next(informe); + } + selectResumen(resumen: IResumenInternacion) { if (!resumen) { return this.selectedResumen.next({ id: null } as any); @@ -691,8 +699,6 @@ export class MapaCamasService { } censoDiario(fecha, unidadOrganizativa): Observable { - console.log('📞 Llamando a censoDiario con:', fecha, unidadOrganizativa); - return this.camasHTTP.censoDiario(fecha, unidadOrganizativa); } diff --git a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.html b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.html index d477be1a59..e2926572a6 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.html +++ b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.html @@ -16,11 +16,11 @@ - + - + @@ -52,7 +52,7 @@ - diff --git a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts index 58ee95bead..9cc006794f 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/cama-detalle/internacion-detalle/internacion-detalle.component.ts @@ -9,6 +9,7 @@ import { PermisosMapaCamasService } from '../../../services/permisos-mapa-camas. import { ListadoInternacionCapasService } from '../../../views/listado-internacion-capas/listado-internacion-capas.service'; import { ListadoInternacionService } from '../../../views/listado-internacion/listado-internacion.service'; import { IngresoPacienteService } from '../../ingreso/ingreso-paciente-workflow/ingreso-paciente-workflow.service'; +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; @Component({ selector: 'app-internacion-detalle', @@ -78,7 +79,6 @@ export class InternacionDetalleComponent implements OnInit, AfterViewChecked { this.editarIngresoIdInternacion = null; this.editarEgreso = false; this.capa = this.mapaCamasService.capa; - this.mapaCamasService.historialInternacion$.subscribe( historial => { if (historial.length && (this.capa === 'estadistica' || historial.some(mov => mov.extras.egreso))) { @@ -92,31 +92,32 @@ export class InternacionDetalleComponent implements OnInit, AfterViewChecked { } ); - // this.mapaCamasService.prestacion$.subscribe(prestacion => { - // this.estadoPrestacion = ''; - // this.existeIngreso = false; - - // if (prestacion) { - // this.estadoPrestacion = prestacion.estadoActual.tipo; - // if (prestacion.ejecucion.registros[0].valor.informeIngreso) { - // this.existeIngreso = true; - // } - // this.existeEgreso = !!prestacion.ejecucion.registros[1]?.valor?.InformeEgreso; - // this.editarEgreso = !this.existeEgreso; - // this.ingresoPacienteService.selectPaciente(prestacion.paciente?.id); - // } - // // loading se setea en true desde el listado de internacion - // this.mapaCamasService.isLoading(false); - // }); - this.mapaCamasService.informeEstadistica$.subscribe(informe => { - if (informe?.paciente?.id) { - this.ingresoPacienteService.selectPaciente(informe.paciente.id); + this.estadoPrestacion = ''; + this.existeIngreso = false; + + if (informe) { + if (informe.estadoActual?.tipo) { + this.estadoPrestacion = informe.estadoActual.tipo; + + } else if (informe.estados && informe.estados.length > 0) { + this.estadoPrestacion = informe.estados[informe.estados.length - 1].tipo; + + } else if (typeof informe.estado === 'string') { + this.estadoPrestacion = informe.estado; + } + this.existeIngreso = !!informe.informeIngreso; - this.estadoPrestacion = informe.estadoActual?.tipo || 'ejecucion'; - this.editarEgreso = !informe.informeEgreso; + + this.existeEgreso = !!informe.informeEgreso; + this.editarEgreso = !this.existeEgreso; + + this.ingresoPacienteService.selectPaciente(informe.paciente?.id); } + + this.mapaCamasService.isLoading(false); }); + // Configura los tabs a mostrar según capa y vista this.mapaCamasService.resumenInternacion$.pipe( map(resumen => { @@ -155,17 +156,18 @@ export class InternacionDetalleComponent implements OnInit, AfterViewChecked { ); this.anular$ = combineLatest([ - this.mapaCamasService.selectedPrestacion, + this.mapaCamasService.informeEstadistica$, this.registraEgreso$, this.mapaCamasService.view, this.mapaCamasService.loading ]).pipe( auditTime(1), - map(([prestacion, registraEgreso, vista, loading]) => { - this.activateOption(this.items[0].key); - return prestacion?.estadoActual?.tipo !== 'validada' && vista === 'listado-internacion' && !loading; + map(([informe, registraEgreso, vista, loading]) => { + const estado = informe?.estadoActual?.tipo; + return estado !== 'validada' && vista === 'listado-internacion' && !loading; }) ); + } onAnularInternacion() { diff --git a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html index 5bd2babec3..0656e00c1b 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html +++ b/src/app/apps/rup/mapa-camas/sidebar/egreso/egresar-paciente.component.html @@ -12,12 +12,13 @@ [max]="fechaMax || (mapaCamasService.fechaActual$ | async)" [min]="fechaMin" (change)="setFecha()" [debounce]="600" grow="full" (typing)="onType()"> - + - + + @@ -59,12 +60,14 @@ [(ngModel)]="registro.valor.InformeEgreso.diasDeEstada" required readonly> + +
- - + +
@@ -28,20 +28,21 @@ Tipo de egreso

{{informeEgreso.tipoEgreso?.nombre}}

+
Organización destino -

{{informeEgreso.UnidadOrganizativaDestino?.nombre}}

+

{{informeEgreso.tipoEgreso?.OrganizacionDestino?.nombre}}

-
+
Diagnostico Principal al egreso -

{{informeEgreso.diagnosticoPrincipal.codigo}} - - {{informeEgreso.diagnosticoPrincipal.nombre}} +

{{informeEgreso.diagnosticos.principal.codigo}} - + {{informeEgreso.diagnosticos.principal.nombre}}

- + Es primera vez:

SI diff --git a/src/app/apps/rup/mapa-camas/sidebar/egreso/informe-egreso.component.ts b/src/app/apps/rup/mapa-camas/sidebar/egreso/informe-egreso.component.ts index 9476bdeacc..f6e5d1d738 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/egreso/informe-egreso.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/egreso/informe-egreso.component.ts @@ -3,8 +3,9 @@ import { IPrestacion } from '../../../../../modules/rup/interfaces/prestacion.in import { Observable } from 'rxjs'; import { MapaCamasService } from '../../services/mapa-camas.service'; import { notNull } from '@andes/shared'; -import { map } from 'rxjs/operators'; - +import { map, tap } from 'rxjs/operators'; +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; +import { IInformeEgreso } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; @Component({ selector: 'app-informe-egreso', templateUrl: './informe-egreso.component.html', @@ -12,9 +13,9 @@ import { map } from 'rxjs/operators'; export class InformeEgresoComponent implements OnInit { prestacion$: Observable; + informe$: Observable; registro$: Observable; informeEgreso$: Observable; - // VARIABLES public prestacionValidada = false; @@ -23,20 +24,29 @@ export class InformeEgresoComponent implements OnInit { ) { } ngOnInit() { - this.prestacion$ = this.mapaCamasService.prestacion$; - this.registro$ = this.prestacion$.pipe( + this.informe$ = this.mapaCamasService.informeEstadistica$; + + this.registro$ = this.informe$.pipe( notNull(), - map((prestacion) => { - return prestacion.ejecucion.registros[1]; - }) + map(informe => informe) ); - this.informeEgreso$ = this.registro$.pipe( + this.informeEgreso$ = this.informe$.pipe( notNull(), - map((registro) => { - return registro.valor.InformeEgreso; - }) + map(informe => informe.informeEgreso || informe.informeEgreso) ); + // this.informeEgreso$ = this.informe$.pipe( + // notNull(), + // tap(informe => { + // console.log('📘 informe completo:', JSON.parse(JSON.stringify(informe))); + // }), + // map(informe => informe.informeEgreso || informe.informeEgreso), + // tap(informeEgreso => { + // console.log('informeEgreso:', JSON.parse(JSON.stringify(informeEgreso))); + // }) + // ); + + } } diff --git a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts index d4b4bbb291..739714073b 100644 --- a/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts +++ b/src/app/apps/rup/mapa-camas/sidebar/ingreso/ingresar-paciente.component.ts @@ -772,11 +772,17 @@ export class IngresarPacienteComponent implements OnInit, OnDestroy { informeIngreso: { ...this.informeIngreso, situacionLaboral: (typeof this.informeIngreso.situacionLaboral === 'string') - ? this.informeIngreso.situacionLaboral - : this.informeIngreso.situacionLaboral?.nombre || null, + ? { + id: this.informeIngreso.situacionLaboral.toLowerCase().replace(/\s+/g, '-'), + nombre: this.informeIngreso.situacionLaboral + } + : this.informeIngreso.situacionLaboral || null, nivelInstruccion: (typeof this.informeIngreso.nivelInstruccion === 'string') - ? this.informeIngreso.nivelInstruccion - : this.informeIngreso.nivelInstruccion?.nombre || null, + ? { + id: this.informeIngreso.nivelInstruccion.toLowerCase().replace(/\s+/g, '-'), + nombre: this.informeIngreso.nivelInstruccion + } + : this.informeIngreso.nivelInstruccion || null, ocupacionHabitual: this.informeIngreso.ocupacionHabitual, asociado: (typeof this.informeIngreso.asociado === 'string') ? this.informeIngreso.asociado diff --git a/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.ts b/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.ts index 98931f84f6..8cd9de747a 100644 --- a/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.ts +++ b/src/app/apps/rup/mapa-camas/views/listado-internacion/listado-internacion.component.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { Component, OnInit } from '@angular/core'; import { Location } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; @@ -12,6 +13,7 @@ import { IngresoPacienteService } from '../../sidebar/ingreso/ingreso-paciente-w import { PermisosMapaCamasService } from '../../services/permisos-mapa-camas.service'; import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; +import { debug } from 'console'; @Component({ selector: 'app-internacion-listado', @@ -129,7 +131,6 @@ export class InternacionListadoComponent implements OnInit { this.listaInternacion$ = this.listadoInternacionService.listaInternacionFiltrada$.pipe( map((res: any) => { - // Si res es un objeto, intentamos extraer el array if (Array.isArray(res)) { return res; } else if (Array.isArray(res?.data)) { @@ -160,19 +161,119 @@ export class InternacionListadoComponent implements OnInit { ); } + + validar(seleccionarInforme: IInformeEstadistica) { + this.plex.confirm('Luego de validar la prestación ya no podrá editarse.
¿Desea continuar?', 'Confirmar validación').then(validar => { + if (validar) { + if (seleccionarInforme) { + const id = seleccionarInforme._id; + console.log('🔵 Enviando a validarInforme() el ID:', id); + + const egresoExiste = seleccionarInforme.informeEgreso; + const ultimoEstado = seleccionarInforme.estados[seleccionarInforme.estados.length - 1].tipo; + console.log('🟨 Último estado:', ultimoEstado); + if (egresoExiste && ultimoEstado !== 'validada') { + if (egresoExiste.fechaEgreso && egresoExiste.tipoEgreso && + egresoExiste.diagnosticos?.principal) { + this.informeEstadisticaService.validarInforme(id).subscribe({ + next: prestacion => { + this.mapaCamasService.selectInformeEstadistica(seleccionarInforme); + this.verificarPrestacion(prestacion); + this.listadoInternacionService.refresh.next(true); + }, + error: () => this.plex.info('danger', 'ERROR: No es posible validar la informre') + }); + } else { + this.plex.info('danger', 'ERROR: Faltan datos'); + } + } else { + this.plex.info('danger', 'ERROR: Debe completar los datos mínimos de egreso para validar la internación'); + } + } + } + }); + } + + verificarPrestacion(informe: IInformeEstadistica) { + this.puedeValidar = false; + this.puedeRomper = false; + if (informe) { + if (informe.estados[informe.estados.length - 1].tipo !== 'validada') { + const informeEgreso = informe.informeEgreso; + if (informeEgreso) { + if (informeEgreso.fechaEgreso && informeEgreso.tipoEgreso && informeEgreso.diagnosticos?.principal) { + this.puedeValidar = true; + } + } + } else { + this.puedeRomper = true; + } + + } + } devuelveFecha(internacion: IInformeEstadistica, tipo: 'ingreso' | 'egreso') { return tipo === 'ingreso' ? internacion.informeIngreso?.fechaIngreso : internacion.informeEgreso?.fechaEgreso || null; } + romperValidacion(seleccionarInforme: IInformeEstadistica,) { + this.plex.confirm('Esta acción puede traer consecuencias
¿Desea continuar?', 'Romper validación').then(validar => { + if (validar) { + const cambioEstado: any = { + op: 'romperValidacion', + desdeInternacion: true + }; + // En api el estado de la prestación cambia a ejecucion + this.informeEstadisticaService.patch(seleccionarInforme.id, cambioEstado).subscribe({ + next: informe => { + this.mapaCamasService.selectInformeEstadistica(informe); + this.verificarInforme(informe); + this.listadoInternacionService.refresh.next(true); + }, + error: () => this.plex.toast('danger', 'ERROR: No es posible romper la validación de la prestación') + }); + } + }); + } + + verificarInforme(informe: IInformeEstadistica) { + this.puedeValidar = false; + this.puedeRomper = false; + if (informe) { + if (informe) { + if (informe.estados[informe.estados.length - 1].tipo !== 'validada') { + const informeEgreso = informe.informeEgreso; + if (informeEgreso) { + if (informeEgreso.fechaEgreso && informeEgreso.tipoEgreso && informeEgreso.diagnosticos?.principal) { + this.puedeValidar = true; + } + } + } else { + this.puedeRomper = true; + } + } + } + } + seleccionarInforme(informe: IInformeEstadistica, selected: IInformeEstadistica) { + + const id = informe.id || informe._id; + const selectedId = selected?.id || selected?._id; + if (this.mostrar === 'datosInternacion') { - if (selected?.id === informe.id) { + + if (selectedId === id) { this.mapaCamasService.selectInformeEstadistica(null); this.mapaCamasService.select(null); } else { - this.mapaCamasService.selectInformeEstadistica(informe); - this.mapaCamasService.setFecha(informe.informeIngreso?.fechaIngreso); - this.ingresoPacienteService.selectPaciente(informe.paciente.id); + const informeNormalizado = { + ...informe, + id, + _id: id + }; + + this.mapaCamasService.selectInformeEstadistica(informeNormalizado); + this.mapaCamasService.setFecha(informeNormalizado.informeIngreso?.fechaIngreso); + this.ingresoPacienteService.selectPaciente(informeNormalizado.paciente.id); this.mapaCamasService.isLoading(true); } } @@ -206,23 +307,13 @@ export class InternacionListadoComponent implements OnInit { this.location.back(); } - buscando(valor: any) { - this.estaBuscando = true; + onAccion($event) { + this.editando = $event?.accion === 'editando'; + } - if (typeof valor !== 'object') { - console.warn('⚠️ Valor no válido para el filtrado:', valor); - this.estaBuscando = false; - return; - } - this.listadoInternacionService.listaInternacion$.subscribe({ - next: (data) => { - const filtrados = this.listadoInternacionService.filtrarInformesEstadistica(data, valor); - this.estaBuscando = false; - }, - error: (err) => { - this.estaBuscando = false; - } - }); + buscando(valor) { + this.estaBuscando = valor; } + } diff --git a/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts b/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts index 0cc875df1a..ccd6a34bb8 100644 --- a/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts +++ b/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts @@ -1,3 +1,5 @@ +/* eslint-disable no-debugger */ +/* eslint-disable no-console */ import { Auth } from '@andes/auth'; import { Plex } from '@andes/plex'; import { AfterContentInit, Component, EventEmitter, Input, OnInit, Optional, Output, ViewEncapsulation } from '@angular/core'; @@ -19,8 +21,8 @@ import { getSemanticClass } from '../../pipes/semantic-class.pipes'; import { EmitConcepto, RupEjecucionService } from '../../services/ejecucion.service'; import { HUDSService } from '../../services/huds.service'; import { PrestacionesService } from './../../services/prestaciones.service'; - -@Component({ +import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; +import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; @Component({ selector: 'rup-hudsBusqueda', templateUrl: 'hudsBusqueda.html', styleUrls: ['hudsBusqueda.scss', 'buscador.scss'], @@ -64,12 +66,14 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { public tiposPrestacion = []; public prestacionSeleccionada = []; private _prestaciones: any = []; + private _prestacionesEstadisticas: any = []; private prestacionesCopia: any = []; + private prestacionesEstadisticasCopia: any = []; private internaciones; - get prestaciones() { - return this._prestaciones; - } + // get prestaciones() { + // return this._prestaciones; + // } set prestaciones(value) { this._prestaciones = value.sort((a, b) => { @@ -181,6 +185,7 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { constructor( public servicioPrestacion: PrestacionesService, + public informeEstadisticoService: InformeEstadisticaService, public plex: Plex, public auth: Auth, public huds: HUDSService, @@ -352,35 +357,65 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { listarInternaciones() { let request; + + console.log('📌 [listarInternaciones] Buscando internaciones...'); + console.log('➡️ Paciente:', this.paciente); + console.log('➡️ Fecha inicio:', this.fechaInicio); + console.log('➡️ Fecha fin:', this.fechaFin); + if (this.paciente.idPacientePrincipal) { + console.log('👥 Es un paciente con vinculación → usando paciente principal'); + request = this.getPacientePrincipal(this.paciente.idPacientePrincipal).pipe( - switchMap((paciente: IPaciente) => this.resumenHTTP.search({ - ingreso: this.resumenHTTP.queryDateParams(this.fechaInicio, this.fechaFin), - paciente: paciente.vinculos - })) + switchMap((paciente: IPaciente) => { + console.log('🔗 Paciente principal obtenido:', paciente); + + return this.resumenHTTP.search({ + ingreso: this.resumenHTTP.queryDateParams(this.fechaInicio, this.fechaFin), + paciente: paciente.vinculos, + }); + }) ); } else { + console.log('👤 Paciente normal → búsqueda directa'); + request = this.resumenHTTP.search({ ingreso: this.resumenHTTP.queryDateParams(this.fechaInicio, this.fechaFin), paciente: this.paciente.vinculos || this.paciente.id }); } - request.subscribe((internaciones) => this.internaciones = internaciones); + + request.subscribe({ + next: (internaciones) => { + console.log('📄 RESULTADO INTERNACIONES:', internaciones); + + if (!internaciones || internaciones.length === 0) { + console.warn('⚠️ No se encontraron internaciones para este paciente.'); + } + + this.internaciones = internaciones; + }, + error: (err) => { + console.error('❌ ERROR en listarInternaciones:', err); + } + }); } listarPrestaciones() { - function groupBy(prestaciones: IPrestacion[]) { + function groupBy(informeEstadistica: IInformeEstadistica[]) { const resultado = []; - const diccionario = {}; - - prestaciones.forEach(p => { - if (p.groupId) { - if (!diccionario[p.groupId]) { - diccionario[p.groupId] = []; + const diccionario: { [key: string]: IInformeEstadistica[] } = {}; + + informeEstadistica.forEach(inf => { + const key = inf.paciente?.id; // 🔥 El equivalente más estable a groupId + console.log('Key para agrupamiento:', key); + if (key) { + if (!diccionario[key]) { + diccionario[key] = []; } - diccionario[p.groupId].push(p); + diccionario[key].push(inf); } else { - resultado.push(p); + resultado.push(inf); } }); @@ -389,9 +424,33 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { return resultado; } + // listarPrestaciones() { + // function groupBy(prestaciones: IPrestacion[]) { + // const resultado = []; + // const diccionario = {}; + + // prestaciones.forEach(p => { + // if (p.groupId) { + // if (!diccionario[p.groupId]) { + // diccionario[p.groupId] = []; + // } + // diccionario[p.groupId].push(p); + // } else { + // resultado.push(p); + // } + // }); + + // Object.values(diccionario).forEach(dc => resultado.push(dc)); + + // return resultado; + // } + + + // this.servicioPrestacion.getByPaciente(this.paciente.id, false).subscribe(prestaciones => { + this.informeEstadisticoService.getByPaciente(this.paciente.id, false).subscribe(prestaciones => { - this.servicioPrestacion.getByPaciente(this.paciente.id, false).subscribe(prestaciones => { this.prestacionesTotales = prestaciones; + console.log('prestaciones', prestaciones); const validadas = prestaciones.filter(p => p.estados[p.estados.length - 1].tipo === 'validada'); this.prestaciones = groupBy(validadas).map(p => { @@ -481,9 +540,18 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { } private cargarSolicitudesMezcladas() { + // Línea 485: this.solicitudesMezcladas = this.solicitudes.concat(this.solicitudesTOP); + console.log('Solicitudes mezcladas:', this.solicitudesMezcladas); + // Línea 486: Inicia el sort this.solicitudesMezcladas.sort((e1, e2) => { + // --- CONSOLE LOG AÑADIDO PARA DEPURACIÓN --- + console.log('Elemento 1 (e1):', e1); + console.log('Elemento 2 (e2):', e2); + // ------------------------------------------- + + // Línea 487: Aquí ocurre el error const fecha1 = e1.fechaEjecucion ? e1.fechaEjecucion : e1.solicitud.fecha; const fecha2 = e2.fechaEjecucion ? e2.fechaEjecucion : e2.solicitud.fecha; return fecha2 - fecha1; @@ -672,7 +740,7 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { filtrarPorInternacion(prestaciones) { const prestacionesEnInternacion = []; - + debugger; const internaciones = this.internaciones?.map(internacion => { const prestacionesPorInternacion = prestaciones.filter(prestacion => { const fechaIngresoValida = moment(prestacion.fecha).isSameOrAfter(internacion.fechaIngreso); @@ -711,7 +779,7 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { }; }) .filter(grupo => grupo.registros.length); - + debugger; this.indiceInternaciones = internaciones?.reverse(); this.filtrarOtrasPrestaciones(prestaciones, prestacionesEnInternacion); @@ -730,7 +798,10 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { this.prestaciones = this.prestaciones.filter(p => p.fecha >= moment(this.fechaInicio).startOf('day').toDate() && p.fecha <= moment(this.fechaFin).endOf('day').toDate()); } - + console.log('Prestaciones Copia:', this.prestacionesCopia); + console.log('Ambito buscado:', this.ambitoOrigen); + console.log('Fecha inicio:', this.fechaInicio); + console.log('Fecha fin:', this.fechaFin); if (this.ambitoOrigen) { this.prestaciones = this.prestaciones.filter(p => p.ambito === this.ambitoOrigen); diff --git a/src/app/modules/rup/components/ejecucion/hudsBusqueda.html b/src/app/modules/rup/components/ejecucion/hudsBusqueda.html index 65f3f8aa0f..02c610627d 100644 --- a/src/app/modules/rup/components/ejecucion/hudsBusqueda.html +++ b/src/app/modules/rup/components/ejecucion/hudsBusqueda.html @@ -6,9 +6,9 @@

+ (click)="filtroBuscador(filtro.key)">
+ [ngClass]="{'active': filtroActual === filtro.key}">
{{getCantidadResultados(filtro.key)}} @@ -23,32 +23,32 @@
+ [title]="showFiltros ? 'Cerrar filtros' : 'Ver filtros'" class="float-right" tooltipPosition="left" + (click)="toogleFiltros()">
+ *ngIf="filtroActual !== 'solicitudes' && filtroActual !== 'planes' && filtroActual !== 'laboratorios' && filtroActual !== 'vacunas' && filtroActual !== 'dominios'">
+ [autoFocus]="true">
+ label="{{filtroTrastornos ? 'Activos' : 'Todos'}}">
@@ -56,22 +56,27 @@
{{ getTitulo(filtroActual) | uppercas + placeholder="Buscar recetas..." [autoFocus]="true">
  • + [ngModel]="seleccionRecetas[iReceta]" name="seleccionada" type="checkbox" + (change)="seleccionarReceta($event, grupo.recetas, iReceta)">
    -
    - - Tratamiento prolongado: {{ (grupo.recetaVisible?.medicamento?.ordenTratamiento !== null && grupo.recetaVisible?.medicamento?.ordenTratamiento !== undefined) ? (grupo.recetaVisible.medicamento.ordenTratamiento + 1) : 0 }} de {{grupo.recetaVisible?.medicamento.tiempoTratamiento?.id}} -
    -
    + + Tratamiento prolongado: {{ (grupo.recetaVisible?.medicamento?.ordenTratamiento !== + null && grupo.recetaVisible?.medicamento?.ordenTratamiento !== undefined) ? + (grupo.recetaVisible.medicamento.ordenTratamiento + 1) : 0 }} de + {{grupo.recetaVisible?.medicamento.tiempoTratamiento?.id}} +
    +
    {{ getTitulo(filtroActual) | uppercas
    Fecha de Registro: - {{ grupo.recetaVisible?.fechaRegistro | date:'short' }} - -
    - Profesional: {{ - grupo.recetaVisible?.profesional.nombre }} {{ - grupo.recetaVisible?.profesional.apellido }} - + {{ grupo.recetaVisible?.fechaRegistro | + date:'short' }} + +
    + Profesional: {{ + grupo.recetaVisible?.profesional.nombre }} {{ + grupo.recetaVisible?.profesional.apellido }} +
    @@ -105,15 +111,18 @@
    {{ getTitulo(filtroActual) | uppercas
    - - {{ grupo.recetaVisible?.estadoActual?.tipo.replace('-', ' ') }} - - - {{ grupo.recetaVisible?.estadoDispensaActual?.tipo.replace('-', ' ') - }} - + + {{ grupo.recetaVisible?.estadoActual?.tipo.replace('-', ' ') + }} + + + {{ + grupo.recetaVisible?.estadoDispensaActual?.tipo.replace('-', + ' ') + }} +
    @@ -131,7 +140,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay recetas registradas">
    @@ -146,11 +155,11 @@
    {{ getTitulo(filtroActual) | uppercas
  • + [ngClass]="{'active': huds.isOpen(registro, 'solicitud') || huds.isOpen(registro, 'concepto'), 'solicitud': true}" + (click)="clickSolicitud(registro, iPrestacion)">
    + [ngClass]="{'active': huds.isOpen(registro, 'solicitud') || huds.isOpen(registro, 'concepto'), 'rup-border-plan': true}">
    @@ -192,17 +201,16 @@
    {{ getTitulo(filtroActual) | uppercas
    + [type]="registro.estadoActual.tipo === 'validada' ? 'success' :'info'" + *ngIf="registro.estadoActual"> {{ registro.estadoActual.tipo }} + icon="information-outline" title="Registrado por profesional" + titlePosition="left"> + icon="information-outline" title="Registrado por gestión" + titlePosition="left">
    @@ -218,7 +226,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay solicitudes registradas">
    @@ -230,11 +238,11 @@
    {{ getTitulo(filtroActual) | uppercas
  • + [ngClass]="{'active': huds.isOpen(registro, 'concepto'), 'solicitud': registro.esSolicitud}" + (click)="emitTabs(registro, 'concepto', iConcepto)">
    + [ngClass]="{'active': huds.isOpen(registro, 'concepto'), 'rup-border-plan': registro.esSolicitud}">
    @@ -278,7 +286,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay hallazgos registrados">
    @@ -290,17 +298,17 @@
    {{ getTitulo(filtroActual) | uppercas
  • + [ngClass]="{'active': huds.isOpen(registro, 'concepto'), 'solicitud': registro.esSolicitud}" + (click)="emitTabs(registro, 'concepto', iConcepto)">
    + [ngClass]="{'active': huds.isOpen(registro, 'concepto'), 'rup-border-plan': registro.esSolicitud}">
    + [dragScope]="'registros-rup'" [dragData]="registro.concepto" + (onDragStart)="dragStart($event)" (onDragEnd)="dragEnd($event)">
    @@ -328,14 +336,14 @@
    {{ getTitulo(filtroActual) | uppercas
    + [type]="registro.evoluciones[0].estado === 'activo' ? 'success' : 'danger'"> {{ registro.evoluciones[0].estado }}
    @@ -351,7 +359,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay trastornos registrados">
    @@ -363,11 +371,11 @@
    {{ getTitulo(filtroActual) | uppercas
  • + [ngClass]="{'active': huds.isOpen(registro, 'concepto'), 'solicitud': registro.esSolicitud}" + (click)="emitTabs(registro, 'concepto', iConcepto)">
    + [ngClass]="{'active': huds.isOpen(registro, 'concepto'), 'rup-border-registro': registro.esSolicitud}">
    @@ -412,7 +420,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay elementos de registros cargados">
    @@ -424,17 +432,17 @@
    {{ getTitulo(filtroActual) | uppercas
  • + [ngClass]="{'active': huds.isOpen(registro, 'concepto'), 'solicitud': registro.esSolicitud}" + (click)="emitTabs(registro, 'concepto', iPrestacion)">
    + [ngClass]="{'active': huds.isOpen(registro, 'concepto'), 'rup-border-plan': registro.esSolicitud}">
    + [class.adi-mano-corazon]="registro.esSolicitud">
    {{ registro.concepto.term }} @@ -472,7 +480,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay procedimientos registrados">
    @@ -484,26 +492,26 @@
    {{ getTitulo(filtroActual) | uppercas
    + idField="conceptId" labelField="term" (change)="filtrar()" [multiple]="true">
    + idField="id" labelField="nombre" (change)="filtrar()">
    + label="Fecha Desde" [debounce]="400">
    + label="Fecha Hasta" [debounce]="400">
    @@ -517,7 +525,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + name="documento">
    Detalle de la internacion
    @@ -535,9 +543,9 @@
    {{ getTitulo(filtroActual) | uppercas
    + class="item-prestacion list-group-item" + [ngClass]="{'activo': huds.someOpen(internacion, iInternacion)}" + (click)="emitTabs(internacion, 'internacion', iInternacion)">
    @@ -545,7 +553,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + size="lg" name="circulo-paciente">

    {{registro.term || 'Evoluciones y otros registros'}}

    @@ -560,7 +568,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + name="documento">
    Prestación fuera de internación
    @@ -576,15 +584,15 @@
    {{ getTitulo(filtroActual) | uppercas
    + class="item-prestacion list-group-item" + [ngClass]="{'activo': huds.someOpen(internacion, iInternacion)}" + (click)="emitTabs(otrasPrestaciones, 'internacion', iInternacion)">
    + class="icon" size="lg" name="mano-gota">
    + class="icon" size="lg" name="pildoras">
    + size="lg" name="circulo-paciente">

    {{indice.term || 'Evoluciones y otros registros'}}

    @@ -597,7 +605,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay prestaciones registradas">
    @@ -607,11 +615,11 @@
    {{ getTitulo(filtroActual) | uppercas
  • + [ngClass]="{'active': huds.isOpen(prestacion.data, prestacion.tipo)}" + (click)="emitTabs(prestacion, prestacion.tipo, iPrestacion)">
    + [ngClass]="{'active': huds.isOpen(prestacion.data, prestacion.tipo)}">
    @@ -645,7 +653,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + [type]=" prestacion.tipo !== 'ficha-epidemiologica' ? 'success' : 'info'"> {{prestacion.estado}}
    @@ -660,7 +668,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay prestaciones registradas">
    @@ -674,7 +682,7 @@
    {{ getTitulo(filtroActual) | uppercas
  • + (click)="emitTabs(registro, 'concepto', iCronico)">
    @@ -700,7 +708,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + [type]="registro.evoluciones[registro.evoluciones.length-1].estado === 'activo' ? 'success' : 'danger'"> {{ registro.evoluciones[registro.evoluciones.length-1].estado }} @@ -717,7 +725,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay productos registrados">
    @@ -730,7 +738,7 @@
    {{ getTitulo(filtroActual) | uppercas
  • + [ngClass]="{'active': huds.isOpen(laboratorio, laboratorio.idProtocolo ? 'laboratorio' : 'cda')}">
    @@ -742,7 +750,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + (click)="emitTabs(laboratorio, laboratorio.idProtocolo ? 'laboratorio' : 'cda', iLaboratorio)">
    {{ @@ -771,7 +779,7 @@
    {{ getTitulo(filtroActual) | uppercas fecha}}
    + class="text-sm"> Médico solicitante: {{ laboratorio?.medicoSolicitante || laboratorio?.profesional }} @@ -793,7 +801,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + titulo="No hay laboratorios registrados">
    @@ -818,7 +826,7 @@
    {{ getTitulo(filtroActual) | uppercas
    + (click)="emitTabs(unaVacuna, 'cda', iVacuna)"> {{ unaVacuna?.prestacion.term }}
    diff --git a/src/app/modules/rup/components/ejecucion/vistaHuds.component.ts b/src/app/modules/rup/components/ejecucion/vistaHuds.component.ts index 23933670d8..f2f90aa279 100644 --- a/src/app/modules/rup/components/ejecucion/vistaHuds.component.ts +++ b/src/app/modules/rup/components/ejecucion/vistaHuds.component.ts @@ -112,6 +112,16 @@ export class VistaHudsComponent implements OnInit, OnDestroy { idPaciente: id }; this.internacione$ = this.serviceMapaCamasHTTP.getPrestacionesInternacion(filtros); + + // DEBUG: Ver qué devuelve el servicio + this.internacione$.subscribe(data => { + console.log('=== DEBUG SERVICIO getPrestacionesInternacion ==='); + console.log('Datos recibidos del servicio:', data); + if (data && data.length > 0) { + console.log('Primera prestación estructura:', data[0]); + } + console.log('==============================================='); + }); this.plex.setNavbarItem(HeaderPacienteComponent, { paciente: this.paciente }); }); }); diff --git a/src/app/modules/rup/components/elementos/internacionEgreso.component.ts b/src/app/modules/rup/components/elementos/internacionEgreso.component.ts index cab5f02cc7..8dcbd3f5cc 100644 --- a/src/app/modules/rup/components/elementos/internacionEgreso.component.ts +++ b/src/app/modules/rup/components/elementos/internacionEgreso.component.ts @@ -1,6 +1,8 @@ +/* eslint-disable no-console */ import { Component, Output, Input, EventEmitter, OnInit } from '@angular/core'; import { RUPComponent } from '../core/rup.component'; import { RupElement } from '.'; +import { BehaviorSubject } from 'rxjs'; @Component({ selector: 'rup-internacionEgreso', @@ -8,13 +10,21 @@ import { RupElement } from '.'; }) @RupElement('InternacionEgresoComponent') export class InternacionEgresoComponent extends RUPComponent implements OnInit { + informeEgreso$ = new BehaviorSubject(null); ngOnInit() { if (!this.registro.valor) { - this.registro.valor = { - InformeEgreso: {} - }; + this.registro.valor = {}; } + + if (!this.registro.valor.InformeEgreso) { + this.registro.valor.InformeEgreso = {}; + } + + // Inicializar observable + this.informeEgreso$.next(this.registro.valor.InformeEgreso); + + console.log('DEBUG - informeEgreso$', this.registro.valor.InformeEgreso); } } diff --git a/src/app/modules/rup/components/huds/listado-internacion-huds.component.ts b/src/app/modules/rup/components/huds/listado-internacion-huds.component.ts index 9c4d3c6b74..012c523ee0 100644 --- a/src/app/modules/rup/components/huds/listado-internacion-huds.component.ts +++ b/src/app/modules/rup/components/huds/listado-internacion-huds.component.ts @@ -21,7 +21,7 @@ export class ListadoInternacionHudsComponent implements OnInit { label: 'Organizacion', sorteable: true, opcional: true, - sort: (a: any, b: any) => a.ejecucion.organizacion.nombre.localeCompare(b.ejecucion.organizacion.nombre) + sort: (a: any, b: any) => a.organizacion.nombre.localeCompare(b.organizacion.nombre) }, { @@ -41,8 +41,8 @@ export class ListadoInternacionHudsComponent implements OnInit { sorteable: true, opcional: true, sort: (a: any, b: any) => { - const fecha1 = moment(a.ejecucion.registros[0].valor.informeIngreso.fechaIngreso); - const fecha2 = moment(b.ejecucion.registros[0].valor.informeIngreso.fechaIngreso); + const fecha1 = moment(a.informeIngreso?.fechaIngreso); + const fecha2 = moment(b.informeIngreso?.fechaIngreso); return fecha1.diff(fecha2); } }, @@ -52,8 +52,8 @@ export class ListadoInternacionHudsComponent implements OnInit { sorteable: true, opcional: true, sort: (a: any, b: any) => { - const fecha1 = a.ejecucion.registros[1].valor.informeEgreso.fechaEgreso || 0; - const fecha2 = b.ejecucion.registros[1].valor.informeEgreso.fechaEgreso || 0; + const fecha1 = a.informeEgreso?.fechaEgreso || 0; + const fecha2 = b.informeEgreso?.fechaEgreso || 0; return fecha1.getTime() - fecha2.getTime(); } }, @@ -63,8 +63,8 @@ export class ListadoInternacionHudsComponent implements OnInit { sorteable: true, opcional: true, sort: (a: any, b: any) => { - const r1 = a.ejecucion.registros[1]?.valor.InformeEgreso.tipoEgreso.nombre || ''; - const r2 = b.ejecucion.registros[1]?.valor.InformeEgreso.tipoEgreso.nombre || ''; + const r1 = a.informeEgreso?.tipoEgreso?.nombre || ''; + const r2 = b.informeEgreso?.tipoEgreso?.nombre || ''; return r1.localeCompare(r2); } @@ -84,11 +84,23 @@ export class ListadoInternacionHudsComponent implements OnInit { } ngOnInit() { + // DEBUG: Ver la estructura completa de las internaciones + console.log('=== DEBUG INTERNACIONES ==='); + console.log('Todas las internaciones:', this.internaciones); + + if (this.internaciones && this.internaciones.length > 0) { + console.log('Primera internación completa:', this.internaciones[0]); + console.log('Tiene ejecucion?:', this.internaciones[0].ejecucion); + console.log('Tiene ejecucion.organizacion?:', this.internaciones[0].ejecucion?.organizacion); + console.log('Tiene informeEstadistica?:', this.internaciones[0].informeEstadistica); + } + console.log('========================='); + this.internacione$ = of(this.internaciones).pipe( map(prestaciones => { return prestaciones.sort((a, b) => { - const fecha1 = moment(a.ejecucion.registros[0].valor.informeIngreso.fechaIngreso); - const fecha2 = moment(b.ejecucion.registros[0].valor.informeIngreso.fechaIngreso); + const fecha1 = moment(a.informeIngreso?.fechaIngreso); + const fecha2 = moment(b.informeIngreso?.fechaIngreso); return fecha2.diff(fecha1); }); }) diff --git a/src/app/modules/rup/components/huds/listado-internacion-huds.html b/src/app/modules/rup/components/huds/listado-internacion-huds.html index 5b1a6f9d35..8ee8b88dcf 100644 --- a/src/app/modules/rup/components/huds/listado-internacion-huds.html +++ b/src/app/modules/rup/components/huds/listado-internacion-huds.html @@ -7,7 +7,7 @@ - {{internacion.ejecucion.organizacion.nombre}} + {{internacion.organizacion?.nombre}} @@ -17,30 +17,30 @@ - {{ internacion.ejecucion.registros[0].valor.informeIngreso.fechaIngreso | fecha }} + {{ internacion.informeIngreso?.fechaIngreso | fecha }} - {{ internacion.ejecucion.registros[0].valor.informeIngreso.fechaIngreso | hora }} + {{ internacion.informeIngreso?.fechaIngreso | hora }} - + - {{ internacion.ejecucion.registros[1].valor.InformeEgreso?.fechaEgreso | fecha }} + {{ internacion.informeEgreso?.fechaEgreso | fecha }} - {{ internacion.ejecucion.registros[1].valor.InformeEgreso?.fechaEgreso | hora }} + {{ internacion.informeEgreso?.fechaEgreso | hora }} - - {{internacion.ejecucion.registros[1].valor.InformeEgreso?.tipoEgreso.nombre}} + + {{internacion.informeEgreso?.tipoEgreso?.nombre}} + (click)="gotoExploracionVisual(internacion.id)"> diff --git a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts index db27d98302..4bd101c772 100644 --- a/src/app/modules/rup/interfaces/informe-estadistica.interface.ts +++ b/src/app/modules/rup/interfaces/informe-estadistica.interface.ts @@ -17,8 +17,8 @@ export interface IInformeIngreso { otraOrganizacion?: string; }; ocupacionHabitual?: IOcupacion | null; - situacionLaboral?: string; - nivelInstruccion?: string; + situacionLaboral?: { id: string; nombre: string } | null; + nivelInstruccion?: { id: string; nombre: string } | null; especialidades?: ISnomedConcept[]; nroCarpeta?: string | null; motivo?: string; @@ -47,6 +47,7 @@ export interface IObraSocial { } export interface IInformeEgreso { + // para analizar _id: any; fechaEgreso?: Date; procedimientosQuirurgicos?: { procedimiento?: ISnomedConcept; @@ -59,7 +60,8 @@ export interface IInformeEgreso { }; diasDeEstada?: number; tipoEgreso?: { - tipo?: string; + id?: string; + nombre?: string; OrganizacionDestino?: Partial; otraOrganizacion?: string; }; diff --git a/src/app/modules/rup/services/informe-estadistica.service.ts b/src/app/modules/rup/services/informe-estadistica.service.ts index 3a4622263c..909bb1c288 100644 --- a/src/app/modules/rup/services/informe-estadistica.service.ts +++ b/src/app/modules/rup/services/informe-estadistica.service.ts @@ -1,6 +1,7 @@ +/* eslint-disable no-console */ import { Injectable } from '@angular/core'; import { Server } from '@andes/shared'; -import { Observable } from 'rxjs'; +import { catchError, Observable, tap, throwError } from 'rxjs'; import { IInformeEstadistica } from '../interfaces/informe-estadistica.interface'; import { HUDSService } from './huds.service'; @@ -11,6 +12,10 @@ export class InformeEstadisticaService { private baseUrl = '/modules/rup/internacion/informe-estadistica'; // Añadimos la URL base del servicio de Prestaciones, donde residen los endpoints de HUDS (Historial Único de Salud). private prestacionesBaseUrl = '/modules/rup/prestaciones'; + private cache: { [key: string]: Observable } = {}; + private cachePrimeraBusqueda: any = {}; + + constructor( private server: Server, @@ -21,7 +26,6 @@ export class InformeEstadisticaService { return this.server.get(this.baseUrl, { params }); } - // Obtiene un informe estadístico por su ID getById(id: string, options: any = {}): Observable { if (typeof options.showError === 'undefined') { options.showError = true; @@ -34,7 +38,71 @@ export class InformeEstadisticaService { return this.server.post(this.baseUrl, data); } + getByPaciente( + idPaciente: string, + recargarCache: boolean = false, + fechaDesde: string | null = null, + fechaHasta: string | null = null + ): Observable { + + const cacheAnterior = { ...this.cachePrimeraBusqueda }; + + // Guardamos los parámetros que se usarán para detectar cambios + this.cachePrimeraBusqueda[idPaciente] = { + idPaciente, + fechaDesde, + fechaHasta + }; + + // Si ya estaba en cache y no pedimos recargar → devolvemos + const mismaBusqueda = + cacheAnterior[idPaciente] && + cacheAnterior[idPaciente].fechaDesde === fechaDesde && + cacheAnterior[idPaciente].fechaHasta === fechaHasta; + if (!recargarCache && mismaBusqueda && this.cache[idPaciente]) { + return this.cache[idPaciente]; + } + + // Construcción de parámetros de la API + const opt: any = { + params: { + paciente: idPaciente + }, + options: { + showError: true + } + }; + + if (fechaDesde) {opt.params['fechaDesde'] = fechaDesde;} + if (fechaHasta) {opt.params['fechaHasta'] = fechaHasta;} + + // Guardamos el observable cacheado + this.cache[idPaciente] = this.server.get(this.baseUrl, opt).pipe( + tap(informes => { + console.log('📘 Informes Estadísticos (getByPaciente):', informes); + }), + catchError(err => { + console.error('❌ Error en informe estadístico (getByPaciente):', err); + return throwError(() => err); + }) + ); + + return this.cache[idPaciente]; + } + + validarInforme(id: string): Observable { + const url = `${this.baseUrl}/${id}/operacion`; + + const dto: any = { + op: 'estadoPush', + estado: { + tipo: 'validada' + } + }; + + return this.server.patch(url, dto); + } patch(id: string, data: Partial): Observable { const url = `${this.baseUrl}/${id}`; return this.server.patch(url, data); diff --git a/src/app/modules/rup/services/prestaciones.service.ts b/src/app/modules/rup/services/prestaciones.service.ts index 92c27520cb..0dc5be75c4 100644 --- a/src/app/modules/rup/services/prestaciones.service.ts +++ b/src/app/modules/rup/services/prestaciones.service.ts @@ -1,5 +1,6 @@ +/* eslint-disable no-console */ -import { map, switchMap } from 'rxjs/operators'; +import { map, switchMap, tap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Observable, BehaviorSubject, of } from 'rxjs'; import { Auth } from '@andes/auth'; @@ -108,7 +109,12 @@ export class PrestacionesService { * @memberof PrestacionesService */ getSolicitudes(params: any): Observable { - return this.server.get(this.prestacionesUrl + '/solicitudes', { params: params, showError: true }); + return this.server.get(this.prestacionesUrl + '/solicitudes', { + params, + showError: true + }).pipe( + tap(res => console.log('🟩 Respuesta de /solicitudes:', res)) + ); } @@ -190,7 +196,7 @@ export class PrestacionesService { this.cache[idPaciente] = this.server.get(this.prestacionesUrl, opt).pipe( map(prestaciones => { prestaciones.forEach(p => populateRelaciones(p)); - + console.log('prestaciones getByPaciente', prestaciones); this.prestacionesSubject.next(prestaciones); return prestaciones; }), From 2f60920aefe47c5f53b4a4508ceec36453b4392c Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Mon, 8 Dec 2025 09:28:12 -0300 Subject: [PATCH 09/14] feat(IN-671):"Nueva vista en huds basados en el nuevos esquema y api" --- .../ejecucion/hudsBusqueda.component.ts | 258 +++++++++--------- .../ejecucion/vistaHuds.component.ts | 19 +- .../rup/components/ejecucion/vistaHuds.html | 47 ++-- .../detalleRegistroInternacion.html | 197 ++++++++++--- ...leRegistroInternaci\303\263n.component.ts" | 104 ++++++- .../listado-internacion-huds.component.ts | 73 ++--- .../huds/vistaInformeEstadistico.html | 112 ++++++++ .../huds/vistaInformeEstadistico.scss | 29 ++ .../huds/vistaInformeEstadistico.ts | 44 +++ src/app/modules/rup/huds-lib.module.ts | 7 +- .../services/informe-estadistica.service.ts | 4 +- src/app/services/receta.service.ts | 1 - 12 files changed, 633 insertions(+), 262 deletions(-) create mode 100644 src/app/modules/rup/components/huds/vistaInformeEstadistico.html create mode 100644 src/app/modules/rup/components/huds/vistaInformeEstadistico.scss create mode 100644 src/app/modules/rup/components/huds/vistaInformeEstadistico.ts diff --git a/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts b/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts index ccd6a34bb8..fb539ed3d9 100644 --- a/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts +++ b/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts @@ -1,14 +1,14 @@ -/* eslint-disable no-debugger */ -/* eslint-disable no-console */ import { Auth } from '@andes/auth'; import { Plex } from '@andes/plex'; import { AfterContentInit, Component, EventEmitter, Input, OnInit, Optional, Output, ViewEncapsulation } from '@angular/core'; +import { Router } from '@angular/router'; import * as moment from 'moment'; import { LaboratorioService } from 'src/app/services/laboratorio.service'; import { RecetaService } from 'src/app/services/receta.service'; import { Observable, forkJoin } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { InternacionResumenHTTP } from 'src/app/apps/rup/mapa-camas/services/resumen-internacion.http'; +import { InformeEstadisticaService } from '../../services/informe-estadistica.service'; import { IPaciente } from 'src/app/core/mpi/interfaces/IPaciente'; import { PacienteService } from 'src/app/core/mpi/services/paciente.service'; import { SECCION_CLASIFICACION } from 'src/app/modules/epidemiologia/constantes'; @@ -21,8 +21,8 @@ import { getSemanticClass } from '../../pipes/semantic-class.pipes'; import { EmitConcepto, RupEjecucionService } from '../../services/ejecucion.service'; import { HUDSService } from '../../services/huds.service'; import { PrestacionesService } from './../../services/prestaciones.service'; -import { InformeEstadisticaService } from 'src/app/modules/rup/services/informe-estadistica.service'; -import { IInformeEstadistica } from 'src/app/modules/rup/interfaces/informe-estadistica.interface'; @Component({ + +@Component({ selector: 'rup-hudsBusqueda', templateUrl: 'hudsBusqueda.html', styleUrls: ['hudsBusqueda.scss', 'buscador.scss'], @@ -66,14 +66,12 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { public tiposPrestacion = []; public prestacionSeleccionada = []; private _prestaciones: any = []; - private _prestacionesEstadisticas: any = []; private prestacionesCopia: any = []; - private prestacionesEstadisticasCopia: any = []; private internaciones; - // get prestaciones() { - // return this._prestaciones; - // } + get prestaciones() { + return this._prestaciones; + } set prestaciones(value) { this._prestaciones = value.sort((a, b) => { @@ -185,12 +183,13 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { constructor( public servicioPrestacion: PrestacionesService, - public informeEstadisticoService: InformeEstadisticaService, public plex: Plex, public auth: Auth, public huds: HUDSService, private formEpidemiologiaService: FormsEpidemiologiaService, private resumenHTTP: InternacionResumenHTTP, + private informeEstadisticaService: InformeEstadisticaService, + private router: Router, @Optional() private ejecucionService: RupEjecucionService, private pacienteService: PacienteService, private laboratorioService: LaboratorioService, @@ -334,9 +333,29 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { break; case 'internacion': gtag('huds-open', 'rup', 'internacion', index); - registro.id = registro.id; - registro.tipo = 'internacion'; - registro.index = index; + + // Verificar si es un informe estadístico + if (registro.registros && registro.registros[index]?.esInformeEstadistico) { + // Marcar como internación para que abra la pestaña correcta + // El componente detalleRegistroInternacion detectará que es estadístico + registro.tipo = 'internacion'; + registro.index = index; + // Agregar todas las propiedades necesarias en data + if (!registro.data) { + registro.data = {}; + } + registro.data.id = registro.id; + registro.data.index = index; + registro.data.registros = registro.registros; + registro.data.fechaIngreso = registro.fechaIngreso; + registro.data.prestaciones = registro.prestaciones; // Agregar prestaciones filtradas + registro.data.esInformeEstadistico = true; + } else { + // Prestaciones normales de internación + registro.id = registro.id; + registro.tipo = 'internacion'; + registro.index = index; + } break; case 'laboratorio': gtag('huds-open', tipo, 'laboratorio', index); @@ -356,66 +375,53 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { } listarInternaciones() { - let request; - - console.log('📌 [listarInternaciones] Buscando internaciones...'); - console.log('➡️ Paciente:', this.paciente); - console.log('➡️ Fecha inicio:', this.fechaInicio); - console.log('➡️ Fecha fin:', this.fechaFin); - - if (this.paciente.idPacientePrincipal) { - console.log('👥 Es un paciente con vinculación → usando paciente principal'); + // Usar el nuevo servicio de informes estadísticos + const params: any = { + idPaciente: this.paciente.id, // IMPORTANTE: Filtrar por paciente + estado: 'validada' // Solo internaciones validadas + }; + + // Agregar filtros de fecha si existen + if (this.fechaInicio) { + params.fechaDesde = this.fechaInicio; + } + if (this.fechaFin) { + params.fechaHasta = this.fechaFin; + } - request = this.getPacientePrincipal(this.paciente.idPacientePrincipal).pipe( - switchMap((paciente: IPaciente) => { - console.log('🔗 Paciente principal obtenido:', paciente); - return this.resumenHTTP.search({ - ingreso: this.resumenHTTP.queryDateParams(this.fechaInicio, this.fechaFin), - paciente: paciente.vinculos, - }); - }) - ); - } else { - console.log('👤 Paciente normal → búsqueda directa'); - request = this.resumenHTTP.search({ - ingreso: this.resumenHTTP.queryDateParams(this.fechaInicio, this.fechaFin), - paciente: this.paciente.vinculos || this.paciente.id - }); - } + this.informeEstadisticaService.search(params).subscribe((informes) => { - request.subscribe({ - next: (internaciones) => { - console.log('📄 RESULTADO INTERNACIONES:', internaciones); - if (!internaciones || internaciones.length === 0) { - console.warn('⚠️ No se encontraron internaciones para este paciente.'); + // Mapear IInformeEstadistica a la estructura esperada por filtrarPorInternacion + this.internaciones = informes.map(informe => ({ + id: informe._id || informe.id, // MongoDB usa _id + fechaIngreso: informe.informeIngreso.fechaIngreso, + fechaEgreso: informe.informeEgreso?.fechaEgreso, + organizacion: { + id: informe.organizacion._id || informe.organizacion.id, + nombre: informe.organizacion.nombre } + })); + - this.internaciones = internaciones; - }, - error: (err) => { - console.error('❌ ERROR en listarInternaciones:', err); - } }); } listarPrestaciones() { - function groupBy(informeEstadistica: IInformeEstadistica[]) { + function groupBy(prestaciones: IPrestacion[]) { const resultado = []; - const diccionario: { [key: string]: IInformeEstadistica[] } = {}; - - informeEstadistica.forEach(inf => { - const key = inf.paciente?.id; // 🔥 El equivalente más estable a groupId - console.log('Key para agrupamiento:', key); - if (key) { - if (!diccionario[key]) { - diccionario[key] = []; + const diccionario = {}; + + prestaciones.forEach(p => { + if (p.groupId) { + if (!diccionario[p.groupId]) { + diccionario[p.groupId] = []; } - diccionario[key].push(inf); + diccionario[p.groupId].push(p); } else { - resultado.push(inf); + resultado.push(p); } }); @@ -424,33 +430,9 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { return resultado; } - // listarPrestaciones() { - // function groupBy(prestaciones: IPrestacion[]) { - // const resultado = []; - // const diccionario = {}; - - // prestaciones.forEach(p => { - // if (p.groupId) { - // if (!diccionario[p.groupId]) { - // diccionario[p.groupId] = []; - // } - // diccionario[p.groupId].push(p); - // } else { - // resultado.push(p); - // } - // }); - - // Object.values(diccionario).forEach(dc => resultado.push(dc)); - - // return resultado; - // } - - - // this.servicioPrestacion.getByPaciente(this.paciente.id, false).subscribe(prestaciones => { - this.informeEstadisticoService.getByPaciente(this.paciente.id, false).subscribe(prestaciones => { + this.servicioPrestacion.getByPaciente(this.paciente.id, false).subscribe(prestaciones => { this.prestacionesTotales = prestaciones; - console.log('prestaciones', prestaciones); const validadas = prestaciones.filter(p => p.estados[p.estados.length - 1].tipo === 'validada'); this.prestaciones = groupBy(validadas).map(p => { @@ -540,18 +522,9 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { } private cargarSolicitudesMezcladas() { - // Línea 485: this.solicitudesMezcladas = this.solicitudes.concat(this.solicitudesTOP); - console.log('Solicitudes mezcladas:', this.solicitudesMezcladas); - // Línea 486: Inicia el sort this.solicitudesMezcladas.sort((e1, e2) => { - // --- CONSOLE LOG AÑADIDO PARA DEPURACIÓN --- - console.log('Elemento 1 (e1):', e1); - console.log('Elemento 2 (e2):', e2); - // ------------------------------------------- - - // Línea 487: Aquí ocurre el error const fecha1 = e1.fechaEjecucion ? e1.fechaEjecucion : e1.solicitud.fecha; const fecha2 = e2.fechaEjecucion ? e2.fechaEjecucion : e2.solicitud.fecha; return fecha2 - fecha1; @@ -740,20 +713,42 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { filtrarPorInternacion(prestaciones) { const prestacionesEnInternacion = []; - debugger; - const internaciones = this.internaciones?.map(internacion => { + this.indiceInternaciones = []; + + this.internaciones?.forEach((internacion) => { + + // Log de la primera prestación para ver su estructura + if (prestaciones.length > 0) { + const ejemploPrestacion = prestaciones[0]; + // Verificar por qué no coincide + const fechaIngresoValida = moment(ejemploPrestacion.fecha).isSameOrAfter(internacion.fechaIngreso); + const fechaEgresoValida = internacion.fechaEgreso + ? moment(ejemploPrestacion.fecha).isSameOrBefore(internacion.fechaEgreso) + : moment(ejemploPrestacion.fecha).isSameOrBefore(moment().toDate()); + const organizacionValida = internacion.organizacion?.id + ? internacion.organizacion.id === ejemploPrestacion.organizacion + : internacion.organizacion === ejemploPrestacion.data?.solicitud?.organizacion?.nombre; + + } + + // Buscar prestaciones que coincidan con esta internación por fecha y organización const prestacionesPorInternacion = prestaciones.filter(prestacion => { const fechaIngresoValida = moment(prestacion.fecha).isSameOrAfter(internacion.fechaIngreso); - const fechaEgresoValida = internacion.fechaEgreso ? moment(prestacion.fecha).isSameOrBefore(internacion.fechaEgreso) : moment(prestacion.fecha).isSameOrBefore(moment().toDate()); - const organizacionValida = internacion.organizacion.id === prestacion.organizacion; + const fechaEgresoValida = internacion.fechaEgreso + ? moment(prestacion.fecha).isSameOrBefore(internacion.fechaEgreso) + : moment(prestacion.fecha).isSameOrBefore(moment().toDate()); + + // Comparar organización (puede ser ID u objeto) + const organizacionValida = internacion.organizacion?.id + ? internacion.organizacion.id === prestacion.organizacion + : internacion.organizacion === prestacion.data?.solicitud?.organizacion?.nombre; - if (fechaIngresoValida && fechaEgresoValida && organizacionValida) { - prestacionesEnInternacion.push(prestacion); + const coincide = fechaIngresoValida && fechaEgresoValida && organizacionValida; - return prestacion; - } else { return null; } + return coincide; }); + const indicePrestaciones = prestacionesPorInternacion.reduce((grupo, prestacion) => { return ({ ...grupo, [prestacion.data.id]: prestacion }); }, {}); @@ -761,47 +756,58 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { const registros = prestacionesPorInternacion.flatMap((prestacion) => prestacion.data.ejecucion.registros); const grupoRegistros = registros.reduce((grupo, registro) => { - const dataRegistro = { conceptId: registro.concepto.conceptId, term: registro.concepto.term, id: registro.id, idPrestacion: registro.idPrestacion }; + const dataRegistro = { + conceptId: registro.concepto.conceptId, + term: registro.concepto.term, + id: registro.id, + idPrestacion: registro.idPrestacion + }; if (this.planIndicaciones.includes(registro.concepto.conceptId)) { return ({ ...grupo, [registro.concepto.conceptId]: dataRegistro }); } - return ({ ...grupo, ['otras']: { ...grupo['otras'], [registro.idPrestacion]: { ...indicePrestaciones[registro.idPrestacion] } } }); + return ({ + ...grupo, + ['otras']: { + ...grupo['otras'], + [registro.idPrestacion]: { ...indicePrestaciones[registro.idPrestacion] } + } + }); }, {}); - return { + const registrosArray = Object.values(grupoRegistros); + + + + // Si no hay registros (internación estadística sin prestaciones), crear un registro especial + if (registrosArray.length === 0) { + + registrosArray.push({ + conceptId: 'informe-estadistico', + term: 'Evoluciones y otros registros', + id: internacion.id, + esInformeEstadistico: true + }); + } + + this.indiceInternaciones.push({ id: internacion.id, fechaIngreso: internacion.fechaIngreso, fechaEgreso: internacion.fechaEgreso, - organizacion: internacion.organizacion.nombre, - registros: Object.values(grupoRegistros) - }; - }) - .filter(grupo => grupo.registros.length); - debugger; - this.indiceInternaciones = internaciones?.reverse(); + organizacion: internacion.organizacion?.nombre || internacion.organizacion, + registros: registrosArray, + prestaciones: prestacionesPorInternacion // Agregar las prestaciones filtradas + }); + }); + + this.filtrarOtrasPrestaciones(prestaciones, prestacionesEnInternacion); } filtrar() { - this.prestaciones = this.prestacionesCopia.slice(); - if (this.prestacionSeleccionada && this.prestacionSeleccionada.length > 0) { - const prestacionesTemp = this.prestacionSeleccionada.map(e => e.conceptId); - this.prestaciones = this.prestaciones.filter(p => prestacionesTemp.find(e => e === p.prestacion.conceptId)); - } - if (this.fechaInicio || this.fechaFin) { - this.fechaInicio = this.fechaInicio ? this.fechaInicio : new Date(); - this.fechaFin = this.fechaFin ? this.fechaFin : new Date(); - this.prestaciones = this.prestaciones.filter(p => p.fecha >= moment(this.fechaInicio).startOf('day').toDate() && - p.fecha <= moment(this.fechaFin).endOf('day').toDate()); - } - console.log('Prestaciones Copia:', this.prestacionesCopia); - console.log('Ambito buscado:', this.ambitoOrigen); - console.log('Fecha inicio:', this.fechaInicio); - console.log('Fecha fin:', this.fechaFin); if (this.ambitoOrigen) { this.prestaciones = this.prestaciones.filter(p => p.ambito === this.ambitoOrigen); diff --git a/src/app/modules/rup/components/ejecucion/vistaHuds.component.ts b/src/app/modules/rup/components/ejecucion/vistaHuds.component.ts index f2f90aa279..1ecca25c38 100644 --- a/src/app/modules/rup/components/ejecucion/vistaHuds.component.ts +++ b/src/app/modules/rup/components/ejecucion/vistaHuds.component.ts @@ -4,6 +4,7 @@ import { Location } from '@angular/common'; import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; import { MapaCamasHTTP } from 'src/app/apps/rup/mapa-camas/services/mapa-camas.http'; import { HeaderPacienteComponent } from '../../../../components/paciente/headerPaciente.component'; import { IPaciente } from '../../../../core/mpi/interfaces/IPaciente'; @@ -109,19 +110,13 @@ export class VistaHudsComponent implements OnInit, OnDestroy { const filtros = { fechaIngresoDesde: moment('2016-01-01').toDate(), - idPaciente: id + idPaciente: id, + estado: 'validada' // Solo mostrar internaciones validadas }; - this.internacione$ = this.serviceMapaCamasHTTP.getPrestacionesInternacion(filtros); - - // DEBUG: Ver qué devuelve el servicio - this.internacione$.subscribe(data => { - console.log('=== DEBUG SERVICIO getPrestacionesInternacion ==='); - console.log('Datos recibidos del servicio:', data); - if (data && data.length > 0) { - console.log('Primera prestación estructura:', data[0]); - } - console.log('==============================================='); - }); + this.internacione$ = this.serviceMapaCamasHTTP.getPrestacionesInternacion(filtros).pipe( + tap(internaciones => { + }) + ); this.plex.setNavbarItem(HeaderPacienteComponent, { paciente: this.paciente }); }); }); diff --git a/src/app/modules/rup/components/ejecucion/vistaHuds.html b/src/app/modules/rup/components/ejecucion/vistaHuds.html index 19ee4a6cfc..9a29caef36 100644 --- a/src/app/modules/rup/components/ejecucion/vistaHuds.html +++ b/src/app/modules/rup/components/ejecucion/vistaHuds.html @@ -5,9 +5,9 @@
    + *ngIf="elementosRUPService.ready | async"> + type="info" size="sm" class="mr-2" (click)="onExploracionClick()"> @@ -17,7 +17,7 @@ + esTab="true"> @@ -46,36 +46,36 @@ + [color]="registro.data.class" *ngIf="registro.tipo === 'concepto'"> + [registro]="registro.data" [paciente]="paciente"> + [registro]="registro.data" [paciente]="paciente"> + [paciente]="paciente"> + [class]="registro.data.class" color="solicitud" *ngIf="registro.tipo === 'rup'"> - + + color="solicitud"> + [paciente]="paciente"> + [class]="registro.data.class" color="solicitud" *ngIf="registro.tipo === 'rup-group'"> @@ -84,42 +84,41 @@ + label="Informe de Laboratorio"> + [class]="registro.class" *ngIf="registro.tipo === 'solicitud'"> + [label]="registro.data.prestacion.snomed.term" [class]="registro.data.class"> + + *ngIf="registro.tipo === 'ficha-epidemiologica'"> + [paciente]="paciente" [fichaPaciente]="registro.data" [editFicha]="false" + [fichaName]="registro.data.type.name" [hideVolver]="true" [accesoHuds]="true"> + [paciente]="paciente" [fichaPaciente]="registro.data" [editFicha]="false" + [fichaName]="registro.data.type.name" [volverBuscador]="false" [accesoHuds]="true"> + [class]="registro.data.class"> + [label]="recetaService.getLabel(registro.data.recetas)"> diff --git a/src/app/modules/rup/components/huds/internacion/detalleRegistroInternacion.html b/src/app/modules/rup/components/huds/internacion/detalleRegistroInternacion.html index 40468ffa14..fd9a482f45 100644 --- a/src/app/modules/rup/components/huds/internacion/detalleRegistroInternacion.html +++ b/src/app/modules/rup/components/huds/internacion/detalleRegistroInternacion.html @@ -1,36 +1,37 @@
    +
    + case="capitalize" titulo="Fecha De Validación" + subtitulo="{{ prestacion.estadoActual.createdAt | date: 'EEE dd/MM/yyyy HH:mm' }}"> + titulo="Organización que Valida" + subtitulo="{{ prestacion.estadoActual.createdBy.organizacion.nombre}}">
    + titulo="Profesional que inicia" + subtitulo="{{ prestacion.solicitud.profesional | nombre }}"> + titulo="Organización Ejecutante" subtitulo="{{ prestacion.solicitud.organizacion.nombre }}"> + subtitulo="{{ prestacion.solicitud.ambitoOrigen }}">
    + label="{{ mostrarMas ? 'Ocultar' : 'Mostrar más' }}" justify="center" (click)="mostrar()"> @@ -39,6 +40,40 @@
    + + +
    +

    🐛 DEBUG INFO

    +
    +

    Tipo: {{ tipo }}

    +

    Total Registros: {{ registro?.length || 0 }}

    +

    Total Paginación: {{ paginacion?.length || 0 }}

    +

    Es Informe Estadístico: {{ informeEstadistico ? 'SÍ' : 'NO' }}

    +

    Loading Informe: {{ loadingInforme ? 'SÍ' : 'NO' }}

    +

    Página Actual: {{ pagina }} / {{ totalPaginas() }}

    +
    +
    + Ver Registro Completo (JSON) + +
    {{ registro | json }}
    +
    +
    + Ver Paginación (JSON) +
    {{ paginacion | json }}
    +
    +
    + Ver Informe Estadístico (JSON) + +
    {{ informeEstadistico | json }}
    +
    +
    +
    + +
    {{ registro.length }} resultados, página {{ pagina < 1 ? '1' : pagina> totalPaginas() @@ -46,19 +81,19 @@ totalPaginas() : pagina }} de {{ totalPaginas() }} + icon="chevron-double-left"> + icon="pico-izquierda"> + class="selector-pagina {{ paginaInvalida ? 'has-danger' : '' }}"> + icon="pico-derecha"> + icon="chevron-double-right">
    El número de página no puede ser mayor que {{ totalPaginas() }} @@ -76,19 +111,19 @@ totalPaginas() : pagina }} de {{ totalPaginas() }} + icon="chevron-double-left"> + icon="pico-izquierda"> + class="selector-pagina {{ paginaInvalida ? 'has-danger' : '' }}"> + icon="pico-derecha"> + icon="chevron-double-right">
    El número de página no puede ser mayor que {{ totalPaginas() }} @@ -96,36 +131,45 @@
    +
    - +
    + subtitulo="{{ prestacion.data.estadoActual.createdAt | date: 'EEE dd/MM/yyyy HH:mm' }}"> -
    +
    + titulo="Profesional que valida" + subtitulo="{{ prestacion.data.solicitud.profesional | nombre }}"> + case="capitalize" titulo="Unidad organizativa" + subtitulo="{{ prestacion.data.unidadOrganizativa?.term || 'Sin unidad organizativa' }}"> + +
    +
    +
    + icon="{{ colapsable.includes(iPrestacion) ? 'chevron-up' : 'chevron-down'}}">
    -
    + +
    @@ -137,7 +181,7 @@ {{ elemento.nombre[0].toUpperCase() + elemento.nombre.slice(1) }}
    + *ngIf="elemento?.relacionadoCon && elemento?.relacionadoCon.length > 1"> Relacionado con: @@ -147,8 +191,9 @@
    - + Relacionado con: {{ elemento.relacionadoCon[0].concepto?.term[0].toUpperCase() + elemento.relacionadoCon[0].concepto?.term.slice(1)}} @@ -169,10 +214,10 @@
    + [params]="elementosRUPService.getParams(elemento)" + [prestacion]="prestacion.data" [registro]="elemento" + [paciente]="prestacion.data.paciente" [soloValores]="true" + [vistaHUDS]="false">
    @@ -181,6 +226,78 @@
    + + +
    + +
    + + + Documento De Solicitud De Admisión + + + + + + + + + + + + + + + + + +
    + + +
    + + + Alta Del Paciente + + + + + + + + + + + + +
    + Diagnóstico Principal al egreso: +

    {{ prestacion.informe.informeEgreso.diagnosticoPrincipal.term }}

    +
    + +
    + Otros diagnósticos: +
      +
    • + {{ diagnostico.term }} +
    • +
    +
    +
    +
    diff --git "a/src/app/modules/rup/components/huds/internacion/detalleRegistroInternaci\303\263n.component.ts" "b/src/app/modules/rup/components/huds/internacion/detalleRegistroInternaci\303\263n.component.ts" index 3ab521bc1a..7d76613741 100644 --- "a/src/app/modules/rup/components/huds/internacion/detalleRegistroInternaci\303\263n.component.ts" +++ "b/src/app/modules/rup/components/huds/internacion/detalleRegistroInternaci\303\263n.component.ts" @@ -6,6 +6,8 @@ import { IPaciente } from 'src/app/core/mpi/interfaces/IPaciente'; import { DocumentosService } from 'src/app/services/documentos.service'; import { ElementosRUPService } from '../../../services/elementosRUP.service'; import { PrestacionesService } from '../../../services/prestaciones.service'; +import { InformeEstadisticaService } from '../../../services/informe-estadistica.service'; +import { IInformeEstadistica } from '../../../interfaces/informe-estadistica.interface'; @Component({ selector: 'detalle-registro-internacion', @@ -39,25 +41,62 @@ export class DetalleRegistroInternacionComponent implements OnInit { public paginaInvalida = false; public collapse = false; + // Para internaciones estadísticas + public informeEstadistico: IInformeEstadistica; + public loadingInforme = false; + constructor( public servicioPrestacion: PrestacionesService, public elementosRUPService: ElementosRUPService, private planIndicacionesServices: PlanIndicacionesServices, private servicioDocumentos: DocumentosService, - private auth: Auth + private auth: Auth, + private informeEstadisticaService: InformeEstadisticaService ) { } ngOnInit() { - const { data: { id, index, registros, fechaIngreso } } = this.internacion; + + // HUDSService envuelve el objeto en data, así que puede estar en data.data + const internacionData = this.internacion.data.data || this.internacion.data; + const { id, index, registros, fechaIngreso, esInformeEstadistico, prestaciones } = internacionData; + + + this.puedeDescargarInforme = this.auth.check('huds:impresion'); - this.cargarRegistros(id, registros, index, fechaIngreso); + + // Si es una internación estadística, cargar el informe PRIMERO + if (esInformeEstadistico) { + this.cargarInformeEstadistico(id, () => { + // Cargar registros DESPUÉS de que el informe se haya cargado + this.cargarRegistros(id, registros, index, fechaIngreso, prestaciones); + }); + } else { + this.cargarRegistros(id, registros, index, fechaIngreso, null); + } + } + + cargarInformeEstadistico(id: string, callback?: () => void) { + this.loadingInforme = true; + this.informeEstadisticaService.getById(id).subscribe( + (informe: IInformeEstadistica) => { + this.informeEstadistico = informe; + this.loadingInforme = false; + if (callback) { + callback(); + } + }, + (error) => { + this.loadingInforme = false; + } + ); } esPlanIndicacion(registro) { return registro.conceptId && ['33633005', '430147008'].includes(registro.conceptId); } - cargarRegistros(idInternacion, registros, index, fechaIngreso) { + cargarRegistros(idInternacion, registros, index, fechaIngreso, prestaciones = null) { + this.registro = registros[index]; if (this.esPlanIndicacion(this.registro)) { @@ -65,15 +104,57 @@ export class DetalleRegistroInternacionComponent implements OnInit { this.getIndicaciones(this.registro.conceptId, idInternacion, fechaIngreso); this.getPrestacion(this.registro.idPrestacion); } else { - this.registro = Object.values(this.registro); + // Si es un informe estadístico, usar las prestaciones que vienen de hudsBusqueda + if (this.informeEstadistico && prestaciones) { + + // Crear el objeto de prestación para el informe estadístico + const informePrestacion = { + prestacion: { + term: 'INTERNACIÓN' + }, + data: { + estadoActual: { + createdAt: this.informeEstadistico.informeEgreso?.fechaEgreso || this.informeEstadistico.informeIngreso?.fechaIngreso, + createdBy: { nombreCompleto: 'Sistema' } + } + }, + esInformeEstadistico: true, + informe: this.informeEstadistico + }; + + + // Mapear prestaciones al formato esperado + const prestacionesMapeadas = prestaciones.map((p, idx) => { + const mapped = { + prestacion: p.solicitud?.tipoPrestacion || { term: 'Sin tipo' }, + data: p, + esInformeEstadistico: false + }; + return mapped; + }); + + + + // Agregar el informe al inicio + las prestaciones médicas + this.registro = [informePrestacion, ...prestacionesMapeadas]; - if (idInternacion) { this.tipo = 'registrosInternacion'; + + this.actualizarPaginacion(); } else { - this.tipo = 'fueraDeInternacion'; - } - this.actualizarPaginacion(); + + // Prestaciones normales + this.registro = Object.values(this.registro); + + if (idInternacion) { + this.tipo = 'registrosInternacion'; + } else { + this.tipo = 'fueraDeInternacion'; + } + + this.actualizarPaginacion(); + } } } @@ -141,10 +222,15 @@ export class DetalleRegistroInternacionComponent implements OnInit { } actualizarPaginacion() { + + const startIndex = (this.pagina - 1) * this.sizePagina; const endIndex = startIndex + this.sizePagina; + this.paginacion = this.registro.slice(startIndex, endIndex); + + } primera() { diff --git a/src/app/modules/rup/components/huds/listado-internacion-huds.component.ts b/src/app/modules/rup/components/huds/listado-internacion-huds.component.ts index 012c523ee0..c7fc76eb17 100644 --- a/src/app/modules/rup/components/huds/listado-internacion-huds.component.ts +++ b/src/app/modules/rup/components/huds/listado-internacion-huds.component.ts @@ -1,19 +1,19 @@ - -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, SimpleChanges, OnChanges } from '@angular/core'; import { Router } from '@angular/router'; import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; +import * as moment from 'moment'; +import { IInformeEstadistica } from '../../interfaces/informe-estadistica.interface'; + @Component({ selector: 'listado-internacion-huds', templateUrl: 'listado-internacion-huds.html' }) +export class ListadoInternacionHudsComponent implements OnInit, OnChanges { -export class ListadoInternacionHudsComponent implements OnInit { - - @Input() internaciones: any[]; - - public internacione$: Observable; + @Input() internaciones: IInformeEstadistica[]; + public internacione$: Observable; public columns = [ { @@ -21,15 +21,18 @@ export class ListadoInternacionHudsComponent implements OnInit { label: 'Organizacion', sorteable: true, opcional: true, - sort: (a: any, b: any) => a.organizacion.nombre.localeCompare(b.organizacion.nombre) - + sort: (a: IInformeEstadistica, b: IInformeEstadistica) => { + const org1 = (a.organizacion?.nombre || '') as string; + const org2 = (b.organizacion?.nombre || '') as string; + return org1.localeCompare(org2); + } }, { key: 'unidad_organizativa', label: 'Servicio', sorteable: true, opcional: true, - sort: (a: any, b: any) => { + sort: (a: IInformeEstadistica, b: IInformeEstadistica) => { const u1 = a.unidadOrganizativa?.term || ''; const u2 = b.unidadOrganizativa?.term || ''; return u1.localeCompare(u2); @@ -40,7 +43,7 @@ export class ListadoInternacionHudsComponent implements OnInit { label: 'Fecha Ingreso', sorteable: true, opcional: true, - sort: (a: any, b: any) => { + sort: (a: IInformeEstadistica, b: IInformeEstadistica) => { const fecha1 = moment(a.informeIngreso?.fechaIngreso); const fecha2 = moment(b.informeIngreso?.fechaIngreso); return fecha1.diff(fecha2); @@ -51,10 +54,10 @@ export class ListadoInternacionHudsComponent implements OnInit { label: 'Fecha Egreso', sorteable: true, opcional: true, - sort: (a: any, b: any) => { - const fecha1 = a.informeEgreso?.fechaEgreso || 0; - const fecha2 = b.informeEgreso?.fechaEgreso || 0; - return fecha1.getTime() - fecha2.getTime(); + sort: (a: IInformeEstadistica, b: IInformeEstadistica) => { + const fecha1 = a.informeEgreso?.fechaEgreso ? new Date(a.informeEgreso.fechaEgreso).getTime() : 0; + const fecha2 = b.informeEgreso?.fechaEgreso ? new Date(b.informeEgreso.fechaEgreso).getTime() : 0; + return fecha1 - fecha2; } }, { @@ -62,55 +65,33 @@ export class ListadoInternacionHudsComponent implements OnInit { label: 'razon alta', sorteable: true, opcional: true, - sort: (a: any, b: any) => { + sort: (a: IInformeEstadistica, b: IInformeEstadistica) => { const r1 = a.informeEgreso?.tipoEgreso?.nombre || ''; const r2 = b.informeEgreso?.tipoEgreso?.nombre || ''; return r1.localeCompare(r2); } - }, { key: 'accion', label: 'accion', opcional: true - }, - + } ]; + constructor( private router: Router - ) { - - - } + ) { } ngOnInit() { - // DEBUG: Ver la estructura completa de las internaciones - console.log('=== DEBUG INTERNACIONES ==='); - console.log('Todas las internaciones:', this.internaciones); + } - if (this.internaciones && this.internaciones.length > 0) { - console.log('Primera internación completa:', this.internaciones[0]); - console.log('Tiene ejecucion?:', this.internaciones[0].ejecucion); - console.log('Tiene ejecucion.organizacion?:', this.internaciones[0].ejecucion?.organizacion); - console.log('Tiene informeEstadistica?:', this.internaciones[0].informeEstadistica); + ngOnChanges(changes: SimpleChanges) { + if (changes['internaciones'] && changes['internaciones'].currentValue) { + this.internacione$ = of(this.internaciones); } - console.log('========================='); - - this.internacione$ = of(this.internaciones).pipe( - map(prestaciones => { - return prestaciones.sort((a, b) => { - const fecha1 = moment(a.informeIngreso?.fechaIngreso); - const fecha2 = moment(b.informeIngreso?.fechaIngreso); - return fecha2.diff(fecha1); - }); - }) - ); } - gotoExploracionVisual(idInternacion) { + gotoExploracionVisual(idInternacion: string) { this.router.navigate([`/mapa-camas/internacion/estadistica/resumen/${idInternacion}`]); - } - - } diff --git a/src/app/modules/rup/components/huds/vistaInformeEstadistico.html b/src/app/modules/rup/components/huds/vistaInformeEstadistico.html new file mode 100644 index 0000000000..9aa9e3d2d6 --- /dev/null +++ b/src/app/modules/rup/components/huds/vistaInformeEstadistico.html @@ -0,0 +1,112 @@ +
    + +

    Cargando informe estadístico...

    +
    + +
    + + + +
    + + + + + + +
    + + +
    +
    +
    + + Documento de solicitud de admisión + elemento de registro +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    + + +
    +
    +
    + + Alta del paciente + + Procedimiento / diagnóstico principal + +
    +
    + + + + + + + + + +
    + + +
    + + +
    +
    Otros diagnósticos:
    +
      +
    • + {{ diagnostico.codificacionProfesional?.term || diagnostico.concepto?.term }} +
    • +
    +
    + + +
    +
    Procedimientos quirúrgicos:
    +
      +
    • + {{ procedimiento.concepto?.term }} +
    • +
    +
    +
    +
    +
    +
    + +
    + +
    \ No newline at end of file diff --git a/src/app/modules/rup/components/huds/vistaInformeEstadistico.scss b/src/app/modules/rup/components/huds/vistaInformeEstadistico.scss new file mode 100644 index 0000000000..582c35bb2f --- /dev/null +++ b/src/app/modules/rup/components/huds/vistaInformeEstadistico.scss @@ -0,0 +1,29 @@ +.lista-prestacion { + .rup-card { + border: 1px solid #dee2e6; + border-radius: 4px; + overflow: hidden; + + .rup-header { + display: flex; + align-items: center; + font-size: 14px; + + &.bg-success { + background-color: #28a745 !important; + } + + &.bg-danger { + background-color: #dc3545 !important; + } + } + + .rup-body { + background-color: #f8f9fa; + } + } +} + +.prestacion-label { + margin-bottom: 10px; +} diff --git a/src/app/modules/rup/components/huds/vistaInformeEstadistico.ts b/src/app/modules/rup/components/huds/vistaInformeEstadistico.ts new file mode 100644 index 0000000000..00c169a26c --- /dev/null +++ b/src/app/modules/rup/components/huds/vistaInformeEstadistico.ts @@ -0,0 +1,44 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { IPaciente } from 'src/app/core/mpi/interfaces/IPaciente'; +import { InformeEstadisticaService } from '../../services/informe-estadistica.service'; +import { IInformeEstadistica } from '../../interfaces/informe-estadistica.interface'; + +@Component({ + selector: 'vista-informe-estadistico', + templateUrl: './vistaInformeEstadistico.html', + styleUrls: ['./vistaInformeEstadistico.scss'] +}) +export class VistaInformeEstadisticoComponent implements OnInit { + @Input() informeId: string; + @Input() paciente: IPaciente; + + public informe: IInformeEstadistica; + public loading = true; + + constructor( + private informeEstadisticaService: InformeEstadisticaService + ) { } + + ngOnInit() { + + if (this.informeId) { + this.cargarInforme(); + } else { + this.loading = false; + } + } + + cargarInforme() { + this.loading = true; + + this.informeEstadisticaService.getById(this.informeId).subscribe( + (informe: IInformeEstadistica) => { + this.informe = informe; + this.loading = false; + }, + (error) => { + this.loading = false; + } + ); + } +} diff --git a/src/app/modules/rup/huds-lib.module.ts b/src/app/modules/rup/huds-lib.module.ts index e445751369..d5a834066b 100644 --- a/src/app/modules/rup/huds-lib.module.ts +++ b/src/app/modules/rup/huds-lib.module.ts @@ -37,6 +37,7 @@ import { MotivosHudsService } from 'src/app/services/motivosHuds.service'; import { VistaLaboratorioComponent } from './components/ejecucion/laboratorios/vista-laboratorio.component'; import { VistaRecetaComponent } from './components/huds/vistaReceta'; import { SuspenderMedicacionComponent } from './components/ejecucion/recetas/suspenderMedicacion'; +import { VistaInformeEstadisticoComponent } from './components/huds/vistaInformeEstadistico'; @NgModule({ imports: [ @@ -80,7 +81,8 @@ import { SuspenderMedicacionComponent } from './components/ejecucion/recetas/sus VistaHistorialTurnosComponent, HudsBusquedaComponent, ListadoInternacionHudsComponent, - SuspenderMedicacionComponent + SuspenderMedicacionComponent, + VistaInformeEstadisticoComponent ], exports: [ VistaCDAComponent, @@ -103,7 +105,8 @@ import { SuspenderMedicacionComponent } from './components/ejecucion/recetas/sus VistaHistorialTurnosComponent, HudsBusquedaComponent, ListadoInternacionHudsComponent, - SuspenderMedicacionComponent + SuspenderMedicacionComponent, + VistaInformeEstadisticoComponent ], providers: [MotivosHudsService] diff --git a/src/app/modules/rup/services/informe-estadistica.service.ts b/src/app/modules/rup/services/informe-estadistica.service.ts index 909bb1c288..d265073844 100644 --- a/src/app/modules/rup/services/informe-estadistica.service.ts +++ b/src/app/modules/rup/services/informe-estadistica.service.ts @@ -74,8 +74,8 @@ export class InformeEstadisticaService { } }; - if (fechaDesde) {opt.params['fechaDesde'] = fechaDesde;} - if (fechaHasta) {opt.params['fechaHasta'] = fechaHasta;} + if (fechaDesde) { opt.params['fechaDesde'] = fechaDesde; } + if (fechaHasta) { opt.params['fechaHasta'] = fechaHasta; } // Guardamos el observable cacheado this.cache[idPaciente] = this.server.get(this.baseUrl, opt).pipe( diff --git a/src/app/services/receta.service.ts b/src/app/services/receta.service.ts index 480b78685d..d42470bdc3 100644 --- a/src/app/services/receta.service.ts +++ b/src/app/services/receta.service.ts @@ -78,4 +78,3 @@ export class RecetaService { return label; } } - From dbfdb178bac1ff20531e8b8ef2e727e01e7b21f7 Mon Sep 17 00:00:00 2001 From: nicolasarana <90768149+nicolasarana@users.noreply.github.com> Date: Fri, 12 Dec 2025 15:29:49 -0300 Subject: [PATCH 10/14] =?UTF-8?q?feat(IN-671)"Versi=C3=B3n=20mejorada=20us?= =?UTF-8?q?ando=20la=20vista=20de=20huds"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ejecucion/hudsBusqueda.component.ts | 463 +++++++++++++----- .../components/ejecucion/hudsBusqueda.html | 168 +++---- .../elementos/internacionEgreso.component.ts | 2 - .../detalleRegistroInternacion.html | 284 ++++------- ...leRegistroInternaci\303\263n.component.ts" | 115 +---- .../listado-internacion-huds.component.ts | 70 +-- .../huds/vistaInformeEstadistico.ts | 60 ++- src/app/modules/rup/huds.module.ts | 2 + .../services/informe-estadistica.service.ts | 8 - 9 files changed, 621 insertions(+), 551 deletions(-) diff --git a/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts b/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts index fb539ed3d9..958ef3458f 100644 --- a/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts +++ b/src/app/modules/rup/components/ejecucion/hudsBusqueda.component.ts @@ -1,14 +1,12 @@ import { Auth } from '@andes/auth'; import { Plex } from '@andes/plex'; import { AfterContentInit, Component, EventEmitter, Input, OnInit, Optional, Output, ViewEncapsulation } from '@angular/core'; -import { Router } from '@angular/router'; import * as moment from 'moment'; import { LaboratorioService } from 'src/app/services/laboratorio.service'; import { RecetaService } from 'src/app/services/receta.service'; import { Observable, forkJoin } from 'rxjs'; -import { switchMap } from 'rxjs/operators'; +import { switchMap, tap } from 'rxjs/operators'; import { InternacionResumenHTTP } from 'src/app/apps/rup/mapa-camas/services/resumen-internacion.http'; -import { InformeEstadisticaService } from '../../services/informe-estadistica.service'; import { IPaciente } from 'src/app/core/mpi/interfaces/IPaciente'; import { PacienteService } from 'src/app/core/mpi/services/paciente.service'; import { SECCION_CLASIFICACION } from 'src/app/modules/epidemiologia/constantes'; @@ -21,7 +19,24 @@ import { getSemanticClass } from '../../pipes/semantic-class.pipes'; import { EmitConcepto, RupEjecucionService } from '../../services/ejecucion.service'; import { HUDSService } from '../../services/huds.service'; import { PrestacionesService } from './../../services/prestaciones.service'; - +import { InformeEstadisticaService } from '../../services/informe-estadistica.service'; +import { IInformeEstadistica } from '../../interfaces/informe-estadistica.interface'; + + +interface IInternacionExtendida { + id: string; + fechaIngreso: any; + fechaEgreso: any; + paciente?: any; + esEstadistica?: boolean; + informesEstadisticos?: IInformeEstadistica[]; + registros?: any[]; + ambito?: string; + ingreso?: any; + organizacion?: any; + tipo_egreso?: string | null; + [key: string]: any; +} @Component({ selector: 'rup-hudsBusqueda', templateUrl: 'hudsBusqueda.html', @@ -44,6 +59,7 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { public loading = false; public cdas = []; + public informe: IInformeEstadistica[] = []; @Input() paciente: IPaciente; @Input() vistaHuds = false; @@ -67,7 +83,9 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { public prestacionSeleccionada = []; private _prestaciones: any = []; private prestacionesCopia: any = []; - private internaciones; + // private internaciones; + private internaciones: IInternacionExtendida[] = []; + get prestaciones() { return this._prestaciones; @@ -188,13 +206,12 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { public huds: HUDSService, private formEpidemiologiaService: FormsEpidemiologiaService, private resumenHTTP: InternacionResumenHTTP, - private informeEstadisticaService: InformeEstadisticaService, - private router: Router, @Optional() private ejecucionService: RupEjecucionService, private pacienteService: PacienteService, private laboratorioService: LaboratorioService, private recetasService: RecetaService, private profesionalService: ProfesionalService, + private informeEstadisticaService: InformeEstadisticaService, ) { } @@ -205,13 +222,23 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { */ ngAfterContentInit() { if (this.paciente) { - this.listarInternaciones(); - this.listarPrestaciones(); this.listarConceptos(); + + forkJoin({ + internaciones: this.listarInternaciones(), + prestaciones: this.listarPrestaciones(), + informes: this.listarInformeEstadistico() + }).subscribe(() => { + this.mergeInternacionesConInformes(); + + if (this.internaciones && this.internaciones.length > 0) { + this.setAmbitoOrigen('internacion'); + } else { + this.setAmbitoOrigen('ambulatorio'); + } + }); } const token = this.huds.getHudsToken(); - // Cuando se inicia una prestación debemos volver a consultar si hay CDA nuevos al ratito. - // [TODO] Ser notificado via websockets setTimeout(() => { this.buscarCDAPacientes(token); }, 1000 * 30); @@ -333,29 +360,9 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { break; case 'internacion': gtag('huds-open', 'rup', 'internacion', index); - - // Verificar si es un informe estadístico - if (registro.registros && registro.registros[index]?.esInformeEstadistico) { - // Marcar como internación para que abra la pestaña correcta - // El componente detalleRegistroInternacion detectará que es estadístico - registro.tipo = 'internacion'; - registro.index = index; - // Agregar todas las propiedades necesarias en data - if (!registro.data) { - registro.data = {}; - } - registro.data.id = registro.id; - registro.data.index = index; - registro.data.registros = registro.registros; - registro.data.fechaIngreso = registro.fechaIngreso; - registro.data.prestaciones = registro.prestaciones; // Agregar prestaciones filtradas - registro.data.esInformeEstadistico = true; - } else { - // Prestaciones normales de internación - registro.id = registro.id; - registro.tipo = 'internacion'; - registro.index = index; - } + registro.id = registro.id; + registro.tipo = 'internacion'; + registro.index = index; break; case 'laboratorio': gtag('huds-open', tipo, 'laboratorio', index); @@ -373,42 +380,113 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { getPacientePrincipal(id): Observable { return this.pacienteService.getById(id); } + listarInformeEstadistico() { + return this.informeEstadisticaService.getByPaciente( + this.paciente.id, + false, + this.fechaInicio, + this.fechaFin + ).pipe(tap((informe) => { + const informesFiltrados = informe.filter(inf => { + const idPacienteInforme = inf.paciente?.id || (inf.paciente as any)?._id; + return idPacienteInforme === this.paciente.id; + }); - listarInternaciones() { - // Usar el nuevo servicio de informes estadísticos - const params: any = { - idPaciente: this.paciente.id, // IMPORTANTE: Filtrar por paciente - estado: 'validada' // Solo internaciones validadas - }; - // Agregar filtros de fecha si existen - if (this.fechaInicio) { - params.fechaDesde = this.fechaInicio; - } - if (this.fechaFin) { - params.fechaHasta = this.fechaFin; - } + this.informe = informesFiltrados; + })); + } + + mergeInternacionesConInformes() { + const base: IInternacionExtendida[] = this.internaciones || []; + const informes: IInformeEstadistica[] = this.informe || []; + const internacionesPorId = new Map( + base.map(i => [i.id, i]) + ); + const internacionesResultantes: IInternacionExtendida[] = [...base]; + + for (const inf of informes) { + + const idInternacionReal = inf._id || inf.id; + + const existente = internacionesPorId.get(idInternacionReal); + + if (!existente) { + + const nuevaInternacion: IInternacionExtendida = { + id: idInternacionReal, + fechaIngreso: inf.informeIngreso?.fechaIngreso || null, + fechaEgreso: inf.informeEgreso?.fechaEgreso || null, + paciente: inf.paciente, + esEstadistica: true, + informesEstadisticos: [inf], + + registros: [], + ambito: 'internacion', + ingreso: null, + organizacion: inf.organizacion || null, + tipo_egreso: null, + createdAt: inf.createdAt || null + }; - this.informeEstadisticaService.search(params).subscribe((informes) => { + internacionesResultantes.push(nuevaInternacion); + internacionesPorId.set(idInternacionReal, nuevaInternacion); + } else { - // Mapear IInformeEstadistica a la estructura esperada por filtrarPorInternacion - this.internaciones = informes.map(informe => ({ - id: informe._id || informe.id, // MongoDB usa _id - fechaIngreso: informe.informeIngreso.fechaIngreso, - fechaEgreso: informe.informeEgreso?.fechaEgreso, - organizacion: { - id: informe.organizacion._id || informe.organizacion.id, - nombre: informe.organizacion.nombre + if (!existente.informesEstadisticos) { + existente.informesEstadisticos = []; } - })); + existente.informesEstadisticos.push(inf); + } + } + + this.internaciones = internacionesResultantes; + } + mezclarInformes(informes) { + this.internaciones = this.internaciones.map(int => { + const informe = informes.find(i => i.idInternacion === int.id); + + if (informe) { + int.registros = [ + ...int.registros, + { + term: 'Informe Estadístico', + conceptId: null, + tipo: 'informe-estadistico', + data: informe + } + ]; + } + return int; }); } + listarInternaciones() { + let request; + if (this.paciente.idPacientePrincipal) { + request = this.getPacientePrincipal(this.paciente.idPacientePrincipal).pipe( + switchMap((paciente: IPaciente) => this.resumenHTTP.search({ + ingreso: this.resumenHTTP.queryDateParams(this.fechaInicio, this.fechaFin), + paciente: paciente.vinculos + })) + ); + } else { + request = this.resumenHTTP.search({ + ingreso: this.resumenHTTP.queryDateParams(this.fechaInicio, this.fechaFin), + paciente: this.paciente.vinculos || this.paciente.id + }); + } + + return request.pipe(tap((internaciones: any) => { + this.internaciones = internaciones; + })); + } + listarPrestaciones() { function groupBy(prestaciones: IPrestacion[]) { const resultado = []; @@ -431,7 +509,7 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { } - this.servicioPrestacion.getByPaciente(this.paciente.id, false).subscribe(prestaciones => { + return this.servicioPrestacion.getByPaciente(this.paciente.id, false).pipe(tap(prestaciones => { this.prestacionesTotales = prestaciones; const validadas = prestaciones.filter(p => p.estados[p.estados.length - 1].tipo === 'validada'); @@ -462,14 +540,14 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { } }); this.prestacionesCopia = this.prestaciones.slice(); - this.setAmbitoOrigen('ambulatorio'); + // this.setAmbitoOrigen('ambulatorio'); this.tiposPrestacion = this._prestaciones.map(p => p.prestacion); this.organizaciones = this.prestaciones.filter(p => p.data.ejecucion?.organizacion); this.organizaciones = this.organizaciones.map(o => o.data.ejecucion.organizacion); this.buscarCDAPacientes(this.huds.getHudsToken()); this.buscarFichasEpidemiologicas(); - }); + })); } // Trae los hallazgos @@ -628,7 +706,18 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { case 'procedimiento': return this.registrosTotalesCopia.procedimiento.length; case 'planes': - return this.prestacionesCopia.length; + // Contar prestaciones en internaciones combinadas + let totalPrestaciones = 0; + if (this.indiceInternaciones && this.indiceInternaciones.length > 0) { + this.indiceInternaciones.forEach((internacion: any) => { + internacion.registros.forEach((registro: any) => { + if (registro.otras) { + totalPrestaciones += Object.keys(registro.otras).length; + } + }); + }); + } + return totalPrestaciones; case 'producto': return this.registrosTotalesCopia.producto.length; case 'laboratorios': @@ -711,44 +800,139 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { this.otrasPrestaciones = { fechaDesde, fechaHasta, indices: Object.values(indiceRegistros.indices), registros: Object.values(indiceRegistros.registros) }; } + filtrarPorInternacion(prestaciones) { + + const prestacionesEnInternacion = []; - this.indiceInternaciones = []; - - this.internaciones?.forEach((internacion) => { - - // Log de la primera prestación para ver su estructura - if (prestaciones.length > 0) { - const ejemploPrestacion = prestaciones[0]; - // Verificar por qué no coincide - const fechaIngresoValida = moment(ejemploPrestacion.fecha).isSameOrAfter(internacion.fechaIngreso); - const fechaEgresoValida = internacion.fechaEgreso - ? moment(ejemploPrestacion.fecha).isSameOrBefore(internacion.fechaEgreso) - : moment(ejemploPrestacion.fecha).isSameOrBefore(moment().toDate()); - const organizacionValida = internacion.organizacion?.id - ? internacion.organizacion.id === ejemploPrestacion.organizacion - : internacion.organizacion === ejemploPrestacion.data?.solicitud?.organizacion?.nombre; + // Importar las constantes SNOMED para ingreso y egreso + const snomedIngreso = { + fsn: 'documento de solicitud de admisión (elemento de registro)', + semanticTag: 'elemento de registro', + conceptId: '721915006', + term: 'documento de solicitud de admisión' + }; + + const snomedEgreso = { + fsn: 'alta del paciente (procedimiento)', + semanticTag: 'procedimiento', + conceptId: '58000006', + term: 'alta del paciente' + }; + + const internaciones = this.internaciones?.map(internacion => { + + if (internacion.esEstadistica) { + const registrosFormateados = {}; + + internacion.informesEstadisticos?.forEach((informe, index) => { + const id = informe._id || informe.id; + + const registrosRUP = []; + + const origenString = informe.informeIngreso?.origen?.tipo || + informe.informeIngreso?.origen?.organizacionOrigen?.nombre || + informe.informeIngreso?.origen?.otraOrganizacion || + 'Consultorio externo'; + + registrosRUP.push({ + id: `${id}-ingreso-registro`, + concepto: snomedIngreso, + nombre: snomedIngreso.term, + valor: { + informeIngreso: { + ...informe.informeIngreso, + origen: origenString + } + } + }); + + if (informe.informeEgreso) { + registrosRUP.push({ + id: `${id}-egreso-registro`, + concepto: snomedEgreso, + nombre: snomedEgreso.term, + valor: { + InformeEgreso: informe.informeEgreso + } + }); + } + + const registroCombinadoKey = `informe-estadistico-${id}`; + registrosFormateados[registroCombinadoKey] = { + prestacion: { + term: 'Informe Estadístico de Internación', + conceptId: '32485007' // internación + }, + data: { + id: id, + estadoActual: { + createdAt: informe.informeIngreso?.fechaIngreso || informe.createdAt || new Date(), + createdBy: informe.createdBy || {} + }, + solicitud: { + profesional: informe.createdBy || {}, + organizacion: informe.organizacion || {}, + ambitoOrigen: 'internacion' + }, + unidadOrganizativa: { + term: informe.unidadOrganizativa?.term || 'Unidad Estadística' + }, + paciente: informe.paciente, + ejecucion: { + registros: registrosRUP + }, + _esInformeEstadistico: false + } + }; + }); + + const prestacionesPorInternacion = prestaciones.filter(prestacion => { + const fechaIngresoValida = moment(prestacion.fecha).isSameOrAfter(internacion.fechaIngreso); + const fechaEgresoValida = internacion.fechaEgreso ? moment(prestacion.fecha).isSameOrBefore(internacion.fechaEgreso) : moment(prestacion.fecha).isSameOrBefore(moment().toDate()); + const organizacionValida = internacion.organizacion._id === prestacion.organizacion || internacion.organizacion.id === prestacion.organizacion; + + if (fechaIngresoValida && fechaEgresoValida && organizacionValida) { + prestacionesEnInternacion.push(prestacion); + return prestacion; + } else { return null; } + }); + + + // Agregar las prestaciones RUP al objeto registrosFormateados + prestacionesPorInternacion.forEach(prestacion => { + registrosFormateados[prestacion.data.id] = { + prestacion: prestacion.prestacion, + data: prestacion.data + }; + }); + + const resultado = { + id: internacion.id, + fechaIngreso: internacion.fechaIngreso, + fechaEgreso: internacion.fechaEgreso, + organizacion: internacion.organizacion?.nombre || 'Organización Estadística', + registros: [{ + otras: registrosFormateados + }] + }; + + return resultado; } - // Buscar prestaciones que coincidan con esta internación por fecha y organización const prestacionesPorInternacion = prestaciones.filter(prestacion => { const fechaIngresoValida = moment(prestacion.fecha).isSameOrAfter(internacion.fechaIngreso); - const fechaEgresoValida = internacion.fechaEgreso - ? moment(prestacion.fecha).isSameOrBefore(internacion.fechaEgreso) - : moment(prestacion.fecha).isSameOrBefore(moment().toDate()); - - // Comparar organización (puede ser ID u objeto) - const organizacionValida = internacion.organizacion?.id - ? internacion.organizacion.id === prestacion.organizacion - : internacion.organizacion === prestacion.data?.solicitud?.organizacion?.nombre; + const fechaEgresoValida = internacion.fechaEgreso ? moment(prestacion.fecha).isSameOrBefore(internacion.fechaEgreso) : moment(prestacion.fecha).isSameOrBefore(moment().toDate()); + const organizacionValida = internacion.organizacion.id === prestacion.organizacion; - const coincide = fechaIngresoValida && fechaEgresoValida && organizacionValida; + if (fechaIngresoValida && fechaEgresoValida && organizacionValida) { + prestacionesEnInternacion.push(prestacion); - return coincide; + return prestacion; + } else { return null; } }); - const indicePrestaciones = prestacionesPorInternacion.reduce((grupo, prestacion) => { return ({ ...grupo, [prestacion.data.id]: prestacion }); }, {}); @@ -756,57 +940,98 @@ export class HudsBusquedaComponent implements AfterContentInit, OnInit { const registros = prestacionesPorInternacion.flatMap((prestacion) => prestacion.data.ejecucion.registros); const grupoRegistros = registros.reduce((grupo, registro) => { - const dataRegistro = { - conceptId: registro.concepto.conceptId, - term: registro.concepto.term, - id: registro.id, - idPrestacion: registro.idPrestacion - }; + const dataRegistro = { conceptId: registro.concepto.conceptId, term: registro.concepto.term, id: registro.id, idPrestacion: registro.idPrestacion }; if (this.planIndicaciones.includes(registro.concepto.conceptId)) { return ({ ...grupo, [registro.concepto.conceptId]: dataRegistro }); } - return ({ - ...grupo, - ['otras']: { - ...grupo['otras'], - [registro.idPrestacion]: { ...indicePrestaciones[registro.idPrestacion] } - } - }); + return ({ ...grupo, ['otras']: { ...grupo['otras'], [registro.idPrestacion]: { ...indicePrestaciones[registro.idPrestacion] } } }); }, {}); - const registrosArray = Object.values(grupoRegistros); + return { + id: internacion.id, + fechaIngreso: internacion.fechaIngreso, + fechaEgreso: internacion.fechaEgreso, + organizacion: internacion.organizacion.nombre, + registros: Object.values(grupoRegistros) + }; + }) + .filter(grupo => grupo.registros.length); + internaciones.forEach((int, idx) => { + const ingreso = int.fechaIngreso ? new Date(int.fechaIngreso).toLocaleString() : 'sin fecha'; + const egreso = int.fechaEgreso ? new Date(int.fechaEgreso).toLocaleString() : 'sin fecha'; + }); + const internacionesCombinadas = []; + const procesadas = new Set(); - // Si no hay registros (internación estadística sin prestaciones), crear un registro especial - if (registrosArray.length === 0) { + for (let i = 0; i < internaciones.length; i++) { + if (procesadas.has(i)) { continue; } - registrosArray.push({ - conceptId: 'informe-estadistico', - term: 'Evoluciones y otros registros', - id: internacion.id, - esInformeEstadistico: true - }); - } + const internacionBase = internaciones[i]; - this.indiceInternaciones.push({ - id: internacion.id, - fechaIngreso: internacion.fechaIngreso, - fechaEgreso: internacion.fechaEgreso, - organizacion: internacion.organizacion?.nombre || internacion.organizacion, - registros: registrosArray, - prestaciones: prestacionesPorInternacion // Agregar las prestaciones filtradas + let otrasCombinadas: any = {}; + + internacionBase.registros.forEach((registro: any) => { + if (registro.otras) { + otrasCombinadas = { ...otrasCombinadas, ...registro.otras }; + } else { + otrasCombinadas = { ...otrasCombinadas, ...registro }; + } }); - }); + procesadas.add(i); + + for (let j = i + 1; j < internaciones.length; j++) { + if (procesadas.has(j)) { continue; } + const otraInternacion = internaciones[j]; + + const mismoDia = moment(internacionBase.fechaIngreso).isSame(otraInternacion.fechaIngreso, 'day'); + const cercanas = Math.abs(moment(internacionBase.fechaIngreso).diff(otraInternacion.fechaIngreso, 'hours')) < 24; + + if (mismoDia || cercanas) { + + otraInternacion.registros.forEach((registro: any) => { + if (registro.otras) { + otrasCombinadas = { ...otrasCombinadas, ...registro.otras }; + } else { + otrasCombinadas = { ...otrasCombinadas, ...registro }; + } + }); + + procesadas.add(j); + } + } + + internacionesCombinadas.push({ + ...internacionBase, + registros: [{ + otras: otrasCombinadas + }] + }); + } + + this.indiceInternaciones = internacionesCombinadas?.reverse(); this.filtrarOtrasPrestaciones(prestaciones, prestacionesEnInternacion); } filtrar() { + this.prestaciones = this.prestacionesCopia.slice(); + if (this.prestacionSeleccionada && this.prestacionSeleccionada.length > 0) { + const prestacionesTemp = this.prestacionSeleccionada.map(e => e.conceptId); + this.prestaciones = this.prestaciones.filter(p => prestacionesTemp.find(e => e === p.prestacion.conceptId)); + } + + if (this.fechaInicio || this.fechaFin) { + this.fechaInicio = this.fechaInicio ? this.fechaInicio : new Date(); + this.fechaFin = this.fechaFin ? this.fechaFin : new Date(); + this.prestaciones = this.prestaciones.filter(p => p.fecha >= moment(this.fechaInicio).startOf('day').toDate() && + p.fecha <= moment(this.fechaFin).endOf('day').toDate()); + } if (this.ambitoOrigen) { this.prestaciones = this.prestaciones.filter(p => p.ambito === this.ambitoOrigen); diff --git a/src/app/modules/rup/components/ejecucion/hudsBusqueda.html b/src/app/modules/rup/components/ejecucion/hudsBusqueda.html index 02c610627d..4f99b6a26d 100644 --- a/src/app/modules/rup/components/ejecucion/hudsBusqueda.html +++ b/src/app/modules/rup/components/ejecucion/hudsBusqueda.html @@ -1,14 +1,13 @@