Especificación Técnica: mae_empresas¶
Esquema: core.identidad
Base de Datos: core
Servicio: svc-identidad
Tabla Legacy Origen: core_sigfa.mae_empresas
Propósito: Maestro de empresas del núcleo; identidad organizacional raíz para empresas, sucursales y operación.
1. Justificación y Mejoras de Arquitectura¶
- PK BIGINT con identity: integración natural con sistemas legados y jerarquías existentes.
- Identificación con tipo/pais/ciudad referenciados por UUID (F3 del modelo docs-site).
- Unique sobre identificacion evita dobles registros tributarios.
- Evolución del legacy core_sigfa.mae_empresas en core.identidad.
2. Definiciones de Implementación¶
Table core.identidad.mae_empresas {
id bigint [pk]
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]
direccion varchar(300)
telefono varchar(20)
email varchar(150)
// 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_empresas_identificacion']
}
}
CREATE TABLE IF NOT EXISTS core.identidad.mae_empresas (
id BIGINT GENERATED BY DEFAULT AS IDENTITY 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,
direccion VARCHAR(300),
telefono VARCHAR(20),
email VARCHAR(150),
-- 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_empresas_identificacion UNIQUE (identificacion),
CONSTRAINT fk_mae_empresas_pais FOREIGN KEY (pais_id) REFERENCES core.identidad.cat_paises (id),
CONSTRAINT fk_mae_empresas_ciudad FOREIGN KEY (ciudad_id) REFERENCES core.identidad.cat_ciudades (id),
CONSTRAINT fk_mae_empresas_tipo_identificacion FOREIGN KEY (tipo_identificacion_id) REFERENCES core.identidad.cat_tipos_identificacion (id)
);
-- Comentarios
COMMENT ON COLUMN core.identidad.mae_empresas.nombre IS 'Razón social de la empresa';
COMMENT ON COLUMN core.identidad.mae_empresas.nombre_comercial IS 'Nombre comercial';
COMMENT ON COLUMN core.identidad.mae_empresas.identificacion IS 'Número de identificación fiscal';
COMMENT ON COLUMN core.identidad.mae_empresas.pais_id IS 'País de la empresa';
COMMENT ON COLUMN core.identidad.mae_empresas.ciudad_id IS 'Ciudad de la empresa';
COMMENT ON COLUMN core.identidad.mae_empresas.tipo_identificacion_id IS 'Tipo de identificación';
COMMENT ON COLUMN core.identidad.mae_empresas.direccion IS 'Dirección principal';
COMMENT ON COLUMN core.identidad.mae_empresas.telefono IS 'Teléfono principal';
COMMENT ON COLUMN core.identidad.mae_empresas.email IS 'Correo principal';
from datetime import datetime, date
from typing import Optional
import uuid
from sqlalchemy import (
BigInteger,
Boolean,
CheckConstraint,
Date,
DateTime,
ForeignKey,
Identity,
Index,
Integer,
SmallInteger,
String,
Text,
UniqueConstraint,
text,
)
from sqlalchemy.dialects import postgresql
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
pass
class MaeEmpresa(Base):
__tablename__ = 'mae_empresas'
__table_args__ = (
UniqueConstraint('identificacion', name='uq_mae_empresas_identificacion'),
{"schema": 'core.identidad'},
)
id: Mapped[int] = mapped_column(
BigInteger,
primary_key=True,
Identity(),
)
nombre: Mapped[str] = mapped_column(
String(200),
nullable=False,
comment='Razón social de la empresa',
)
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',
)
pais_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("cat_paises.id"),
comment='País de la empresa',
)
ciudad_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("cat_ciudades.id"),
comment='Ciudad de la empresa',
)
tipo_identificacion_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("cat_tipos_identificacion.id"),
comment='Tipo de identificación',
)
direccion: Mapped[str | None] = mapped_column(
String(300),
comment='Dirección principal',
)
telefono: Mapped[str | None] = mapped_column(
String(20),
comment='Teléfono principal',
)
email: Mapped[str | None] = mapped_column(
String(150),
comment='Correo principal',
)
# Auditoría General
is_activo: Mapped[bool] = mapped_column(
Boolean,
nullable=False,
server_default=text("true"),
comment='Estado lógico del registro',
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
server_default=text("now()"),
comment='Fecha de creación',
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
server_default=text("now()"),
comment='Fecha de última actualización',
)
deleted_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True),
comment='Fecha de eliminación lógica',
)
created_by: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
comment='Usuario creador',
)
updated_by: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
comment='Usuario modificador',
)
"""revision: core_id_0007
create table core.identidad.mae_empresas
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
revision: str = 'core_id_0007'
down_revision: str | None = 'core_id_0006'
branch_labels: str | None = None
depends_on: str | None = None
def upgrade() -> None:
op.create_table(
'mae_empresas',
sa.Column("id", sa.BigInteger(), primary_key=True, sa.Identity()),
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("direccion", sa.String(length=300)),
sa.Column("telefono", sa.String(length=20)),
sa.Column("email", sa.String(length=150)),
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_empresas_identificacion'),
sa.ForeignKeyConstraint(['pais_id'], ['core.identidad.cat_paises.id'], name='fk_mae_empresas_pais'),
sa.ForeignKeyConstraint(['ciudad_id'], ['core.identidad.cat_ciudades.id'], name='fk_mae_empresas_ciudad'),
sa.ForeignKeyConstraint(['tipo_identificacion_id'], ['core.identidad.cat_tipos_identificacion.id'], name='fk_mae_empresas_tipo_identificacion'),
schema='core.identidad',
)
def downgrade() -> None:
op.drop_table('mae_empresas', schema='core.identidad')