Herramientas¶
Conexion a la Base de Datos¶
psql (linea de comandos)¶
# Formato generico
psql "postgresql://USER:PASSWORD@HOST:PORT/DATABASE"
# Conectar a un schema especifico
psql "postgresql://USER:PASSWORD@HOST:PORT/DATABASE" -c "SET search_path TO '200_muni', public;"
pgAdmin 4¶
- Descargar desde pgadmin.org
- Registrar servidor nuevo:
- Host: el host del servidor (ej:
localhost) - Port: el puerto PostgreSQL (ej:
5432) - Database:
railway - Username:
postgres - Password: password de la base de datos
- Host: el host del servidor (ej:
- En el panel izquierdo, expandir: Servers > PostgreSQL > Databases > railway > Schemas
- Los schemas de organizacion aparecen como
200_muni,201_otra, etc.
DBeaver¶
- Nueva conexion PostgreSQL
- Configurar host, puerto, database, usuario, password
- En la pestana "PostgreSQL", marcar "Show all databases"
Scripts Python¶
Todos los scripts estan en GDI-BD/tools/ y requieren la variable de entorno DATABASE_URL.
Configuracion¶
# Opcion 1: Variable de entorno
export DATABASE_URL='postgresql://USER:PASSWORD@HOST:PORT/DATABASE'
# Opcion 2: Archivo .env (en GDI-BD/)
cp .env.example .env
# Editar .env con los valores reales
install.py - Instalacion limpia¶
Elimina y recrea todo el entorno de desarrollo (200_muni).
======================================================================
GDI LATAM - INSTALACION LIMPIA (200_muni)
======================================================================
DATABASE_URL: postgresql://postgres:xxxxx@localhost:5432/railway
Flujo: 01-install.sql -> 02-seed-global.sql -> 04-seed-demo.sql
ATENCION: Esto eliminara los schemas 200_muni y 200_muni_audit
y recreara toda la estructura desde cero.
Continuar? (s/N): s
Operacion destructiva
install.py ejecuta DROP SCHEMA IF EXISTS ... CASCADE sobre 200_muni y 200_muni_audit. Todos los datos se pierden.
create_municipio.py - Crear organizacion¶
Script interactivo para crear una nueva organizacion en produccion.
======================================================================
GDI LATAM - CREAR MUNICIPIO NUEVO
======================================================================
--- Datos del municipio ---
Nombre del municipio (ej: Municipalidad de La Plata): Municipalidad de La Plata
Acronimo (4 chars max, ej: LPLA): LPLA
Codigo pais (2 chars) [AR]: AR
Ciudad (ej: La Plata, Buenos Aires): La Plata
Color primario hex sin # (ej: 16158C) [16158C]: 1A5276
--- Buckets Cloudflare R2 ---
Bucket oficial [gdi-lpla-oficial]:
Bucket tosign [gdi-lpla-tosign]:
======================================================================
RESUMEN - Nuevo Municipio
======================================================================
Nombre: Municipalidad de La Plata
Acronimo: LPLA
Pais: AR
Ciudad: La Plata
Color primario: #1A5276
Schema number: 101
Schema name: 101_lpla
Audit schema: 101_lpla_audit
Bucket oficial: gdi-lpla-oficial
Bucket tosign: gdi-lpla-tosign
======================================================================
Confirmar creacion? (s/N): s
Despues de crear la organizacion, el script muestra los pasos manuales pendientes:
- Crear buckets en Cloudflare R2
- Configurar permisos CORS
- Crear usuarios en Auth0
- Subir logo via BackOffice
run_single_script.py - Ejecutar script individual¶
cd GDI-BD/tools
python run_single_script.py 02-seed-global.sql
python run_single_script.py migrations/023_add_primary_color_departments_sectors.sql
verify_db.py - Verificar integridad¶
================================================================================
VERIFICACION DE SCHEMAS Y TABLAS
================================================================================
[Schema PUBLIC]
Tablas: 9
- api_key_users
- api_keys
- document_display_states
- global_case_templates
- global_document_types
- global_registry_families
- municipalities
- roles
- user_registry
[Schema 200_muni]
Tablas: 33
- case_movements
- case_official_documents
- cases
- ...
[Datos en SCHEMA PUBLIC]
Roles: 3
Global Document Types: 61
Global Case Templates: 30
Municipalities: 1
Document Display States: 6
================================================================================
[OK] Base de datos verificada correctamente
================================================================================
Queries Utiles¶
Listar schemas de organizaciones¶
SELECT schema_name, name, acronym, country, is_active
FROM public.municipalities
ORDER BY schema_number;
Contar tablas por schema¶
SELECT table_schema, COUNT(*) as table_count
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
AND table_schema NOT IN ('pg_catalog', 'information_schema')
GROUP BY table_schema
ORDER BY table_schema;
Ver usuarios de una organizacion¶
SELECT u.id, u.email, u.full_name, s.acronym as sector,
d.name as departamento, d.acronym as dept_acronym
FROM "200_muni".users u
LEFT JOIN "200_muni".sectors s ON u.sector_id = s.id
LEFT JOIN "200_muni".departments d ON s.department_id = d.id
ORDER BY d.name, u.full_name;
Ver tipos de documento activos¶
SELECT id, acronym, name, type, trust, is_active
FROM "200_muni".document_types
WHERE is_active = true
ORDER BY id;
Documentos oficiales recientes¶
SELECT od.official_number, od.reference,
dt.acronym as tipo, od.signed_at,
u.full_name as numerador
FROM "200_muni".official_documents od
JOIN "200_muni".document_types dt ON od.document_type_id = dt.id
JOIN "200_muni".users u ON od.numerator_id = u.id
ORDER BY od.signed_at DESC
LIMIT 20;
Expedientes activos con ultimo movimiento¶
SELECT c.case_number, c.reference, c.status,
d.name as departamento_actual,
cm.type as ultimo_movimiento,
cm.created_at as fecha_movimiento
FROM "200_muni".cases c
JOIN "200_muni".departments d ON c.owner_department_id = d.id
LEFT JOIN LATERAL (
SELECT type, created_at
FROM "200_muni".case_movements
WHERE case_id = c.id
ORDER BY created_at DESC
LIMIT 1
) cm ON true
WHERE c.status = 'active'
ORDER BY cm.created_at DESC;
Ver registros de auditoria recientes¶
SELECT event_time, table_name, operation,
user_id, auth_source, changed_fields
FROM "200_muni_audit".audit_log
ORDER BY event_time DESC
LIMIT 50;
Verificar indices de un schema¶
SELECT indexname, tablename, indexdef
FROM pg_indexes
WHERE schemaname = '200_muni'
ORDER BY tablename, indexname;
Tamano de tablas¶
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) as total_size,
pg_size_pretty(pg_relation_size(schemaname || '.' || tablename)) as table_size,
pg_size_pretty(pg_indexes_size(schemaname || '.' || tablename)) as index_size
FROM pg_tables
WHERE schemaname = '200_muni'
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC;
Buscar con unaccent (sin acentos)¶
-- Busca "tramite" y encuentra "tramite" (y viceversa)
SELECT * FROM "200_muni".document_draft
WHERE unaccent(reference) ILIKE '%' || unaccent('tramite') || '%';
Dependencias Python¶
Los scripts Python de GDI-BD/tools/ requieren:
- psycopg2-binary: Driver PostgreSQL para Python
- python-dotenv: Para cargar
.envautomaticamente (usado porrun_single_script.py)