Saltar a contenido

Especificación Técnica: mae_entidades

Esquema: core.identidad
Base de Datos: core
Servicio: svc-identidad
Tabla Legacy Origen: — (nueva, patrón party)
Propósito: Raíz polimórfica de la que "heredan" personas naturales (mae_personas) y jurídicas (mae_personas_juridicas). mae_usuarios referencia una entidad sin importar el subtipo.


1. Justificación y Mejoras de Arquitectura

  • Patrón party: un usuario puede representar a una persona natural (cédula) o a una persona jurídica externa (RUC); mae_usuarios necesita un único FK (entidad_id) y no debe condicionar en código.
  • Herencia por tabla (joined table inheritance): el id nace aquí y la fila hija copia el mismo UUID; las hijas no tienen DEFAULT gen_random_uuid().
  • tipo_entidad es el discriminador (PERSONA_NATURAL / PERSONA_JURIDICA).
  • Tabla global (sin empresa_id ni RLS): igual que mae_personas, la identidad no pertenece a una sola empresa.
  • Sin columnas de auditoría propias: el estado (is_activo) y la auditoría viven en cada subtipo (mae_personas, mae_personas_juridicas).

2. Definiciones de Implementación

Table core.identidad.mae_entidades {
    id            uuid          [pk, default: `gen_random_uuid()`]
    tipo_entidad  varchar(20)   [not null, note: 'PERSONA_NATURAL | PERSONA_JURIDICA']

    Note: 'CHECK chk_mae_entidades_tipo: tipo_entidad IN (PERSONA_NATURAL, PERSONA_JURIDICA)'
}
CREATE TABLE IF NOT EXISTS core.identidad.mae_entidades (
    id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
    tipo_entidad VARCHAR(20) NOT NULL,
    CONSTRAINT chk_mae_entidades_tipo
        CHECK (tipo_entidad IN ('PERSONA_NATURAL', 'PERSONA_JURIDICA'))
);

-- Comentarios
COMMENT ON COLUMN core.identidad.mae_entidades.tipo_entidad IS 'Discriminador (PERSONA_NATURAL/PERSONA_JURIDICA)';
class MaeEntidad(Base):
    __tablename__ = 'mae_entidades'
    __table_args__ = (
        CheckConstraint(
            "tipo_entidad IN ('PERSONA_NATURAL', 'PERSONA_JURIDICA')",
            name='chk_mae_entidades_tipo',
        ),
        {"schema": 'identidad'},
    )

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        primary_key=True,
        server_default=text("gen_random_uuid()"),
    )
    tipo_entidad: Mapped[str] = mapped_column(
        String(20),
        nullable=False,
        comment='Discriminador (PERSONA_NATURAL/PERSONA_JURIDICA)',
    )

    __mapper_args__ = {
        "polymorphic_on": tipo_entidad,
        "with_polymorphic": "*",
    }

    @property
    def nombre_mostrar(self) -> str:
        raise NotImplementedError
"""Pertenece a la migración 0005_entidades de svc-identidad.

revision: 0005_entidades
down_revision: 0004_usuarios
create table identidad.mae_entidades
"""

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql


def upgrade() -> None:
    op.create_table(
        'mae_entidades',
        sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text("gen_random_uuid()")),
        sa.Column("tipo_entidad", sa.String(length=20), nullable=False),
        sa.CheckConstraint(
            "tipo_entidad IN ('PERSONA_NATURAL', 'PERSONA_JURIDICA')",
            name="chk_mae_entidades_tipo",
        ),
        schema='identidad',
    )


def downgrade() -> None:
    op.drop_table('mae_entidades', schema='identidad')