Cambio de histograma
This commit is contained in:
parent
02e3afa684
commit
35f380784f
@ -8,6 +8,7 @@
|
||||
<h2>Importación de Excel (PLANILLA vs HISTOR)</h2>
|
||||
|
||||
<div *ngIf="errorImport" class="error">{{ errorImport }}</div>
|
||||
<div *ngIf="mensajeImport" class="info">{{ mensajeImport }}</div>
|
||||
|
||||
<div class="info" *ngIf="cargandoImport">Consultando estado...</div>
|
||||
|
||||
@ -34,22 +35,39 @@
|
||||
<div>
|
||||
<strong>Citas programadas (PLANILLA)</strong>
|
||||
<input type="file" (change)="onSeleccionarPlanilla($event)" />
|
||||
<button (click)="subirPlanilla()" [disabled]="subiendoPlanilla">
|
||||
{{ subiendoPlanilla ? 'Cargando...' : 'Cargar citas programadas' }}
|
||||
<button (click)="subirPlanilla()" [disabled]="subiendoPlanilla || sincronizando">
|
||||
{{ subiendoPlanilla ? 'Cargando...' : 'Cargar planilla' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<strong>Citas realizadas (HISTOR)</strong>
|
||||
<input type="file" (change)="onSeleccionarHistor($event)" />
|
||||
<button (click)="subirHistor()" [disabled]="subiendoHistor">
|
||||
{{ subiendoHistor ? 'Cargando...' : 'Cargar citas realizadas' }}
|
||||
<button (click)="subirHistor()" [disabled]="subiendoHistor || sincronizando">
|
||||
{{ subiendoHistor ? 'Cargando...' : 'Cargar histor' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button (click)="refrescarEstadoImport()">Refrescar estado</button>
|
||||
<button (click)="refrescarEstadoImport()" [disabled]="sincronizando">Refrescar estado</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
(click)="sincronizarImportacion()"
|
||||
[disabled]="sincronizando || !estadoImport?.planilla_cargada || !estadoImport?.histor_cargada"
|
||||
>
|
||||
{{ sincronizando ? 'Procesando...' : 'Procesar excels (sincronizar)' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button (click)="limpiarImportacion()" [disabled]="sincronizando">Limpiar</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="sincronizando" class="info" style="margin-top:10px;">
|
||||
⏳ Por favor espera: se están procesando los excels (puede tardar).
|
||||
</div>
|
||||
|
||||
<div *ngIf="logImport.length > 0" class="info" style="margin-top:10px; white-space:pre-wrap;">
|
||||
@ -64,7 +82,7 @@
|
||||
<div class="seccion">
|
||||
<h2>Histograma general (plan anual real)</h2>
|
||||
|
||||
<button (click)="cargarHistogramaGeneral()" [disabled]="cargandoHistGeneral">
|
||||
<button (click)="cargarHistogramaGeneral()" [disabled]="cargandoHistGeneral || sincronizando">
|
||||
{{ cargandoHistGeneral ? 'Cargando...' : 'Ver histograma general' }}
|
||||
</button>
|
||||
|
||||
@ -114,7 +132,7 @@
|
||||
: 'Ej: JHONATHAN, GUALDRON...'"
|
||||
(keyup.enter)="buscar()"
|
||||
/>
|
||||
<button (click)="buscar()">Buscar</button>
|
||||
<button (click)="buscar()" [disabled]="sincronizando">Buscar</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="cargando" class="info">Cargando pacientes...</div>
|
||||
@ -186,8 +204,8 @@
|
||||
({{ histPaciente.cumplimiento.porcentaje_mes_actual }}%)
|
||||
|
|
||||
<strong>Hasta hoy:</strong>
|
||||
{{ histPaciente.cumplimiento.asistidas_hasta_hoy }}/{{ histPaciente.cumplimiento.esperado_hasta_hoy }}
|
||||
({{ histPaciente.cumplimiento.porcentaje_hasta_hoy }}%)
|
||||
{{ hastaHoyAsistidas() }}/{{ hastaHoyEsperado() }}
|
||||
({{ hastaHoyPorcentaje() }}%)
|
||||
</p>
|
||||
|
||||
<canvas #canvasPaciente style="width:100%; max-width:1100px; height:360px;"></canvas>
|
||||
@ -197,18 +215,20 @@
|
||||
<tr>
|
||||
<th>Mes</th>
|
||||
<th>Rango</th>
|
||||
<th>Esperado</th>
|
||||
<th>Asistidas</th>
|
||||
<th>Pendientes</th>
|
||||
<th>Esperado (mes)</th>
|
||||
<th>Asistidas (mes + arrastre)</th>
|
||||
<th>Pendiente (mes)</th>
|
||||
<th>Pendientes total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let m of histPaciente.porMes">
|
||||
<td>{{ m.mes }}</td>
|
||||
<td>{{ m.inicio }} → {{ m.fin }}</td>
|
||||
<td>{{ m.esperado }}</td>
|
||||
<td>{{ m.asistidas }}</td>
|
||||
<td>{{ m.pendientes }}</td>
|
||||
<td>{{ valorEsperadoMes(m) }}</td>
|
||||
<td>{{ valorAsistidasMes(m) }}</td>
|
||||
<td>{{ valorPendienteMes(m) }}</td>
|
||||
<td>{{ valorPendientesTotal(m) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -218,109 +238,6 @@
|
||||
<h4>Citas</h4>
|
||||
<div *ngIf="cargandoCitas" class="info">Cargando citas...</div>
|
||||
|
||||
<table *ngIf="!cargandoCitas && citas.length > 0" class="tabla">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Fecha</th>
|
||||
<th>Hora</th>
|
||||
<th>Especialidad</th>
|
||||
<th>Tipo</th>
|
||||
<th>Modalidad</th>
|
||||
<th>Asistió</th>
|
||||
<th>Observaciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let c of citas; let i = index">
|
||||
<td>{{ c.fecha_cita | date:'yyyy-MM-dd' }}</td>
|
||||
<td>{{ c.hora_cita || '-' }}</td>
|
||||
<td>{{ c.especialidad }}</td>
|
||||
<td>{{ c.tipo_cita || '-' }}</td>
|
||||
<td>{{ c.modalidad || '-' }}</td>
|
||||
<td>
|
||||
<ng-container *ngIf="i < 2 && c.asistio !== true; else asistioFijo">
|
||||
<input
|
||||
type="checkbox"
|
||||
[ngModel]="false"
|
||||
(ngModelChange)="onToggleAsistencia(c, $event)"
|
||||
[disabled]="guardandoAsistenciaId === c.id_cita"
|
||||
/>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #asistioFijo>
|
||||
{{ c.asistio ? 'Sí' : 'No' }}
|
||||
</ng-template>
|
||||
</td>
|
||||
<td>{{ c.observaciones || '-' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p *ngIf="errorAsistencia" class="error">{{ errorAsistencia }}</p>
|
||||
|
||||
<p *ngIf="!cargandoCitas && citas.length === 0" class="info">
|
||||
Este paciente no tiene citas registradas.
|
||||
</p>
|
||||
|
||||
<!-- Formulario para agendar nueva cita -->
|
||||
<div class="seccion-agendar">
|
||||
<h4>Agendar nueva cita</h4>
|
||||
|
||||
<div *ngIf="errorCita" class="error">{{ errorCita }}</div>
|
||||
<div *ngIf="mensajeCita" class="ok">{{ mensajeCita }}</div>
|
||||
|
||||
<div class="form-grid">
|
||||
<div class="campo">
|
||||
<label>Especialidad</label>
|
||||
<select [(ngModel)]="formCita.id_especialidad">
|
||||
<option value="">-- Selecciona --</option>
|
||||
<option *ngFor="let e of especialidades" [value]="e.id_especialidad">
|
||||
{{ e.nombre }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="campo">
|
||||
<label>Fecha de cita</label>
|
||||
<input type="date" [(ngModel)]="formCita.fecha_cita" />
|
||||
</div>
|
||||
|
||||
<div class="campo">
|
||||
<label>Tipo de cita</label>
|
||||
<input
|
||||
type="text"
|
||||
[(ngModel)]="formCita.tipo_cita"
|
||||
placeholder="Primera vez, Control..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="campo">
|
||||
<label>Hora de cita</label>
|
||||
<input type="time" [(ngModel)]="formCita.hora_cita" />
|
||||
</div>
|
||||
|
||||
<div class="campo">
|
||||
<label>Modalidad</label>
|
||||
<select [(ngModel)]="formCita.modalidad">
|
||||
<option value="">-- Selecciona --</option>
|
||||
<option value="PRESENCIAL">Presencial</option>
|
||||
<option value="TELEMEDICINA">Telemedicina</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="campo campo-full">
|
||||
<label>Observaciones</label>
|
||||
<textarea
|
||||
rows="3"
|
||||
[(ngModel)]="formCita.observaciones"
|
||||
placeholder="Notas sobre la cita"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button (click)="guardarCita()" [disabled]="guardandoCita">
|
||||
{{ guardandoCita ? 'Guardando...' : 'Guardar cita' }}
|
||||
</button>
|
||||
</div>
|
||||
<!-- (tu bloque de citas sigue igual abajo) -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -24,7 +24,8 @@ import {
|
||||
EstadoImportacion,
|
||||
RespuestaImportacion,
|
||||
HistogramaPaciente,
|
||||
HistogramaGeneral
|
||||
HistogramaGeneral,
|
||||
HistPacienteMes
|
||||
} from './servicios/importacion';
|
||||
|
||||
@Component({
|
||||
@ -74,6 +75,9 @@ export class AppComponent implements OnInit {
|
||||
cargandoImport = false;
|
||||
subiendoPlanilla = false;
|
||||
subiendoHistor = false;
|
||||
sincronizando = false;
|
||||
mensajeImport: string | null = null;
|
||||
|
||||
logImport: string[] = [];
|
||||
errorImport: string | null = null;
|
||||
|
||||
@ -153,6 +157,16 @@ export class AppComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
cargarLogImport(): void {
|
||||
this.importacionService.log().subscribe({
|
||||
next: (r) => {
|
||||
this.logImport = r.lines || [];
|
||||
this.cdr.markForCheck();
|
||||
},
|
||||
error: () => {}
|
||||
});
|
||||
}
|
||||
|
||||
onSeleccionarPlanilla(ev: Event): void {
|
||||
const input = ev.target as HTMLInputElement;
|
||||
this.archivoPlanilla = input.files && input.files.length ? input.files[0] : null;
|
||||
@ -171,7 +185,7 @@ export class AppComponent implements OnInit {
|
||||
|
||||
this.subiendoPlanilla = true;
|
||||
this.errorImport = null;
|
||||
this.logImport = [];
|
||||
this.mensajeImport = null;
|
||||
|
||||
this.importacionService
|
||||
.subirPlanilla(this.archivoPlanilla)
|
||||
@ -181,17 +195,9 @@ export class AppComponent implements OnInit {
|
||||
}))
|
||||
.subscribe({
|
||||
next: (r: RespuestaImportacion) => {
|
||||
this.logImport.push(r.mensaje || '✅ Planilla cargada.');
|
||||
if (r.stdout) this.logImport.push(r.stdout);
|
||||
if (r.stderr) this.logImport.push('⚠️ ' + r.stderr);
|
||||
|
||||
this.mensajeImport = r.mensaje || '✅ Planilla cargada.';
|
||||
this.cargarLogImport();
|
||||
this.refrescarEstadoImport();
|
||||
this.cargarHistogramaGeneral();
|
||||
|
||||
if (this.pacienteSeleccionado) {
|
||||
this.cargarCitas(this.pacienteSeleccionado.numero_documento);
|
||||
this.cargarHistogramaPaciente(this.pacienteSeleccionado.numero_documento);
|
||||
}
|
||||
},
|
||||
error: (err: any) => {
|
||||
this.errorImport = err?.error?.detalle || 'Error subiendo planilla.';
|
||||
@ -207,7 +213,7 @@ export class AppComponent implements OnInit {
|
||||
|
||||
this.subiendoHistor = true;
|
||||
this.errorImport = null;
|
||||
this.logImport = [];
|
||||
this.mensajeImport = null;
|
||||
|
||||
this.importacionService
|
||||
.subirHistor(this.archivoHistor)
|
||||
@ -217,24 +223,104 @@ export class AppComponent implements OnInit {
|
||||
}))
|
||||
.subscribe({
|
||||
next: (r: RespuestaImportacion) => {
|
||||
this.logImport.push(r.mensaje || '✅ Histor cargado.');
|
||||
if (r.stdout) this.logImport.push(r.stdout);
|
||||
if (r.stderr) this.logImport.push('⚠️ ' + r.stderr);
|
||||
|
||||
this.mensajeImport = r.mensaje || '✅ Histor cargado.';
|
||||
this.cargarLogImport();
|
||||
this.refrescarEstadoImport();
|
||||
this.cargarHistogramaGeneral();
|
||||
},
|
||||
error: (err: any) => {
|
||||
this.errorImport = err?.error?.detalle || 'Error subiendo histor.';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sincronizarImportacion(): void {
|
||||
if (!this.estadoImport?.planilla_cargada || !this.estadoImport?.histor_cargada) {
|
||||
this.errorImport = 'Debes cargar PLANILLA y HISTOR antes de procesar.';
|
||||
return;
|
||||
}
|
||||
|
||||
this.sincronizando = true;
|
||||
this.errorImport = null;
|
||||
this.mensajeImport = '⏳ Procesando excels... por favor espera.';
|
||||
this.logImport = [];
|
||||
|
||||
this.importacionService
|
||||
.sincronizar()
|
||||
.pipe(finalize(() => {
|
||||
this.sincronizando = false;
|
||||
this.cdr.markForCheck();
|
||||
}))
|
||||
.subscribe({
|
||||
next: (r) => {
|
||||
this.mensajeImport = r.mensaje || '✅ Sincronización terminada.';
|
||||
this.cargarLogImport();
|
||||
this.refrescarEstadoImport();
|
||||
|
||||
// refrescar data
|
||||
this.cargarHistogramaGeneral();
|
||||
if (this.pacienteSeleccionado) {
|
||||
this.cargarCitas(this.pacienteSeleccionado.numero_documento);
|
||||
this.cargarHistogramaPaciente(this.pacienteSeleccionado.numero_documento);
|
||||
}
|
||||
},
|
||||
error: (err: any) => {
|
||||
this.errorImport = err?.error?.detalle || 'Error subiendo histor.';
|
||||
this.errorImport = err?.error?.mensaje || '❌ Error procesando excels.';
|
||||
this.cargarLogImport();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
limpiarImportacion(): void {
|
||||
this.errorImport = null;
|
||||
this.mensajeImport = null;
|
||||
|
||||
this.importacionService.limpiar().subscribe({
|
||||
next: (r) => {
|
||||
this.mensajeImport = r.mensaje || '✅ Estado limpiado.';
|
||||
this.logImport = [];
|
||||
this.refrescarEstadoImport();
|
||||
this.cdr.markForCheck();
|
||||
},
|
||||
error: () => this.errorImport = 'No se pudo limpiar la importación.'
|
||||
});
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Helpers Histograma (para arreglar "Hasta hoy")
|
||||
// =========================
|
||||
hastaHoyEsperado(): number {
|
||||
const c: any = this.histPaciente?.cumplimiento;
|
||||
return Number(c?.esperado_base_hasta_hoy ?? c?.esperado_hasta_hoy ?? 0);
|
||||
}
|
||||
|
||||
hastaHoyAsistidas(): number {
|
||||
const c: any = this.histPaciente?.cumplimiento;
|
||||
return Number(c?.asistidas_plan_hasta_hoy ?? c?.asistidas_hasta_hoy ?? 0);
|
||||
}
|
||||
|
||||
hastaHoyPorcentaje(): number {
|
||||
const c: any = this.histPaciente?.cumplimiento;
|
||||
return Number(c?.porcentaje_base_hasta_hoy ?? c?.porcentaje_hasta_hoy ?? 0);
|
||||
}
|
||||
|
||||
valorEsperadoMes(m: any): number {
|
||||
return Number(m?.esperado_mes ?? m?.esperado ?? 0);
|
||||
}
|
||||
|
||||
valorAsistidasMes(m: any): number {
|
||||
return Number(m?.asistidas_total ?? m?.asistidas ?? 0);
|
||||
}
|
||||
|
||||
valorPendienteMes(m: any): number {
|
||||
const esperadoMes = Number(m?.esperado_mes ?? m?.esperado ?? 0);
|
||||
const asistidasMes = Number(m?.asistidas_mes ?? 0); // solo del mes (sin arrastre)
|
||||
return Math.max(0, esperadoMes - asistidasMes);
|
||||
}
|
||||
|
||||
valorPendientesTotal(m: any): number {
|
||||
return Number(m?.retraso_fin ?? m?.retraso ?? m?.pendientes ?? 0);
|
||||
}
|
||||
|
||||
// =========================
|
||||
// HISTOGRAMA GENERAL + GRAFICOS
|
||||
// =========================
|
||||
@ -343,8 +429,8 @@ export class AppComponent implements OnInit {
|
||||
if (!this.histPaciente?.porMes || !this.canvasPaciente) return;
|
||||
|
||||
const labels = this.histPaciente.porMes.map(x => `Mes ${x.mes}`);
|
||||
const esperado = this.histPaciente.porMes.map(x => x.esperado);
|
||||
const asistidas = this.histPaciente.porMes.map(x => x.asistidas);
|
||||
const esperado = this.histPaciente.porMes.map(x => (x as any).esperado ?? (x as any).esperado_mes ?? 0);
|
||||
const asistidas = this.histPaciente.porMes.map(x => (x as any).asistidas ?? (x as any).asistidas_total ?? 0);
|
||||
|
||||
if (this.grafPaciente) this.grafPaciente.destroy();
|
||||
|
||||
@ -476,7 +562,6 @@ export class AppComponent implements OnInit {
|
||||
this.formCita.tipo_cita = '';
|
||||
this.formCita.observaciones = '';
|
||||
|
||||
// refrescar histogramas
|
||||
if (this.pacienteSeleccionado) {
|
||||
this.cargarHistogramaPaciente(this.pacienteSeleccionado.numero_documento);
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ export interface EstadoImportacion {
|
||||
planilla_nombre: string | null;
|
||||
histor_nombre: string | null;
|
||||
ultima_sync: string | null;
|
||||
ultima_sync_resultado?: any;
|
||||
}
|
||||
|
||||
export interface RespuestaImportacion {
|
||||
@ -16,6 +17,7 @@ export interface RespuestaImportacion {
|
||||
stdout?: string;
|
||||
stderr?: string;
|
||||
detalle?: any;
|
||||
resultado?: any;
|
||||
}
|
||||
|
||||
export interface HistGeneralEspecialidad {
|
||||
@ -30,6 +32,9 @@ export interface HistGeneralMesPrograma {
|
||||
mes: number;
|
||||
esperado: number;
|
||||
asistidas: number;
|
||||
// opcionales por si luego los quieres mostrar
|
||||
retraso?: number;
|
||||
pendientes?: number;
|
||||
}
|
||||
|
||||
export interface HistogramaGeneral {
|
||||
@ -46,9 +51,18 @@ export interface HistPacienteMes {
|
||||
mes: number;
|
||||
inicio: string;
|
||||
fin: string;
|
||||
esperado: number;
|
||||
asistidas: number;
|
||||
pendientes: number;
|
||||
|
||||
// compat
|
||||
esperado?: number;
|
||||
asistidas?: number;
|
||||
pendientes?: number;
|
||||
|
||||
// nuevos (si vienen del backend)
|
||||
esperado_mes?: number;
|
||||
asistidas_mes?: number;
|
||||
asistidas_arrastre?: number;
|
||||
asistidas_total?: number;
|
||||
retraso_fin?: number;
|
||||
}
|
||||
|
||||
export interface HistogramaPaciente {
|
||||
@ -59,11 +73,31 @@ export interface HistogramaPaciente {
|
||||
esperado_mes_actual: number;
|
||||
asistidas_mes_actual: number;
|
||||
porcentaje_mes_actual: number;
|
||||
esperado_hasta_hoy: number;
|
||||
asistidas_hasta_hoy: number;
|
||||
porcentaje_hasta_hoy: number;
|
||||
|
||||
// ✅ NUEVOS (tu backend actualizado)
|
||||
esperado_base_hasta_hoy?: number;
|
||||
asistidas_plan_hasta_hoy?: number;
|
||||
porcentaje_base_hasta_hoy?: number;
|
||||
|
||||
// (info adicional si lo usas)
|
||||
asistidas_arrastre_mes_actual?: number;
|
||||
asistidas_total_mes_actual?: number;
|
||||
retraso_actual?: number;
|
||||
|
||||
// ✅ VIEJOS (por si algún endpoint todavía lo devuelve)
|
||||
esperado_hasta_hoy?: number;
|
||||
asistidas_hasta_hoy?: number;
|
||||
porcentaje_hasta_hoy?: number;
|
||||
};
|
||||
porMes: HistPacienteMes[];
|
||||
extras?: Array<{ mes: number; fecha: string; especialidad: string }>;
|
||||
}
|
||||
|
||||
export interface ImportLog {
|
||||
running: boolean;
|
||||
inicio: string | null;
|
||||
fin: string | null;
|
||||
lines: string[];
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
@ -88,6 +122,19 @@ export class ImportacionService {
|
||||
return this.http.post<RespuestaImportacion>(`${this.baseUrl}/api/importacion/histor`, form);
|
||||
}
|
||||
|
||||
// ✅ Procesar cuando tú quieras (endpoint nuevo)
|
||||
sincronizar(): Observable<RespuestaImportacion> {
|
||||
return this.http.post<RespuestaImportacion>(`${this.baseUrl}/api/importacion/sincronizar`, {});
|
||||
}
|
||||
|
||||
limpiar(): Observable<{ ok: boolean; mensaje: string }> {
|
||||
return this.http.post<{ ok: boolean; mensaje: string }>(`${this.baseUrl}/api/importacion/limpiar`, {});
|
||||
}
|
||||
|
||||
log(): Observable<ImportLog> {
|
||||
return this.http.get<ImportLog>(`${this.baseUrl}/api/importacion/log`);
|
||||
}
|
||||
|
||||
histogramaGeneral(): Observable<HistogramaGeneral> {
|
||||
return this.http.get<HistogramaGeneral>(`${this.baseUrl}/api/histogramas/general`);
|
||||
}
|
||||
|
||||
9
backend/nodemon.json
Normal file
9
backend/nodemon.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"watch": ["src"],
|
||||
"ignore": [
|
||||
"src/uploads/*",
|
||||
"src/salida_importacion/*",
|
||||
"src/outputs/*",
|
||||
"src/import_state.json"
|
||||
]
|
||||
}
|
||||
1040
backend/package-lock.json
generated
1040
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -7,12 +7,14 @@
|
||||
"start": "node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"archiver": "^7.0.1",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.6.1",
|
||||
"express": "^4.22.0",
|
||||
"multer": "^2.0.2",
|
||||
"pg": "^8.16.3",
|
||||
"twilio": "^5.10.6"
|
||||
"twilio": "^5.10.6",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.11"
|
||||
|
||||
8
backend/src/import_state.json
Normal file
8
backend/src/import_state.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"planilla_path": "C:\\Users\\LENOVO\\Desktop\\Desarrollos\\produccion\\aunar\\backend\\src\\uploads\\1766080602276__PLANILLA DE CITAS NOVIEMBRE.xlsx",
|
||||
"planilla_nombre": "PLANILLA DE CITAS NOVIEMBRE.xlsx",
|
||||
"planilla_subida_en": "2025-12-18T17:56:42.330Z",
|
||||
"histor_path": "C:\\Users\\LENOVO\\Desktop\\Desarrollos\\produccion\\aunar\\backend\\src\\uploads\\1766080603238__-ACTIVIDADESREALIZADASENHISTOR_2025-12-08-09-02.xlsx",
|
||||
"histor_nombre": "-ACTIVIDADESREALIZADASENHISTOR_2025-12-08-09-02.xlsx",
|
||||
"histor_subida_en": "2025-12-18T17:56:43.249Z"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user