feat: modelado BD con schema, seeds y docker-compose
This commit is contained in:
192
init/01_schema.sql
Normal file
192
init/01_schema.sql
Normal file
@@ -0,0 +1,192 @@
|
||||
-- ================================================================
|
||||
-- SCHEMA - App Recolección Inteligente · Hackathon Celaya 2026
|
||||
-- ================================================================
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS postgis;
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 1. USERS
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email VARCHAR(255) UNIQUE,
|
||||
phone VARCHAR(20) UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
fcm_token VARCHAR(500),
|
||||
rol VARCHAR(20) NOT NULL DEFAULT 'ciudadano',
|
||||
activo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT chk_contacto CHECK (email IS NOT NULL OR phone IS NOT NULL)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 2. RUTAS
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE rutas (
|
||||
id SERIAL PRIMARY KEY,
|
||||
route_id VARCHAR(20) NOT NULL UNIQUE,
|
||||
nombre VARCHAR(255) NOT NULL,
|
||||
truck_id SMALLINT NOT NULL,
|
||||
hora_inicio TIME NOT NULL,
|
||||
hora_fin_ref TIME NOT NULL,
|
||||
activa BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 3. RUTA_POSICIONES
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE ruta_posiciones (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
ruta_id INT NOT NULL REFERENCES rutas(id) ON DELETE CASCADE,
|
||||
position_id SMALLINT NOT NULL,
|
||||
lat DECIMAL(9,6) NOT NULL,
|
||||
lng DECIMAL(9,6) NOT NULL,
|
||||
speed_kmh SMALLINT NOT NULL DEFAULT 0,
|
||||
ts_referencia TIMESTAMPTZ NOT NULL,
|
||||
offset_seg INT NOT NULL DEFAULT 0,
|
||||
punto GEOGRAPHY(POINT, 4326) NOT NULL,
|
||||
CONSTRAINT uq_ruta_posicion UNIQUE (ruta_id, position_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ruta_pos_ruta ON ruta_posiciones (ruta_id, position_id);
|
||||
CREATE INDEX idx_ruta_pos_punto ON ruta_posiciones USING GIST (punto);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 4. COLONIAS
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE colonias (
|
||||
id SERIAL PRIMARY KEY,
|
||||
nombre VARCHAR(255) NOT NULL UNIQUE,
|
||||
ruta_id INT NOT NULL REFERENCES rutas(id),
|
||||
horario_turno VARCHAR(20) NOT NULL,
|
||||
hora_inicio_est TIME NOT NULL,
|
||||
hora_fin_est TIME NOT NULL,
|
||||
poligono GEOGRAPHY(POLYGON, 4326),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_colonias_ruta ON colonias (ruta_id);
|
||||
CREATE INDEX idx_colonias_pol ON colonias USING GIST (poligono) WHERE poligono IS NOT NULL;
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 5. DOMICILIOS
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE domicilios (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
alias VARCHAR(50) NOT NULL,
|
||||
direccion_texto TEXT NOT NULL,
|
||||
lat DECIMAL(9,6) NOT NULL,
|
||||
lng DECIMAL(9,6) NOT NULL,
|
||||
coordenada GEOGRAPHY(POINT, 4326) NOT NULL,
|
||||
colonia_id INT REFERENCES colonias(id) ON DELETE SET NULL,
|
||||
validado BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT uq_domicilio_alias UNIQUE (user_id, alias)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_domicilios_user ON domicilios (user_id);
|
||||
CREATE INDEX idx_domicilios_col ON domicilios (colonia_id);
|
||||
CREATE INDEX idx_domicilios_coord ON domicilios USING GIST (coordenada);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 6. ESTADO_RUTA (actualizado por el simulador/cron)
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE estado_ruta (
|
||||
ruta_id INT PRIMARY KEY REFERENCES rutas(id) ON DELETE CASCADE,
|
||||
estado VARCHAR(20) NOT NULL DEFAULT 'INACTIVA',
|
||||
position_id_actual SMALLINT NOT NULL DEFAULT 1,
|
||||
lat_actual DECIMAL(9,6),
|
||||
lng_actual DECIMAL(9,6),
|
||||
hora_real_inicio TIMESTAMPTZ,
|
||||
hora_estim_fin TIMESTAMPTZ,
|
||||
minutos_retraso SMALLINT NOT NULL DEFAULT 0,
|
||||
motivo_retraso TEXT,
|
||||
actualizado_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 7. NOTIFICACION_TEMPLATES
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE notificacion_templates (
|
||||
id SERIAL PRIMARY KEY,
|
||||
trigger_event VARCHAR(30) NOT NULL UNIQUE,
|
||||
position_id_trigger SMALLINT NOT NULL,
|
||||
titulo VARCHAR(150) NOT NULL,
|
||||
cuerpo TEXT NOT NULL,
|
||||
activo BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 8. NOTIFICACIONES
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE notificaciones (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
domicilio_id UUID REFERENCES domicilios(id) ON DELETE SET NULL,
|
||||
template_id INT REFERENCES notificacion_templates(id),
|
||||
ruta_id INT REFERENCES rutas(id),
|
||||
titulo VARCHAR(150) NOT NULL,
|
||||
mensaje TEXT NOT NULL,
|
||||
enviada_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
leida BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
leida_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_notif_user ON notificaciones (user_id, enviada_at DESC);
|
||||
CREATE INDEX idx_notif_no_leida ON notificaciones (user_id) WHERE leida = FALSE;
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 9. REPORTES
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE reportes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
domicilio_id UUID REFERENCES domicilios(id) ON DELETE SET NULL,
|
||||
ruta_id INT REFERENCES rutas(id),
|
||||
tipo VARCHAR(40) NOT NULL,
|
||||
descripcion TEXT,
|
||||
calificacion SMALLINT CHECK (calificacion BETWEEN 1 AND 5),
|
||||
estado VARCHAR(20) NOT NULL DEFAULT 'abierto',
|
||||
creado_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_reportes_user ON reportes (user_id);
|
||||
CREATE INDEX idx_reportes_ruta ON reportes (ruta_id, creado_at);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- 10. GUÍA DE SEPARACIÓN
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE TABLE residuos_categorias (
|
||||
id SERIAL PRIMARY KEY,
|
||||
nombre VARCHAR(50) NOT NULL,
|
||||
descripcion TEXT,
|
||||
color_hex CHAR(7),
|
||||
icono VARCHAR(100)
|
||||
);
|
||||
|
||||
CREATE TABLE residuos_ejemplos (
|
||||
id SERIAL PRIMARY KEY,
|
||||
categoria_id INT NOT NULL REFERENCES residuos_categorias(id) ON DELETE CASCADE,
|
||||
nombre VARCHAR(255) NOT NULL,
|
||||
descripcion TEXT
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------
|
||||
-- TRIGGERS
|
||||
-- ----------------------------------------------------------------
|
||||
CREATE OR REPLACE FUNCTION fn_set_updated_at()
|
||||
RETURNS TRIGGER LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER trg_users_updated_at
|
||||
BEFORE UPDATE ON users
|
||||
FOR EACH ROW EXECUTE FUNCTION fn_set_updated_at();
|
||||
Reference in New Issue
Block a user