Saltar a contenido

Especificación Técnica: mae_personas_juridicas

Esquema: core.identidad
Base de Datos: core
Servicio: svc-identidad
Tabla Legacy Origen: — (nueva, personas jurídicas externas)
Propósito: Personas jurídicas externas al grupo (empresas cliente, consultores que facturan con RUC) que pueden tener cuenta de usuario. Hereda de mae_entidades.


1. Justificación y Mejoras de Arquitectura

  • Un usuario puede representar a una persona jurídica externa; sus datos (identificación fiscal, razón social, ubicación) no van en mae_personas (exclusiva de personas naturales con cédula).
  • No es una empresa del grupo: esas viven en mae_empresas (tenencia/RLS). De ahí el nombre mae_personas_juridicas.
  • PK = FK a mae_entidades.id; sin DEFAULT: el id nace en mae_entidades y se copia en la misma transacción.
  • Identificación, país, ciudad y tipo de documento referenciados por UUID a los catálogos globales (igual que mae_empresas).
  • Tabla global (sin empresa_id ni RLS).
  • Columnas de auditoría propias (is_activo, created_at, updated_at, deleted_at, created_by, updated_by), igual que mae_personas.

2. Definiciones de Implementación

Table core.identidad.mae_personas_juridicas {
    id                         uuid          [pk, ref: > mae_entidades.id]
    nombre                     varchar(200)  [not null]
    nombre_comercial           varchar(200)
    identificacion             varchar(20)   [not null]
    pais_id                    uuid          [ref: > cat_paises.id]
    ciudad_id                  uuid          [ref: > cat_ciudades.id]
    tipo_identificacion_id     uuid          [ref: > cat_tipos_identificacion.id]

    // Auditoría General
    is_activo               boolean       [not null, default: `true`, note: 'Estado lógico del registro']
    created_at              timestamptz   [not null, default: `now()`, note: 'Fecha de creación']
    updated_at              timestamptz   [not null, default: `now()`, note: 'Fecha de última actualización']
    deleted_at              timestamptz   [note: 'Fecha de eliminación lógica']
    created_by              uuid          [note: 'Usuario creador']
    updated_by              uuid          [note: 'Usuario modificador']

    Indexes {
        (identificacion) [unique, name: 'uq_mae_personas_juridicas_identificacion']
    }
}
CREATE TABLE IF NOT EXISTS core.identidad.mae_personas_juridicas (
    id UUID NOT NULL PRIMARY KEY,
    nombre VARCHAR(200) NOT NULL,
    nombre_comercial VARCHAR(200),
    identificacion VARCHAR(20) NOT NULL,
    pais_id UUID,
    ciudad_id UUID,
    tipo_identificacion_id UUID,

    -- Auditoría General
    is_activo BOOLEAN NOT NULL DEFAULT true,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    deleted_at TIMESTAMPTZ,
    created_by UUID,
    updated_by UUID,
    CONSTRAINT uq_mae_personas_juridicas_identificacion UNIQUE (identificacion),
    CONSTRAINT fk_mae_personas_juridicas_entidad FOREIGN KEY (id) REFERENCES core.identidad.mae_entidades (id),
    CONSTRAINT fk_mae_personas_juridicas_pais FOREIGN KEY (pais_id) REFERENCES core.identidad.cat_paises (id),
    CONSTRAINT fk_mae_personas_juridicas_ciudad FOREIGN KEY (ciudad_id) REFERENCES core.identidad.cat_ciudades (id),
    CONSTRAINT fk_mae_personas_juridicas_tipo_identificacion FOREIGN KEY (tipo_identificacion_id) REFERENCES core.identidad.cat_tipos_identificacion (id)
);

-- Comentarios
COMMENT ON COLUMN core.identidad.mae_personas_juridicas.id IS 'Mismo id de mae_entidades (herencia de tabla)';
COMMENT ON COLUMN core.identidad.mae_personas_juridicas.nombre IS 'Razón social';
COMMENT ON COLUMN core.identidad.mae_personas_juridicas.nombre_comercial IS 'Nombre comercial';
COMMENT ON COLUMN core.identidad.mae_personas_juridicas.identificacion IS 'Número de identificación fiscal (RUC)';
COMMENT ON COLUMN core.identidad.mae_personas_juridicas.pais_id IS 'País';
COMMENT ON COLUMN core.identidad.mae_personas_juridicas.ciudad_id IS 'Ciudad';
COMMENT ON COLUMN core.identidad.mae_personas_juridicas.tipo_identificacion_id IS 'Tipo de identificación';
class MaePersonaJuridica(MaeEntidad):
    __tablename__ = 'mae_personas_juridicas'
    __table_args__ = (
        UniqueConstraint('identificacion', name='uq_mae_personas_juridicas_identificacion'),
        {"schema": 'identidad'},
    )
    __mapper_args__ = {"polymorphic_identity": "PERSONA_JURIDICA"}

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("identidad.mae_entidades.id"),
        primary_key=True,
        comment='Mismo id de mae_entidades (herencia de tabla)',
    )
    nombre: Mapped[str] = mapped_column(String(200), nullable=False, comment='Razón social')
    nombre_comercial: Mapped[str | None] = mapped_column(String(200), comment='Nombre comercial')
    identificacion: Mapped[str] = mapped_column(
        String(20), nullable=False, comment='Número de identificación fiscal (RUC)'
    )
    pais_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("identidad.cat_paises.id"), comment='País'
    )
    ciudad_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("identidad.cat_ciudades.id"), comment='Ciudad'
    )
    tipo_identificacion_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("identidad.cat_tipos_identificacion.id"),
        comment='Tipo de identificación',
    )

    # Auditoría General
    is_activo: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default=text("true"))
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=text("now()"))
    updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=text("now()"), onupdate=func.now())
    deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    created_by: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
    updated_by: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))

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

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

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


def upgrade() -> None:
    op.create_table(
        'mae_personas_juridicas',
        sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column("nombre", sa.String(length=200), nullable=False),
        sa.Column("nombre_comercial", sa.String(length=200)),
        sa.Column("identificacion", sa.String(length=20), nullable=False),
        sa.Column("pais_id", postgresql.UUID(as_uuid=True)),
        sa.Column("ciudad_id", postgresql.UUID(as_uuid=True)),
        sa.Column("tipo_identificacion_id", postgresql.UUID(as_uuid=True)),
        sa.Column("is_activo", sa.Boolean(), nullable=False, server_default=sa.text("true")),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("now()")),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("now()")),
        sa.Column("deleted_at", sa.DateTime(timezone=True)),
        sa.Column("created_by", postgresql.UUID(as_uuid=True)),
        sa.Column("updated_by", postgresql.UUID(as_uuid=True)),
        sa.UniqueConstraint('identificacion', name='uq_mae_personas_juridicas_identificacion'),
        sa.ForeignKeyConstraint(['id'], ['identidad.mae_entidades.id'], name='fk_mae_personas_juridicas_entidad'),
        sa.ForeignKeyConstraint(['pais_id'], ['identidad.cat_paises.id'], name='fk_mae_personas_juridicas_pais'),
        sa.ForeignKeyConstraint(['ciudad_id'], ['identidad.cat_ciudades.id'], name='fk_mae_personas_juridicas_ciudad'),
        sa.ForeignKeyConstraint(['tipo_identificacion_id'], ['identidad.cat_tipos_identificacion.id'], name='fk_mae_personas_juridicas_tipo_identificacion'),
        schema='identidad',
    )


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