feat: add backend FastAPI structure and Supabase schema
This commit is contained in:
3
server/app/db/__init__.py
Normal file
3
server/app/db/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from app.db.database import get_connection, init_db
|
||||
|
||||
__all__ = ["get_connection", "init_db"]
|
||||
142
server/app/db/database.py
Normal file
142
server/app/db/database.py
Normal file
@@ -0,0 +1,142 @@
|
||||
"""
|
||||
Base de datos SQLite — esquema unificado con Persona A.
|
||||
Tablas propias del módulo B: truck_status, notificaciones, ws_sessions.
|
||||
"""
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
|
||||
DB_PATH = Path("basura.db")
|
||||
|
||||
|
||||
def get_connection() -> sqlite3.Connection:
|
||||
conn = sqlite3.connect(DB_PATH, check_same_thread=False)
|
||||
conn.row_factory = sqlite3.Row
|
||||
conn.execute("PRAGMA journal_mode=WAL")
|
||||
conn.execute("PRAGMA foreign_keys=ON")
|
||||
return conn
|
||||
|
||||
|
||||
def init_db() -> None:
|
||||
conn = get_connection()
|
||||
conn.executescript("""
|
||||
-- ── Tablas de Persona A (las creamos aquí para que el módulo B
|
||||
-- pueda leerlas aunque A no haya corrido aún) ──────────────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
phone TEXT,
|
||||
password_hash TEXT NOT NULL,
|
||||
fcm_token TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS addresses (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
alias TEXT,
|
||||
lat REAL NOT NULL,
|
||||
lng REAL NOT NULL,
|
||||
route_id TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notification_preferences (
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
notify_proximity BOOLEAN DEFAULT 1,
|
||||
notify_breakdown BOOLEAN DEFAULT 1,
|
||||
notify_delay BOOLEAN DEFAULT 1,
|
||||
notify_route_start BOOLEAN DEFAULT 1,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notification_templates (
|
||||
id INTEGER PRIMARY KEY,
|
||||
trigger_event TEXT UNIQUE,
|
||||
title TEXT,
|
||||
body TEXT
|
||||
);
|
||||
|
||||
-- ── Tablas del módulo B ───────────────────────────────────────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS truck_status (
|
||||
route_id TEXT PRIMARY KEY,
|
||||
current_position_id INTEGER DEFAULT 1,
|
||||
last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
status TEXT DEFAULT 'EN_RUTA'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rutas (
|
||||
id TEXT PRIMARY KEY,
|
||||
nombre TEXT NOT NULL,
|
||||
turno TEXT NOT NULL DEFAULT 'mañana'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS puntos_ruta (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
ruta_id TEXT NOT NULL REFERENCES rutas(id),
|
||||
orden INTEGER NOT NULL,
|
||||
nombre TEXT NOT NULL,
|
||||
lat REAL NOT NULL,
|
||||
lng REAL NOT NULL,
|
||||
tiempo_estimado_min INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notificaciones (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tipo TEXT NOT NULL,
|
||||
ruta_id TEXT NOT NULL,
|
||||
address_id INTEGER,
|
||||
mensaje TEXT NOT NULL,
|
||||
eta_minutos INTEGER,
|
||||
creada_en TEXT NOT NULL
|
||||
);
|
||||
""")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
_seed_datos_demo()
|
||||
|
||||
|
||||
def _seed_datos_demo() -> None:
|
||||
conn = get_connection()
|
||||
existe = conn.execute("SELECT 1 FROM rutas WHERE id='RUTA-01'").fetchone()
|
||||
if existe:
|
||||
conn.close()
|
||||
return
|
||||
|
||||
conn.executescript("""
|
||||
-- Ruta de demo (Celaya, Guanajuato)
|
||||
INSERT INTO rutas VALUES ('RUTA-01', 'Ruta 01 — Sector Centro', 'mañana');
|
||||
|
||||
INSERT INTO puntos_ruta (ruta_id, orden, nombre, lat, lng, tiempo_estimado_min)
|
||||
VALUES
|
||||
('RUTA-01', 1, 'Estación Central', 20.5238, -100.8143, 0),
|
||||
('RUTA-01', 2, 'Col. Independencia', 20.5255, -100.8090, 8),
|
||||
('RUTA-01', 3, 'Blvd. A. López Mateos', 20.5271, -100.8021, 18),
|
||||
('RUTA-01', 4, 'Col. Jardines del Bosque', 20.5290, -100.7965, 28),
|
||||
('RUTA-01', 5, 'Mercado Hidalgo', 20.5310, -100.7910, 38);
|
||||
|
||||
INSERT INTO truck_status VALUES ('RUTA-01', 1, CURRENT_TIMESTAMP, 'EN_RUTA');
|
||||
|
||||
-- Usuario de demo
|
||||
INSERT INTO users (email, phone, password_hash)
|
||||
VALUES ('demo@basura.app', '4611234567', 'hashed_demo');
|
||||
|
||||
-- Domicilio de demo asignado a RUTA-01
|
||||
INSERT INTO addresses (user_id, alias, lat, lng, route_id)
|
||||
VALUES (1, 'Casa', 20.5285, -100.7980, 'RUTA-01');
|
||||
|
||||
-- Preferencias por defecto para usuario demo
|
||||
INSERT INTO notification_preferences VALUES (1, 1, 1, 1, 1);
|
||||
|
||||
-- Templates de notificación
|
||||
INSERT INTO notification_templates (trigger_event, title, body) VALUES
|
||||
('ruta_iniciada', 'Ruta iniciada', 'El camión ha comenzado su ruta. Prepárate.'),
|
||||
('aproximandose', '¡Camión cerca!', 'El camión llega en ~{eta} minutos. Saca tu basura.'),
|
||||
('falla_mecanica', 'Aviso de servicio', 'El camión reportó una falla. Te notificaremos cuando se reanude.'),
|
||||
('ruta_tarde', 'Cambio de horario', 'El camión de la mañana pasará en el turno de la tarde.'),
|
||||
('completado', 'Ruta completada', 'El camión completó su paso por tu zona. ¡Hasta mañana!');
|
||||
""")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user