141 lines
4.8 KiB
Plaintext
141 lines
4.8 KiB
Plaintext
// IPSExtractor — esquema de integración PostgreSQL
|
|
// Fuente: services/extraction/infrastructure/database.py
|
|
// services/cleaning/infrastructure/database.py
|
|
//
|
|
// Visualizar en https://dbdiagram.io (importar este archivo)
|
|
// o con la CLI de dbml: npx @dbml/cli dbml2sql docs/database.dbml
|
|
|
|
Project ipsextractor {
|
|
database_type: 'PostgreSQL'
|
|
Note: '''
|
|
Base de datos compartida entre los microservicios de extracción y limpieza.
|
|
Cada servicio define su propia copia del modelo SQLAlchemy y ejecuta
|
|
`init_db()` con bloqueo advisory (pg_advisory_lock) para crear tablas
|
|
sin condiciones de carrera.
|
|
'''
|
|
}
|
|
|
|
TableGroup pipeline {
|
|
extraction_batches
|
|
extraction_rows
|
|
cleaning_jobs
|
|
cleaned_rows
|
|
}
|
|
|
|
TableGroup async_jobs {
|
|
tasks
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Extracción
|
|
// ---------------------------------------------------------------------------
|
|
|
|
Table extraction_batches {
|
|
id varchar(36) [pk, note: 'UUID v4']
|
|
status varchar(32) [not null, default: 'pending', note: 'pending | running | completed | failed']
|
|
root_path text [note: 'Ruta raíz de documentos procesados (IPS_DOCUMENT_ROOT)']
|
|
request jsonb [not null, default: '{}', note: 'ExtractionRequest serializado (keywords, fields, doc_types, etc.)']
|
|
error text
|
|
created_at timestamptz [not null]
|
|
updated_at timestamptz [not null]
|
|
|
|
indexes {
|
|
status
|
|
}
|
|
|
|
Note: 'Lote creado al iniciar una extracción; agrupa todas las filas extraídas de un procesamiento.'
|
|
}
|
|
|
|
Table extraction_rows {
|
|
id integer [pk, increment]
|
|
batch_id varchar(36) [not null, ref: > extraction_batches.id]
|
|
radicado varchar(255) [note: 'Identificador del radicado IPS']
|
|
source_pdf text [note: 'Ruta del PDF origen dentro del volumen montado']
|
|
row_index integer [not null, default: 0, note: 'Orden estable dentro del lote']
|
|
row_json jsonb [not null, default: '{}', note: 'Fila aplanada con campos solicitados']
|
|
raw_json jsonb [not null, default: '{}', note: 'Resultado bruto del procesador por radicado']
|
|
created_at timestamptz [not null]
|
|
|
|
indexes {
|
|
batch_id
|
|
radicado
|
|
}
|
|
|
|
Note: 'Una o más filas por radicado según flatten_extraction_result().'
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Tareas asíncronas (API de extracción)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
Table tasks {
|
|
id varchar(36) [pk, note: 'UUID v4']
|
|
type varchar(64) [not null, note: 'p. ej. extraction']
|
|
status varchar(32) [not null, default: 'pending', note: 'pending | running | completed | failed']
|
|
title text
|
|
request jsonb [not null, default: '{}', note: 'Payload de la petición que originó la tarea']
|
|
result jsonb [not null, default: '{}', note: 'Al completar incluye extraction_batch_id']
|
|
error text
|
|
owner_id varchar(36) [note: 'Reservado para multi-usuario']
|
|
created_at timestamptz [not null]
|
|
updated_at timestamptz [not null]
|
|
started_at timestamptz
|
|
finished_at timestamptz
|
|
|
|
indexes {
|
|
type
|
|
status
|
|
owner_id
|
|
}
|
|
|
|
Note: '''
|
|
Cola de trabajos en segundo plano del servicio de extracción.
|
|
No hay FK a extraction_batches; el vínculo se guarda en
|
|
result.extraction_batch_id al finalizar la tarea.
|
|
'''
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Limpieza
|
|
// ---------------------------------------------------------------------------
|
|
|
|
Table cleaning_jobs {
|
|
id varchar(36) [pk, note: 'UUID v4']
|
|
extraction_batch_id varchar(36) [not null, ref: > extraction_batches.id]
|
|
status varchar(32) [not null, default: 'pending', note: 'pending | running | completed | failed']
|
|
request jsonb [not null, default: '{}', note: 'CleaningRequest (rules_per_column, cop_mod_*, etc.)']
|
|
log jsonb [not null, default: '[]', note: 'Lista de mensajes de auditoría del job']
|
|
error text
|
|
created_at timestamptz [not null]
|
|
updated_at timestamptz [not null]
|
|
|
|
indexes {
|
|
extraction_batch_id
|
|
status
|
|
}
|
|
|
|
Note: 'Ejecución de reglas de limpieza sobre las filas de un lote de extracción.'
|
|
}
|
|
|
|
Table cleaned_rows {
|
|
id integer [pk, increment]
|
|
cleaning_job_id varchar(36) [not null, ref: > cleaning_jobs.id]
|
|
extraction_batch_id varchar(36) [not null, ref: > extraction_batches.id]
|
|
row_index integer [not null, default: 0, note: 'Conserva el orden del lote original']
|
|
row_json jsonb [not null, default: '{}', note: 'Fila tras aplicar reglas de limpieza']
|
|
created_at timestamptz [not null]
|
|
|
|
indexes {
|
|
cleaning_job_id
|
|
extraction_batch_id
|
|
}
|
|
|
|
Note: 'Salida del servicio de limpieza; reemplaza las filas previas del mismo job en cada ejecución.'
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Relaciones lógicas (sin FK en BD)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// tasks.result.extraction_batch_id -> extraction_batches.id (referencia en JSON)
|