feat: implement route assignment management and sequencing module with interactive data visualization and editing capabilities

This commit is contained in:
2026-08-31 17:56:33 -04:00
parent cd5c57c5ee
commit 9f42175afc
29 changed files with 458 additions and 218 deletions
@@ -7,7 +7,6 @@ import { RutasService } from '../../core/services/router.service';
import { RouteState } from '../../core/route-state/route';
import { ApiResponse } from '../../core/models/route.model';
import { ExcelPreviewService, PreviewResult } from '../../shared/services/excel-preview.service';
import { DEFAULT_PARAMS } from '../../shared/schemas/params.schema';
import { Subscription } from 'rxjs';
import { PlanningKpisComponent } from './planning-kpis/planning-kpis.component';
import { PlanningInputService } from '../../core/services/planning-input.service';
@@ -30,32 +29,13 @@ export class HomeComponent {
isLoading = false;
private calcSub: Subscription | null = null;
// P2-A params
radioKm: 30 | 50 | 80 = DEFAULT_PARAMS.radioKm;
velocidad: number = DEFAULT_PARAMS.velocidad;
constructor(
private rutasService: RutasService,
private routeState: RouteState,
private previewService: ExcelPreviewService,
private planningInput: PlanningInputService,
private cdr: ChangeDetectorRef
) {
try {
const raw = sessionStorage.getItem('rp_params');
if (raw) {
const p = JSON.parse(raw) as { radioKm?: number; velocidad?: number };
if ([30, 50, 80].includes(p.radioKm as number)) this.radioKm = p.radioKm as 30|50|80;
if (typeof p.velocidad === 'number' && p.velocidad >= 20 && p.velocidad <= 80) this.velocidad = p.velocidad;
}
} catch { /* ignore */ }
}
onRadioChange() { this.persistParams(); }
onVelocidadChange() { this.persistParams(); }
private persistParams() {
try { sessionStorage.setItem('rp_params', JSON.stringify({ radioKm: this.radioKm, velocidad: this.velocidad })); } catch { /* ignore */ }
}
) {}
async onPdvFileChange(event: Event) {
const input = event.target as HTMLInputElement;
@@ -69,7 +49,7 @@ export class HomeComponent {
return;
}
this.pdvFile = file;
if (this.usuariosFile) this.planningInput.setFiles(file, this.usuariosFile, this.radioKm, this.velocidad);
if (this.usuariosFile) this.planningInput.setFiles(file, this.usuariosFile);
this.uploadError = null;
this.pdvPreviewLoading = true;
this.pdvPreview = null;
@@ -110,7 +90,7 @@ export class HomeComponent {
return;
}
this.usuariosFile = file;
if (this.pdvFile) this.planningInput.setFiles(this.pdvFile, file, this.radioKm, this.velocidad);
if (this.pdvFile) this.planningInput.setFiles(this.pdvFile, file);
this.uploadError = null;
this.usuariosPreviewLoading = true;
this.usuariosPreview = null;
@@ -172,19 +152,27 @@ export class HomeComponent {
return null;
}
cargarRutas() {
async cargarRutas() {
if (!this.canSubmit) return;
this.isLoading = true;
this.uploadError = null;
this.routeState.setLoading(true);
this.planningInput.setFiles(this.pdvFile!, this.usuariosFile!, this.radioKm, this.velocidad);
let pdvForOptimizer: File;
try {
pdvForOptimizer = await this.previewService.preparePdvForOptimizer(this.pdvFile!);
} catch {
this.uploadError = 'No se pudo preparar el archivo PDV para el optimizador.';
this.routeState.setLoading(false);
this.isLoading = false;
this.cdr.detectChanges();
return;
}
this.planningInput.setFiles(pdvForOptimizer, this.usuariosFile!);
const formData = new FormData();
formData.append('pdv_file', this.pdvFile!, this.pdvFile!.name);
formData.append('pdv_file', pdvForOptimizer, pdvForOptimizer.name);
formData.append('usuarios_file', this.usuariosFile!, this.usuariosFile!.name);
formData.append('radio_km', String(this.radioKm));
formData.append('velocidad', String(this.velocidad));
this.calcSub?.unsubscribe();
this.calcSub = this.rutasService.calcularRutas(formData).subscribe({