Refactor database models to use server defaults for boolean and timestamp fields
- Updated `TimestampMixin` to use `server_default` for `created_at` and `updated_at` fields. - Modified various models in the `fa_classes`, `doc_types_dig`, `ports`, `units_of_measure`, `invoices`, `parts`, `trailers`, `licenses`, `tenants`, and `user_tenant` modules to set `server_default` for boolean fields and other relevant fields. - Adjusted the `trailer_types` model to change the schema from `a76` to `public`. - Implemented database migration execution during application startup in `main.py`. - Removed old Alembic migration execution logic from the entrypoint script. - Updated seed data for units of measure and removed unused seed files.
This commit is contained in:
@@ -1,333 +0,0 @@
|
||||
"""create material_types table
|
||||
|
||||
Revision ID: 531bf8cdae06
|
||||
Revises:
|
||||
Create Date: 2025-10-19 18:23:39.613953
|
||||
|
||||
"""
|
||||
|
||||
# pylint: disable=no-member
|
||||
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "531bf8cdae06"
|
||||
down_revision: Union[str, Sequence[str], None] = None
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table(
|
||||
"containers",
|
||||
sa.Column("key", sa.String(length=3), nullable=False),
|
||||
sa.Column("description", sa.String(length=500), nullable=False),
|
||||
sa.PrimaryKeyConstraint("key", name="containers_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"countries",
|
||||
sa.Column("m3_key", sa.String(length=3), nullable=False),
|
||||
sa.Column("mex_key", sa.String(length=2), nullable=False),
|
||||
sa.Column("ame_key", sa.String(length=2), nullable=False),
|
||||
sa.Column("description_es", sa.String(length=50), nullable=False),
|
||||
sa.Column("description_en", sa.String(length=50), nullable=False),
|
||||
sa.PrimaryKeyConstraint("m3_key", name="countries_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_index(
|
||||
"ak_country_ame", "countries", ["ame_key"], unique=True, schema="public"
|
||||
)
|
||||
op.create_table(
|
||||
"currency_types",
|
||||
sa.Column("code", sa.String(length=3), nullable=False),
|
||||
sa.Column("currency_name", sa.String(length=15), nullable=False),
|
||||
sa.Column("country_description", sa.String(length=50), nullable=False),
|
||||
sa.PrimaryKeyConstraint("code", name="currency_types_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"customs_sections",
|
||||
sa.Column("customs_code", sa.String(length=3), nullable=False),
|
||||
sa.Column("section_name", sa.String(length=255), nullable=False),
|
||||
sa.PrimaryKeyConstraint("customs_code", name="customs_code_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"customs_warehouses",
|
||||
sa.Column("key", sa.String(length=3), nullable=False),
|
||||
sa.Column("customs", sa.String(length=100), nullable=False),
|
||||
sa.Column("fiscalized_warehouse", sa.String(length=1000), nullable=False),
|
||||
sa.PrimaryKeyConstraint("key", "customs", name="pk_customs_warehouse"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"incoterms",
|
||||
sa.Column("code", sa.String(length=5), nullable=False),
|
||||
sa.Column("description_es", sa.String(length=256), nullable=False),
|
||||
sa.Column("description_en", sa.String(length=256), nullable=False),
|
||||
sa.PrimaryKeyConstraint("code", name="incoterms_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"invoice_types",
|
||||
sa.Column("key", sa.String(length=5), nullable=False),
|
||||
sa.Column("description", sa.String(length=50), nullable=False),
|
||||
sa.Column("note", sa.String(length=500), nullable=False),
|
||||
sa.Column("type", sa.String(length=15), nullable=False),
|
||||
sa.Column("operation", sa.String(length=5), nullable=False),
|
||||
sa.PrimaryKeyConstraint("key", name="invoice_types_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"material_types",
|
||||
sa.Column("key", sa.String(length=10), nullable=False),
|
||||
sa.Column("type", sa.String(length=15), nullable=False),
|
||||
sa.Column("description", sa.String(length=256), nullable=False),
|
||||
sa.PrimaryKeyConstraint("key", name="material_types_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"payment_methods",
|
||||
sa.Column("key", sa.String(length=2), nullable=False),
|
||||
sa.Column("description", sa.String(length=100), nullable=False),
|
||||
sa.PrimaryKeyConstraint("key", name="payment_methods_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"pedimento_codes",
|
||||
sa.Column("code", sa.String(length=3), nullable=False),
|
||||
sa.Column("description", sa.String(length=250), nullable=False),
|
||||
sa.PrimaryKeyConstraint("code", name="pedimento_codes_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"pedimento_regimens",
|
||||
sa.Column("code", sa.String(length=3), nullable=False),
|
||||
sa.Column("description", sa.String(length=100), nullable=False),
|
||||
sa.PrimaryKeyConstraint("code", name="pedimento_regimens_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"sectors",
|
||||
sa.Column("key", sa.String(length=8), nullable=False),
|
||||
sa.Column("description", sa.String(length=150), nullable=False),
|
||||
sa.Column("authorized", sa.SmallInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("key", name="sectors_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"states",
|
||||
sa.Column("m3_key", sa.String(length=3), nullable=False),
|
||||
sa.Column("description", sa.String(length=50), nullable=False),
|
||||
sa.Column("mex_key", sa.String(length=3), nullable=True),
|
||||
sa.Column("ame_key", sa.String(length=2), nullable=True),
|
||||
sa.PrimaryKeyConstraint("m3_key", "description", name="states_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"transport_modes",
|
||||
sa.Column("key", sa.String(length=3), nullable=False),
|
||||
sa.Column("name", sa.String(length=30), nullable=False),
|
||||
sa.PrimaryKeyConstraint("key", name="transport_modes_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"transport_types",
|
||||
sa.Column("transport_code", sa.String(length=2), nullable=False),
|
||||
sa.Column("description", sa.String(length=100), nullable=False),
|
||||
sa.PrimaryKeyConstraint("transport_code", name="transport_types_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"valuation_methods",
|
||||
sa.Column("key", sa.String(length=2), nullable=False),
|
||||
sa.Column("description", sa.String(length=200), nullable=False),
|
||||
sa.PrimaryKeyConstraint("key", name="valuation_methods_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
op.create_table(
|
||||
"code_pedimento_regimens",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("pedimento_code", sa.String(length=3), nullable=False),
|
||||
sa.Column("regimen_code", sa.String(length=3), nullable=False),
|
||||
sa.Column("type_code", sa.String(length=1), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["pedimento_code"], ["public.pedimento_codes.code"], name="fk_codeped"
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["regimen_code"], ["public.pedimento_regimens.code"], name="fk_regimenped"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id", name="clave_pedimento_regimens_pkey"),
|
||||
schema="public",
|
||||
)
|
||||
|
||||
# Tablas de Unidades de Medida (A76)
|
||||
|
||||
# 1. Tabla: unit_of_measure_ace (ACE Units)
|
||||
op.create_table(
|
||||
'unit_of_measure_ace',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('code', sa.String(length=4), nullable=False),
|
||||
sa.Column('description', sa.String(length=49), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('code', name='uq_uom_ace_code'),
|
||||
schema='a76'
|
||||
)
|
||||
|
||||
# 2. Tabla: unit_of_measure_oma (OMA Units)
|
||||
op.create_table(
|
||||
'unit_of_measure_oma',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('code', sa.String(length=10), nullable=False),
|
||||
sa.Column('description', sa.String(length=200), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('code', name='uq_uom_oma_code'),
|
||||
schema='a76'
|
||||
)
|
||||
|
||||
# 3. Tabla: unit_of_measure_american (American Units)
|
||||
op.create_table(
|
||||
'unit_of_measure_american',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('code', sa.String(length=3), nullable=False),
|
||||
sa.Column('description', sa.String(length=40), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('code', name='uq_uom_american_code'),
|
||||
schema='a76'
|
||||
)
|
||||
|
||||
# 4. Tabla: unit_of_measure_customs (Customs Units)
|
||||
op.create_table(
|
||||
'unit_of_measure_customs',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('code', sa.String(length=10), nullable=False),
|
||||
sa.Column('description', sa.String(length=50), nullable=True),
|
||||
sa.Column('scaii_unit_code', sa.String(length=5), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('code', name='uq_uom_customs_code'),
|
||||
schema='a76'
|
||||
)
|
||||
|
||||
# 5. Tabla: units_of_measure (Main Unit of Measure)
|
||||
op.create_table(
|
||||
'units_of_measure',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('code', sa.String(length=10), nullable=False),
|
||||
sa.Column('description', sa.String(length=100), nullable=True),
|
||||
sa.Column('description_en', sa.String(length=100), nullable=True),
|
||||
sa.Column('customs_code', sa.String(length=10), nullable=True),
|
||||
sa.Column('american_code', sa.String(length=3), nullable=True),
|
||||
sa.Column('ace_code', sa.String(length=4), nullable=True),
|
||||
sa.Column('oma_code', sa.String(length=10), nullable=True),
|
||||
sa.Column('tenant_id', sa.Integer(), nullable=False),
|
||||
sa.Column('company_id', sa.Integer(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
['customs_code'],
|
||||
['a76.unit_of_measure_customs.code'],
|
||||
name='fk_uom_customs'
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
['american_code'],
|
||||
['a76.unit_of_measure_american.code'],
|
||||
name='fk_uom_american'
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
['ace_code'],
|
||||
['a76.unit_of_measure_ace.code'],
|
||||
name='fk_uom_ace'
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
['oma_code'],
|
||||
['a76.unit_of_measure_oma.code'],
|
||||
name='fk_uom_oma'
|
||||
),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('code', 'tenant_id', 'company_id', name='uq_uom_code'),
|
||||
schema='a76'
|
||||
)
|
||||
|
||||
# 6. Tabla: units_of_measure_general (General/Conversion Units)
|
||||
op.create_table(
|
||||
'units_of_measure_general',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('code', sa.String(length=10), nullable=False),
|
||||
sa.Column('description', sa.String(length=100), nullable=True),
|
||||
sa.Column('conversion_factor', sa.Numeric(precision=13, scale=6), nullable=True),
|
||||
sa.Column('mexico_unit', sa.String(length=10), nullable=True),
|
||||
sa.Column('american_unit_code', sa.String(length=5), nullable=True),
|
||||
sa.Column('customs_code', sa.String(length=10), nullable=True),
|
||||
sa.Column('ace_code', sa.String(length=4), nullable=True),
|
||||
sa.Column('tenant_id', sa.Integer(), nullable=False),
|
||||
sa.Column('company_id', sa.Integer(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
['customs_code'],
|
||||
['a76.unit_of_measure_customs.code'],
|
||||
name='fk_uom_general_customs'
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
['ace_code'],
|
||||
['a76.unit_of_measure_ace.code'],
|
||||
name='fk_uom_general_ace'
|
||||
),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('code', 'tenant_id', 'company_id', name='uq_uom_general_code'),
|
||||
schema='a76'
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
# Eliminar tablas de unidades de medida
|
||||
op.drop_table('units_of_measure_general', schema='a76')
|
||||
op.drop_table('units_of_measure', schema='a76')
|
||||
op.drop_table('unit_of_measure_customs', schema='a76')
|
||||
op.drop_table('unit_of_measure_american', schema='a76')
|
||||
op.drop_table('unit_of_measure_oma', schema='a76')
|
||||
op.drop_table('unit_of_measure_ace', schema='a76')
|
||||
|
||||
# Eliminar tablas públicas
|
||||
op.drop_table("code_pedimento_regimens", schema="public")
|
||||
op.drop_table("valuation_methods", schema="public")
|
||||
op.drop_table("transport_types", schema="public")
|
||||
op.drop_table("transport_modes", schema="public")
|
||||
op.drop_table("states", schema="public")
|
||||
op.drop_table("sectors", schema="public")
|
||||
op.drop_table("pedimento_regimens", schema="public")
|
||||
op.drop_table("pedimento_codes", schema="public")
|
||||
op.drop_table("payment_methods", schema="public")
|
||||
op.drop_table("material_types", schema="public")
|
||||
op.drop_table("invoice_types", schema="public")
|
||||
op.drop_table("incoterms", schema="public")
|
||||
op.drop_table("customs_warehouses", schema="public")
|
||||
op.drop_table("customs_sections", schema="public")
|
||||
op.drop_table("currency_types", schema="public")
|
||||
op.drop_index("ak_country_ame", table_name="countries", schema="public")
|
||||
op.drop_table("countries", schema="public")
|
||||
op.drop_table("containers", schema="public")
|
||||
# ### end Alembic commands ###
|
||||
@@ -50,18 +50,37 @@ from api.v1.modules.public.reference_data.transport_modes.seed import (
|
||||
from api.v1.modules.public.reference_data.transport_types.seed import (
|
||||
seed as transport_types_seed,
|
||||
)
|
||||
from api.v1.modules.public.reference_data.trailer_types.seed import (
|
||||
seed as trailer_types_seed,
|
||||
)
|
||||
from api.v1.modules.public.reference_data.valuation_methods.seed import (
|
||||
seed as valuation_methods_seed,
|
||||
)
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_med import seed as units_of_measure_seed
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_ace import seed as ace_seed
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_oma import seed as oma_seed
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_ame import seed as ame_seed
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_adua import seed as adua_seed
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed import (
|
||||
seed as units_of_measure_seed,
|
||||
)
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_ace import (
|
||||
seed as ace_seed,
|
||||
)
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_oma import (
|
||||
seed as oma_seed,
|
||||
)
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_ame import (
|
||||
seed as ame_seed,
|
||||
)
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.seed_adua import (
|
||||
seed as adua_seed,
|
||||
)
|
||||
from api.v1.modules.core.permissions.seed import (
|
||||
seed_invoices,
|
||||
seed_user,
|
||||
seed_report,
|
||||
seed_roles,
|
||||
)
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "7937209f9718"
|
||||
down_revision: Union[str, Sequence[str], None] = "531bf8cdae06"
|
||||
down_revision: Union[str, Sequence[str], None] = None
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
@@ -69,25 +88,10 @@ depends_on: Union[str, Sequence[str], None] = None
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
|
||||
# --- AMPLIAR COLUMNAS ANTES DE INSERTAR DATOS ---
|
||||
op.execute("ALTER TABLE a76.unit_of_measure_ace ALTER COLUMN code TYPE VARCHAR(20);")
|
||||
op.execute("ALTER TABLE a76.unit_of_measure_oma ALTER COLUMN code TYPE VARCHAR(20);")
|
||||
op.execute("ALTER TABLE a76.unit_of_measure_american ALTER COLUMN code TYPE VARCHAR(20);")
|
||||
op.execute("ALTER TABLE a76.unit_of_measure_customs ALTER COLUMN code TYPE VARCHAR(20);")
|
||||
op.execute("ALTER TABLE a76.units_of_measure ALTER COLUMN code TYPE VARCHAR(20);")
|
||||
op.execute("ALTER TABLE a76.units_of_measure ALTER COLUMN customs_code TYPE VARCHAR(20);")
|
||||
op.execute("ALTER TABLE a76.units_of_measure ALTER COLUMN american_code TYPE VARCHAR(20);")
|
||||
op.execute("ALTER TABLE a76.units_of_measure ALTER COLUMN ace_code TYPE VARCHAR(20);")
|
||||
op.execute("ALTER TABLE a76.units_of_measure ALTER COLUMN oma_code TYPE VARCHAR(20);")
|
||||
|
||||
# --- AGREGAR COLUMNAS deleted_at ---
|
||||
op.execute("ALTER TABLE a76.units_of_measure ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMP;")
|
||||
op.execute("ALTER TABLE a76.units_of_measure_general ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMP;")
|
||||
|
||||
# --- UTILIDAD DE FORMATEO ---
|
||||
def format_value(val):
|
||||
if val is None or str(val).strip() == '' or str(val).upper() == 'NONE':
|
||||
return 'NULL'
|
||||
if val is None or str(val).strip() == "" or str(val).upper() == "NONE":
|
||||
return "NULL"
|
||||
return f"'{str(val).replace(chr(39), chr(39)*2)}'"
|
||||
|
||||
# --- SEEDS PUBLIC (Tablas base) ---
|
||||
@@ -302,6 +306,20 @@ def upgrade() -> None:
|
||||
"""
|
||||
)
|
||||
|
||||
values_trailert = ", ".join(
|
||||
[
|
||||
f"('{code}', '{desc.replace(chr(39), chr(39)*2)}')"
|
||||
for code, desc in trailer_types_seed
|
||||
]
|
||||
)
|
||||
op.execute(
|
||||
f"""
|
||||
INSERT INTO public.trailer_type (trailer_type_key, description) VALUES
|
||||
{values_trailert}
|
||||
ON CONFLICT (trailer_type_key) DO NOTHING;
|
||||
"""
|
||||
)
|
||||
|
||||
values_vm = ", ".join(
|
||||
[
|
||||
f"('{key}', '{desc.replace(chr(39), chr(39)*2)}')"
|
||||
@@ -319,94 +337,159 @@ def upgrade() -> None:
|
||||
# --- SEEDS A76 (Unidades de Medida) ---
|
||||
|
||||
# ACE
|
||||
val_ace = ", ".join([f"({format_value(c)}, {format_value(d)})" for c, d in ace_seed])
|
||||
op.execute(f"INSERT INTO a76.unit_of_measure_ace (code, description) VALUES {val_ace} ON CONFLICT ON CONSTRAINT uq_uom_ace_code DO NOTHING;")
|
||||
val_ace = ", ".join(
|
||||
[f"({format_value(c)}, {format_value(d)})" for c, d in ace_seed]
|
||||
)
|
||||
op.execute(
|
||||
f"INSERT INTO a76.unit_of_measure_ace (code, description) VALUES {val_ace} ON CONFLICT ON CONSTRAINT uq_uom_ace_code DO NOTHING;"
|
||||
)
|
||||
|
||||
# OMA
|
||||
val_oma = ", ".join([f"({format_value(c)}, {format_value(d)})" for c, d in oma_seed])
|
||||
op.execute(f"INSERT INTO a76.unit_of_measure_oma (code, description) VALUES {val_oma} ON CONFLICT ON CONSTRAINT uq_uom_oma_code DO NOTHING;")
|
||||
val_oma = ", ".join(
|
||||
[f"({format_value(c)}, {format_value(d)})" for c, d in oma_seed]
|
||||
)
|
||||
op.execute(
|
||||
f"INSERT INTO a76.unit_of_measure_oma (code, description) VALUES {val_oma} ON CONFLICT ON CONSTRAINT uq_uom_oma_code DO NOTHING;"
|
||||
)
|
||||
|
||||
# AME
|
||||
val_ame = ", ".join([f"({format_value(c)}, {format_value(d)})" for c, d in ame_seed])
|
||||
op.execute(f"INSERT INTO a76.unit_of_measure_american (code, description) VALUES {val_ame} ON CONFLICT ON CONSTRAINT uq_uom_american_code DO NOTHING;")
|
||||
val_ame = ", ".join(
|
||||
[f"({format_value(c)}, {format_value(d)})" for c, d in ame_seed]
|
||||
)
|
||||
op.execute(
|
||||
f"INSERT INTO a76.unit_of_measure_american (code, description) VALUES {val_ame} ON CONFLICT ON CONSTRAINT uq_uom_american_code DO NOTHING;"
|
||||
)
|
||||
|
||||
# ADUA (Customs)
|
||||
val_adua = ", ".join([f"({format_value(c)}, {format_value(d)})" for c, d in adua_seed])
|
||||
op.execute(f"INSERT INTO a76.unit_of_measure_customs (code, description) VALUES {val_adua} ON CONFLICT ON CONSTRAINT uq_uom_customs_code DO NOTHING;")
|
||||
val_adua = ", ".join(
|
||||
[f"({format_value(c)}, {format_value(d)})" for c, d in adua_seed]
|
||||
)
|
||||
op.execute(
|
||||
f"INSERT INTO a76.unit_of_measure_customs (code, description) VALUES {val_adua} ON CONFLICT ON CONSTRAINT uq_uom_customs_code DO NOTHING;"
|
||||
)
|
||||
|
||||
# Recolectar códigos adicionales que faltan en los catálogos
|
||||
additional_customs = set()
|
||||
additional_american = set()
|
||||
additional_ace = set()
|
||||
additional_oma = set()
|
||||
|
||||
|
||||
existing_customs = {c for c, d in adua_seed}
|
||||
existing_american = {c for c, d in ame_seed}
|
||||
existing_ace = {c for c, d in ace_seed}
|
||||
existing_oma = {c for c, d in oma_seed}
|
||||
|
||||
|
||||
for code, desc, desc_en, customs, american, ace, oma in units_of_measure_seed:
|
||||
if customs and customs.strip() and customs not in existing_customs:
|
||||
additional_customs.add((customs, f'Auto-generated from {code}'))
|
||||
additional_customs.add((customs, f"Auto-generated from {code}"))
|
||||
if american and american.strip() and american not in existing_american:
|
||||
additional_american.add((american, f'Auto-generated from {code}'))
|
||||
additional_american.add((american, f"Auto-generated from {code}"))
|
||||
if ace and ace.strip() and ace not in existing_ace:
|
||||
additional_ace.add((ace, f'Auto-generated from {code}'))
|
||||
additional_ace.add((ace, f"Auto-generated from {code}"))
|
||||
if oma and oma.strip() and oma not in existing_oma:
|
||||
additional_oma.add((oma, f'Auto-generated from {code}'))
|
||||
|
||||
additional_oma.add((oma, f"Auto-generated from {code}"))
|
||||
|
||||
# Insertar códigos adicionales
|
||||
if additional_customs:
|
||||
val_add_customs = ", ".join([f"({format_value(c)}, {format_value(d)})" for c, d in additional_customs])
|
||||
op.execute(f"INSERT INTO a76.unit_of_measure_customs (code, description) VALUES {val_add_customs} ON CONFLICT ON CONSTRAINT uq_uom_customs_code DO NOTHING;")
|
||||
|
||||
val_add_customs = ", ".join(
|
||||
[f"({format_value(c)}, {format_value(d)})" for c, d in additional_customs]
|
||||
)
|
||||
op.execute(
|
||||
f"INSERT INTO a76.unit_of_measure_customs (code, description, a76_unit_code) VALUES {val_add_customs} ON CONFLICT ON CONSTRAINT uq_uom_customs_code DO NOTHING;"
|
||||
)
|
||||
|
||||
if additional_american:
|
||||
val_add_american = ", ".join([f"({format_value(c)}, {format_value(d)})" for c, d in additional_american])
|
||||
op.execute(f"INSERT INTO a76.unit_of_measure_american (code, description) VALUES {val_add_american} ON CONFLICT ON CONSTRAINT uq_uom_american_code DO NOTHING;")
|
||||
|
||||
val_add_american = ", ".join(
|
||||
[f"({format_value(c)}, {format_value(d)})" for c, d in additional_american]
|
||||
)
|
||||
op.execute(
|
||||
f"INSERT INTO a76.unit_of_measure_american (code, description) VALUES {val_add_american} ON CONFLICT ON CONSTRAINT uq_uom_american_code DO NOTHING;"
|
||||
)
|
||||
|
||||
if additional_ace:
|
||||
val_add_ace = ", ".join([f"({format_value(c)}, {format_value(d)})" for c, d in additional_ace])
|
||||
op.execute(f"INSERT INTO a76.unit_of_measure_ace (code, description) VALUES {val_add_ace} ON CONFLICT ON CONSTRAINT uq_uom_ace_code DO NOTHING;")
|
||||
|
||||
val_add_ace = ", ".join(
|
||||
[f"({format_value(c)}, {format_value(d)})" for c, d in additional_ace]
|
||||
)
|
||||
op.execute(
|
||||
f"INSERT INTO a76.unit_of_measure_ace (code, description) VALUES {val_add_ace} ON CONFLICT ON CONSTRAINT uq_uom_ace_code DO NOTHING;"
|
||||
)
|
||||
|
||||
if additional_oma:
|
||||
val_add_oma = ", ".join([f"({format_value(c)}, {format_value(d)})" for c, d in additional_oma])
|
||||
op.execute(f"INSERT INTO a76.unit_of_measure_oma (code, description) VALUES {val_add_oma} ON CONFLICT ON CONSTRAINT uq_uom_oma_code DO NOTHING;")
|
||||
val_add_oma = ", ".join(
|
||||
[f"({format_value(c)}, {format_value(d)})" for c, d in additional_oma]
|
||||
)
|
||||
op.execute(
|
||||
f"INSERT INTO a76.unit_of_measure_oma (code, description) VALUES {val_add_oma} ON CONFLICT ON CONSTRAINT uq_uom_oma_code DO NOTHING;"
|
||||
)
|
||||
|
||||
# TABLA MAESTRA UOM
|
||||
val_uom = ", ".join([
|
||||
f"({format_value(code)}, {format_value(desc)}, {format_value(desc_en)}, "
|
||||
f"{format_value(customs)}, {format_value(american)}, {format_value(ace)}, {format_value(oma)}, 1, 1)"
|
||||
for code, desc, desc_en, customs, american, ace, oma in units_of_measure_seed
|
||||
])
|
||||
op.execute(f"""
|
||||
# TODO: Generar tenant_id y company_id correctos
|
||||
val_uom = ", ".join(
|
||||
[
|
||||
f"({format_value(code)}, {format_value(desc)}, {format_value(desc_en)}, "
|
||||
f"{format_value(customs)}, {format_value(american)}, {format_value(ace)}, {format_value(oma)}, 1, 1)"
|
||||
for code, desc, desc_en, customs, american, ace, oma in units_of_measure_seed
|
||||
]
|
||||
)
|
||||
op.execute("ALTER TABLE a76.units_of_measure DISABLE TRIGGER ALL;")
|
||||
op.execute(
|
||||
f"""
|
||||
INSERT INTO a76.units_of_measure
|
||||
(code, description, description_en, customs_code, american_code, ace_code, oma_code, tenant_id, company_id)
|
||||
VALUES {val_uom}
|
||||
ON CONFLICT (code, tenant_id, company_id) DO NOTHING;
|
||||
""")
|
||||
"""
|
||||
)
|
||||
op.execute("ALTER TABLE a76.units_of_measure ENABLE TRIGGER ALL;")
|
||||
|
||||
# --- SEEDS CORE (Permissions) ---
|
||||
|
||||
# Combinar todas las seeds de permisos
|
||||
all_permissions = seed_invoices + seed_user + seed_report + seed_roles
|
||||
|
||||
values_permissions = ", ".join(
|
||||
[
|
||||
f"({format_value(code)}, {format_value(description)}, {format_value(module)}, {format_value(action)})"
|
||||
for code, description, module, action in all_permissions
|
||||
]
|
||||
)
|
||||
|
||||
if values_permissions:
|
||||
op.execute(
|
||||
f"""
|
||||
INSERT INTO core.permissions (code, description, module, action)
|
||||
VALUES {values_permissions}
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
|
||||
op.execute("DELETE FROM a76.units_of_measure;")
|
||||
op.execute("DELETE FROM a76.unit_of_measure_customs;")
|
||||
op.execute("DELETE FROM a76.unit_of_measure_american;")
|
||||
op.execute("DELETE FROM a76.unit_of_measure_oma;")
|
||||
op.execute("DELETE FROM a76.unit_of_measure_ace;")
|
||||
op.execute("DELETE FROM public.valuation_methods;")
|
||||
op.execute("DELETE FROM public.transport_types;")
|
||||
op.execute("DELETE FROM public.transport_modes;")
|
||||
op.execute("DELETE FROM public.sectors;")
|
||||
op.execute("DELETE FROM public.payment_methods;")
|
||||
op.execute("DELETE FROM public.material_types;")
|
||||
op.execute("DELETE FROM public.invoice_types;")
|
||||
op.execute("DELETE FROM public.incoterms;")
|
||||
op.execute("DELETE FROM public.customs_warehouses;")
|
||||
op.execute("DELETE FROM public.customs_sections;")
|
||||
op.execute("DELETE FROM public.currency_types;")
|
||||
op.execute("DELETE FROM public.countries;")
|
||||
op.execute("DELETE FROM public.containers;")
|
||||
op.execute("DELETE FROM public.code_pedimento_regimens;")
|
||||
op.execute("DELETE FROM public.pedimento_regimens;")
|
||||
op.execute("DELETE FROM public.pedimento_codes;")
|
||||
op.drop_table("valuation_methods", schema="public")
|
||||
op.drop_table("transport_types", schema="public")
|
||||
op.drop_table("transport_modes", schema="public")
|
||||
op.drop_table("sectors", schema="public")
|
||||
op.drop_table("payment_methods", schema="public")
|
||||
op.drop_table("material_types", schema="public")
|
||||
op.drop_table("invoice_types", schema="public")
|
||||
op.drop_table("incoterms", schema="public")
|
||||
op.drop_table("customs_warehouses", schema="public")
|
||||
op.drop_table("customs_sections", schema="public")
|
||||
op.drop_table("currency_types", schema="public")
|
||||
op.drop_table("countries", schema="public")
|
||||
op.drop_table("containers", schema="public")
|
||||
op.drop_table("code_pedimento_regimens", schema="public")
|
||||
op.drop_table("pedimento_regimens", schema="public")
|
||||
op.drop_table("pedimento_codes", schema="public")
|
||||
op.drop_table("user_client_permissions", schema="core")
|
||||
op.drop_table("user_client_roles", schema="core")
|
||||
op.drop_table("role_permissions", schema="core")
|
||||
op.drop_table("client_roles", schema="core")
|
||||
op.drop_table("permissions", schema="core")
|
||||
op.drop_table("units_of_measure", schema="a76")
|
||||
op.drop_table("unit_of_measure_customs", schema="a76")
|
||||
op.drop_table("unit_of_measure_american", schema="a76")
|
||||
op.drop_table("unit_of_measure_oma", schema="a76")
|
||||
op.drop_table("unit_of_measure_ace", schema="a76")
|
||||
|
||||
@@ -9,10 +9,10 @@ class TimestampMixin:
|
||||
"""Mixin for common timestamp fields"""
|
||||
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime, nullable=False, default=func.now()
|
||||
DateTime, nullable=False, server_default=func.now()
|
||||
)
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime, nullable=False, default=func.now(), onupdate=func.now()
|
||||
DateTime, nullable=False, server_default=func.now(), onupdate=func.now()
|
||||
)
|
||||
deleted_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
|
||||
|
||||
@@ -18,18 +18,32 @@ class QClasses(Base, TenantScopedMixin, TimestampMixin):
|
||||
__tablename__ = "fa_classes" # QClases
|
||||
__table_args__ = (
|
||||
PrimaryKeyConstraint("id", name="qclases_pk"),
|
||||
ForeignKeyConstraint(["class_id"], ["a76.classes.id"], name="fk_qclasses_classes"),
|
||||
ForeignKeyConstraint(
|
||||
["class_id"], ["a76.classes.id"], name="fk_qclasses_classes"
|
||||
),
|
||||
{"schema": "a24"},
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
class_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
|
||||
import_tariff_code: Mapped[Optional[str]] = mapped_column(String(10), nullable=True) # FRACCIONIMPO
|
||||
import_tariff_type: Mapped[Optional[str]] = mapped_column(String(6), nullable=True) # TIPOFRACIMPO
|
||||
export_tariff_code: Mapped[Optional[str]] = mapped_column(String(10), nullable=True) # FRACCIONEXPO
|
||||
export_tariff_type: Mapped[Optional[str]] = mapped_column(String(6), nullable=True) # TIPOFRACEXPO
|
||||
depreciation_rate: Mapped[Optional[Decimal]] = mapped_column(Numeric(5, 2), nullable=True) # TASADEPRECIA
|
||||
import_tariff_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(10), nullable=True
|
||||
) # FRACCIONIMPO
|
||||
import_tariff_type: Mapped[Optional[str]] = mapped_column(
|
||||
String(6), nullable=True
|
||||
) # TIPOFRACIMPO
|
||||
export_tariff_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(10), nullable=True
|
||||
) # FRACCIONEXPO
|
||||
export_tariff_type: Mapped[Optional[str]] = mapped_column(
|
||||
String(6), nullable=True
|
||||
) # TIPOFRACEXPO
|
||||
depreciation_rate: Mapped[Optional[Decimal]] = mapped_column(
|
||||
Numeric(5, 2), nullable=True
|
||||
) # TASADEPRECIA
|
||||
fda_code: Mapped[Optional[str]] = mapped_column(String(20), nullable=True) # FDA
|
||||
eccn_code: Mapped[Optional[str]] = mapped_column(String(20), nullable=True) # ECCN
|
||||
class_enabled: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) # HABILITADESHABILITACLASE
|
||||
class_enabled: Mapped[bool] = mapped_column(
|
||||
Boolean, default=True, server_default="true", nullable=False
|
||||
) # HABILITADESHABILITACLASE
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
|
||||
from core.database import Base
|
||||
from sqlalchemy import Boolean, Integer, PrimaryKeyConstraint, String, Text, UniqueConstraint
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
Integer,
|
||||
PrimaryKeyConstraint,
|
||||
String,
|
||||
Text,
|
||||
UniqueConstraint,
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
|
||||
@@ -22,4 +29,4 @@ class DocumentTypeDigitization(Base, TenantScopedMixin, TimestampMixin):
|
||||
id: Mapped[int] = mapped_column(Integer)
|
||||
code: Mapped[str] = mapped_column(String(10), nullable=False, index=True)
|
||||
description: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
active: Mapped[bool] = mapped_column(Boolean, default=True, server_default="true")
|
||||
|
||||
@@ -11,7 +11,7 @@ class PortBase(BaseModel):
|
||||
location_description: Optional[str] = Field(
|
||||
None, max_length=20, description="Location Description")
|
||||
port_type: PortType = Field(
|
||||
default=PortType.ENTRY, description="Port Type (ENTRY, EXIT, BOTH)")
|
||||
server_default=PortType.ENTRY, description="Port Type (ENTRY, EXIT, BOTH)")
|
||||
|
||||
|
||||
class PortCreate(PortBase):
|
||||
|
||||
@@ -32,4 +32,4 @@ class Port(Base, TenantScopedMixin, TimestampMixin):
|
||||
|
||||
# New column requested
|
||||
port_type: Mapped[PortType] = mapped_column(
|
||||
String(15), nullable=False, default=PortType.ENTRY)
|
||||
String(15), nullable=False, server_default=PortType.ENTRY)
|
||||
|
||||
@@ -13,8 +13,6 @@ from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
|
||||
from core.database import Base
|
||||
|
||||
# 1. GUniMedACE
|
||||
|
||||
|
||||
class UnitOfMeasureACE(Base, TimestampMixin):
|
||||
__tablename__ = "unit_of_measure_ace"
|
||||
__table_args__ = (
|
||||
@@ -28,8 +26,6 @@ class UnitOfMeasureACE(Base, TimestampMixin):
|
||||
|
||||
|
||||
# 2. GUMOMA
|
||||
|
||||
|
||||
class UnitOfMeasureOMA(Base, TimestampMixin):
|
||||
__tablename__ = "unit_of_measure_oma"
|
||||
__table_args__ = (
|
||||
@@ -43,8 +39,6 @@ class UnitOfMeasureOMA(Base, TimestampMixin):
|
||||
|
||||
|
||||
# 3. GUMAme
|
||||
|
||||
|
||||
class UnitOfMeasureAmerican(Base, TimestampMixin):
|
||||
__tablename__ = "unit_of_measure_american"
|
||||
__table_args__ = (
|
||||
@@ -58,8 +52,6 @@ class UnitOfMeasureAmerican(Base, TimestampMixin):
|
||||
|
||||
|
||||
# 4. GUMAduana
|
||||
|
||||
|
||||
class UnitOfMeasureCustoms(Base, TimestampMixin):
|
||||
__tablename__ = "unit_of_measure_customs"
|
||||
__table_args__ = (
|
||||
@@ -68,52 +60,15 @@ class UnitOfMeasureCustoms(Base, TimestampMixin):
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
code: Mapped[str] = mapped_column(String(2), nullable=False) # CLAVE
|
||||
description: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)
|
||||
scaii_unit_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(5), nullable=True
|
||||
) # UNIDADSCAII
|
||||
code: Mapped[str] = mapped_column(Integer, nullable=False) # CLAVE
|
||||
description: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)
|
||||
|
||||
|
||||
# 5. GUniMedida (Main)
|
||||
|
||||
|
||||
class UnitOfMeasure(Base, TenantScopedMixin, TimestampMixin):
|
||||
__tablename__ = "units_of_measure"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("code", "tenant_id", "company_id", name="uq_uom_code"),
|
||||
ForeignKeyConstraint(
|
||||
["customs_code"],
|
||||
[
|
||||
"a76.unit_of_measure_customs.code"
|
||||
],
|
||||
use_alter=True,
|
||||
name="fk_uom_customs",
|
||||
),
|
||||
ForeignKeyConstraint(
|
||||
["american_code"],
|
||||
[
|
||||
"a76.unit_of_measure_american.code"
|
||||
],
|
||||
use_alter=True,
|
||||
name="fk_uom_american",
|
||||
),
|
||||
ForeignKeyConstraint(
|
||||
["ace_code"],
|
||||
[
|
||||
"a76.unit_of_measure_ace.code"
|
||||
],
|
||||
use_alter=True,
|
||||
name="fk_uom_ace",
|
||||
),
|
||||
ForeignKeyConstraint(
|
||||
["oma_code"],
|
||||
[
|
||||
"a76.unit_of_measure_oma.code"
|
||||
],
|
||||
use_alter=True,
|
||||
name="fk_uom_oma",
|
||||
),
|
||||
UniqueConstraint("code", "tenant_id", "company_id", name="uq_uom_code"),
|
||||
{"schema": "a76", "extend_existing": True},
|
||||
)
|
||||
|
||||
@@ -122,35 +77,19 @@ class UnitOfMeasure(Base, TenantScopedMixin, TimestampMixin):
|
||||
description: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
||||
description_en: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
||||
|
||||
customs_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(2), nullable=True
|
||||
) # CLAVE_AMEX
|
||||
american_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(3), nullable=True
|
||||
) # CLAVE_AAMER
|
||||
ace_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(4), nullable=True
|
||||
) # CLAVEACE
|
||||
oma_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(10), nullable=True
|
||||
) # CLAVEOMA
|
||||
customs_code: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.unit_of_measure_customs.code"), nullable=True) # CLAVE_AMEX
|
||||
american_code: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.unit_of_measure_american.code"), nullable=True) # CLAVE_AAMER
|
||||
ace_code: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.unit_of_measure_ace.code"), nullable=True) # CLAVEACE
|
||||
oma_code: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.unit_of_measure_oma.code"), nullable=True) # CLAVEOMA
|
||||
|
||||
# Relationships omitted for simplicity or need explicit primaryjoin
|
||||
customs_unit: Mapped[Optional["UnitOfMeasureCustoms"]] = relationship()
|
||||
american_unit: Mapped[Optional["UnitOfMeasureAmerican"]] = relationship(
|
||||
overlaps="customs_unit"
|
||||
)
|
||||
ace_unit: Mapped[Optional["UnitOfMeasureACE"]] = relationship(
|
||||
overlaps="american_unit,customs_unit"
|
||||
)
|
||||
oma_unit: Mapped[Optional["UnitOfMeasureOMA"]] = relationship(
|
||||
overlaps="ace_unit,american_unit,customs_unit"
|
||||
)
|
||||
american_unit: Mapped[Optional["UnitOfMeasureAmerican"]] = relationship(overlaps="customs_unit")
|
||||
ace_unit: Mapped[Optional["UnitOfMeasureACE"]] = relationship(overlaps="american_unit,customs_unit")
|
||||
oma_unit: Mapped[Optional["UnitOfMeasureOMA"]] = relationship(overlaps="ace_unit,american_unit,customs_unit")
|
||||
|
||||
|
||||
# 6. GUniMed (General/Conversion)
|
||||
|
||||
|
||||
class UnitOfMeasureGeneral(Base, TenantScopedMixin, TimestampMixin):
|
||||
__tablename__ = "units_of_measure_general"
|
||||
__table_args__ = (
|
||||
@@ -178,14 +117,10 @@ class UnitOfMeasureGeneral(Base, TenantScopedMixin, TimestampMixin):
|
||||
)
|
||||
mexico_unit: Mapped[Optional[str]] = mapped_column(String(5), nullable=True)
|
||||
# UNIDAD_AME (Note: GUniMed has UNIDAD_AME varchar(5), but GUMAme has CLAVE varchar(3). Keeping as string for now)
|
||||
american_unit_code: Mapped[Optional[str]] = mapped_column(String(5), nullable=True)
|
||||
american_unit_code: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.unit_of_measure_american.code"), nullable=True)
|
||||
|
||||
customs_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(2), nullable=True
|
||||
) # CLAVE_ADUANA
|
||||
ace_code: Mapped[Optional[str]] = mapped_column(
|
||||
String(4), nullable=True
|
||||
) # CLAVEACE
|
||||
customs_code: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.unit_of_measure_customs.code"), nullable=True) # CLAVE_ADUANA
|
||||
ace_code: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.unit_of_measure_ace.code"), nullable=True) # CLAVEACE
|
||||
|
||||
customs_unit: Mapped[Optional["UnitOfMeasureCustoms"]] = relationship()
|
||||
ace_unit: Mapped[Optional["UnitOfMeasureACE"]] = relationship(
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
seed = [
|
||||
('KGS', 'Kilo'),
|
||||
('KW', 'Kilowatt'),
|
||||
('MILLR', 'Millar'),
|
||||
('JGO', 'Juego'),
|
||||
('KWH', 'Kilowatt/Hora'),
|
||||
('TON', 'Tonelada'),
|
||||
('BARR', 'Barril'),
|
||||
('GRN', 'Gramo Neto'),
|
||||
('DEC', 'Decenas'),
|
||||
('CIEN', 'Cientos'),
|
||||
('DOCE', 'Decenas (Docenas)'),
|
||||
('GR', 'Gramo'),
|
||||
('CAJA', 'Caja'),
|
||||
('PZA', 'Botella'),
|
||||
('CARAT', 'Carat'),
|
||||
('MT', 'Metro Lineal'),
|
||||
('M2', 'Metro Cuadrado'),
|
||||
('M3', 'Metro Cubico'),
|
||||
('PZA', 'Pieza'),
|
||||
('PZA', 'Cabeza'),
|
||||
('LT', 'Litro'),
|
||||
('PAR', 'Par'),
|
||||
("1", "Kilo"),
|
||||
("2", "Gramo"),
|
||||
("3", "Metro Lineal"),
|
||||
("4", "Metro Cuadrado"),
|
||||
("5", "Metro Cubico"),
|
||||
("6", "Pieza"),
|
||||
("7", "Cabeza"),
|
||||
("8", "Litro"),
|
||||
("9", "Par"),
|
||||
("10", "Kilowatt"),
|
||||
("11", "Millar"),
|
||||
("12", "Juego"),
|
||||
("13", "Kilowatt/Hora"),
|
||||
("14", "Tonelada"),
|
||||
("15", "Barril"),
|
||||
("16", "Gramo Neto"),
|
||||
("17", "Decenas"),
|
||||
("18", "Cientos"),
|
||||
("19", "Decenas"),
|
||||
("20", "Caja"),
|
||||
("21", "Botella"),
|
||||
("22", "Carat"),
|
||||
]
|
||||
@@ -1,44 +0,0 @@
|
||||
seed = [
|
||||
# (code, desc_es, desc_en, customs, american, ace, oma)
|
||||
('BARR', 'BARRIL', 'BARIEL', '', 'BBL', 'BLL', ''),
|
||||
('BD FT', 'PIE TABLA', 'BD FEET', '', 'FT', 'BFT', ''),
|
||||
('BOLS', 'BOLSA', 'BAG', '', 'PCS', 'BG', ''),
|
||||
('BTL', 'BOTELLA', 'BOTTLE', '', 'PCS', 'BO', ''),
|
||||
('BULT', 'BULTO', 'BULK', '', 'PCS', 'VQ', ''),
|
||||
('CAJA', 'CAJA', 'BOX', '', '', 'BX', ''),
|
||||
('CARAT', 'CARAT', 'CARAT', '', '', 'HE', ''),
|
||||
('CBZA', 'CABEZA', 'HEAD', '', 'PCS', 'Z4', ''),
|
||||
('CIEN', 'CIENTO', 'CIEN', '', '', 'CEN', ''),
|
||||
('CM', 'CENTIMETRO', 'CM', 'CM', 'CM', 'CMT', ''),
|
||||
('CM2', 'CENTIMETRO CUADRADO', 'CM2', 'CM2', 'CM2', 'CMK', ''),
|
||||
('DEC', 'DECENA', '', '', '', 'DC', ''),
|
||||
('DM', 'DECIMETRO', 'DM', '', '', 'DMT', ''),
|
||||
('DM2', 'DECIMETRO CUADRADO', 'SQ DM', '', '', 'DMK', ''),
|
||||
('DOCE', 'DOCENA', 'DOZ', '', 'DOZ', 'DZN', 'DZ'),
|
||||
('FOZ', 'ONZA LIQUIDA', 'FOZ', 'FOZ', 'FOZ', 'OZA', ''),
|
||||
('FT', 'PIES', 'FT', 'FT', 'FT', 'LF', ''),
|
||||
('FT2', 'PIE CUADRADO', 'FT2', '', 'SFT', 'FTK', ''),
|
||||
('GAL', 'GALON', 'GAL', 'GAL', 'GAL', 'GLL', ''),
|
||||
('GR', 'GRAMO', 'GRAM', '', '', 'GRM', ''),
|
||||
('IN', 'PULGADA', 'IN', '', '', 'LI', ''),
|
||||
('IN2', 'PULGADA CUADRADA', 'IN2', '', '', 'INK', ''),
|
||||
('JGO', 'JUEGO', 'SET', '', '', 'SET', ''),
|
||||
('KGS', 'KILOGRAMOS', 'KGS', '', 'KG2', 'KGM', ''),
|
||||
('LB', 'LIBRAS', 'LB', '', '', 'LBR', ''),
|
||||
('LT', 'LITRO', 'LT', 'LT', 'L', 'LTR', ''),
|
||||
('M2', 'METRO CUADRADO', 'M2', 'M2', 'M2', 'MTK', ''),
|
||||
('M3', 'METRO CUBICO', 'M3', 'M3', 'M3', 'MTQ', ''),
|
||||
('MI', 'MILLA', 'MILE', '', 'KM', 'SMI', ''),
|
||||
('MILLR', 'MILLAR', 'MILLR', '', '', 'MIL', ''),
|
||||
('MT', 'METROS', 'MT', 'MT', 'M', 'MTR', ''),
|
||||
('OZ', 'ONZA', 'OZ', 'FOZ', 'FOZ', 'OZ', ''),
|
||||
('PAR', 'PAR', 'PAIR', '', '', 'PB', ''),
|
||||
('PQ', 'PAQUETE', 'PACKAGE', '', 'PCS', 'PK_1', ''),
|
||||
('PZA', 'PIEZA', 'PCS', 'PCS', 'PCS', 'C62_1', ''),
|
||||
('QGL', 'CUARTO DE GALON', 'QGL', '', '', 'QT', ''),
|
||||
('ROLL', 'ROLLO', 'ROLL', '', '', 'RO', ''),
|
||||
('TON', 'TONELADA', 'TON', 'TON', 'TON', 'TNE_1', ''),
|
||||
('TOZ', 'ONZA TROY', 'TOZ', '', 'TOZ', 'APZ', ''),
|
||||
('YD', 'YARDA', 'YD', 'YD', 'YD', 'YRD', ''),
|
||||
('YD2', 'YARDA CUADRADA', 'YD2', '', 'SYD', 'YDK', ''),
|
||||
]
|
||||
@@ -10,6 +10,7 @@ from sqlalchemy import (
|
||||
String,
|
||||
Text,
|
||||
TIMESTAMP,
|
||||
func,
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from core.database import Base
|
||||
@@ -101,7 +102,7 @@ class InvoiceHeader(Base, TenantScopedMixin, TimestampMixin):
|
||||
# Dates
|
||||
invoice_date: Mapped[datetime] = mapped_column(Date) # FECHAFACTURA
|
||||
capture_date: Mapped[datetime] = mapped_column(
|
||||
TIMESTAMP(timezone=False), default=datetime.now
|
||||
TIMESTAMP(timezone=False), server_default=func.now()
|
||||
) # FECHACAPTURA + HORAACTUAL
|
||||
emission_date: Mapped[Optional[datetime]] = mapped_column(Date) # FECHAEMISION
|
||||
|
||||
@@ -153,13 +154,13 @@ class InvoiceHeader(Base, TenantScopedMixin, TimestampMixin):
|
||||
|
||||
# Generation flags
|
||||
generate_id: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # GENERAID
|
||||
generate_desc_parties: Mapped[Optional[str]] = mapped_column(
|
||||
String(12)
|
||||
) # GENDESCPARTIDAS / Generar descripción de partidas
|
||||
apply_manual_discount: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # APLICADESCMANUAL
|
||||
|
||||
# Bulk & Downloads
|
||||
@@ -287,7 +288,7 @@ class InvoiceComplianceMx(Base, TenantScopedMixin, TimestampMixin):
|
||||
Integer
|
||||
) # APENDICE17 / Apéndice 17
|
||||
is_regime_change: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # ESCAMBIOREGIMEN / Es cambio de régimen
|
||||
which_exchange_rate: Mapped[Optional[str]] = mapped_column(
|
||||
String(5)
|
||||
@@ -299,15 +300,15 @@ class InvoiceComplianceMx(Base, TenantScopedMixin, TimestampMixin):
|
||||
String(5)
|
||||
) # ACTVALOR / Actualizar valor
|
||||
is_pedimento_pending: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # PED_PENDIENTE_ASIGNAR (Mapear 1 -> True, 0 -> False)
|
||||
|
||||
# Ownership & Balances
|
||||
is_owner_of_goods: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # ESDUENOMCIA / Es dueño de mercancía
|
||||
generate_balances: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # GENERARSALDOS / Generar saldos
|
||||
was_reviewed_by_company: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean
|
||||
@@ -413,102 +414,102 @@ class InvoiceFinancials(Base, TenantScopedMixin, TimestampMixin):
|
||||
|
||||
# Merchandise Values (MN = National Currency, ME = Foreign Currency, MC = Third Currency)
|
||||
value_mn: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORIMPOMN/VALOREXPOMN/VALORENTMN/VALORSALMN
|
||||
value_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORIMPOME/VALOREXPOME/VALORENTME/VALORSALME
|
||||
value_mc: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORIMPOMC/VALOREXPOMC
|
||||
|
||||
# Customs Value
|
||||
customs_value_mn: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORADUANASMN / Valor en aduanas MN
|
||||
customs_value_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORADUANASME / Valor en aduanas ME
|
||||
|
||||
# Raw Materials
|
||||
raw_material_value_mn: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORMPMN / Valor materia prima MN
|
||||
raw_material_value_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORMPME / Valor materia prima ME
|
||||
|
||||
# Aggregate Value
|
||||
aggregate_value_mn: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORAGREMN / Valor agregado MN
|
||||
aggregate_value_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORAGREME / Valor agregado ME
|
||||
aggregate_value_mc: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORAGREMC / Valor agregado MC
|
||||
|
||||
# Mexican Merchandise Value
|
||||
mexican_value_mn: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORVMEXMN / Valor mercancía mexicana MN
|
||||
mexican_value_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORVMEXME / Valor mercancía mexicana ME
|
||||
mexican_value_mc: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORVMEXMC / Valor mercancía mexicana MC
|
||||
|
||||
# National Packaging
|
||||
national_packaging_mn: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALEMPAQUENACMN / Valor empaque nacional MN
|
||||
national_packaging_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALEMPAQUENACME / Valor empaque nacional ME
|
||||
national_packaging_mc: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALEMPAQUENACMC / Valor empaque nacional MC
|
||||
|
||||
# Costs & Increments
|
||||
freight: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(19, 8), default=0
|
||||
Numeric(19, 8), default=0, server_default="0"
|
||||
) # FLETE / Flete
|
||||
insurance: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(19, 8), default=0
|
||||
Numeric(19, 8), default=0, server_default="0"
|
||||
) # SEGUROS / Seguros
|
||||
insurance_value: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(19, 8), default=0
|
||||
Numeric(19, 8), default=0, server_default="0"
|
||||
) # VALSEGUROS / Valor seguros
|
||||
packaging: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(19, 8), default=0
|
||||
Numeric(19, 8), default=0, server_default="0"
|
||||
) # EMBALAJES / Embalajes
|
||||
other_increments: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(19, 8), default=0
|
||||
Numeric(19, 8), default=0, server_default="0"
|
||||
) # OTROSINCREMENTA / Otros incrementables
|
||||
total_increments_mn: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # TOTALINCREMMN / Total incrementables MN
|
||||
total_increments_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # TOTALINCREMME / Total incrementables ME
|
||||
|
||||
# Taxes
|
||||
iva_mn: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # IVAEXPOMN/VALORIVAMN / IVA en MN
|
||||
iva_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # IVAEXPOME/VALORIVAME / IVA en ME
|
||||
iva_mc: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # IVAEXPOMC / IVA en MC
|
||||
iva_factor: Mapped[Optional[str]] = mapped_column(
|
||||
String(10)
|
||||
) # FACTORIVA / Factor IVA (puede ser varchar en imports)
|
||||
tax_value_me: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(23, 8), default=0
|
||||
Numeric(23, 8), default=0, server_default="0"
|
||||
) # VALORIMPUESTOME / Valor impuesto ME
|
||||
seal_value_2500: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean
|
||||
@@ -554,7 +555,7 @@ class InvoiceLogistics(Base, TenantScopedMixin, TimestampMixin):
|
||||
String(10)
|
||||
) # TRANSPORTISTAAME / Transportista americano
|
||||
transport_type: Mapped[TransportType] = mapped_column(
|
||||
String(15), default="none"
|
||||
String(15), server_default="none"
|
||||
) # TRANSPORTE / Tipo de transporte
|
||||
transport_num: Mapped[Optional[str]] = mapped_column(
|
||||
String(20)
|
||||
@@ -566,7 +567,7 @@ class InvoiceLogistics(Base, TenantScopedMixin, TimestampMixin):
|
||||
String(80)
|
||||
) # CONDUCTOR / Nombre del conductor
|
||||
is_rail: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # ESFERROCARRIL / Es ferrocarril
|
||||
rail_id: Mapped[Optional[str]] = mapped_column(
|
||||
String(31)
|
||||
@@ -655,7 +656,7 @@ class InvoiceLogistics(Base, TenantScopedMixin, TimestampMixin):
|
||||
|
||||
# Delivery Control
|
||||
delivered_status: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # ENTREGADO / Estado de entrega
|
||||
received_by: Mapped[Optional[str]] = mapped_column(
|
||||
String(50)
|
||||
@@ -671,7 +672,7 @@ class InvoiceLogistics(Base, TenantScopedMixin, TimestampMixin):
|
||||
|
||||
# CTM Process
|
||||
is_ctm_process: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=False
|
||||
Boolean, default=False, server_default="false"
|
||||
) # SETRATAPROCESOCTM / Se trata de proceso CTM
|
||||
|
||||
# Relationship
|
||||
|
||||
@@ -89,7 +89,9 @@ class Part(Base, TenantScopedMixin, TimestampMixin):
|
||||
export_code: Mapped[Optional[str]] = mapped_column(String(2))
|
||||
exclusion_symbol: Mapped[Optional[str]] = mapped_column(String(19))
|
||||
|
||||
is_active: Mapped[Optional[bool]] = mapped_column(Boolean, default=True)
|
||||
is_active: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean, default=True, server_default="true"
|
||||
)
|
||||
part_photo: Mapped[Optional[str]] = mapped_column(String(255))
|
||||
|
||||
creation_date: Mapped[Optional[int]] = mapped_column()
|
||||
|
||||
@@ -12,7 +12,7 @@ class Trailer(Base, TenantScopedMixin, TimestampMixin):
|
||||
trailer_number = Column(String(20), primary_key=True, nullable=False)
|
||||
ace_trailer_number = Column(String(10), nullable=True)
|
||||
trailer_type_key = Column(
|
||||
String(2), ForeignKey("a76.trailer_type.trailer_type_key"), nullable=True
|
||||
String(2), ForeignKey("public.trailer_type.trailer_type_key"), nullable=True
|
||||
)
|
||||
seal = Column(String(15), nullable=True)
|
||||
entity_code = Column(String(1), nullable=True)
|
||||
|
||||
@@ -44,21 +44,29 @@ class License(Base, TimestampMixin):
|
||||
)
|
||||
|
||||
# Plan y características
|
||||
plan = Column(SQLEnum(LicensePlan), default=LicensePlan.FREE, nullable=False)
|
||||
plan = Column(
|
||||
SQLEnum(LicensePlan),
|
||||
default=LicensePlan.FREE,
|
||||
server_default="FREE",
|
||||
nullable=False,
|
||||
)
|
||||
status = Column(
|
||||
SQLEnum(LicenseStatus), default=LicenseStatus.PENDING, nullable=False
|
||||
SQLEnum(LicenseStatus),
|
||||
default=LicenseStatus.PENDING,
|
||||
server_default="PENDING",
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
# Límites del plan
|
||||
max_users = Column(Integer, default=5, nullable=False)
|
||||
max_storage_gb = Column(Integer, default=10, nullable=False)
|
||||
max_monthly_operations = Column(Integer, default=1000, nullable=False)
|
||||
max_users = Column(Integer, server_default="5", nullable=False)
|
||||
max_storage_gb = Column(Integer, server_default="10", nullable=False)
|
||||
max_monthly_operations = Column(Integer, server_default="1000", nullable=False)
|
||||
|
||||
# Features habilitadas (booleans)
|
||||
feature_api_access = Column(Boolean, default=True)
|
||||
feature_advanced_reports = Column(Boolean, default=False)
|
||||
feature_integrations = Column(Boolean, default=False)
|
||||
feature_dedicated_support = Column(Boolean, default=False)
|
||||
feature_api_access = Column(Boolean, default=True, server_default="true")
|
||||
feature_advanced_reports = Column(Boolean, default=False, server_default="false")
|
||||
feature_integrations = Column(Boolean, default=False, server_default="false")
|
||||
feature_dedicated_support = Column(Boolean, default=False, server_default="false")
|
||||
|
||||
# Vigencia
|
||||
starts_at = Column(DateTime(timezone=True), nullable=False)
|
||||
@@ -85,10 +93,10 @@ class LicenseUsage(Base, TimestampMixin):
|
||||
period_start = Column(DateTime(timezone=True), nullable=False)
|
||||
period_end = Column(DateTime(timezone=True), nullable=False)
|
||||
|
||||
active_users = Column(Integer, default=0)
|
||||
storage_used_gb = Column(Integer, default=0)
|
||||
operations_count = Column(Integer, default=0)
|
||||
api_calls_count = Column(Integer, default=0)
|
||||
active_users = Column(Integer, default=0, server_default="0")
|
||||
storage_used_gb = Column(Integer, default=0, server_default="0")
|
||||
operations_count = Column(Integer, default=0, server_default="0")
|
||||
api_calls_count = Column(Integer, default=0, server_default="0")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<LicenseUsage(tenant_id={self.tenant_id}, operations={self.operations_count})>"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from .auth.routes import router as auth_router
|
||||
from .licenses.routes import router as licenses_router
|
||||
from .permissions.routes import router as permissions_router
|
||||
from .tenants.routes import router as tenants_router
|
||||
from .user_tenant.routes import router as user_tenant_router
|
||||
from .users.routes import router as users_router
|
||||
@@ -13,4 +14,5 @@ router.include_router(tenants_router, prefix="/core", tags=["core / tenants"])
|
||||
router.include_router(user_tenant_router, prefix="/core", tags=["core / user-tenants"])
|
||||
router.include_router(users_router, prefix="/core", tags=["core / users"])
|
||||
router.include_router(licenses_router, prefix="/core", tags=["core / licenses"])
|
||||
router.include_router(permissions_router, prefix="/core", tags=["core / permissions"])
|
||||
router.include_router(dashboard_router, prefix="/core", tags=["core / dashboard"])
|
||||
|
||||
@@ -37,7 +37,12 @@ class Tenant(Base, TimestampMixin):
|
||||
slug = Column(String(100), unique=True, nullable=False, index=True)
|
||||
|
||||
# Tipo de tenant (compartido o dedicado)
|
||||
type = Column(SQLEnum(TenantType), default=TenantType.SHARED, nullable=False)
|
||||
type = Column(
|
||||
SQLEnum(TenantType),
|
||||
default=TenantType.SHARED,
|
||||
server_default="SHARED",
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
# Keycloak realm asociado
|
||||
keycloak_realm = Column(String(255), nullable=False)
|
||||
@@ -51,7 +56,7 @@ class Tenant(Base, TimestampMixin):
|
||||
contact_phone = Column(String(50))
|
||||
|
||||
# Estado
|
||||
is_active = Column(Boolean, default=True, nullable=False)
|
||||
is_active = Column(Boolean, default=True, server_default="true", nullable=False)
|
||||
|
||||
# Relación con UserTenant
|
||||
user_relations: Mapped[List["UserTenant"]] = relationship(
|
||||
|
||||
@@ -45,7 +45,9 @@ class UserTenant(Base, TenantScopedMixin, TimestampMixin):
|
||||
)
|
||||
|
||||
# Estado de la relación
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
||||
is_active: Mapped[bool] = mapped_column(
|
||||
Boolean, default=True, server_default="true", nullable=False
|
||||
)
|
||||
|
||||
# Información adicional - Rol del usuario en este tenant (opcional)
|
||||
role: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
|
||||
|
||||
@@ -3,10 +3,10 @@ from core.database import Base
|
||||
from sqlalchemy import Column, ForeignKeyConstraint, String
|
||||
|
||||
|
||||
class TrailerType(Base, TenantScopedMixin, TimestampMixin):
|
||||
class TrailerType(Base, TimestampMixin):
|
||||
__tablename__ = "trailer_type"
|
||||
__table_args__ = (
|
||||
{"schema": "a76"},
|
||||
{"schema": "public"},
|
||||
)
|
||||
|
||||
trailer_type_key = Column(String(2), primary_key=True, nullable=False)
|
||||
|
||||
@@ -4,6 +4,7 @@ Backend API con FastAPI + Keycloak + SQLAlchemy
|
||||
"""
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
from api.v1.router import router as api_v1_router
|
||||
from core.config import settings
|
||||
@@ -75,12 +76,19 @@ async def http_exception_handler(request: Request, exc: HTTPException):
|
||||
)
|
||||
|
||||
|
||||
def run_migrations():
|
||||
subprocess.run(
|
||||
["alembic", "upgrade", "head"],
|
||||
check=True
|
||||
)
|
||||
|
||||
# Inicializar la base de datos
|
||||
@app.on_event("startup")
|
||||
async def on_startup():
|
||||
"""Evento de inicio de la aplicación"""
|
||||
logger.info("Iniciando la aplicación Anexo76...")
|
||||
init_db()
|
||||
run_migrations()
|
||||
logger.info("Base de datos inicializada correctamente.")
|
||||
|
||||
|
||||
|
||||
@@ -41,18 +41,18 @@ wait_for_tcp "${CORE_DB_HOST:-postgres-a76}" "${CORE_DB_PORT:-5432}" "PostgreSQL
|
||||
wait_for_tcp "keycloak" "8080" "Keycloak"
|
||||
|
||||
# Ejecutar migraciones de Alembic
|
||||
if [ -d "/app/alembic" ]; then
|
||||
echo "Ejecutando migraciones de Alembic..."
|
||||
alembic upgrade head || {
|
||||
echo "⚠ WARNING: Error al ejecutar migraciones"
|
||||
echo " Verificando estado de la base de datos..."
|
||||
alembic current || echo " No se pudo determinar la versión actual"
|
||||
}
|
||||
echo "✓ Migraciones completadas"
|
||||
else
|
||||
echo "⚠ WARNING: Directorio /app/alembic no encontrado"
|
||||
echo " Las migraciones de base de datos no se ejecutaron"
|
||||
fi
|
||||
#if [ -d "/app/alembic" ]; then
|
||||
# echo "Ejecutando migraciones de Alembic..."
|
||||
# alembic upgrade head || {
|
||||
# echo "⚠ WARNING: Error al ejecutar migraciones"
|
||||
# echo " Verificando estado de la base de datos..."
|
||||
# alembic current || echo " No se pudo determinar la versión actual"
|
||||
# }
|
||||
# echo "✓ Migraciones completadas"
|
||||
#else
|
||||
# echo "⚠ WARNING: Directorio /app/alembic no encontrado"
|
||||
# echo " Las migraciones de base de datos no se ejecutaron"
|
||||
#fi
|
||||
|
||||
echo "=========================================="
|
||||
echo "Iniciando aplicación FastAPI..."
|
||||
|
||||
@@ -530,7 +530,7 @@ if [ $TENANT_QUERY_STATUS -ne 0 ]; then
|
||||
echo -e "${RED}✗ Error al consultar el tenant:${NC}"
|
||||
echo "$TENANT_ID_RESULT"
|
||||
echo -e "${YELLOW}Verificando si la tabla existe...${NC}"
|
||||
docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "\dt core.tenants;"
|
||||
exec_pg_sql "\dt core.tenants;"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -540,7 +540,7 @@ if [ -z "$TENANT_ID" ]; then
|
||||
echo -e "${RED}✗ Error: No se pudo obtener el ID del tenant${NC}"
|
||||
echo "Resultado de la consulta: '$TENANT_ID_RESULT'"
|
||||
echo -e "${YELLOW}Intentando ver todos los tenants...${NC}"
|
||||
docker exec -e PGPASSWORD="${POSTGRES_PASSWORD}" anexo76-postgres-a76 psql -h localhost -p 5432 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "SELECT id, slug FROM core.tenants LIMIT 10;"
|
||||
exec_pg_sql "SELECT id, slug FROM core.tenants LIMIT 10;"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user