Sistema de Optimizacion de Rutas y Gestion de Entregas
Una alternativa open-source a SimpliRoute, OptimoRoute y LogiNext — sin costos por conductor.
- Por que BetterRoute?
- Caracteristicas
- Arquitectura
- Requisitos
- Instalacion
- Configuracion
- Uso
- Estructura del Proyecto
- Base de Datos
- API Reference
- App Movil
- Roadmap
- Contribuir
- Licencia
Las empresas de logistica y distribucion enfrentan un problema critico: las soluciones SaaS de optimizacion de rutas como SimpliRoute, OptimoRoute o LogiNext cobran por conductor activo, lo que resulta en costos prohibitivos:
| Solucion | Precio por conductor/mes | 50 conductores/mes |
|---|---|---|
| SimpliRoute | ~$35-50 USD | $1,750 - $2,500 |
| OptimoRoute | ~$40-60 USD | $2,000 - $3,000 |
| LogiNext | ~$50-80 USD | $2,500 - $4,000 |
| BetterRoute | $0 (self-hosted) | $0 + hosting |
BetterRoute es un sistema completo de optimizacion de rutas que puedes hospedar en tu propia infraestructura. Pagas solo por el servidor (desde ~$20/mes en un VPS) sin importar cuantos conductores tengas.
Ahorro potencial: Una empresa con 50 conductores puede ahorrar $24,000 - $48,000 USD al ano.
- Motor VROOM + OSRM — Rapido y escalable, ideal para operaciones de ultima milla con 1000+ paradas por plan
- Distancias reales — Calculo basado en red vial via OSRM, no linea recta
- Zonas con isolation hard — La planificacion se particiona por zona (
createZoneBatches) para que un vehiculo no cruce limites de servicio - Verifier independiente del solver — Capa de validacion HARD/SOFT/INFO que confirma que las rutas cumplen las restricciones antes de confirmarse
- Presets de optimizacion — Configuraciones reutilizables (factor de trafico, distancia maxima, ventanas flexibles, rutas abiertas, balance de carga, etc.)
- Intercambio de vehiculos — Swap completo de rutas entre vehiculos con reoptimizacion automatica
- Restricciones avanzadas:
- Capacidad de vehiculos (peso, volumen, bultos)
- Ventanas horarias de entrega (con tolerancia flexible configurable)
- Habilidades requeridas (cadena de frio, carga pesada, etc.)
- Horarios de trabajo de conductores
- Zonas de servicio
- Distancia maxima por ruta
- Factor de trafico configurable (0-100%)
- Rutas abiertas (sin retorno a origen)
- Minimizacion de vehiculos basada en capacidad real
- Importacion masiva desde CSV/Excel
- Geocodificacion automatica de direcciones
- Estados de entrega en tiempo real
- Evidencia fotografica de entregas
- Motivos de no entrega configurables
- Vehiculos con capacidades y restricciones
- Asignacion de conductores
- Historial de mantenimiento
- Seguimiento GPS en tiempo real
- Cada empresa define sus propios campos en pedidos sin cambios de codigo
- Tipos:
text,number,select,date,currency,phone,email,boolean - Configurables por visibilidad: tabla, app movil, CSV import
- Validacion automatica (min/max, required, pattern)
- Renderizado dinamico en formularios, tablas, CSV import y app movil
- Cada empresa define sus propios estados de entrega
- Transiciones configurables entre estados
- Requisitos por estado: foto, firma, motivo, notas
- Colores e iconos personalizables
- Integrado con app movil Flutter
- Aislamiento completo de datos por empresa (JWT-cross-validated)
- Sistema RBAC end-to-end con permisos tipados (TypeScript template literal)
- Roles legacy predefinidos + roles personalizables por empresa via UI
/roles - Perfiles de optimizacion por empresa
- Contrato unificado server/cliente —
EntityType,ActionyPermissionensrc/lib/auth/permissions/son la unica fuente de verdad - Gating UI declarativo —
<Can perm="order:update">esconde botones segun permiso - Fail-closed por defecto —
<ProtectedPage>deniega si olvidas declararrequiredPermission - Custom roles dinamicos — Los permisos adicionales asignados via DB se aplican tanto en UI como en enforcement server
- Imposible typear mal —
<Can perm="order:edit">es error de compilacion (Action.EDITno existe)
- Mapa con ubicacion de conductores
- Estado de entregas actualizado
- Alertas configurables
- Dashboard con metricas clave
- Visualizacion de ruta asignada
- Navegacion integrada (Google Maps/Waze)
- Captura de evidencia
- Envio de ubicacion GPS al servidor
- Funciona offline (cola de sincronizacion)
+------------------------------------------------------------------+
| FRONTEND |
| +----------------+ +----------------+ +------------------+ |
| | Next.js Web | | Flutter App | | API Clients | |
| | (React 19) | | (Android/iOS) | | (Integraciones) | |
| +-------+--------+ +-------+--------+ +--------+---------+ |
+----------|-------------------|---------------------|---------------+
| | |
v v v
+------------------------------------------------------------------+
| BACKEND |
| +--------------------------------------------------------------+ |
| | Next.js API Routes | |
| | * /api/auth/* * /api/orders/* | |
| | * /api/optimization/* * /api/mobile/driver/* | |
| | * /api/monitoring/* * /api/vehicles/* | |
| +--------------------------------------------------------------+ |
| | |
| +---------------+---------------+ |
| v v v |
| +-------------+ +-------------+ +------------------+ |
| | PostgreSQL | | Redis | | Cloudflare R2 | |
| | (Drizzle) | | (Upstash) | | (S3 Storage) | |
| +-------------+ +-------------+ +------------------+ |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| ROUTING ENGINES |
| +-------------------------------+ +--------------------------+ |
| | VROOM | | OSRM | |
| | (Fast VRP, zone-batched, | | (Road network distance | |
| | 1000+ orders per plan) | | and duration matrix) | |
| +-------------------------------+ +--------------------------+ |
+------------------------------------------------------------------+
- Bun 1.0+ (recomendado) o Node.js 20+
- PostgreSQL 15+
- Docker (para VROOM + OSRM)
- 4GB RAM, 2 CPU cores
- VPS con 8GB RAM, 4 CPU cores
- SSD 50GB+ (para mapas OSRM)
- Redis (Upstash o self-hosted)
- S3-compatible storage (Cloudflare R2, MinIO)
git clone https://github.com/tu-usuario/betterroute.git
cd betterroute# Con Bun (recomendado)
bun install
# O con npm
npm installcp .env.example .envEdita .env con tus valores:
# Base de datos PostgreSQL
DATABASE_URL=postgresql://user:password@localhost:5432/betterroute
# JWT Secret (genera uno seguro para produccion)
JWT_SECRET=tu-secreto-super-seguro-minimo-32-caracteres
# Redis para cache (opcional pero recomendado)
UPSTASH_REDIS_REST_URL=https://tu-instancia.upstash.io
UPSTASH_REDIS_REST_TOKEN=tu-token
# Motores de rutas
VROOM_URL=http://localhost:5000
OSRM_URL=http://localhost:5001
# Cloudflare R2 para almacenamiento (fotos de evidencia)
R2_ACCOUNT_ID=tu-account-id
R2_ACCESS_KEY_ID=tu-access-key
R2_SECRET_ACCESS_KEY=tu-secret-key
R2_BUCKET_NAME=betterroute-files
R2_PUBLIC_URL=https://tu-bucket.tu-dominio.comDescarga los datos de tu pais/region:
# Crear directorio para datos
mkdir -p docker/osrm
cd docker/osrm
# Descargar mapa (ejemplo: Peru)
wget https://download.geofabrik.de/south-america/peru-latest.osm.pbf
# Procesar mapa (puede tardar 10-30 minutos)
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/peru-latest.osm.pbf
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-partition /data/peru-latest.osrm
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-customize /data/peru-latest.osrm
cd ../..Mapas disponibles: https://download.geofabrik.de/
docker compose --profile routing up -dEsto inicia:
- OSRM en
http://localhost:5001— calculo de distancias/tiempos - VROOM en
http://localhost:5000— optimizacion de rutas
# Ejecutar migraciones
bun run db:migrate
# Cargar datos de ejemplo (opcional)
bun run db:seed# Desarrollo
bun run dev
# Produccion
bun run build
bun run startLa aplicacion estara disponible en http://localhost:3000
Despues de bun run db:seed:
| Rol | Contrasena | |
|---|---|---|
| Admin Sistema | admin@planeamiento.com |
admin123 |
Para crear un set completo de usuarios de prueba (uno por rol legacy,
todos sobre una empresa TestCo RBAC), usa el script de verificacion:
bun run scripts/create-test-users.tsEso provisiona:
| Rol | Contrasena | |
|---|---|---|
| ADMIN_SISTEMA | admin@test.local |
test123 |
| ADMIN_FLOTA | adminflota@test.local |
test123 |
| PLANIFICADOR | planificador@test.local |
test123 |
| MONITOR | monitor@test.local |
test123 |
| CONDUCTOR | conductor@test.local |
test123 |
Para verificar que el camino de custom roles (roles dinamicos via DB) funciona correctamente end-to-end:
bun run scripts/verify-custom-role.tsImportante: Cambia estas contrasenas en produccion.
Cada empresa puede configurar:
- Campos de pedido — Que columnas mostrar en CSV
- Restricciones de vehiculos — Capacidad, peso maximo, etc.
- Parametros de optimizacion — Balance velocidad/calidad
- Ventanas horarias — Presets reutilizables
| Rol | Descripcion |
|---|---|
ADMIN_SISTEMA |
Acceso total (wildcard), gestion multi-empresa |
ADMIN_FLOTA |
Flota, vehiculos, conductores, skills, zonas + configuracion de empresa (workflow, custom fields, presets) |
PLANIFICADOR |
Pedidos (CRUD + import + bulk delete), planes (create/update/confirm/cancel), asignacion de rutas |
MONITOR |
Lectura + accionar alertas + actualizar status de paradas desde la web |
CONDUCTOR |
Solo sus rutas asignadas, update de status de paradas desde la app movil |
Ademas de los roles legacy, cada empresa puede crear roles personalizados
desde /roles con permisos toggleables por entidad x accion. Los permisos
resultantes son la union del rol legacy base + los custom roles asignados.
El enforcement server-side aplica ambos en una sola consulta.
Para el patron completo (como agregar una feature con RBAC, anti-patterns,
convenciones), ver src/lib/auth/permissions/README.md.
planeamiento/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (auth)/ # Paginas de autenticacion
│ │ ├── (protected)/ # Paginas protegidas
│ │ │ ├── dashboard/
│ │ │ ├── orders/
│ │ │ ├── vehicles/
│ │ │ ├── planificacion/
│ │ │ ├── monitoring/
│ │ │ ├── custom-fields/ # Admin campos personalizados
│ │ │ ├── workflow/ # Config workflow states
│ │ │ └── ...
│ │ └── api/ # API Routes (~70 handlers)
│ │ ├── auth/
│ │ ├── orders/
│ │ ├── companies/ # CRUD empresas + field definitions
│ │ ├── optimization/ # Jobs, config, swap, confirm, reassign
│ │ ├── mobile/ # APIs para app movil
│ │ └── monitoring/
│ ├── components/ # Componentes React
│ │ ├── ui/ # shadcn/ui components
│ │ ├── layout/ # AppShell, Sidebar, CompanyProvider
│ │ ├── custom-fields/ # Admin campos personalizados
│ │ ├── orders/ # Formularios y tablas de ordenes
│ │ ├── monitoring/ # Vista monitoreo con mapa
│ │ └── optimization/ # Dashboard con swap, presets, resultados
│ ├── db/ # Drizzle ORM
│ │ ├── schema.ts # Definicion de tablas
│ │ └── seed.ts # Datos de ejemplo
│ ├── tests/ # Tests de integracion
│ │ └── integration/ # 170+ tests, real PostgreSQL
│ └── lib/ # Logica de negocio
│ ├── auth/ # Autenticacion + RBAC
│ │ ├── permissions/ # Contrato tipado (EntityType, Action, Permission)
│ │ └── authorization.ts # Role permissions matrix + DB checks
│ ├── optimization/ # VROOM adapter, runner, verifier
│ ├── orders/ # Profile schema, CSV import pipeline
│ ├── geo/ # Zone batching, OSRM matrix helpers
│ ├── custom-fields/ # Validacion y seed de campos custom
│ ├── workflow/ # Seed de workflow states
│ ├── infra/ # Infraestructura (cache, tenant, api-middleware)
│ └── services/ # Servicios externos (VROOM, S3)
├── scripts/ # Scripts operativos
│ ├── create-test-users.ts # Seed idempotente de users por rol
│ └── verify-custom-role.ts # E2E verification del merge legacy + custom roles
├── drizzle/ # Migraciones SQL
├── docker/ # Configuracion Docker
│ ├── osrm/ # Datos de mapas
│ └── vroom/ # Config VROOM
├── docker-compose.yml
├── .env.example
└── package.json
# Ver estado de migraciones
bun run db:studio
# Generar nueva migracion
bun run db:generate --name nombre_descriptivo
# Aplicar migraciones pendientes
bun run db:migrate
# Sincronizar schema (desarrollo)
bun run db:push| Tabla | Descripcion |
|---|---|
companies |
Empresas/tenants |
users |
Usuarios y conductores |
vehicles |
Vehiculos de la flota |
fleets |
Flotas/grupos de vehiculos |
orders |
Pedidos a entregar |
optimization_jobs |
Trabajos de optimizacion |
route_stops |
Paradas de ruta confirmadas |
driver_locations |
Historial de ubicaciones GPS |
company_workflow_states |
Estados de workflow custom por empresa |
company_workflow_transitions |
Transiciones entre estados |
company_field_definitions |
Campos personalizados por empresa |
roles / permissions |
Sistema RBAC |
| Archivo | Descripcion |
|---|---|
0000_amused_night_nurse.sql |
Schema inicial completo |
0001_stormy_ironclad.sql |
Ajustes menores |
0002_white_rumiko_fujikawa.sql |
Alertas y notificaciones |
0003_brave_secret_warriors.sql |
Historial de estados |
0004_kind_post.sql |
Campos adicionales |
0005_add-vehicle-skill-assignments.sql |
Habilidades de vehiculos |
0006_add_driver_locations.sql |
Tracking GPS de conductores |
# Login
POST /api/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "admin123"
}
# Response
{
"accessToken": "eyJ...",
"refreshToken": "eyJ...",
"user": { ... }
}Authorization: Bearer <accessToken>
X-Company-Id: <uuid> # Para endpoints multi-tenant
| Metodo | Endpoint | Descripcion |
|---|---|---|
| GET | /api/orders |
Listar pedidos |
| POST | /api/orders/import |
Importar CSV |
| POST | /api/optimization/configure |
Crear configuracion de optimizacion |
| POST | /api/optimization/jobs |
Crear y ejecutar optimizacion |
| GET | /api/optimization/jobs/:id |
Estado de optimizacion |
| POST | /api/optimization/jobs/:id/confirm |
Confirmar plan |
| POST | /api/optimization/jobs/:id/swap-vehicles |
Intercambiar rutas entre vehiculos |
| GET | /api/optimization-presets |
Presets de optimizacion |
| POST | /api/driver-assignment/manual |
Asignacion manual de conductor |
| POST | /api/driver-assignment/suggestions |
Sugerencias de conductor |
| POST | /api/reassignment/options |
Opciones de reasignacion |
| GET | /api/monitoring/geojson |
GeoJSON para mapa |
| GET | /api/monitoring/summary |
Resumen de monitoreo |
| POST | /api/mobile/driver/location |
Enviar ubicacion GPS |
| GET | /api/mobile/driver/my-route |
Ruta del conductor |
| PATCH | /api/route-stops/:id |
Actualizar parada |
| GET | /api/companies/:id/field-definitions |
Listar campos custom |
| GET | /api/mobile/driver/workflow-states |
Estados de workflow |
| GET | /api/tracking/:token |
Tracking publico de pedido |
La app movil esta en un repositorio separado: better-route-mobile (Flutter).
- Lista de paradas del dia
- Navegacion a cada parada (Google Maps / Waze)
- Marcar entregas como completadas
- Capturar foto de evidencia
- Registrar motivo de no entrega
- Envio automatico de ubicacion GPS cada 20 segundos
- Cola offline para envios fallidos
- Workflow states dinamicos — Botones de accion generados segun la configuracion de la empresa
- Campos personalizados — Muestra campos custom definidos por la empresa en el detalle de cada parada
Editar lib/core/constants.dart:
class ApiConfig {
// Cambiar para produccion
static const String baseUrl = 'https://tu-api.com';
}
class AppConstants {
// Configuracion de tracking
static const int trackingIntervalSeconds = 20;
static const int trackingRetryAttempts = 3;
}flutter pub get
flutter build apk --releaseSistema de autorizacion con contrato TypeScript unico entre server y cliente. <Can> component + useCan hook tipados, <ProtectedPage> fail-closed, custom roles via DB con merge automatico legacy + dinamico, enforcement server-side garantizado para ambos.
Cada empresa puede definir campos personalizados en sus pedidos desde la UI de admin. Los campos se renderizan dinamicamente en formularios, tablas, CSV import y la app movil.
Configuraciones reutilizables que fluyen desde la UI hasta el motor VROOM: factor de trafico, distancia maxima, ventanas flexibles, rutas abiertas, balance de carga, minimizacion de vehiculos, etc.
Swap completo de rutas entre vehiculos con reoptimizacion automatica via VROOM desde la interfaz de planificacion.
Pagina publica de seguimiento de pedidos via token unico. Los clientes finales pueden ver el estado de su entrega sin necesidad de cuenta.
- Reoptimizacion en vivo — Recalcular rutas automaticamente cuando un conductor reporta un problema
- ETA en tiempo real — Notificaciones al cliente final con hora estimada de llegada actualizada
- Reportes y analytics — Dashboards con KPIs historicos (cumplimiento, tiempos, costos)
- Webhooks — Notificaciones push a sistemas externos en eventos clave
- Multi-dia — Planificacion de rutas que abarcan multiples dias
App Movil — better-route-mobile
Evolucionar la app Flutter con nuevas funcionalidades: tracking GPS en tiempo real (SSE), firma digital de recepcion, modo offline mejorado y notificaciones push.
| Categoria | Tecnologia |
|---|---|
| Frontend | Next.js 16, React 19, TailwindCSS 4 |
| UI Components | shadcn/ui, Radix UI |
| State | SWR |
| Maps | MapLibre GL |
| Backend | Next.js API Routes |
| Database | PostgreSQL + Drizzle ORM |
| Cache | Upstash Redis |
| Storage | Cloudflare R2 (S3) |
| Auth | JWT (jose) |
| Routing Engine | VROOM + OSRM |
| Mobile | Flutter + Riverpod |
| Testing | Bun Test (integration), Playwright (e2e) |
| Linting | Biome |
- VROOM Project — Motor de optimizacion
- OSRM — Calculo de rutas
- Next.js — Framework web
- Drizzle ORM — ORM TypeScript
- shadcn/ui — Componentes UI
- MapLibre — Mapas open-source
Las contribuciones son bienvenidas. Consulta CONTRIBUTING.md para conocer las convenciones del proyecto y como enviar tu primer Pull Request.
Este proyecto esta licenciado bajo la Licencia MIT.
BetterRoute — Optimiza tus entregas, no tu presupuesto.