feat: implement route planning dashboard including KPIs, user workload tracking, and route assignment management features
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export * from './pdv.schema';
|
||||
export * from './usuario.schema';
|
||||
export * from './params.schema';
|
||||
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const paramsSchema = z.object({
|
||||
radioKm: z.union([z.literal(30), z.literal(50), z.literal(80)]),
|
||||
velocidad: z.number().min(15).max(80),
|
||||
});
|
||||
|
||||
export type Params = z.infer<typeof paramsSchema>;
|
||||
// Urbano denso Santo Domingo: 22-28 km/h es más realista que 46 (autopista).
|
||||
// P2-A default 28; 46 sigue disponible como "Mixto rápido" pero ya no default.
|
||||
export const DEFAULT_PARAMS: Params = { radioKm: 50, velocidad: 28 };
|
||||
@@ -0,0 +1,41 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const PDV_REQUIRED_HEADERS = [
|
||||
'ID',
|
||||
'Nombre del PDV',
|
||||
'Segmentación',
|
||||
'Latitud',
|
||||
'Longitud',
|
||||
'Visitas semanales',
|
||||
'Duración visita(horas)',
|
||||
'Prioridad',
|
||||
] as const;
|
||||
|
||||
export const PDV_NORMALIZED_REQUIRED = [
|
||||
'id',
|
||||
'nombre_del_pdv',
|
||||
'segmentacion',
|
||||
'latitud',
|
||||
'longitud',
|
||||
'visitas_semanales',
|
||||
'duracion_visitahoras',
|
||||
'prioridad',
|
||||
] as const;
|
||||
|
||||
export const SEGMENTACIONES = ['AA', 'A', 'B', 'C', 'D'] as const;
|
||||
|
||||
export const pdvRowSchema = z.object({
|
||||
id: z.union([z.string(), z.number()]).refine(v => String(v).trim() !== '', { message: 'ID requerido' }),
|
||||
nombre_del_pdv: z.string().min(1, 'Nombre del PDV requerido'),
|
||||
segmentacion: z.string().refine(v => (SEGMENTACIONES as readonly string[]).includes(v.toUpperCase()), {
|
||||
message: `Segmentación debe ser ${SEGMENTACIONES.join(', ')}`,
|
||||
}),
|
||||
latitud: z.number().min(-90, 'Latitud mínima -90').max(90, 'Latitud máxima 90'),
|
||||
longitud: z.number().min(-180, 'Longitud mínima -180').max(180, 'Longitud máxima 180'),
|
||||
visitas_semanales: z.number().int('Visitas semanales debe ser entero').min(1, 'Visitas semanales mínimo 1').max(7, 'Visitas semanales máximo 7'),
|
||||
duracion_visitahoras: z.number().min(0.01, 'Duración visita debe ser >0').max(24, 'Duración visita máximo 24'),
|
||||
prioridad: z.number().int('Prioridad debe ser entero').min(1, 'Prioridad mínimo 1').max(5, 'Prioridad máximo 5'),
|
||||
});
|
||||
|
||||
export type PdvRow = z.infer<typeof pdvRowSchema>;
|
||||
export const PDV_MAX_ROWS = 2000;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const USUARIO_REQUIRED_HEADERS = [
|
||||
'ID',
|
||||
'Nombre del empleado',
|
||||
'Latitud',
|
||||
'Longitud',
|
||||
'Horas por día usuario',
|
||||
'Horas por semana usuario',
|
||||
] as const;
|
||||
|
||||
export const USUARIO_NORMALIZED_REQUIRED = [
|
||||
'id',
|
||||
'nombre_del_empleado',
|
||||
'latitud',
|
||||
'longitud',
|
||||
'horas_por_dia_usuario',
|
||||
'horas_por_semana_usuario',
|
||||
] as const;
|
||||
|
||||
export const usuarioRowSchema = z.object({
|
||||
id: z.union([z.string(), z.number()]).refine(v => String(v).trim() !== '', { message: 'ID requerido' }),
|
||||
nombre_del_empleado: z.string().min(1, 'Nombre del empleado requerido'),
|
||||
latitud: z.number().min(-90, 'Latitud mínima -90').max(90, 'Latitud máxima 90'),
|
||||
longitud: z.number().min(-180, 'Longitud mínima -180').max(180, 'Longitud máxima 180'),
|
||||
horas_por_dia_usuario: z.number().min(0.5, 'Horas por día mínimo 0.5').max(24, 'Horas por día máximo 24'),
|
||||
horas_por_semana_usuario: z.number().min(1, 'Horas por semana mínimo 1').max(168, 'Horas por semana máximo 168'),
|
||||
}).superRefine((data, ctx) => {
|
||||
if (data.horas_por_semana_usuario > data.horas_por_dia_usuario * 7) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Horas por semana no puede exceder 7 × horas por día',
|
||||
path: ['horas_por_semana_usuario'],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export type UsuarioRow = z.infer<typeof usuarioRowSchema>;
|
||||
export const USUARIO_MAX_ROWS = 50;
|
||||
Reference in New Issue
Block a user