-- Script base para despliegue limpio (solo API INVIMA + autenticacion) DROP TABLE IF EXISTS app_sessions CASCADE; DROP TABLE IF EXISTS app_users CASCADE; DROP TABLE IF EXISTS invima_api_catalog CASCADE; DROP TABLE IF EXISTS invima_api_raw CASCADE; CREATE TABLE app_users ( id bigserial PRIMARY KEY, username text NOT NULL UNIQUE, full_name text NOT NULL, role text NOT NULL DEFAULT 'ADMIN', password_hash text NOT NULL, is_active boolean NOT NULL DEFAULT true, created_at timestamptz NOT NULL DEFAULT NOW(), updated_at timestamptz NOT NULL DEFAULT NOW() ); CREATE TABLE app_sessions ( token_hash text PRIMARY KEY, user_id bigint NOT NULL REFERENCES app_users(id) ON DELETE CASCADE, expires_at timestamptz NOT NULL, created_at timestamptz NOT NULL DEFAULT NOW(), last_used_at timestamptz NOT NULL DEFAULT NOW(), user_agent text, ip_address text ); CREATE INDEX idx_app_sessions_user_id ON app_sessions (user_id); CREATE INDEX idx_app_sessions_expires_at ON app_sessions (expires_at); CREATE TABLE invima_api_raw ( id bigserial PRIMARY KEY, source_dataset_key text NOT NULL, source_dataset_id text NOT NULL, source_uid text NOT NULL, raw_payload jsonb NOT NULL, fetched_at timestamptz NOT NULL DEFAULT NOW(), created_at timestamptz NOT NULL DEFAULT NOW(), updated_at timestamptz NOT NULL DEFAULT NOW(), CONSTRAINT invima_api_raw_unique UNIQUE (source_dataset_key, source_uid) ); CREATE TABLE invima_api_catalog ( source_dataset_key text NOT NULL, source_dataset_id text NOT NULL, source_uid text NOT NULL, source_dataset_name text NOT NULL, categoria_linea text NOT NULL, categoria_canonica text, categoria_slug text, expediente text, registro_sanitario text, producto text, titular text, estado_registro text, fecha_expedicion date, fecha_vencimiento date, modalidad text, grupo text, marca text, principio_activo text, forma_farmaceutica text, presentacion_comercial text, atc text, rol_nombre text, rol_tipo text, ciudad_titular text, pais_titular text, fabricante text, importador text, vigencia text, search_text text, extra jsonb NOT NULL, fetched_at timestamptz NOT NULL DEFAULT NOW(), updated_at timestamptz NOT NULL DEFAULT NOW(), CONSTRAINT invima_api_catalog_pk PRIMARY KEY (source_dataset_key, source_uid) ); CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE INDEX idx_invima_api_catalog_dataset ON invima_api_catalog (source_dataset_key); CREATE INDEX idx_invima_api_catalog_categoria_slug ON invima_api_catalog (categoria_slug); CREATE INDEX idx_invima_api_catalog_estado ON invima_api_catalog (estado_registro); CREATE INDEX idx_invima_api_catalog_registro ON invima_api_catalog (registro_sanitario); CREATE INDEX idx_invima_api_catalog_expediente ON invima_api_catalog (expediente); CREATE INDEX idx_invima_api_catalog_modalidad ON invima_api_catalog (modalidad); CREATE INDEX idx_invima_api_catalog_grupo ON invima_api_catalog (grupo); CREATE INDEX idx_invima_api_catalog_vencimiento ON invima_api_catalog (fecha_vencimiento); CREATE INDEX idx_invima_api_catalog_expedicion ON invima_api_catalog (fecha_expedicion); CREATE INDEX idx_invima_api_catalog_search_fts ON invima_api_catalog USING GIN (to_tsvector('spanish', COALESCE(search_text, ''))); CREATE INDEX idx_invima_api_catalog_search_trgm ON invima_api_catalog USING GIN (search_text gin_trgm_ops);