-- ================================================================================= -- 1. ESQUEMA GLOBAL (Catálogos y Maestros Estáticos) -- ================================================================================= create schema if not exists global; -- 1.1 Países create table global.paises ( pais_id int generated always as identity, nombre varchar(100) not null, siglas char(3) not null, -- PRY, ARG codigo_telefonico varchar(5), gentilicio varchar(100), -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, -- Borrado Lógico eliminado_en timestamptz default null, eliminado_por bigint, constraint pk_paises primary key (pais_id), constraint uq_paises_siglas unique (siglas) ); -- 1.2 Tipos de Documento (Refactorizado a ID Numérico) create table global.tipos_documentos ( tipo_documento_id int generated always as identity, -- Ahora es INT codigo varchar(10) not null, -- 'CI', 'RUC', 'PAS' descripcion varchar(50) not null, mascara_validacion varchar(100), -- Regex para frontend es_fiscal boolean default false, -- True si sirve para tributación -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, -- Borrado Lógico eliminado_en timestamptz default null, eliminado_por bigint, constraint pk_tipos_documento primary key (tipo_documento_id), constraint uq_tipos_doc_codigo unique (codigo) ); -- 1.3 Ciudades create table global.ciudades ( ciudad_id int generated always as identity, pais_id int not null, nombre varchar(100) not null, codigo_postal varchar(20), -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_ciudades primary key (ciudad_id), constraint fk_ciudades_pais foreign key (pais_id) references global.paises(pais_id), constraint uq_ciudades_nombre_pais unique (pais_id, nombre) ); -- 1.4 Estados Civiles create table global.estados_civiles ( estado_civil_id int generated always as identity, descripcion varchar(50) not null, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_estados_civiles primary key (estado_civil_id), constraint uq_estados_civiles_desc unique (descripcion) ); -- 1.5 Sexos (Refactorizado a ID Numérico) create table global.sexos ( sexo_id int generated always as identity, -- Ahora es INT sigla char(1) not null, -- 'M', 'F' descripcion varchar(20) not null, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_sexos primary key (sexo_id), constraint uq_sexos_sigla unique (sigla) ); -- 1.6 Tipos de Sociedad (Jurídica) create table global.tipos_sociedad ( tipo_sociedad_id int generated always as identity, siglas varchar(10), -- 'SA', 'SRL' descripcion varchar(100) not null, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_tipos_sociedad primary key (tipo_sociedad_id) ); -- 1.7 Régimen Patrimonial (Gananciales, Separación) create table global.regimenes_matrimoniales ( regimen_id int generated always as identity, descripcion varchar(100) not null, constraint pk_regimenes primary key (regimen_id) ); -- 1.8 Nivel Educativo create table global.niveles_educativos ( nivel_educativo_id int generated always as identity, descripcion varchar(100) not null, -- 'Primaria', 'Universitario' constraint pk_niveles_educativos primary key (nivel_educativo_id) ); -- 1.9 Actividades Económicas (Para Socio y Empleador) create table global.actividades_economicas ( actividad_id int generated always as identity, descripcion varchar(150) not null, -- 'Ganadería', 'Salud', 'Software' sector varchar(50), -- 'PRIMARIO', 'SERVICIOS' constraint pk_actividades_economicas primary key (actividad_id) ); -- 1.10 Tipos de Relación Laboral create table global.tipos_relacion_laboral ( tipo_relacion_id int generated always as identity, descripcion varchar(100) not null, -- 'Nombrado', 'Jornalero', 'Independiente' constraint pk_tipos_relacion_laboral primary key (tipo_relacion_id) ); -- 1.11 Situación Vivienda create table global.tipos_vivienda ( tipo_vivienda_id int generated always as identity, descripcion varchar(100) not null, -- 'Propia', 'Alquilada' constraint pk_tipos_vivienda primary key (tipo_vivienda_id) ); -- 1.12 Tenencia de Tierra create table global.tipos_tenencia_tierra ( tenencia_id int generated always as identity, descripcion varchar(100) not null, -- 'Propietario con título', 'Ocupante' constraint pk_tipos_tenencia primary key (tenencia_id) ); -- 3.3 Régimen Tributario (IVA General, IRE, etc.) create table global.regimenes_tributarios ( regimen_id int generated always as identity, descripcion varchar(100) not null, -- 'IVA General', 'IRE SIMPLE' siglas varchar(20), constraint pk_regimenes_tributarios primary key (regimen_id) ); -- 3.3 Rangos de Ingresos Anuales (Para perfilamiento) create table global.rangos_ingresos ( rango_ingreso_id int generated always as identity, descripcion varchar(100) not null, -- '0 - 500 Millones', '+ 3.000 Millones' valor_minimo numeric(19, 2), -- Para lógica de negocio (scoring) valor_maximo numeric(19, 2), moneda varchar(3) default 'PYG', constraint pk_rangos_ingresos primary key (rango_ingreso_id) ); -- 3.3 Rangos de Cantidad de Empleados create table global.rangos_empleados ( rango_empleado_id int generated always as identity, descripcion varchar(50) not null, -- '1-5', '6-20', '+50' min_empleados int, max_empleados int, constraint pk_rangos_empleados primary key (rango_empleado_id) ); -- ================================================================================= -- 2. ESQUEMA CORE (Identidad y Datos Maestros) -- ================================================================================= create schema if not exists core; -- 2.1 TABLA MAESTRA: PERSONAS create table core.personas ( persona_id bigint generated always as identity, tipo_persona char(1) not null, -- Propósito del Registro (Punto 1) motivo_registro varchar(50) not null, -- 'CANDIDATO_SOCIO', 'CODEUDOR', 'REPRESENTANTE' pais_emision_id int not null, tipo_documento_id int not null, numero_documento varchar(30) not null, nombre_completo_normalizado varchar(255) not null, estado varchar(20) default 'ACTIVO', version int default 1, -- Optimistic Locking (Punto 4) -- Auditoría Híbrida creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, -- Borrado Lógico eliminado_en timestamptz default null, eliminado_por bigint, constraint pk_personas primary key (persona_id), constraint fk_personas_pais foreign key (pais_emision_id) references global.paises(pais_id), constraint fk_personas_tipo_doc foreign key (tipo_documento_id) references global.tipos_documento(tipo_documento_id), constraint uq_personas_identidad unique (pais_emision_id, tipo_documento_id, numero_documento), constraint ck_personas_tipo check (tipo_persona in ('F', 'J')) ); create index idx_personas_activos on core.personas(persona_id) where eliminado_en is null; create index idx_personas_fecha_registro on core.personas(creado_en desc); -- 2.2 ESPECIFICACIÓN: PERSONAS FÍSICAS create table core.personas_fisicas ( persona_id bigint not null, nombres varchar(100) not null, apellidos varchar(100) not null, fecha_nacimiento date not null, sexo_id int not null, ciudad_nacimiento_id int, -- 3.5 Perfil Personal y Familiar estado_civil_id int, regimen_matrimonial_id int, -- Visible solo si es Casado (Validar en App) cantidad_dependientes int default 0, tiene_hijos_escolar boolean default false, -- 3.6 Perfil Socioeconómico (Resumen) nivel_educativo_id int, profesion_oficio varchar(150), -- Texto libre para especificidad -- 3.7 Perfil de Riesgo y Cumplimiento situacion_vivienda_id int, tenencia_tierra_id int, posee_seguro_medico boolean default false, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_personas_fisicas primary key (persona_id), constraint fk_fisicas_persona foreign key (persona_id) references core.personas(persona_id) on delete cascade, constraint fk_fisicas_sexo foreign key (sexo_id) references global.sexos(sexo_id), constraint fk_fisicas_est_civil foreign key (estado_civil_id) references global.estados_civiles(estado_civil_id), constraint fk_fisicas_regimen foreign key (regimen_matrimonial_id) references global.regimenes_matrimoniales(regimen_id), constraint fk_fisicas_educacion foreign key (nivel_educativo_id) references global.niveles_educativos(nivel_educativo_id), constraint fk_fisicas_vivienda foreign key (situacion_vivienda_id) references global.tipos_vivienda(tipo_vivienda_id), constraint fk_fisicas_tierra foreign key (tenencia_tierra_id) references global.tipos_tenencia_tierra(tenencia_id) ); -- 2.3 ESPECIFICACIÓN: PERSONAS JURÍDICAS create table core.personas_juridicas ( persona_id bigint not null, -- 3.1 Identificación razon_social varchar(200) not null, nombre_fantasia varchar(200), -- Nombre Comercial tipo_sociedad_id int not null, fecha_constitucion date, -- Legal -- 3.3 Perfil de Negocio y Operativo fecha_inicio_operaciones date, -- Para calcular "Antigüedad del Negocio" actividad_economica_id int, -- CIUU (Ya creado en paso anterior) regimen_tributario_id int, -- Nuevo rango_ingreso_anual_id int, -- Nuevo rango_cantidad_empleados_id int, -- Nuevo sitio_web varchar(150), -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, -- CONSTRAINTS constraint pk_personas_juridicas primary key (persona_id), constraint fk_juridicas_persona foreign key (persona_id) references core.personas(persona_id) on delete cascade, constraint fk_juridicas_tipo_soc foreign key (tipo_sociedad_id) references global.tipos_sociedad(tipo_sociedad_id), -- Foreign Keys a los nuevos catálogos constraint fk_juridicas_actividad foreign key (actividad_economica_id) references global.actividades_economicas(actividad_id), constraint fk_juridicas_regimen foreign key (regimen_tributario_id) references global.regimenes_tributarios(regimen_id), constraint fk_juridicas_rango_ing foreign key (rango_ingreso_anual_id) references global.rangos_ingresos(rango_ingreso_id), constraint fk_juridicas_rango_emp foreign key (rango_cantidad_empleados_id) references global.rangos_empleados(rango_empleado_id) ); -- 2.4 DIRECCIONES (Agregada y Completa) create table core.direcciones ( direccion_id bigint generated always as identity, persona_id bigint not null, ciudad_id int not null, barrio varchar(100), calle_principal varchar(150) not null, numeracion varchar(20), referencia_ubicacion text, -- Geolocalización para mapas latitud decimal(10, 8), longitud decimal(11, 8), es_principal boolean default false, tipo_direccion varchar(20) default 'PARTICULAR', -- 'LABORAL', 'LEGAL' -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_direcciones primary key (direccion_id), constraint fk_direcciones_persona foreign key (persona_id) references core.personas(persona_id), constraint fk_direcciones_ciudad foreign key (ciudad_id) references global.ciudades(ciudad_id) ); -- ================================================================================= -- 3. ESQUEMA RELACIONES (Vínculos N:M) -- ================================================================================= create schema if not exists relaciones; -- 3.1 Catálogo de Tipos de Vínculo create table relaciones.tipos_vinculo ( tipo_vinculo_id int generated always as identity, descripcion varchar(50) not null, es_reciproco boolean default false, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_tipos_vinculo primary key (tipo_vinculo_id) ); -- 3.2 Tabla de Vínculos create table relaciones.vinculos_personas ( vinculo_id bigint generated always as identity, persona_origen_id bigint not null, persona_destino_id bigint not null, tipo_vinculo_id int not null, es_garante boolean default false, fecha_inicio date default current_date, activo boolean default true, -- Auditoría Completa creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_vinculos_personas primary key (vinculo_id), constraint fk_vinculos_origen foreign key (persona_origen_id) references core.personas(persona_id), constraint fk_vinculos_destino foreign key (persona_destino_id) references core.personas(persona_id), constraint fk_vinculos_tipo foreign key (tipo_vinculo_id) references relaciones.tipos_vinculo(tipo_vinculo_id), constraint ck_vinculos_bucle check (persona_origen_id <> persona_destino_id) ); -- ================================================================================= -- 4. ESQUEMA RIESGO -- ================================================================================= create schema if not exists riesgo; -- 4.1 Calificaciones create table riesgo.calificaciones ( calificacion_id bigint generated always as identity, persona_id bigint not null, fuente_informacion varchar(50) not null, fecha_consulta timestamptz default now() not null, estado_resultado varchar(50) not null, score_numerico int, respuesta_json_raw jsonb, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_calificaciones primary key (calificacion_id), constraint fk_calificaciones_persona foreign key (persona_id) references core.personas(persona_id) ); -- 4.2 Registros PEP create table riesgo.registros_pep ( pep_id bigint generated always as identity, persona_id bigint not null, es_pep_actual boolean default true, cargo varchar(150), institucion varchar(150), fecha_inicio date, fecha_fin date, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_registros_pep primary key (pep_id), constraint fk_pep_persona foreign key (persona_id) references core.personas(persona_id) ); -- ================================================================================= -- 5. ESQUEMA SOCIOECONÓMICO -- ================================================================================= create schema if not exists socioeconomico; create table socioeconomico.perfiles_laborales ( laboral_id bigint generated always as identity, persona_id bigint not null, lugar_trabajo varchar(150), cargo varchar(100), fecha_ingreso date, ingreso_mensual_declarado numeric(19, 4), moneda varchar(3) default 'PYG', es_trabajo_principal boolean default true, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, constraint pk_perfiles_laborales primary key (laboral_id), constraint fk_laboral_persona foreign key (persona_id) references core.personas(persona_id) ); -- ================================================================================= -- 6. ESQUEMA AUDITORÍA (Centralizada) -- ================================================================================= create schema if not exists auditoria; create table auditoria.logs_eventos ( log_id bigint generated always as identity, fecha_evento timestamptz default now() not null, usuario_id bigint, ip_origen varchar(45), operacion varchar(10) not null, esquema_afectado varchar(63) not null, tabla_afectada varchar(63) not null, pk_registro_afectado text not null, datos_anteriores jsonb, datos_nuevos jsonb, constraint pk_logs_eventos primary key (log_id), constraint ck_logs_operacion check (operacion in ('INSERT', 'UPDATE', 'DELETE')) ) partition by range (fecha_evento); -- Particiones create table auditoria.logs_eventos_y2025 partition of auditoria.logs_eventos for values from ('2025-01-01') to ('2026-01-01'); create table auditoria.logs_eventos_y2026 partition of auditoria.logs_eventos for values from ('2026-01-01') to ('2027-01-01'); ----------------------------------------------------- -- Nueva versión más normalizada ------------------------------------------------------ -- ================================================================================= -- 1. ESQUEMA GLOBAL (Catálogos y Estados Centralizados) -- ================================================================================= create schema if not exists global; -- 1.1 TABLA MAESTRA DE ESTADOS (Centralizada) create table global.estados_sistema ( estado_id int generated by default as identity, dominio varchar(50) not null, -- 'PERSONA', 'PRESTAMO', 'USUARIO', 'CUENTA' codigo varchar(50) not null, -- 'ACTIVO', 'PENDIENTE', 'BLOQUEADO', 'MORA_30' descripcion varchar(100) not null, es_estado_final boolean default false, -- Útil para saber si permite transiciones color_hex varchar(7), -- Para el Frontend (ej: '#FF0000') creado_en timestamptz default now() not null, constraint pk_estados_sistema primary key (estado_id), -- Asegura que no dupliquemos el código dentro del mismo dominio constraint uq_estados_dominio_codigo unique (dominio, codigo) ); -- Datos Semilla (Ejemplos conceptuales) -- INSERT INTO global.estados_sistema (dominio, codigo, descripcion) VALUES -- ('PERSONA', 'ACTIVO', 'Socio habilitado para operar'), -- ('PERSONA', 'BLOQUEADO', 'Bloqueo por cumplimiento o mora'), -- ('PERSONA', 'FALLECIDO', 'Cese de operaciones por deceso'); -- 1.2 Países (Identity by Default para migración) create table global.paises ( pais_id int generated by default as identity, nombre varchar(100) not null, codigo_iso_alpha3 char(3) not null, constraint pk_paises primary key (pais_id), constraint uq_paises_iso unique (codigo_iso_alpha3) ); -- (Se mantienen tipos_documento, ciudades, etc. con 'BY DEFAULT') -- ... Resumido para brevedad, asume que todos usan "generated by default" ... create table global.tipos_documento ( tipo_documento_id int generated by default as identity, codigo varchar(10) not null, descripcion varchar(50) not null, mascara_validacion varchar(100), es_fiscal boolean default false, constraint pk_tipos_documento primary key (tipo_documento_id), constraint uq_tipos_doc_codigo unique (codigo) ); create table global.actividades_economicas ( actividad_id int generated by default as identity, descripcion varchar(150) not null, sector varchar(50), constraint pk_actividades_economicas primary key (actividad_id) ); create table global.regimenes_tributarios ( regimen_id int generated by default as identity, descripcion varchar(100) not null, constraint pk_regimenes_tributarios primary key (regimen_id) ); -- ================================================================================= -- 2. ESQUEMA CORE (Aplicando Estados Centralizados y Migración) -- ================================================================================= create schema if not exists core; create table core.personas ( persona_id bigint generated by default as identity, -- CAMBIO CLAVE PARA MIGRACIÓN tipo_persona char(1) not null, motivo_registro varchar(50) not null, pais_emision_id int not null, tipo_documento_id int not null, numero_documento varchar(30) not null, nombre_completo_normalizado varchar(255) not null, fecha_nacimiento_constitucion date not null, actividad_economica_id int, regimen_tributario_id int, email_principal varchar(150), telefono_principal varchar(50), sitio_web varchar(150), -- ESTADO CENTRALIZADO -- Ahora apuntamos a la tabla maestra. estado_id int not null, version int default 1, creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, eliminado_en timestamptz, eliminado_por bigint, constraint pk_personas primary key (persona_id), constraint fk_personas_pais foreign key (pais_emision_id) references global.paises(pais_id), constraint fk_personas_tipo_doc foreign key (tipo_documento_id) references global.tipos_documento(tipo_documento_id), constraint fk_personas_actividad foreign key (actividad_economica_id) references global.actividades_economicas(actividad_id), constraint fk_personas_regimen foreign key (regimen_tributario_id) references global.regimenes_tributarios(regimen_id), -- FK AL ESTADO constraint fk_personas_estado foreign key (estado_id) references global.estados_sistema(estado_id), constraint uq_personas_identidad unique (pais_emision_id, tipo_documento_id, numero_documento), constraint ck_personas_tipo check (tipo_persona in ('F', 'J')) ); create index idx_personas_activos on core.personas(persona_id) where eliminado_en is null; -- Las tablas hijas (fisicas/juridicas) heredan la identidad "By Default" create table core.personas_fisicas ( persona_id bigint not null, -- ... campos ... constraint pk_personas_fisicas primary key (persona_id), constraint fk_fisicas_persona foreign key (persona_id) references core.personas(persona_id) on delete cascade ); create table core.personas_juridicas ( persona_id bigint not null, -- ... campos ... constraint pk_personas_juridicas primary key (persona_id), constraint fk_juridicas_persona foreign key (persona_id) references core.personas(persona_id) on delete cascade ); create schema if not exists core; create table core.personas ( persona_id bigint generated by default as identity, -- ========================================== -- NUEVA COLUMNA: TRAZABILIDAD LEGADA -- ========================================== id_legado varchar(50), -- El ID original del sistema viejo (ej: '5040' o 'CLI-99') -- Discriminador tipo_persona char(1) not null, motivo_registro varchar(50) not null, -- Identidad pais_emision_id int not null, tipo_documento_id int not null, numero_documento varchar(30) not null, nombre_completo_normalizado varchar(255) not null, -- Datos Promovidos fecha_nacimiento_constitucion date not null, actividad_economica_id int, regimen_tributario_id int, email_principal varchar(150), telefono_principal varchar(50), sitio_web varchar(150), -- Estado Centralizado estado_id int not null, version int default 1, -- Auditoría creado_en timestamptz default now() not null, creado_por bigint, actualizado_en timestamptz, actualizado_por bigint, eliminado_en timestamptz, eliminado_por bigint, constraint pk_personas primary key (persona_id), -- Constraints FK (Resumidos) constraint fk_personas_pais foreign key (pais_emision_id) references global.paises(pais_id), constraint fk_personas_tipo_doc foreign key (tipo_documento_id) references global.tipos_documento(tipo_documento_id), constraint fk_personas_actividad foreign key (actividad_economica_id) references global.actividades_economicas(actividad_id), constraint fk_personas_regimen foreign key (regimen_tributario_id) references global.regimenes_tributarios(regimen_id), constraint fk_personas_estado foreign key (estado_id) references global.estados_sistema(estado_id), constraint uq_personas_identidad unique (pais_emision_id, tipo_documento_id, numero_documento), constraint ck_personas_tipo check (tipo_persona in ('F', 'J')) ); -- ÍNDICE ÚNICO PARA ID LEGADO -- Vital para asegurar que no migres el mismo cliente viejo dos veces. create unique index uq_personas_id_legado on core.personas(id_legado) where id_legado is not null; -- Índices de performance create index idx_personas_activos on core.personas(persona_id) where eliminado_en is null;