feat: implement route assignment management and sequencing module with interactive data visualization and editing capabilities
This commit is contained in:
@@ -9,6 +9,20 @@ export interface SequencedRoute {
|
||||
previousPdvName: string | null;
|
||||
}
|
||||
|
||||
export interface DailyRouteSummary {
|
||||
key: string;
|
||||
userId: string;
|
||||
userName: string;
|
||||
day: string;
|
||||
routes: SequencedRoute[];
|
||||
distanceKm: number;
|
||||
travelHours: number;
|
||||
workHours: number;
|
||||
capacityHours: number;
|
||||
totalHours: number;
|
||||
exceedsCapacity: boolean;
|
||||
}
|
||||
|
||||
export function sequenceRoutes(routes: RouteAssignedResponse[]): SequencedRoute[] {
|
||||
const groups = new Map<string, RouteAssignedResponse[]>();
|
||||
for (const route of routes) {
|
||||
@@ -23,17 +37,22 @@ export function sequenceRoutes(routes: RouteAssignedResponse[]): SequencedRoute[
|
||||
const first = group[0].json;
|
||||
let current: [number, number] = [Number(first.longitud_usuario), Number(first.latitud_usuario)];
|
||||
let previousPdvName: string | null = null;
|
||||
const remaining = [...group];
|
||||
const hasManualOrder = group.every(route => Number.isFinite(route.json.visit_order));
|
||||
const remaining = hasManualOrder
|
||||
? [...group].sort((a, b) => Number(a.json.visit_order) - Number(b.json.visit_order))
|
||||
: [...group];
|
||||
|
||||
while (remaining.length) {
|
||||
let nearestIndex = 0;
|
||||
let nearestDistance = Number.POSITIVE_INFINITY;
|
||||
for (let index = 0; index < remaining.length; index++) {
|
||||
const candidate = remaining[index].json;
|
||||
const distance = haversineKm(current, [Number(candidate.longitud_pdv), Number(candidate.latitud_pdv)]);
|
||||
if (distance < nearestDistance) {
|
||||
nearestDistance = distance;
|
||||
nearestIndex = index;
|
||||
if (!hasManualOrder) {
|
||||
let nearestDistance = Number.POSITIVE_INFINITY;
|
||||
for (let index = 0; index < remaining.length; index++) {
|
||||
const candidate = remaining[index].json;
|
||||
const distance = haversineKm(current, [Number(candidate.longitud_pdv), Number(candidate.latitud_pdv)]);
|
||||
if (distance < nearestDistance) {
|
||||
nearestDistance = distance;
|
||||
nearestIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +74,38 @@ export function sequenceRoutes(routes: RouteAssignedResponse[]): SequencedRoute[
|
||||
return sequenced;
|
||||
}
|
||||
|
||||
export function summarizeDailyRoutes(routes: RouteAssignedResponse[]): DailyRouteSummary[] {
|
||||
const sequences = sequenceRoutes(routes);
|
||||
const grouped = new Map<string, SequencedRoute[]>();
|
||||
for (const segment of sequences) {
|
||||
const key = `${segment.route.json.usuario_id}\u0000${segment.route.json.dia}`;
|
||||
const group = grouped.get(key) ?? [];
|
||||
group.push(segment);
|
||||
grouped.set(key, group);
|
||||
}
|
||||
return Array.from(grouped, ([key, segments]) => {
|
||||
const first = segments[0].route.json;
|
||||
const distanceKm = segments.reduce((sum, segment) => sum + haversineKm(segment.origin, segment.destination), 0);
|
||||
const travelHours = segments.reduce((sum, segment) => sum + Number(segment.route.json.horas_desplazamiento || 0), 0);
|
||||
const workHours = segments.reduce((sum, segment) => sum + Number(segment.route.json.horas_trabajo || segment.route.json.hora_minima_semanal_pdv || 0), 0);
|
||||
const capacityHours = Number(first.hora_laboral_semanal_usuario || 0) / 5;
|
||||
const totalHours = workHours + travelHours;
|
||||
return {
|
||||
key,
|
||||
userId: String(first.usuario_id),
|
||||
userName: first.nombre_usuario,
|
||||
day: first.dia,
|
||||
routes: segments,
|
||||
distanceKm,
|
||||
travelHours,
|
||||
workHours,
|
||||
capacityHours,
|
||||
totalHours,
|
||||
exceedsCapacity: totalHours > capacityHours
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function haversineKm(origin: [number, number], destination: [number, number]): number {
|
||||
const toRadians = (value: number) => value * Math.PI / 180;
|
||||
const [lon1, lat1] = origin;
|
||||
|
||||
Reference in New Issue
Block a user