Compare commits
4 Commits
fbb378b009
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 52328897f6 | |||
| 7d696e6f16 | |||
| f2ae1cef58 | |||
| 65fe788281 |
@@ -86,7 +86,13 @@ export class PlanningKpisComponent implements OnInit, OnDestroy {
|
|||||||
private refresh(): void {
|
private refresh(): void {
|
||||||
const assigned = this.routeState.getAssignedSnapshot();
|
const assigned = this.routeState.getAssignedSnapshot();
|
||||||
const unassigned = this.routeState.getNoAssignedSnapshot();
|
const unassigned = this.routeState.getNoAssignedSnapshot();
|
||||||
const totalPdvs = assigned.length + unassigned.length;
|
const assignedPdvIds = new Set(assigned.map(route => String(route.json.pdv_id)));
|
||||||
|
// A PDV with at least one scheduled visit is assigned; repeated weekly visits and
|
||||||
|
// partial-assignment alerts must not inflate the planning coverage counters.
|
||||||
|
const unassignedPdvIds = new Set(unassigned
|
||||||
|
.map(route => String(route.pdv_id))
|
||||||
|
.filter(pdvId => !assignedPdvIds.has(pdvId)));
|
||||||
|
const totalPdvs = new Set([...assignedPdvIds, ...unassignedPdvIds]).size;
|
||||||
const dailyRoutes = summarizeDailyRoutes(assigned);
|
const dailyRoutes = summarizeDailyRoutes(assigned);
|
||||||
const totalDistance = dailyRoutes.reduce((sum, day) => sum + day.distanceKm, 0);
|
const totalDistance = dailyRoutes.reduce((sum, day) => sum + day.distanceKm, 0);
|
||||||
const totalTravelHours = dailyRoutes.reduce((sum, day) => sum + day.travelHours, 0);
|
const totalTravelHours = dailyRoutes.reduce((sum, day) => sum + day.travelHours, 0);
|
||||||
@@ -134,9 +140,9 @@ export class PlanningKpisComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.summary = {
|
this.summary = {
|
||||||
totalPdvs,
|
totalPdvs,
|
||||||
assignedPdvs: assigned.length,
|
assignedPdvs: assignedPdvIds.size,
|
||||||
unassignedPdvs: unassigned.length,
|
unassignedPdvs: unassignedPdvIds.size,
|
||||||
coverage: totalPdvs ? (assigned.length / totalPdvs) * 100 : 0,
|
coverage: totalPdvs ? (assignedPdvIds.size / totalPdvs) * 100 : 0,
|
||||||
users,
|
users,
|
||||||
days,
|
days,
|
||||||
totalDistance,
|
totalDistance,
|
||||||
@@ -149,9 +155,15 @@ export class PlanningKpisComponent implements OnInit, OnDestroy {
|
|||||||
assignmentBalance
|
assignmentBalance
|
||||||
};
|
};
|
||||||
|
|
||||||
const reasonCounts = new Map<string, number>();
|
const reasonByPdv = new Map<string, string>();
|
||||||
for (const route of unassigned) {
|
for (const route of unassigned) {
|
||||||
|
const pdvId = String(route.pdv_id);
|
||||||
|
if (assignedPdvIds.has(pdvId) || reasonByPdv.has(pdvId)) continue;
|
||||||
const reason = route.motivo?.trim() || 'Sin motivo especificado';
|
const reason = route.motivo?.trim() || 'Sin motivo especificado';
|
||||||
|
reasonByPdv.set(pdvId, reason);
|
||||||
|
}
|
||||||
|
const reasonCounts = new Map<string, number>();
|
||||||
|
for (const reason of reasonByPdv.values()) {
|
||||||
reasonCounts.set(reason, (reasonCounts.get(reason) ?? 0) + 1);
|
reasonCounts.set(reason, (reasonCounts.get(reason) ?? 0) + 1);
|
||||||
}
|
}
|
||||||
this.reasons = Array.from(reasonCounts.entries())
|
this.reasons = Array.from(reasonCounts.entries())
|
||||||
|
|||||||
+6
-19
@@ -51,7 +51,7 @@ export class RouteOverviewMapComponent implements OnInit, OnDestroy, AfterViewIn
|
|||||||
|
|
||||||
usuarios: { id: string; nombre: string }[] = [];
|
usuarios: { id: string; nombre: string }[] = [];
|
||||||
dias: string[] = [];
|
dias: string[] = [];
|
||||||
selectedUsuarioId: string | null = null;
|
selectedUsuarioId: string = 'Todos';
|
||||||
selectedDia: string = 'Todos';
|
selectedDia: string = 'Todos';
|
||||||
selectedRouteDetail: RouteAssignedResponse | null = null;
|
selectedRouteDetail: RouteAssignedResponse | null = null;
|
||||||
|
|
||||||
@@ -112,11 +112,12 @@ export class RouteOverviewMapComponent implements OnInit, OnDestroy, AfterViewIn
|
|||||||
this.allRoutes = [...routes];
|
this.allRoutes = [...routes];
|
||||||
this.usuarios = this.routeState.getUsuariosUnicos();
|
this.usuarios = this.routeState.getUsuariosUnicos();
|
||||||
this.dias = this.routeState.getDiasUnicos();
|
this.dias = this.routeState.getDiasUnicos();
|
||||||
// Init from queryParams default (Todos)
|
// Start each map load with the complete planning selected by default.
|
||||||
const qp = this.activatedRoute.snapshot.queryParams;
|
const qp = this.activatedRoute.snapshot.queryParams;
|
||||||
if (qp['usuario_id']) this.selectedUsuarioId = String(qp['usuario_id']);
|
if (qp['pdv_id']) {
|
||||||
else if (!this.selectedUsuarioId && this.usuarios.length) this.selectedUsuarioId = 'Todos';
|
this.selectedUsuarioId = 'Todos';
|
||||||
if (qp['dia']) this.selectedDia = String(qp['dia']);
|
this.selectedDia = 'Todos';
|
||||||
|
}
|
||||||
// If focus pdv provided, auto-select detail after map loads
|
// If focus pdv provided, auto-select detail after map loads
|
||||||
this.applyFilter();
|
this.applyFilter();
|
||||||
this.cdr.detectChanges();
|
this.cdr.detectChanges();
|
||||||
@@ -135,20 +136,6 @@ export class RouteOverviewMapComponent implements OnInit, OnDestroy, AfterViewIn
|
|||||||
// React to queryParams changes
|
// React to queryParams changes
|
||||||
this.subs.push(
|
this.subs.push(
|
||||||
this.activatedRoute.queryParams.subscribe(qp => {
|
this.activatedRoute.queryParams.subscribe(qp => {
|
||||||
let changed = false;
|
|
||||||
if (qp['usuario_id'] && String(qp['usuario_id']) !== this.selectedUsuarioId) {
|
|
||||||
this.selectedUsuarioId = String(qp['usuario_id']);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if (qp['dia'] && qp['dia'] !== this.selectedDia) {
|
|
||||||
this.selectedDia = String(qp['dia']);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if (changed) {
|
|
||||||
this.applyFilter();
|
|
||||||
if (this.map) this.renderFiltered();
|
|
||||||
this.cdr.detectChanges();
|
|
||||||
}
|
|
||||||
// Focus a specific route if pdv_id passed
|
// Focus a specific route if pdv_id passed
|
||||||
if (qp['pdv_id'] && this.filteredRoutes.length) {
|
if (qp['pdv_id'] && this.filteredRoutes.length) {
|
||||||
const found = this.filteredRoutes.find(r => String(r.json.pdv_id) === String(qp['pdv_id']));
|
const found = this.filteredRoutes.find(r => String(r.json.pdv_id) === String(qp['pdv_id']));
|
||||||
|
|||||||
Reference in New Issue
Block a user