fix: Enum RouteStatus uppercase conflict with postgres type
This commit is contained in:
@ -9,9 +9,9 @@ from sqlalchemy import DateTime, func
|
|||||||
|
|
||||||
class RouteStatus(str, Enum):
|
class RouteStatus(str, Enum):
|
||||||
"""Route status enumeration."""
|
"""Route status enumeration."""
|
||||||
ACTIVE = "active"
|
ACTIVE = "ACTIVE"
|
||||||
INACTIVE = "inactive"
|
INACTIVE = "INACTIVE"
|
||||||
MAINTENANCE = "maintenance"
|
MAINTENANCE = "MAINTENANCE"
|
||||||
|
|
||||||
|
|
||||||
class Route(SQLModel, table=True):
|
class Route(SQLModel, table=True):
|
||||||
|
|||||||
140
backend/inject_routes.py
Normal file
140
backend/inject_routes.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
"""
|
||||||
|
Script de emergencia: Inyectar rutas directamente en la BD de producción
|
||||||
|
Ejecutar desde el servidor Render o con acceso directo a la BD.
|
||||||
|
|
||||||
|
USO: python inject_routes.py
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Añadir el path del backend
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
from sqlmodel import Session, create_engine, select, SQLModel
|
||||||
|
from app.models.route import Route, RouteStatus
|
||||||
|
from app.core.config import settings
|
||||||
|
|
||||||
|
# Rutas de bus más importantes de Boquete / Chiriquí
|
||||||
|
SAMPLE_ROUTES = [
|
||||||
|
{
|
||||||
|
"name": "Boquete - David",
|
||||||
|
"origin_city": "Boquete",
|
||||||
|
"destination_city": "David",
|
||||||
|
"color": "#FEE715",
|
||||||
|
"direction": "outbound",
|
||||||
|
"distance_km": 38.0,
|
||||||
|
"estimated_duration_minutes": 55,
|
||||||
|
"average_speed_kmh": 40.0,
|
||||||
|
"status": RouteStatus.ACTIVE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "David - Boquete",
|
||||||
|
"origin_city": "David",
|
||||||
|
"destination_city": "Boquete",
|
||||||
|
"color": "#FEE715",
|
||||||
|
"direction": "inbound",
|
||||||
|
"distance_km": 38.0,
|
||||||
|
"estimated_duration_minutes": 55,
|
||||||
|
"average_speed_kmh": 40.0,
|
||||||
|
"status": RouteStatus.ACTIVE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Boquete - Caldera",
|
||||||
|
"origin_city": "Boquete",
|
||||||
|
"destination_city": "Caldera",
|
||||||
|
"color": "#4CAF50",
|
||||||
|
"direction": "outbound",
|
||||||
|
"distance_km": 22.0,
|
||||||
|
"estimated_duration_minutes": 35,
|
||||||
|
"average_speed_kmh": 38.0,
|
||||||
|
"status": RouteStatus.ACTIVE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Caldera - Boquete",
|
||||||
|
"origin_city": "Caldera",
|
||||||
|
"destination_city": "Boquete",
|
||||||
|
"color": "#4CAF50",
|
||||||
|
"direction": "inbound",
|
||||||
|
"distance_km": 22.0,
|
||||||
|
"estimated_duration_minutes": 35,
|
||||||
|
"average_speed_kmh": 38.0,
|
||||||
|
"status": RouteStatus.ACTIVE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "David - Paso Canoas",
|
||||||
|
"origin_city": "David",
|
||||||
|
"destination_city": "Paso Canoas",
|
||||||
|
"color": "#2196F3",
|
||||||
|
"direction": "outbound",
|
||||||
|
"distance_km": 52.0,
|
||||||
|
"estimated_duration_minutes": 70,
|
||||||
|
"average_speed_kmh": 45.0,
|
||||||
|
"status": RouteStatus.ACTIVE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "David - Cerro Punta",
|
||||||
|
"origin_city": "David",
|
||||||
|
"destination_city": "Cerro Punta",
|
||||||
|
"color": "#9C27B0",
|
||||||
|
"direction": "outbound",
|
||||||
|
"distance_km": 75.0,
|
||||||
|
"estimated_duration_minutes": 100,
|
||||||
|
"average_speed_kmh": 45.0,
|
||||||
|
"status": RouteStatus.ACTIVE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "David - Volcán",
|
||||||
|
"origin_city": "David",
|
||||||
|
"destination_city": "Volcán",
|
||||||
|
"color": "#FF5722",
|
||||||
|
"direction": "outbound",
|
||||||
|
"distance_km": 62.0,
|
||||||
|
"estimated_duration_minutes": 85,
|
||||||
|
"average_speed_kmh": 44.0,
|
||||||
|
"status": RouteStatus.ACTIVE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Boquete - Dolega",
|
||||||
|
"origin_city": "Boquete",
|
||||||
|
"destination_city": "Dolega",
|
||||||
|
"color": "#00BCD4",
|
||||||
|
"direction": "outbound",
|
||||||
|
"distance_km": 28.0,
|
||||||
|
"estimated_duration_minutes": 40,
|
||||||
|
"average_speed_kmh": 42.0,
|
||||||
|
"status": RouteStatus.ACTIVE,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def inject_routes():
|
||||||
|
db_url = settings.get_database_url
|
||||||
|
engine = create_engine(db_url, echo=True)
|
||||||
|
|
||||||
|
with Session(engine) as session:
|
||||||
|
inserted = 0
|
||||||
|
skipped = 0
|
||||||
|
|
||||||
|
for route_data in SAMPLE_ROUTES:
|
||||||
|
# Verificar si ya existe
|
||||||
|
existing = session.exec(
|
||||||
|
select(Route).where(Route.name == route_data["name"])
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if existing:
|
||||||
|
print(f" [SKIP] Ya existe: {route_data['name']}")
|
||||||
|
skipped += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
route = Route(**route_data)
|
||||||
|
session.add(route)
|
||||||
|
print(f" [ADD] {route_data['name']} ({route_data['origin_city']} → {route_data['destination_city']})")
|
||||||
|
inserted += 1
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
print(f"\n✅ Listo: {inserted} rutas insertadas, {skipped} ya existían.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("🚌 Inyectando rutas de bus en producción...\n")
|
||||||
|
inject_routes()
|
||||||
@ -1,6 +1,6 @@
|
|||||||
/** Type definitions for the SIBU transportation app */
|
/** Type definitions for the SIBU transportation app */
|
||||||
|
|
||||||
export type RouteStatus = 'active' | 'inactive' | 'maintenance'
|
export type RouteStatus = 'ACTIVE' | 'INACTIVE' | 'MAINTENANCE'
|
||||||
export type StopType = 'terminal' | 'regular' | 'express_only'
|
export type StopType = 'terminal' | 'regular' | 'express_only'
|
||||||
export type ScheduleType = 'weekday' | 'weekend' | 'holiday'
|
export type ScheduleType = 'weekday' | 'weekend' | 'holiday'
|
||||||
|
|
||||||
|
|||||||
@ -346,7 +346,7 @@ async function confirmCreateRoute() {
|
|||||||
name: computedRouteName.value,
|
name: computedRouteName.value,
|
||||||
origin_city: newRouteForm.value.origin,
|
origin_city: newRouteForm.value.origin,
|
||||||
destination_city: newRouteForm.value.destination,
|
destination_city: newRouteForm.value.destination,
|
||||||
status: 'active',
|
status: 'ACTIVE',
|
||||||
color: '#FEE715',
|
color: '#FEE715',
|
||||||
direction: 'outbound'
|
direction: 'outbound'
|
||||||
})
|
})
|
||||||
|
|||||||
@ -60,7 +60,7 @@ const correlimientos = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const getStatusClass = (status: string) => {
|
const getStatusClass = (status: string) => {
|
||||||
if (status === 'active') return 'bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-400'
|
if (status === 'ACTIVE') return 'bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-400'
|
||||||
return 'bg-slate-100 dark:bg-zinc-800 text-slate-500 dark:text-zinc-400'
|
return 'bg-slate-100 dark:bg-zinc-800 text-slate-500 dark:text-zinc-400'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
52
inject_api.py
Normal file
52
inject_api.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
base_url = "https://sibu-backend.onrender.com"
|
||||||
|
|
||||||
|
def login():
|
||||||
|
response = requests.post(f"{base_url}/api/auth/login", json={"email": "admin@sibu.com", "password": "admin"})
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json().get("access_token")
|
||||||
|
else:
|
||||||
|
print("Login failed:", response.status_code, response.text)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def create_route(token, route_data):
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
||||||
|
response = requests.post(f"{base_url}/api/routes", headers=headers, json=route_data)
|
||||||
|
if response.status_code == 200:
|
||||||
|
print(f"✅ Creada: {route_data['name']}")
|
||||||
|
else:
|
||||||
|
print(f"❌ Error en {route_data['name']}:", response.status_code, response.text)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Iniciando sesión...")
|
||||||
|
token = login()
|
||||||
|
if not token:
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Inyectando rutas...")
|
||||||
|
routes = [
|
||||||
|
{"name": "Boquete - David", "origin_city": "Boquete", "destination_city": "David", "color": "#FEE715", "direction": "outbound", "distance_km": 38.0, "estimated_duration_minutes": 55, "average_speed_kmh": 40.0, "status": "active"},
|
||||||
|
{"name": "David - Boquete", "origin_city": "David", "destination_city": "Boquete", "color": "#FEE715", "direction": "inbound", "distance_km": 38.0, "estimated_duration_minutes": 55, "average_speed_kmh": 40.0, "status": "active"},
|
||||||
|
{"name": "Caldera - David", "origin_city": "Caldera", "destination_city": "David", "color": "#4CAF50", "direction": "outbound", "distance_km": 55.0, "estimated_duration_minutes": 75, "average_speed_kmh": 44.0, "status": "active"},
|
||||||
|
{"name": "David - Caldera", "origin_city": "David", "destination_city": "Caldera", "color": "#4CAF50", "direction": "inbound", "distance_km": 55.0, "estimated_duration_minutes": 75, "average_speed_kmh": 44.0, "status": "active"},
|
||||||
|
{"name": "Boquete - Caldera", "origin_city": "Boquete", "destination_city": "Caldera", "color": "#2196F3", "direction": "outbound", "distance_km": 22.0, "estimated_duration_minutes": 35, "average_speed_kmh": 38.0, "status": "active"},
|
||||||
|
{"name": "Caldera - Boquete", "origin_city": "Caldera", "destination_city": "Boquete", "color": "#2196F3", "direction": "inbound", "distance_km": 22.0, "estimated_duration_minutes": 35, "average_speed_kmh": 38.0, "status": "active"}
|
||||||
|
]
|
||||||
|
|
||||||
|
for route in routes:
|
||||||
|
create_route(token, route)
|
||||||
|
|
||||||
|
# Verificar rutas
|
||||||
|
print("\nVerificando rutas actuales en el servidor:")
|
||||||
|
r = requests.get(f"{base_url}/api/routes")
|
||||||
|
if r.status_code == 200:
|
||||||
|
current_routes = r.json()
|
||||||
|
print(f"Total rutas en el servidor: {len(current_routes)}")
|
||||||
|
if len(current_routes) > 0:
|
||||||
|
for rt in current_routes:
|
||||||
|
print(f" - {rt['name']}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user