From 7abe79405e1f66e07c2d849681ca72a39385feb5 Mon Sep 17 00:00:00 2001 From: Galindo97 Date: Fri, 9 Jan 2026 15:34:13 -0600 Subject: [PATCH 1/4] feat: add unit of measure tables and seed data for material types management --- ...31bf8cdae06_create_material_types_table.py | 142 +++++++++++++++ .../7937209f9718_seed_initial_data.py | 44 ++++- ...2e8e8cd3_create_units_of_measure_tables.py | 163 ++++++++++++++++++ .../reference_data/material_types/routes.py | 6 + .../dashboard/refrence_data/material_types.ts | 17 +- 5 files changed, 367 insertions(+), 5 deletions(-) create mode 100644 backend/alembic/versions/d9b22e8e8cd3_create_units_of_measure_tables.py diff --git a/backend/alembic/versions/531bf8cdae06_create_material_types_table.py b/backend/alembic/versions/531bf8cdae06_create_material_types_table.py index bfdc01b1..2629548a 100644 --- a/backend/alembic/versions/531bf8cdae06_create_material_types_table.py +++ b/backend/alembic/versions/531bf8cdae06_create_material_types_table.py @@ -167,12 +167,154 @@ def upgrade() -> None: 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('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.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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('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.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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('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.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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=2), nullable=False), + sa.Column('description', sa.String(length=20), nullable=True), + sa.Column('scaii_unit_code', sa.String(length=5), 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.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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=5), 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=2), 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.ForeignKeyConstraint( + ['customs_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_customs.code', 'a76.unit_of_measure_customs.tenant_id', 'a76.unit_of_measure_customs.company_id'], + name='fk_uom_customs' + ), + sa.ForeignKeyConstraint( + ['american_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_american.code', 'a76.unit_of_measure_american.tenant_id', 'a76.unit_of_measure_american.company_id'], + name='fk_uom_american' + ), + sa.ForeignKeyConstraint( + ['ace_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_ace.code', 'a76.unit_of_measure_ace.tenant_id', 'a76.unit_of_measure_ace.company_id'], + name='fk_uom_ace' + ), + sa.ForeignKeyConstraint( + ['oma_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_oma.code', 'a76.unit_of_measure_oma.tenant_id', 'a76.unit_of_measure_oma.company_id'], + 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=5), 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=5), nullable=True), + sa.Column('american_unit_code', sa.String(length=5), nullable=True), + sa.Column('customs_code', sa.String(length=2), 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', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_customs.code', 'a76.unit_of_measure_customs.tenant_id', 'a76.unit_of_measure_customs.company_id'], + name='fk_uom_general_customs' + ), + sa.ForeignKeyConstraint( + ['ace_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_ace.code', 'a76.unit_of_measure_ace.tenant_id', 'a76.unit_of_measure_ace.company_id'], + 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") diff --git a/backend/alembic/versions/7937209f9718_seed_initial_data.py b/backend/alembic/versions/7937209f9718_seed_initial_data.py index 864f6c72..75a6ce9b 100644 --- a/backend/alembic/versions/7937209f9718_seed_initial_data.py +++ b/backend/alembic/versions/7937209f9718_seed_initial_data.py @@ -53,12 +53,13 @@ from api.v1.modules.public.reference_data.transport_types.seed import ( 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 import seed as units_of_measure_seed # revision identifiers, used by Alembic. revision: str = "7937209f9718" down_revision: Union[str, Sequence[str], None] = "531bf8cdae06" branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = "531bf8cdae06" +depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: @@ -288,6 +289,46 @@ def upgrade() -> None: """ ) + # Insertar seeds de Unidades de Medida + # Preparar valores únicos para cada tabla auxiliar + ace_codes = set() + oma_codes = set() + american_codes = set() + customs_codes = set() + + for code, desc, desc_en, customs, american, ace, oma in units_of_measure_seed: + if ace and ace.strip(): + ace_codes.add(ace.strip()) + if oma and oma.strip(): + oma_codes.add(oma.strip()) + if american and american.strip(): + american_codes.add(american.strip()) + if customs and customs.strip(): + customs_codes.add(customs.strip()) + + # Insertar seeds (con tenant_id=1, company_id=1 por defecto) + # IMPORTANTE: En producción necesitarás ajustar estos valores + + def format_value(val): + """Formatea valores para SQL, manejando None y strings vacíos""" + if not val or val.strip() == '': + return 'NULL' + return f"'{val.replace(chr(39), chr(39)*2)}'" + + values_uom = ", ".join([ + f"('{code}', {format_value(desc)}, {format_value(desc_en)}, " + f"{format_value(customs)}, {format_value(american)}, " + f"{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""" + INSERT INTO a76.units_of_measure + (code, description, description_en, customs_code, american_code, ace_code, oma_code, tenant_id, company_id) + VALUES {values_uom} + ON CONFLICT (code, tenant_id, company_id) DO NOTHING; + """) + def downgrade() -> None: """Downgrade schema.""" @@ -308,3 +349,4 @@ def downgrade() -> None: op.execute("DELETE FROM public.code_pedimento_regimens;") op.execute("DELETE FROM public.pedimento_regimens;") op.execute("DELETE FROM public.pedimento_codes;") + op.execute("DELETE FROM a76.units_of_measure;") diff --git a/backend/alembic/versions/d9b22e8e8cd3_create_units_of_measure_tables.py b/backend/alembic/versions/d9b22e8e8cd3_create_units_of_measure_tables.py new file mode 100644 index 00000000..89113e85 --- /dev/null +++ b/backend/alembic/versions/d9b22e8e8cd3_create_units_of_measure_tables.py @@ -0,0 +1,163 @@ +"""create_units_of_measure_tables + +Revision ID: d9b22e8e8cd3 +Revises: 7937209f9718 +Create Date: 2026-01-09 14:51:56.669491 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'd9b22e8e8cd3' +down_revision: Union[str, Sequence[str], None] = '7937209f9718' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + + # 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('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.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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('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.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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('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.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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=2), nullable=False), + sa.Column('description', sa.String(length=20), nullable=True), + sa.Column('scaii_unit_code', sa.String(length=5), 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.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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=5), 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=2), 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(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True), + sa.ForeignKeyConstraint( + ['customs_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_customs.code', 'a76.unit_of_measure_customs.tenant_id', 'a76.unit_of_measure_customs.company_id'], + name='fk_uom_customs' + ), + sa.ForeignKeyConstraint( + ['american_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_american.code', 'a76.unit_of_measure_american.tenant_id', 'a76.unit_of_measure_american.company_id'], + name='fk_uom_american' + ), + sa.ForeignKeyConstraint( + ['ace_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_ace.code', 'a76.unit_of_measure_ace.tenant_id', 'a76.unit_of_measure_ace.company_id'], + name='fk_uom_ace' + ), + sa.ForeignKeyConstraint( + ['oma_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_oma.code', 'a76.unit_of_measure_oma.tenant_id', 'a76.unit_of_measure_oma.company_id'], + 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=5), 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=5), nullable=True), + sa.Column('american_unit_code', sa.String(length=5), nullable=True), + sa.Column('customs_code', sa.String(length=2), 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(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True), + sa.ForeignKeyConstraint( + ['customs_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_customs.code', 'a76.unit_of_measure_customs.tenant_id', 'a76.unit_of_measure_customs.company_id'], + name='fk_uom_general_customs' + ), + sa.ForeignKeyConstraint( + ['ace_code', 'tenant_id', 'company_id'], + ['a76.unit_of_measure_ace.code', 'a76.unit_of_measure_ace.tenant_id', 'a76.unit_of_measure_ace.company_id'], + name='fk_uom_general_ace' + ), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code', 'tenant_id', 'company_id', name='uq_uom_general_code'), + schema='a76' + ) + + +def downgrade() -> None: + """Downgrade schema.""" + 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') diff --git a/backend/api/v1/modules/public/reference_data/material_types/routes.py b/backend/api/v1/modules/public/reference_data/material_types/routes.py index a25d3fb9..a90f7b06 100644 --- a/backend/api/v1/modules/public/reference_data/material_types/routes.py +++ b/backend/api/v1/modules/public/reference_data/material_types/routes.py @@ -15,11 +15,17 @@ router = APIRouter(prefix="/material-types") async def list_material_types( page: int = Query(1, ge=1, description="Número de página"), page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"), + type: str = Query(None, description="Filtrar por tipo (ACTIVO FIJO, MATERIALES, PRODUCTOS)"), db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user), ): skip = (page - 1) * page_size query = db.query(MaterialType) + + # Aplicar filtro por tipo si se proporciona + if type: + query = query.filter(MaterialType.type == type) + items = query.offset(skip).limit(page_size).all() total = query.count() return { diff --git a/frontend/src/lib/api/dashboard/refrence_data/material_types.ts b/frontend/src/lib/api/dashboard/refrence_data/material_types.ts index e9457401..3e9e1671 100644 --- a/frontend/src/lib/api/dashboard/refrence_data/material_types.ts +++ b/frontend/src/lib/api/dashboard/refrence_data/material_types.ts @@ -37,11 +37,20 @@ export const materialTypesApi = { * Lista todos los tipos de material con paginación * @param page - Número de página (por defecto 1) * @param pageSize - Tamaño de página (por defecto 50) + * @param type - Filtrar por tipo (ACTIVO FIJO, MATERIALES, PRODUCTOS) */ - list: (page = 1, pageSize = 50) => - api.get( - `/v1/public/refrence_data/material-types?page=${page}&page_size=${pageSize}` - ), + list: (page = 1, pageSize = 50, type?: string) => { + const params = new URLSearchParams({ + page: page.toString(), + page_size: pageSize.toString() + }); + if (type) { + params.append('type', type); + } + return api.get( + `/v1/public/refrence_data/material-types?${params.toString()}` + ); + }, /** * Obtiene un tipo de material por key From c2d1961994b55ed8f90dd0c78a2214065738a501 Mon Sep 17 00:00:00 2001 From: Galindo97 Date: Fri, 9 Jan 2026 15:38:07 -0600 Subject: [PATCH 2/4] feat: remove unit of measure tables migration script --- ...2e8e8cd3_create_units_of_measure_tables.py | 163 ------------------ 1 file changed, 163 deletions(-) delete mode 100644 backend/alembic/versions/d9b22e8e8cd3_create_units_of_measure_tables.py diff --git a/backend/alembic/versions/d9b22e8e8cd3_create_units_of_measure_tables.py b/backend/alembic/versions/d9b22e8e8cd3_create_units_of_measure_tables.py deleted file mode 100644 index 89113e85..00000000 --- a/backend/alembic/versions/d9b22e8e8cd3_create_units_of_measure_tables.py +++ /dev/null @@ -1,163 +0,0 @@ -"""create_units_of_measure_tables - -Revision ID: d9b22e8e8cd3 -Revises: 7937209f9718 -Create Date: 2026-01-09 14:51:56.669491 - -""" -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision: str = 'd9b22e8e8cd3' -down_revision: Union[str, Sequence[str], None] = '7937209f9718' -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - """Upgrade schema.""" - - # 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('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.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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('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.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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('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.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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=2), nullable=False), - sa.Column('description', sa.String(length=20), nullable=True), - sa.Column('scaii_unit_code', sa.String(length=5), 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.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', 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=5), 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=2), 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(timezone=True), server_default=sa.text('now()'), nullable=True), - sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True), - sa.ForeignKeyConstraint( - ['customs_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_customs.code', 'a76.unit_of_measure_customs.tenant_id', 'a76.unit_of_measure_customs.company_id'], - name='fk_uom_customs' - ), - sa.ForeignKeyConstraint( - ['american_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_american.code', 'a76.unit_of_measure_american.tenant_id', 'a76.unit_of_measure_american.company_id'], - name='fk_uom_american' - ), - sa.ForeignKeyConstraint( - ['ace_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_ace.code', 'a76.unit_of_measure_ace.tenant_id', 'a76.unit_of_measure_ace.company_id'], - name='fk_uom_ace' - ), - sa.ForeignKeyConstraint( - ['oma_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_oma.code', 'a76.unit_of_measure_oma.tenant_id', 'a76.unit_of_measure_oma.company_id'], - 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=5), 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=5), nullable=True), - sa.Column('american_unit_code', sa.String(length=5), nullable=True), - sa.Column('customs_code', sa.String(length=2), 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(timezone=True), server_default=sa.text('now()'), nullable=True), - sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True), - sa.ForeignKeyConstraint( - ['customs_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_customs.code', 'a76.unit_of_measure_customs.tenant_id', 'a76.unit_of_measure_customs.company_id'], - name='fk_uom_general_customs' - ), - sa.ForeignKeyConstraint( - ['ace_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_ace.code', 'a76.unit_of_measure_ace.tenant_id', 'a76.unit_of_measure_ace.company_id'], - name='fk_uom_general_ace' - ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', name='uq_uom_general_code'), - schema='a76' - ) - - -def downgrade() -> None: - """Downgrade schema.""" - 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') From 0aea981cf1c806ea844a25559cb96b189643a12e Mon Sep 17 00:00:00 2001 From: Galindo97 Date: Mon, 12 Jan 2026 10:36:43 -0600 Subject: [PATCH 3/4] feat(api): add Units of Measure API client with CRUD operations - Implemented interfaces for UnitOfMeasure, UnitOfMeasureListResponse, CreateUnitOfMeasureData, and UpdateUnitOfMeasureData. - Added API methods for listing, retrieving, creating, updating, and deleting units of measure. - Included pagination support for the list method. --- ...31bf8cdae06_create_material_types_table.py | 54 +- .../7937209f9718_seed_initial_data.py | 114 +- .../units_of_measure/models.py | 64 +- .../units_of_measure/seed_ace.py | 58 + .../units_of_measure/seed_adua.py | 24 + .../units_of_measure/seed_ame.py | 48 + .../units_of_measure/seed_med.py | 44 + .../units_of_measure/seed_oma.py | 1205 +++++++++++++++++ .../lib/api/dashboard/a76/units_of_measure.ts | 101 ++ .../dashboard/refrence_data/material_types.ts | 10 +- .../goods/classes/create-edit-dialog.svelte | 82 +- .../classes/forms/FixedAssetClassForm.svelte | 36 +- 12 files changed, 1693 insertions(+), 147 deletions(-) create mode 100644 backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_ace.py create mode 100644 backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_adua.py create mode 100644 backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_ame.py create mode 100644 backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_med.py create mode 100644 backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_oma.py create mode 100644 frontend/src/lib/api/dashboard/a76/units_of_measure.ts diff --git a/backend/alembic/versions/531bf8cdae06_create_material_types_table.py b/backend/alembic/versions/531bf8cdae06_create_material_types_table.py index 2629548a..5205a7e2 100644 --- a/backend/alembic/versions/531bf8cdae06_create_material_types_table.py +++ b/backend/alembic/versions/531bf8cdae06_create_material_types_table.py @@ -176,12 +176,10 @@ def upgrade() -> None: 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('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.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', name='uq_uom_ace_code'), + sa.UniqueConstraint('code', name='uq_uom_ace_code'), schema='a76' ) @@ -191,12 +189,10 @@ def upgrade() -> None: 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('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.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', name='uq_uom_oma_code'), + sa.UniqueConstraint('code', name='uq_uom_oma_code'), schema='a76' ) @@ -206,12 +202,10 @@ def upgrade() -> None: 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('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.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', name='uq_uom_american_code'), + sa.UniqueConstraint('code', name='uq_uom_american_code'), schema='a76' ) @@ -219,15 +213,13 @@ def upgrade() -> None: op.create_table( 'unit_of_measure_customs', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('code', sa.String(length=2), nullable=False), - sa.Column('description', sa.String(length=20), nullable=True), + 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('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.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('code', 'tenant_id', 'company_id', name='uq_uom_customs_code'), + sa.UniqueConstraint('code', name='uq_uom_customs_code'), schema='a76' ) @@ -235,10 +227,10 @@ def upgrade() -> None: op.create_table( 'units_of_measure', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('code', sa.String(length=5), 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=2), 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), @@ -247,23 +239,23 @@ def upgrade() -> None: 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', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_customs.code', 'a76.unit_of_measure_customs.tenant_id', 'a76.unit_of_measure_customs.company_id'], + ['customs_code'], + ['a76.unit_of_measure_customs.code'], name='fk_uom_customs' ), sa.ForeignKeyConstraint( - ['american_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_american.code', 'a76.unit_of_measure_american.tenant_id', 'a76.unit_of_measure_american.company_id'], + ['american_code'], + ['a76.unit_of_measure_american.code'], name='fk_uom_american' ), sa.ForeignKeyConstraint( - ['ace_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_ace.code', 'a76.unit_of_measure_ace.tenant_id', 'a76.unit_of_measure_ace.company_id'], + ['ace_code'], + ['a76.unit_of_measure_ace.code'], name='fk_uom_ace' ), sa.ForeignKeyConstraint( - ['oma_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_oma.code', 'a76.unit_of_measure_oma.tenant_id', 'a76.unit_of_measure_oma.company_id'], + ['oma_code'], + ['a76.unit_of_measure_oma.code'], name='fk_uom_oma' ), sa.PrimaryKeyConstraint('id'), @@ -275,25 +267,25 @@ def upgrade() -> None: op.create_table( 'units_of_measure_general', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('code', sa.String(length=5), 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=5), 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=2), 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', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_customs.code', 'a76.unit_of_measure_customs.tenant_id', 'a76.unit_of_measure_customs.company_id'], + ['customs_code'], + ['a76.unit_of_measure_customs.code'], name='fk_uom_general_customs' ), sa.ForeignKeyConstraint( - ['ace_code', 'tenant_id', 'company_id'], - ['a76.unit_of_measure_ace.code', 'a76.unit_of_measure_ace.tenant_id', 'a76.unit_of_measure_ace.company_id'], + ['ace_code'], + ['a76.unit_of_measure_ace.code'], name='fk_uom_general_ace' ), sa.PrimaryKeyConstraint('id'), diff --git a/backend/alembic/versions/7937209f9718_seed_initial_data.py b/backend/alembic/versions/7937209f9718_seed_initial_data.py index 75a6ce9b..46eede98 100644 --- a/backend/alembic/versions/7937209f9718_seed_initial_data.py +++ b/backend/alembic/versions/7937209f9718_seed_initial_data.py @@ -53,7 +53,11 @@ from api.v1.modules.public.reference_data.transport_types.seed import ( 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 import seed as units_of_measure_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 # revision identifiers, used by Alembic. revision: str = "7937209f9718" @@ -64,6 +68,25 @@ 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);") + + # --- UTILIDAD DE FORMATEO --- + def format_value(val): + 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) --- # Seeds values_pc = ", ".join( [ @@ -289,43 +312,72 @@ def upgrade() -> None: """ ) - # Insertar seeds de Unidades de Medida - # Preparar valores únicos para cada tabla auxiliar - ace_codes = set() - oma_codes = set() - american_codes = set() - customs_codes = set() + # --- 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;") + + # 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;") + + # 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;") + + # 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;") + + # 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 ace and ace.strip(): - ace_codes.add(ace.strip()) - if oma and oma.strip(): - oma_codes.add(oma.strip()) - if american and american.strip(): - american_codes.add(american.strip()) - if customs and customs.strip(): - customs_codes.add(customs.strip()) + if customs and customs.strip() and customs not in existing_customs: + 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}')) + if ace and ace.strip() and ace not in existing_ace: + 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}')) - # Insertar seeds (con tenant_id=1, company_id=1 por defecto) - # IMPORTANTE: En producción necesitarás ajustar estos valores + # 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;") - def format_value(val): - """Formatea valores para SQL, manejando None y strings vacíos""" - if not val or val.strip() == '': - return 'NULL' - return f"'{val.replace(chr(39), chr(39)*2)}'" + 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;") - values_uom = ", ".join([ - f"('{code}', {format_value(desc)}, {format_value(desc_en)}, " - f"{format_value(customs)}, {format_value(american)}, " - f"{format_value(ace)}, {format_value(oma)}, 1, 1)" + 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;") + + 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;") + + # 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""" INSERT INTO a76.units_of_measure (code, description, description_en, customs_code, american_code, ace_code, oma_code, tenant_id, company_id) - VALUES {values_uom} + VALUES {val_uom} ON CONFLICT (code, tenant_id, company_id) DO NOTHING; """) @@ -333,6 +385,11 @@ def upgrade() -> None: 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;") @@ -349,4 +406,3 @@ def downgrade() -> None: op.execute("DELETE FROM public.code_pedimento_regimens;") op.execute("DELETE FROM public.pedimento_regimens;") op.execute("DELETE FROM public.pedimento_codes;") - op.execute("DELETE FROM a76.units_of_measure;") diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/models.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/models.py index ffd359db..00fd42ac 100644 --- a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/models.py +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/models.py @@ -8,11 +8,10 @@ from core.database import Base # 1. GUniMedACE -class UnitOfMeasureACE(Base, TenantScopedMixin, TimestampMixin): +class UnitOfMeasureACE(Base, TimestampMixin): __tablename__ = "unit_of_measure_ace" __table_args__ = ( - UniqueConstraint("code", "tenant_id", "company_id", - name="uq_uom_ace_code"), + UniqueConstraint("code", name="uq_uom_ace_code"), {"schema": "a76", "extend_existing": True} ) @@ -25,11 +24,10 @@ class UnitOfMeasureACE(Base, TenantScopedMixin, TimestampMixin): # 2. GUMOMA -class UnitOfMeasureOMA(Base, TenantScopedMixin, TimestampMixin): +class UnitOfMeasureOMA(Base, TimestampMixin): __tablename__ = "unit_of_measure_oma" __table_args__ = ( - UniqueConstraint("code", "tenant_id", "company_id", - name="uq_uom_oma_code"), + UniqueConstraint("code", name="uq_uom_oma_code"), {"schema": "a76", "extend_existing": True} ) @@ -42,11 +40,10 @@ class UnitOfMeasureOMA(Base, TenantScopedMixin, TimestampMixin): # 3. GUMAme -class UnitOfMeasureAmerican(Base, TenantScopedMixin, TimestampMixin): +class UnitOfMeasureAmerican(Base, TimestampMixin): __tablename__ = "unit_of_measure_american" __table_args__ = ( - UniqueConstraint("code", "tenant_id", "company_id", - name="uq_uom_american_code"), + UniqueConstraint("code", name="uq_uom_american_code"), {"schema": "a76", "extend_existing": True} ) @@ -59,19 +56,18 @@ class UnitOfMeasureAmerican(Base, TenantScopedMixin, TimestampMixin): # 4. GUMAduana -class UnitOfMeasureCustoms(Base, TenantScopedMixin, TimestampMixin): +class UnitOfMeasureCustoms(Base, TimestampMixin): __tablename__ = "unit_of_measure_customs" __table_args__ = ( - UniqueConstraint("code", "tenant_id", "company_id", - name="uq_uom_customs_code"), + UniqueConstraint("code", name="uq_uom_customs_code"), {"schema": "a76", "extend_existing": True} ) id: Mapped[int] = mapped_column( Integer, primary_key=True, autoincrement=True) - code: Mapped[str] = mapped_column(String(2), nullable=False) # CLAVE + code: Mapped[str] = mapped_column(String(10), nullable=False) # CLAVE description: Mapped[Optional[str]] = mapped_column( - String(20), nullable=True) + String(50), nullable=True) scaii_unit_code: Mapped[Optional[str]] = mapped_column( String(5), nullable=True) # UNIDADSCAII @@ -84,30 +80,26 @@ class UnitOfMeasure(Base, TenantScopedMixin, TimestampMixin): UniqueConstraint("code", "tenant_id", "company_id", name="uq_uom_code"), ForeignKeyConstraint( - ["customs_code", "tenant_id", "company_id"], - ["a76.unit_of_measure_customs.code", "a76.unit_of_measure_customs.tenant_id", - "a76.unit_of_measure_customs.company_id"], + ["customs_code"], + ["a76.unit_of_measure_customs.code"], use_alter=True, name="fk_uom_customs" ), ForeignKeyConstraint( - ["american_code", "tenant_id", "company_id"], - ["a76.unit_of_measure_american.code", "a76.unit_of_measure_american.tenant_id", - "a76.unit_of_measure_american.company_id"], + ["american_code"], + ["a76.unit_of_measure_american.code"], use_alter=True, name="fk_uom_american" ), ForeignKeyConstraint( - ["ace_code", "tenant_id", "company_id"], - ["a76.unit_of_measure_ace.code", "a76.unit_of_measure_ace.tenant_id", - "a76.unit_of_measure_ace.company_id"], + ["ace_code"], + ["a76.unit_of_measure_ace.code"], use_alter=True, name="fk_uom_ace" ), ForeignKeyConstraint( - ["oma_code", "tenant_id", "company_id"], - ["a76.unit_of_measure_oma.code", "a76.unit_of_measure_oma.tenant_id", - "a76.unit_of_measure_oma.company_id"], + ["oma_code"], + ["a76.unit_of_measure_oma.code"], use_alter=True, name="fk_uom_oma" ), @@ -116,14 +108,14 @@ class UnitOfMeasure(Base, TenantScopedMixin, TimestampMixin): id: Mapped[int] = mapped_column( Integer, primary_key=True, autoincrement=True) - code: Mapped[str] = mapped_column(String(5), nullable=False) # CLAVEUNI + code: Mapped[str] = mapped_column(String(10), nullable=False) # CLAVEUNI 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 + String(10), nullable=True) # CLAVE_AMEX american_code: Mapped[Optional[str]] = mapped_column( String(3), nullable=True) # CLAVE_AAMER ace_code: Mapped[Optional[str]] = mapped_column( @@ -146,16 +138,14 @@ class UnitOfMeasureGeneral(Base, TenantScopedMixin, TimestampMixin): UniqueConstraint("code", "tenant_id", "company_id", name="uq_uom_general_code"), ForeignKeyConstraint( - ["customs_code", "tenant_id", "company_id"], - ["a76.unit_of_measure_customs.code", "a76.unit_of_measure_customs.tenant_id", - "a76.unit_of_measure_customs.company_id"], + ["customs_code"], + ["a76.unit_of_measure_customs.code"], use_alter=True, name="fk_uom_general_customs" ), ForeignKeyConstraint( - ["ace_code", "tenant_id", "company_id"], - ["a76.unit_of_measure_ace.code", "a76.unit_of_measure_ace.tenant_id", - "a76.unit_of_measure_ace.company_id"], + ["ace_code"], + ["a76.unit_of_measure_ace.code"], use_alter=True, name="fk_uom_general_ace" ), @@ -164,19 +154,19 @@ class UnitOfMeasureGeneral(Base, TenantScopedMixin, TimestampMixin): id: Mapped[int] = mapped_column( Integer, primary_key=True, autoincrement=True) - code: Mapped[str] = mapped_column(String(5), nullable=False) # UNIDAD + code: Mapped[str] = mapped_column(String(10), nullable=False) # UNIDAD description: Mapped[Optional[str]] = mapped_column( String(100), nullable=True) conversion_factor: Mapped[Optional[Decimal]] = mapped_column( Numeric(13, 6), nullable=True) mexico_unit: Mapped[Optional[str]] = mapped_column( - String(5), nullable=True) + String(10), 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) customs_code: Mapped[Optional[str]] = mapped_column( - String(2), nullable=True) # CLAVE_ADUANA + String(10), nullable=True) # CLAVE_ADUANA ace_code: Mapped[Optional[str]] = mapped_column( String(4), nullable=True) # CLAVEACE diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_ace.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_ace.py new file mode 100644 index 00000000..37bf24ee --- /dev/null +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_ace.py @@ -0,0 +1,58 @@ +seed = [ + ('BAG', 'Bag'), + ('BBL', 'Barrel'), + ('BDL', 'Bundle'), + ('BIC', 'Bing Chest'), + ('BIN', 'Bin'), + ('BKT', 'Bucket'), + ('BLE', 'Bale'), + ('BLK', 'Bulk'), + ('BOX', 'Box'), + ('BSK', 'Basket'), + ('CAN', 'Can'), + ('CAR', 'Carcass'), + ('CAS', 'Case'), + ('CBC', 'Container Bulk Cargo'), + ('CBY', 'Carboy'), + ('CCS', 'Can Case'), + ('CHS', 'Chest'), + ('COL', 'Coil'), + ('COR', 'Cord'), + ('CRT', 'Crate'), + ('CSK', 'Cask'), + ('CTN', 'Carton'), + ('CYL', 'Cylinder'), + ('DBK', 'Bry Bulk'), + ('DRM', 'Drum'), + ('DZ', 'Dozen'), + ('FT', 'Feet'), + ('GAL', 'Gallon'), + ('HED', 'Heads of Beef'), + ('HMP', 'Hamper'), + ('KEG', 'Keg'), + ('L', 'Liter'), + ('LBK', 'Liquid Bulk'), + ('LOG', 'Logs'), + ('LUG', 'Lugs'), + ('LVN', 'Lift Van'), + ('M', 'Meters'), + ('PAA', 'Pairs'), + ('PAL', 'Pail'), + ('PCL', 'Parcel'), + ('PCS', 'Pieces'), + ('PKG', 'Package'), + ('POV', 'Private Vehicle'), + ('QTR', 'Quarters of Beef'), + ('REL', 'Reel'), + ('ROL', 'Roll'), + ('SAK', 'Sack'), + ('SFT', 'Square Feet'), + ('SHT', 'Sheet'), + ('SID', 'Sides of Beef'), + ('SKD', 'Skid'), + ('TBE', 'Tube'), + ('TBN', 'Tote Bin'), + ('TIN', 'Tin'), + ('TNK', 'Tank'), + ('UNT', 'Unit'), +] diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_adua.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_adua.py new file mode 100644 index 00000000..080b71e4 --- /dev/null +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_adua.py @@ -0,0 +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'), +] \ No newline at end of file diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_ame.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_ame.py new file mode 100644 index 00000000..c7d844af --- /dev/null +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_ame.py @@ -0,0 +1,48 @@ + +seed = [ + ('BBL', 'Barrels (42 Gallons ea) (Volume)'), + ('BOL', 'Boluses (Dosage)'), + ('CAP', 'Capsules (Dosage)'), + ('CAR', 'Carats (Weight)'), + ('CFT', 'Cubic Feet (Volume)'), + ('CGI', 'Centigrams (Weight)'), + ('CM', 'Centimeters (Long)'), + ('CM3', 'Cubic Centimeters (Volume)'), + ('CYD', 'Cubic Yards (Volume)'), + ('DOZ', 'Dozen (Count)'), + ('DPC', 'Dozen Pieces (Count)'), + ('DPR', 'Dozen Pairs (Count)'), + ('FOZ', 'Ounces, fluid (Volume)'), + ('FT', 'Feet (Length)'), + ('G', 'Grams (Weight)'), + ('GAL', 'Gallons (US)(Volume)'), + ('GR', 'Gross (Count)'), + ('KG2', 'Kilograms (Weight)'), + ('KM', 'Kilometers (Length)'), + ('KM2', '1000 sq Meter Area'), + ('KM3', '1,000 Cubic Meters (Volume)'), + ('L', 'Liters (Volume)'), + ('LB', 'Pounds (Weight)'), + ('LNM', 'Linear Meters (Length)'), + ('M', 'Meters (Length)'), + ('M2', 'SQ Meter (Area)'), + ('M3', 'Cubic Meters (Volume)'), + ('MG', 'Miligrams (Weight)'), + ('ML', 'Milliliters (Volume)'), + ('NO', 'Number (Count)'), + ('OZ', 'Weight'), + ('PCS', 'Pieces (Count)'), + ('PRS', 'Pairs (Count)'), + ('PTL', 'Pints, liquid (US)(Volume)'), + ('QTL', 'Quarts, liquid (US)(Volume)'), + ('SFT', 'SQ Feet (Area)'), + ('SQI', 'Sq Inches (Area)'), + ('STN', 'Short Ion (2000 LB)(Weight)'), + ('SUP', 'Suppositories (Dosage)'), + ('SYD', 'Sq. Yards (Area)'), + ('T', 'Metric Ton (Weight)'), + ('TAB', 'Tablets (Dosage)'), + ('TON', 'Long Ton (2,240 LB) (Weight)'), + ('TOZ', 'Ounces, Troy or Apoth (Weight)'), + ('YD', 'Yards (Length)'), +] \ No newline at end of file diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_med.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_med.py new file mode 100644 index 00000000..75131b93 --- /dev/null +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_med.py @@ -0,0 +1,44 @@ +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', ''), +] \ No newline at end of file diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_oma.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_oma.py new file mode 100644 index 00000000..3a783b2d --- /dev/null +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/seed_oma.py @@ -0,0 +1,1205 @@ +seed = [ + ('05', 'LIFT'), + ('06', 'SMALL SPRAY'), + ('08', 'HEAT LOT'), + ('10_1', 'GROUP'), + ('11_1', 'OUTFIT'), + ('13_1', 'RATION'), + ('14_1', 'SHOT'), + ('15_1', 'STICK, MILITARY'), + ('16_1', 'HUNDRED FIFTEEN KG DRUM'), + ('17_1', 'HUNDRED LB DRUM'), + ('18_1', 'FIFTYFIVE GALLON (US) DRUM'), + ('19_1', 'TANK TRUCK'), + ('1A', 'CAR MILE'), + ('1B', 'CAR COUNT'), + ('1C', 'LOCOMOTIVE COUNT'), + ('1D', 'CABOOSE COUNT'), + ('1E', 'EMPY CAR'), + ('1F', 'TRAIN MILE'), + ('1G', 'FUEL USAGE GALLON (US)'), + ('1H', 'CABOOSE MILE'), + ('1I', 'FIXED RATE'), + ('1J', 'TON MILE'), + ('1K', 'LOCOMOTIVE MILE'), + ('1L', 'TOTAL CAR COUNT'), + ('1X', 'QUARTER MILE'), + ('20_1', 'TWENTY FOOT CONTAINER'), + ('21_1', 'FORTY FOOT CONTAINER'), + ('22', 'DECILITRE PER GRAM'), + ('23', 'GRAM PER CUBIC CENTIMETRE'), + ('24', 'THEORETICAL POUND'), + ('25', 'GRAM PER SQUARE CENTIMETRE'), + ('26', 'ACUAL TON'), + ('27', 'THEORETICAL TON'), + ('28', 'KILOGRAM PER SQUARE METRE'), + ('29', 'PUND PER THOUSAND SQUARE FEET'), + ('2A', 'RADIAN PER SECOND'), + ('2B', 'RADIAN PER SECOND SQUARED'), + ('2C', 'ROENTGEN'), + ('2I', 'BRITISH THERMAL UNIT PER HOUR'), + ('2J', 'CUBIC CENTIMETRE PER SECOND'), + ('2K', 'CUBIC FOOT PER HOUR'), + ('2L', 'CUBIC FOOT PER MINUTE'), + ('2M', 'CENTIMETRE PER SECOND'), + ('2N', 'DECIBEL'), + ('2P', 'KILOBYTE'), + ('2Q', 'KILOBECQUEREL'), + ('2R', 'KILOCURIE'), + ('2U', 'MEGAGRAM'), + ('2V', 'MEGAGRAM PER HOUR'), + ('2W', 'BIN'), + ('2X', 'METRE PER MINUTE'), + ('2Y', 'MILLIRÖNTGEN'), + ('2Z', 'MILLIVOLT'), + ('30', 'HORSE POWER DAR PER AIR DRY METRIC TON'), + ('31', 'CATCH WEIGHT'), + ('32', 'KILOGRAM PER AIR DRY METRIC TON'), + ('33', 'KILOPASCAL SQUARE METRES PER GRAM'), + ('34', 'KILOPASCALS PER MILLIMETRE'), + ('35', 'MILLILITRES PER SQUARE CENTIMETRE SECOND'), + ('36', 'CUBIC FEET PER MINUTE PER SQUARE FOOT'), + ('37', 'OUNCE PER SQUARE FOOT'), + ('38', 'OUNCES PER SQUARE FOOT PER 0, 01 INCH'), + ('3B', 'MEGAJOULE'), + ('3C', 'MANMONTH'), + ('3E', 'PUND PER PUND OF PRODUCT'), + ('3G', 'POUND PER PIECE OF PRODUCT'), + ('3H', 'KILOGRAM PER KILOGRAM OF PRODUCT'), + ('3I', 'KILOGRAM PER PIECE OF PRODUCT'), + ('40', 'MILLILITRE PER SECOND'), + ('41', 'MILLILITRE PER MINUTE'), + ('43', 'SUPER BULK BAG'), + ('44', 'FIVEHUNDRED KG BULK BAG'), + ('45', 'THREEHUNDRED KG BULK BAG'), + ('46', 'FIFTY BULK BAG'), + ('47', 'FIFTY LB BAG'), + ('48', 'BULK CAR LOAD'), + ('4A', 'BOBBIN'), + ('4B', 'CAP'), + ('4C', 'CENTISTOKES'), + ('4E', 'TWENTY PACK'), + ('4G', 'MICROLITRE'), + ('4H', 'MICROMETRE (MICRON)'), + ('4K', 'MILLIAMPERE'), + ('4L', 'MEGABYTE'), + ('4M', 'MILLIGRAM PER HOUR'), + ('4N', 'MEGABECQUEREL'), + ('4O', 'MICROFARAD'), + ('4P', 'NEWTON PER METRE'), + ('4Q', 'OUNCE INCHE'), + ('4R', 'OUNCE FOOT'), + ('4T', 'PICOFARAD'), + ('4U', 'PUND PER HOUR'), + ('4W', 'TON (US) PER HOUR'), + ('4X', 'KILOLITRE PER HOUR'), + ('53', 'THEORETICAL KILOGRAMS'), + ('54', 'THEORETICAL TONNE'), + ('56', 'SITAS'), + ('57', 'MESH'), + ('58', 'NET KILOGRAM'), + ('59', 'PART PER MILLION'), + ('5A', 'BARREL (US) PER MINUTE'), + ('5B', 'BATCH'), + ('5C', 'GALLON (US) PER THOUSAND'), + ('5E', 'MMSCF/DAY'), + ('5F', 'POUNDS PER THOUSAND'), + ('5G', 'PUMP'), + ('5H', 'STAGE'), + ('5I', 'STANDARD CUBIC FOOT'), + ('5J', 'HYDRAULIC HORSE POWER'), + ('5K', 'COUNT PER MINUTE'), + ('5P', 'SEISMIC LEVEL'), + ('5Q', 'SEISMIC LINE'), + ('60', 'PERCEN WEIGHT'), + ('61', 'PART PER BILLION (US)'), + ('62', 'PERCENT PER 1000 HOUR'), + ('63', 'FAILURE RATE IN TIME'), + ('64', 'POUND PER SQUARE INCH, GAUGE'), + ('66', 'OERSTED'), + ('69', 'TEST SPECIFIC SCALE'), + ('71', 'VOLT AMPERE PER PUND'), + ('72', 'WATT PER POUND'), + ('73', 'AMPERE TUM PER CENTIMETRE'), + ('74', 'MILLIPASCAL'), + ('76', 'GAUSS'), + ('77', 'MILLI-INCH'), + ('78', 'KILOGAUSS'), + ('80', 'POUNDS PER SAUQRE INCHE ABSOULTE'), + ('81', 'HENRY'), + ('84', 'KILOPOUND PER SQUARE INCH'), + ('85', 'FOOT POUND-FORCE'), + ('87', 'POUND PER CUBIC FOOT'), + ('89', 'POISE'), + ('90', 'SAYBOLD UNIVERSAL SECOND'), + ('91', 'STOKES'), + ('92', 'CALORIE PER CUBIC CENTIMETRE'), + ('93', 'CALORIE PER GRAM'), + ('94', 'CURL UNIT'), + ('95', 'TWENTY THOUSAND GALLON (US) TANKCAR'), + ('96', 'TEN THOUSAND GALLON (US) TANKCAR'), + ('97', 'TEN KG DRUM'), + ('98', 'FIFTEEN KG DRUM'), + ('A1', '15° C CALORIE'), + ('A10', 'AMPERE SQUARE METRE PER JOULE SECOND'), + ('A11', 'ANGSTROM'), + ('A12', 'ASTRONOMICAL UNIT'), + ('A13', 'ATTOJOULE'), + ('A14', 'BARN'), + ('A15', 'BARN PER ELECTRON VOLT'), + ('A16', 'BARN PER STERADIAN ELECTRONVOLT'), + ('A17', 'BARN PER STERADIAN'), + ('A18', 'BECQUEREL PER KILOGRAM'), + ('A19', 'BECQUEREL PER METRE CUBED'), + ('A2', 'AMPERE PER CENTIMETRE'), + ('A20', 'BRITISH THERMAL UNIT PER SECOND SQUARE FOOT DEGREE RANKIN'), + ('A21', 'BRITISH THERMAL UNIT PER POUND DEGREE RANKIN'), + ('A22', 'BRITISH THERMAL UNIT PER SECOND FOOT DEGREE RANKIN'), + ('A23', 'BRITHIS THERMAL UNIT PER HOUR SQUARE FOOT DEGREE RANKIN'), + ('A24', 'CANDELA PER SQUARE METRE'), + ('A25', 'CHEVAL VAPEUR'), + ('A26', 'COULOMB METRE'), + ('A27', 'COULOMB METRE SQUARED PER VOLT'), + ('A28', 'COULOMB PER CUBIC CENTIMETRE'), + ('A29', 'COULOMB PER CUBIC METRE'), + ('A3', 'AMPERE PER MILLIMETRE'), + ('A30', 'COULOMB PER CUBIC MILLIMETRE'), + ('A31', 'COULOMB PER KILOGRAM SECOND'), + ('A32', 'COULOMB PER MOLE'), + ('A33', 'COULOMB PER SQUARE CENTIMETRE'), + ('A34', 'COULOMB PER SQUARE METRE'), + ('A35', 'COULOMB PER SQUARE MILLIMETRE'), + ('A36', 'CUBIC CENTIMETRE PER MOLE'), + ('A37', 'CUBIC DECIMETRE PER MOLE'), + ('A38', 'CUBIC METRE PER COULOMB'), + ('A39', 'CUBIC METRE PER KILOGRAM'), + ('A4', 'AMPERE PER SQURE CENTRIMETRE'), + ('A40', 'CUBIC METRE PER MOLE'), + ('A41', 'AMPERE PER SQUARE METRE'), + ('A42', 'CURIE PER KILOGRAM'), + ('A43', 'DEADWEIGHT TONNAGE'), + ('A44', 'DECALITRE'), + ('A45', 'DECAMETRE'), + ('A47', 'DECITEX'), + ('A48', 'DEGREE RANKIN'), + ('A49', 'DENIER'), + ('A5', 'AMPERE SQUARE METRE'), + ('A50', 'DYNE SECOND PER CUBIC CENTIMETRE'), + ('A51', 'DYNE SECOND PER CENTIMETRE'), + ('A52', 'DYNE SECOND PER CENTIMETRE TO THE FIFTH POWER'), + ('A53', 'ELECTRONVOLT'), + ('A54', 'ELECTRONVOLT PER METRE'), + ('A55', 'ELECTRONVOLT SQUARE METRE'), + ('A56', 'ELECTRONVOLT SQUARE METRE PER KILOGRAM'), + ('A57', 'ERG'), + ('A58', 'ERG PER CENTIMETRE'), + ('A59', '8-PART CLOUD COVER'), + ('A6', 'AMPERE PER SQUARE METRE KELVIN SQUARED'), + ('A60', 'ERG PER CUBIC CENTIMETRE'), + ('A61', 'ERG PER GRAM'), + ('A62', 'ERG PER GRAM SECOND'), + ('A63', 'ERG PER SECOND'), + ('A64', 'ERG PER SECOND SQUARE CENTIMETRE'), + ('A65', 'ERG PER SQUARE CENTIMETRE SECOND'), + ('A66', 'ERG SQUARE CENTIMETRE'), + ('A67', 'ERG SQTUARE CENTIMETRE PER GRAM'), + ('A68', 'EXAJOULE'), + ('A69', 'FARAD PER METRE'), + ('A7', 'AMPERE PER SQUARE MILLIMETRE'), + ('A70', 'FEMTOJOULE'), + ('A71', 'FEMTOMETRE'), + ('A73', 'FOOT PER SECOND SQUARED'), + ('A74', 'FOOT POUND-FORCE PER SECOND'), + ('A75', 'FREIGHT TON'), + ('A76', 'GALLON (US) PER THOUSAND'), + ('A77', 'GAUSSIAN CGS UNIT OF DISPLACEMENT'), + ('A78', 'GAUSSIAN CGS UNIT OF ELECTRIC CURRENT'), + ('A79', 'GAUSSIAN CGS UNIT OF ELECTRIC CHARGE'), + ('A8', 'AMPERE SECOND'), + ('A80', 'GAUSSIAN CGS UNIT OF ELECTRIC FIELD STRENGHT'), + ('A81', 'GAUSSIAN CGS UNIT OF ELECTRIC POLARIZATION'), + ('A82', 'GAUSSIAN CGS UNIT OF ELECTRIC POTENCIAL'), + ('A83', 'GAUSSIAN CGS UNIT OF MAGNETIZATION'), + ('A84', 'GIGACOULOMB PER CUBIC METRE'), + ('A85', 'GIGAELECTRONVOLT'), + ('A86', 'GIGAHERTZ'), + ('A87', 'GIGAOHM'), + ('A88', 'GIGAOHM METRE'), + ('A89', 'GIGAPASCAL'), + ('A9', 'RATE'), + ('A90', 'GIGAWATT'), + ('A91', 'GON'), + ('A92', 'GRADE'), + ('A93', 'GRAM PER CUBIC METRE'), + ('A94', 'GRAM PER MOLE'), + ('A95', 'GRAY'), + ('A96', 'GRAY PER SECOND'), + ('A97', 'HECTOPASCAL'), + ('A98', 'HENRY PER METRE'), + ('A99', 'BIT'), + ('AA', 'BALL'), + ('AB', 'BULK PACK'), + ('ACR', 'ACRE'), + ('ACT', 'ACTIVITY'), + ('AD', 'BYTE'), + ('AE', 'AMPERE PER METRE'), + ('AH', 'ADDITIONAL MINUTE'), + ('AI', 'AVERAGE MINUTE PER CALL'), + ('AJ', 'COP'), + ('AK', 'FATHOM'), + ('AL', 'ACCESS LINE'), + ('AM', 'AMPOULE'), + ('AMH', 'APERE HOUR'), + ('AMP', 'AMPERE'), + ('ANN', 'YEAR'), + ('AP', 'ALUMINUM POUND ONLY'), + ('APZ', 'TROY OUNCE OT APOTHECARY OUNCE'), + ('AQ', 'ANTI-HEMOPHILIC FACTOR (AHF) UNIT'), + ('AR', 'SUPPOSITORY'), + ('ARE', 'ARE'), + ('AS', 'ASSORTMENT'), + ('ASM', 'ALCOHOLIC STRENGHT BY MASS'), + ('ASU', 'ALCOHOLIC STRENGHT BY VOLUME'), + ('ATM', 'STANDARD ATMOSPHERE'), + ('ATT', 'TECHNICAL ATMOSPHERE'), + ('AV', 'CAPSULE'), + ('AW', 'POWDER FILLED VIAL'), + ('AY', 'ASSEMBLY'), + ('AZ', 'BRITHIS THERMAL UNIT PER POUND'), + ('B0', 'BTU PER CUBIC FOOT'), + ('B1', 'BARREL (US) PER DAY'), + ('B10', 'BIT PER SECOND'), + ('B11', 'JOULE PER KILOGRAM KELVIN'), + ('B12', 'JOULE PER METRE'), + ('B13', 'JOULE PER METRE SQUARED'), + ('B13_1', 'JOULE PER SQUARE METRE'), + ('B14', 'JOULE PER METRE TO THE FOURTH POWER'), + ('B15', 'JOULE PER MOLE'), + ('B16', 'JOULE PER MOLE KELVIN'), + ('B17', 'CREDIT'), + ('B18', 'JOULE SECOND'), + ('B19', 'DIGIT'), + ('B2', 'BUNK'), + ('B20', 'JOULE SQUARE METRE PER KILOGRAM'), + ('B21', 'KELVIN PER WATT'), + ('B22', 'KILOAMPERE'), + ('B23', 'KILOAMPERE PER SQUARE METRE'), + ('B24', 'KILOAMPERE PER METRE'), + ('B25', 'KILOBECQUEREL PER KILOGRAM'), + ('B26', 'KILOCOULOMB'), + ('B27', 'KILOCOULOMB PER CUBIC METRE'), + ('B28', 'KILOCOULOMB PER SQUARE METRE'), + ('B29', 'KILOELECTRONVOLT'), + ('B3', 'BATTIN POUND'), + ('B30', 'GIDIBIT'), + ('B31', 'KILOGRAM METRE PER SECOND'), + ('B32', 'KILOGRAM METRE SQUARED'), + ('B33', 'KILOGRAM METRE SQUARED PER SECOND'), + ('B34', 'KILOGRAM PER CUBIC DECIMETRE'), + ('B35', 'KILOGRAM PER LITRE'), + ('B35_1', 'KILOGRAM PER LITRE OF PRODUCT'), + ('B36', 'THERMOCHEMICAL CALORIE PER GRAM'), + ('B37', 'KILOGRAM-FORCE'), + ('B38', 'KILOGRAM-FORCE METRE'), + ('B39', 'KILOGRAM-FORCE METRE PER SECOND'), + ('B4', 'BARREL, IMPERIAL'), + ('B40', 'KILOGRAM-FORCE PER SQUARE METRE'), + ('B41', 'KILOJOULE PER KELVIN'), + ('B42', 'KILOJOULE PER KILOGRAM'), + ('B43', 'KILOJOULE PER KILOGRAM KELVIN'), + ('B44', 'KILOJOULE PER MOLE'), + ('B45', 'KILOMOLE'), + ('B46', 'KILOMOLE PER CUBIC METRE'), + ('B47', 'KILONEWTON'), + ('B48', 'KILONEWTON METRE'), + ('B49', 'KILOOHM'), + ('B5', 'BILLET'), + ('B50', 'KILOOHM METRE'), + ('B51', 'KILOPOND'), + ('B52', 'KILOSECOND'), + ('B53', 'KILOSIEMENS'), + ('B54', 'KILOSIEMENS PE RMETRE'), + ('B55', 'KILOVOLT PER METRE'), + ('B56', 'KILOWEBER PER METRE'), + ('B57', 'LIGHT YEAR'), + ('B58', 'LITRE PER MOLE'), + ('B59', 'LUMEN HOUR'), + ('B6', 'BUNK'), + ('B60', 'LUMEN PER SQUARE METRE'), + ('B61', 'LUMEN PER WATT'), + ('B62', 'LUMEN SECOND'), + ('B63', 'LUX HOUR'), + ('B64', 'LUX SECOND'), + ('B65', 'MAXWELL'), + ('B66', 'MEGAAMPERE PER SQUARE METRE'), + ('B67', 'MEGABECQUEREL PER KILOGRAM'), + ('B68', 'GIGABIT'), + ('B7', 'CYCLE'), + ('B70', 'MEGACOULOMB PER SQUARE METRE'), + ('B71', 'MEGAELECTRONVOLT'), + ('B72', 'MEGAGRAM PER CUBIC METRE'), + ('B73', 'MEGANEWTON'), + ('B74', 'MEGANEWTON METRE'), + ('B75', 'MEGAOHM'), + ('B76', 'MEGAOHM METRE'), + ('B77', 'MEGASIEMENS PER METRE'), + ('B78', 'MEGAVOLT'), + ('B79', 'MEGAVOLT PER METRE'), + ('B8', 'JOULE PER CUBIC METRE'), + ('B80', 'GIGABIT PER SECOND'), + ('B81', 'RECIPROCAL METRE SQUARED RECIPROCAL SECOND'), + ('B82', 'INCHE PER LINEAR FOOT'), + ('B83', 'METRE TO THE FOURTH POWER'), + ('B84', 'MICROAMPERE'), + ('B85', 'MICROBAR'), + ('B86', 'MICROCOULOMB'), + ('B87', 'MICROCOULOMB PER CUBIC METRE'), + ('B88', 'MICROCOULOMB PER SQUARE METRE'), + ('B89', 'MICROFARAD PER METRE'), + ('B9', 'BATTIN POUND'), + ('B90', 'MICROHENRY'), + ('B91', 'MICROHENRY PER METRE'), + ('B92', 'MICRONEWTON'), + ('B93', 'MICRONEWTON METRE'), + ('B94', 'MIOCROOHM'), + ('B95', 'MICROOHM METRE'), + ('B96', 'MICROPASCAL'), + ('B97', 'MICRORADIAN'), + ('B98', 'MICROSECOND'), + ('B99', 'MICROSIEMENS'), + ('BAR', 'BAR [UNIT OF PRESSURE]'), + ('BB', 'BASE BOX'), + ('BD', 'BOARD'), + ('BE', 'BUNDLE'), + ('BFT', 'BOARD FOOT'), + ('BG', 'BAG'), + ('BH', 'BRUSH'), + ('BHP', 'BRAKE HORSE POWER'), + ('BIL_EUR', 'BILLION (EUR)'), + ('BIL_US', 'TRILLION (US)'), + ('BJ', 'BUCKET'), + ('BK', 'BASKET'), + ('BL', 'BALE'), + ('BLD', 'DRY BARREL (S)'), + ('BLL', 'BARREL (US)'), + ('BO', 'BOTTLE'), + ('BP', 'HUNDRED BOARD FEET'), + ('BQL', 'BECQUEREL'), + ('BR', 'BAR [UNIT OF PACKAGING]'), + ('BT', 'BOLT'), + ('BTU', 'BRITISH THERMAL UNIT'), + ('BUA', 'BUSHEL (US)'), + ('BUI', 'BUSHEL (UK)'), + ('BW', 'BASE WEIGHT'), + ('BX', 'BOX'), + ('BZ', 'MILLION BTUS'), + ('C0', 'CALL'), + ('C1', 'COMPOSITE PRODUCT POUND (TOTAL WEIGHT)'), + ('C10', 'MILLIFARAD'), + ('C10_1', 'MILLIVOLT PER METRE'), + ('C11', 'MILLIGAL'), + ('C12', 'MILLIGRAM PER METRE'), + ('C13', 'MILLIGRAY'), + ('C14', 'MILLIHENRY'), + ('C15', 'MILLIJOULE'), + ('C16', 'MILLIMETRE PER SECOND'), + ('C17', 'MILLIMETRE SQUARED PER SECOND'), + ('C18', 'MILLIMOLE'), + ('C19', 'MOLE PER KILOGRAM'), + ('C2', 'CARSET'), + ('C20', 'MILLNEWTON'), + ('C21', 'KIBIBIT'), + ('C22', 'MILLINEWTON PER METRE'), + ('C23', 'MILLIOHM METRE'), + ('C24', 'MILLIPASCAL SECOND'), + ('C25', 'MILLIRADIAN'), + ('C26', 'MILLISECOND'), + ('C27', 'MILLISIEMENS'), + ('C28', 'MILLISIEVERT'), + ('C29', 'MILLITESLA'), + ('C3', 'MICROVOLT PER METRE'), + ('C31', 'MILLIWATT'), + ('C32', 'MILLIWATT PER SQUARE METRE'), + ('C33', 'MILLIWEBER'), + ('C34', 'MOLE'), + ('C35', 'MOLE PER CUBIC DECIMETRE'), + ('C36', 'MOLE PER CUBIC METRE'), + ('C37', 'KILOBIT'), + ('C38', 'MOLE PER LITRE'), + ('C39', 'NANOAMPERE'), + ('C4', 'CARLOAD'), + ('C40', 'NANOCOULOMB'), + ('C41', 'NANOFARAD'), + ('C42', 'NANOFARAD PER METRE'), + ('C43', 'NANOHENRY'), + ('C44', 'NANOHENRY PER METRE'), + ('C45', 'NANOMETRE'), + ('C46', 'NANOOHM METRE'), + ('C47', 'NANOSECOND'), + ('C48', 'NANOTESLA'), + ('C49', 'NANOWATT'), + ('C5', 'COST'), + ('C50', 'NEPER'), + ('C51', 'NEPER PER SECOND'), + ('C52', 'PICOMETRE'), + ('C53', 'NEWTON METRE SECOND'), + ('C54', 'NEWTON METRE SQUARED KILOGRAM SQUARED'), + ('C55', 'NEWTON PER SQUARE METRE'), + ('C56', 'NEWTON PER SQUARE MILLIMETRE'), + ('C57', 'NEWTON SECOND'), + ('C58', 'NEWTON SECOND PER METRE'), + ('C59', 'OCTAVE'), + ('C6', 'CELL'), + ('C60', 'OHM CENTIMETRE'), + ('C61', 'OHM METRE'), + ('C62', 'ONE'), + ('C62_1', 'PIECE'), + ('C62_2', 'UNIT'), + ('C63', 'PARSEC'), + ('C64', 'PASCAL PER KELVIN'), + ('C65', 'PASCAL PER SECOND'), + ('C66', 'PASCAL SECOND PER CUBIC METRE'), + ('C67', 'PASCAL SECOND PER METRE'), + ('C68', 'PETAJOULE'), + ('C69', 'PHON'), + ('C7', 'CENTIPOISE'), + ('C70', 'PICOAMPERE'), + ('C71', 'PICOCOULOMB'), + ('C72', 'PICOFARAD PER METRE'), + ('C73', 'PICOHENRY'), + ('C74', 'KILOBIT PER SECOND'), + ('C75', 'PICOWATT'), + ('C76', 'PICOWATT PER SQUARE METRE'), + ('C77', 'PUND PAGE'), + ('C78', 'PUND-FORCE'), + ('C79', 'KILOVOLT AMPERE HOUR'), + ('C8', 'MILLICOULOMB PER KILOGRAM'), + ('C80', 'RAD'), + ('C81', 'RADIAN'), + ('C82', 'RADIAN SQUARE METRE PER MOLE'), + ('C83', 'RADIAN SQUARE METRE PER KILOGRAM'), + ('C84', 'RADIAN PER METRE'), + ('C85', 'RECIPROCAL ANGSTROM'), + ('C86', 'RECIPROCAL CUBIC METRE'), + ('C87', 'RECIPROCAL CUBIC METRE PER SECOND'), + ('C88', 'RECIPROCAL ELECTRON VOLT PER CUBIC METRE'), + ('C89', 'RECIPROCAL HENRY'), + ('C9', 'COIL GROUP'), + ('C90', 'RECIPROCAL JOUL EPER CUBIC METRE'), + ('C91', 'RECIPROCAL KELVIN OR KELVIN TO THE POWER MINUS ONE'), + ('C92', 'RECIPROCAL METRE'), + ('C93', 'RECIPROCAL METRE SQUARED'), + ('C93_1', 'RECIPROCAL SQUARED METRE'), + ('C94', 'RECIPROCAL MINUTE'), + ('C95', 'RECIPROCAL MOLE'), + ('C96', 'RECIPROCAL PASCAL OR PASCAL TO THE POWER MINUS ONE'), + ('C97', 'RECIPROCAL SECOND'), + ('C98', 'RECIPROCAL SECOND PER CUBIC METRE'), + ('C99', 'RECIPROCAL SECOND PER METRE SQUARED'), + ('CA', 'CAN'), + ('CCT', 'CARRYING CAPACITY IN METRIC TON'), + ('CDL', 'CANDELA'), + ('CEL', 'DEGREE CELSIUS'), + ('CEN', 'HUNDRED'), + ('CG', 'CARD'), + ('CGM', 'CENTIGRAM'), + ('CH', 'CONTAINER'), + ('CJ', 'CONE'), + ('CK', 'CONNECTOR'), + ('CKG', 'COULOMB PER KILOGRAM'), + ('CL', 'COIL'), + ('CLF', 'HUNDRED LEAVE'), + ('CLT', 'CENTILITRE'), + ('CMK', 'SQUARE CENTIMETRE'), + ('CMQ', 'CUBIC CENTRIMETRE'), + ('CMT', 'CENTIMETRE'), + ('CNP', 'HUNDRED PACK'), + ('CNT', 'CENTAL (UK)'), + ('CO', 'CARBOY'), + ('COU', 'COULOMB'), + ('CQ', 'CARTRIDGE'), + ('CR', 'CRATE'), + ('CS', 'CASE'), + ('CT', 'CARTON'), + ('CTG', 'CONTENT GRAM'), + ('CTM', 'METRIC CARAT'), + ('CTN', 'CONTENT TON (METRIC)'), + ('CU', 'CUP'), + ('CUR', 'CURIE'), + ('CV', 'COVER'), + ('CWA', 'HUNDRED POUNDS (CWT)/HUNDRED WEIGHT (US)'), + ('CWI', 'HUNDRED WEIGHT (UK)'), + ('CY', 'CYLINDER'), + ('CZ', 'COMBO'), + ('D03', 'KILOWATT HOUR PER HOUR'), + ('D04', 'LOT [UNIT OF WEIGHT]'), + ('D1', 'RECIPROCAL SECOND PER STERADIAN'), + ('D10', 'SIEMENS PER METRE'), + ('D11', 'MEBIBIT'), + ('D12', 'SIEMENS SQUARE METRE PER MOLE'), + ('D13', 'SIEVERT'), + ('D14', 'THOUSAND LINEAR YARD'), + ('D15', 'SONE'), + ('D16', 'SQUARE CENTIMETRE PER ERG'), + ('D17', 'SQUARE CENTIMETRE PER STERADIAN ERG'), + ('D18', 'METRE KELVIN'), + ('D19', 'SQUARE METRE KELVIN PER WATT'), + ('D2', 'RECIPROCAL SECOND PER STERADIAN METRE SQUARED'), + ('D20', 'SQUARE METRE PER JOULE'), + ('D21', 'SQUARE METRE PER KILOGRAM'), + ('D22', 'SQUARE METRE PER MOLE'), + ('D23', 'PEN GRAM (PROTEIN)'), + ('D24', 'SQUARE METRE PER STERADIAN'), + ('D25', 'SQUARE METRE PER STERADIAN JOULE'), + ('D26', 'SQUARE METRE PER VOLT SECOND'), + ('D27', 'STERADIAN'), + ('D28', 'SYPHON'), + ('D29', 'TERAHERTZ'), + ('D30', 'TERAJOULE'), + ('D31', 'TERAWATT'), + ('D32', 'TERAWATT HOUR'), + ('D33', 'TESLA'), + ('D34', 'TEX'), + ('D35', 'THERMOCHEMICAL CALORIE'), + ('D36', 'MEGABIT'), + ('D37', 'THERMOCHEMICAL CALORIE PER GRAM KELVIN'), + ('D38', 'THERMOCHEMICAL CALORIE PER SECOND CENTIMETRE KELVIN'), + ('D39', 'THERMOCHEMICAL CALORIE PER SECOND SQAURE CENTIMETRE KELVIN'), + ('D40', 'THOUSAND LITRE'), + ('D41', 'TONNE PER CUBIC METRE'), + ('D42', 'TROPICAL YEAR'), + ('D43', 'UNIFIED ATOMIC MASS UNIT'), + ('D44', 'VAR'), + ('D45', 'VOLT SQUARED PER KELVIN SQUARED'), + ('D46', 'VOLT-AMPERE'), + ('D47', 'VOLT PER CENTIMETRE'), + ('D48', 'VOLT PER KELVIN'), + ('D49', 'MILIVOLT PER KELVIN'), + ('D5', 'KILOGRAM PER SQUARE CENTIMETRE'), + ('D50', 'VOLT PER METRE'), + ('D51', 'VOLT PER MILLIMETRE'), + ('D52', 'WATT PER KELVIN'), + ('D53', 'WAT PER METRE KELVIN'), + ('D54', 'WATT PER SQUARE METRE'), + ('D55', 'WATT PER SQUARE METRE KELVIN'), + ('D56', 'WATT PER SQUARE METRE KELVIN TO THE FOURTH POWER'), + ('D57', 'WATT PER STERADIAN'), + ('D58', 'WATT PER STERADIAN SQUARE METRE'), + ('D59', 'WEBER PER METRE'), + ('D6', 'ROENTGEN PER SECOND'), + ('D60', 'WEBER PER MILLIMETRE'), + ('D61', 'MINUTE [UNIT OF ANGLE]'), + ('D62', 'SECOND [UNIT OF ANGLE]'), + ('D63', 'BOOK'), + ('D64', 'BLOCK'), + ('D65', 'ROUND'), + ('D66', 'CASSETTE'), + ('D67', 'DOLLAR PER HOUR'), + ('D68', 'NUMBER OF WORDS'), + ('D69', 'INCH TO THE FOURTH POWER'), + ('D7', 'SANDWICH'), + ('D70', 'INTERNATIONAL TABLE (IT) CALORIE)'), + ('D71', 'INTERNATIONAL TABLE (IT) CALORIE PER SECOND CENTIMETRE KELVIN'), + ('D72', 'INTERNATIONAL TABLE (IT) CALORIE PER SECOND SQUARE CENTIMETRE KELVIN'), + ('D73', 'JOULE SQUARE METRE PER KILOGRAM'), + ('D74', 'KILOGRAM PER MOLE'), + ('D75', 'INTERNATIONAL TABLE (IT) CALORIE PER GRAM'), + ('D76', 'INTERNATIONAL TABLE (IT) CALORIE PER GRAM KELVIN'), + ('D77', 'MEGACOULOMB'), + ('D78', 'MEGAJOULE PER SECOND'), + ('D79', 'BEAM'), + ('D8', 'DRAIZE SCORE'), + ('D80', 'MICROWATT'), + ('D81', 'MICROTESLA'), + ('D82', 'MICROVOLT PER METRE'), + ('D83', 'MILLINEWTON METRE'), + ('D85', 'MICROWATT PER SQUARE METRE'), + ('D86', 'MILLICOULOMB PER KILOGRAM'), + ('D87', 'MILLIMOLE PER KILOGRAM'), + ('D88', 'MILLICOULOMB PER CUBIC METRE'), + ('D89', 'MILLICOULOMB PER SQUARE METRE'), + ('D9', 'DYNE PER SQUARE CENTIMETRE'), + ('D90', 'CUBIC METRE (NET'), + ('D91', 'REM'), + ('D92', 'BAND'), + ('D93', 'SECOND PER CUBIC METRE'), + ('D94', 'SECOND PER RADIAN CUBIC METRE'), + ('D95', 'JOULE PER GRAM'), + ('D96', 'POUND GROSS'), + ('D97', 'PALLET/UNIT LOAD'), + ('D98', 'MASS POUND'), + ('D99', 'SLEEVE'), + ('DAA', 'DECARE'), + ('DAD', 'TEN DAY'), + ('DAY', 'DAY'), + ('DB', 'DRY POUND'), + ('DC', 'DISK (DISC)'), + ('DD', 'DEGREE CELSIUS HUNDRED'), + ('DD_1', 'DEGREE [UNIT OF ANGLE]'), + ('DE', 'DEAL'), + ('DEC', 'DECADE'), + ('DG', 'DECIGRAM'), + ('DI', 'DISPENSE'), + ('DJ', 'DECAGRAM'), + ('DKW', 'KILOGRAM DRAINED NET WEIGHT'), + ('DLT', 'DECILITRE'), + ('DMK', 'SQUARE DECIMETRE'), + ('DMO', 'STANDARD KILOLITRE'), + ('DMQ', 'CUBIC DECIMETRE PER MOLE'), + ('DMT', 'DECIMETRE'), + ('DN', 'DECINEWTON METRE'), + ('DPC', 'DOZEN PIECE'), + ('DPR', 'DOZEN PAIR'), + ('DPT', 'DISPLACEMENT TONNAGE'), + ('DQ', 'DATA RECORD'), + ('DR', 'DRUM'), + ('DRA', 'DRAM (US)'), + ('DRI', 'DRAM (UK)'), + ('DRL', 'DOZEN ROLL'), + ('DRM', 'DRACHM (UK)'), + ('DS', 'DISPLAY'), + ('DT', 'DRY TON'), + ('DTN', 'CENTNER, METRIC 100KG'), + ('DTN_1', 'DECITONNE'), + ('DTN_2', 'QUINTAL, METRIC 100KG'), + ('DU', 'DYNE'), + ('DWT', 'PENNYWEIGHT'), + ('DX', 'DYNE PER CENTIMETRE'), + ('DY', 'DIRECTORY BOOK'), + ('DZN', 'DOZEN'), + ('DZP', 'DOZEN PACK'), + ('E01', 'NEWTON PER SQUARE CENTIMETRE'), + ('E07', 'MEGAWATT HOUR PER HOUR'), + ('E08', 'MEGAWATT PER HERTZ'), + ('E09', 'MILLIAMPERE HOUR'), + ('E10', 'DEGREE DAYS'), + ('E11', 'GIGACALORIE'), + ('E12', 'MILLE'), + ('E14', 'KILOCALORIE (IT)'), + ('E15', 'KILOCALORIE (TH) PER HOUR'), + ('E16', 'MILLION BTU (IT) PER HOUR'), + ('E17', 'CUBIC FOOT PER SECOND'), + ('E18', 'TONNE PER HOUR'), + ('E19', 'PING'), + ('E2', 'BELT'), + ('E20', 'MEGABIT PER SECOND'), + ('E21', 'SHARES'), + ('E22', 'TEU'), + ('E23', 'TYRE'), + ('E25', 'ACTIVE UNIT'), + ('E27', 'DOSE'), + ('E28', 'AIR DRY TON'), + ('E3', 'TRAILER'), + ('E30', 'STRAND'), + ('E31', 'SQUARE METRE PER LITRE'), + ('E32', 'LITRE PER HOUR'), + ('E33', 'FOOT PER THOUSAND'), + ('E34', 'GIGABYTE'), + ('E35', 'TERABYTE'), + ('E36', 'PETABYTE'), + ('E37', 'PIXEL'), + ('E38', 'MEGAPIXEL'), + ('E39', 'DOTS PER INCH'), + ('E4', 'GROSS KILOGRAM'), + ('E40', 'PART PER HUNDRED THOUSAND'), + ('E41', 'KILOGRAM FORCE PER SQUARE MILLIMETRE'), + ('E42', 'KILOGRAM FORCE PER SQUARE CENTIMETRE'), + ('E43', 'JOULE PER SQUARE CENTIMETRE'), + ('E44', 'KILOGRAM-FORCE METRE PER SQUARE CENTIMETRE'), + ('E5', 'METRIC LONG TON'), + ('EA', 'EACH'), + ('EB', 'ELECTRONICA MAIL BOX'), + ('EC', 'EACH PER MONTH'), + ('EP', 'ELEVEN PACK'), + ('EQ', 'EQUIVALEN GALLON'), + ('EV', 'ENVELOPE'), + ('F1', 'THOUSAND CUBIC FEET PER DAY'), + ('F9', 'FIBRE PER CUBIC CENTIMETRE OF AIR'), + ('FAH', 'DEGREE FAHRENHEIT'), + ('FAR', 'FARAD'), + ('FB', 'FIELD'), + ('FBM', 'FIBRE METRE'), + ('FC', 'THOUSAND CUBIC FEET'), + ('FD', 'MILLION PARTICLE PER CUBIC FOOT'), + ('FE', 'TRACK FOOT'), + ('FF', 'HUNDRED CUBIC METRE'), + ('FG', 'TRANSDERMAL PATCH'), + ('FH', 'MICROMOLE'), + ('FL', 'FLAKE TON'), + ('FM', 'MILLION CUBIC FEET'), + ('FOT', 'FOOT PER THOUSAND'), + ('FP', 'POUND PER SQUARE FOOT'), + ('FR', 'FOOT PER MINUTE'), + ('FS', 'FOOT PER SECOND SQUARED'), + ('FTK', 'SQUARE FOOT'), + ('FTQ', 'CUBIC FOOT'), + ('G2', 'US GALLON PER MINUTE'), + ('G3', 'IMPERIAL GALLON PER MINUTE'), + ('G7', 'MICROFICHE SHEET'), + ('GB', 'GALLON (US) PER DAY'), + ('GBQ', 'GIGABECQUEREL'), + ('GC', 'GRAM PER 100 GRAM'), + ('GD', 'GROSS BARREL'), + ('GDW', ' GRAM, DRY WEIGHT'), + ('GE', 'POUND PER GALLON (US)'), + ('GF', 'GRAM PER METRE (GRAM PER 100 CENTIMETRES'), + ('GFI', 'GRAM FISSILE ISOTOPE'), + ('GGR', 'GREAT GROSS'), + ('GH', 'HALF GALLON'), + ('GIA', 'GILL'), + ('GIC', 'GRAM, INCLUDING CONTAINER'), + ('GII', 'GILL (UK)'), + ('GIP', 'GRAM, INCLUDING INNER PACKAGING'), + ('GJ', 'GRAM PER MILLILITRE'), + ('GK', 'GRAM PER KILOGRAM'), + ('GL', 'GRAM PER LITRE'), + ('GLD', 'DRY GALLON (S)'), + ('GLI', 'GALLON (UK)'), + ('GLL', 'GALLON (US)'), + ('GM', 'GRAM PER SQUARE METRE'), + ('GN', 'GROSS GALLON'), + ('GO', 'MILLIGRAMS PER SQUARE METRE'), + ('GP', 'MILLIGRAMS PER CUBIC METRE'), + ('GQ', 'MICROGRAM PER CUBIC METRE'), + ('GRM', 'GRAM'), + ('GRN', 'GRAIN'), + ('GRO', 'GROSS'), + ('GRT', 'GROSS REGISTER TON'), + ('GT', 'GROSS TON'), + ('GT_1', 'METRIC GROSS TON'), + ('GV', 'GIGAJOULE'), + ('GW', 'GALLON PER THOUSAND CUBIC FEET'), + ('GWH', 'GIGAWATT HOUR'), + ('GY', 'GROSS YARD'), + ('GZ', 'GAGE-SYSTEM'), + ('H1', 'HALF PAGE- ELECTRONIC'), + ('H2', 'HALF LITR'), + ('HA', 'HANK'), + ('HAR', 'HECARE'), + ('HBA', 'HECTOBAR'), + ('HBX', 'HUNDRED BOXES'), + ('HC', 'HUNDRED COUNT'), + ('HD', 'HALF DOZEN'), + ('HDW', ' HUNDRED KILOGRAM, DRY WIEIGHT'), + ('HE', 'HUNDREDTH OF A CARAT'), + ('HF', 'HUNDRED FEET'), + ('HGM', 'HECTOGRAM'), + ('HH', 'HUNDRED CUBIC FEET'), + ('HI', 'HUNDRED SHEET'), + ('HIU', 'HUNDRED INTERNATIONAL UNIT'), + ('HJ', 'METRIC HORSE POWER'), + ('HK', 'HUNDRED KILOGRAM, DRY WIEIGHT'), + ('HKM', 'HUNDRED KILOGRAM, NET MASS'), + ('HL', 'HUNDRED FEET (LINEAR)'), + ('HLT', 'HECTOLITRE'), + ('HM', 'MILE PER HOUR'), + ('HMQ', 'MILLION CUBIC METRE'), + ('HMT', 'HECTOMETRE'), + ('HN', 'CONVENTIONAL MILLIMETRE MERCURY'), + ('HO', 'HUNDRED TROY OUNCE'), + ('HP', 'CONVENTIONAL MILLIMETRE OF WATER'), + ('HPA', 'HECTOLITRE OF PURE ALCOHOL'), + ('HS', 'HUNDRED SQUARE FEET'), + ('HT', 'HALF HOUR'), + ('HTZ', 'HERTZ'), + ('HUR', 'HOUR'), + ('HY', 'HUNDRED YARD'), + ('IA', 'INCHE POUND (POUND INCH)'), + ('IC', 'COUNT PER INCHE'), + ('IE', 'PERSON'), + ('IF', 'INCHES OF WATER'), + ('II', 'COLUMN INCH'), + ('IL', 'INCHE PER MINUTE'), + ('IM', 'IMPRESSION INCH'), + ('INH', 'INCH'), + ('INK', 'SQUARE INCH'), + ('INQ', 'CUBIC INCH'), + ('INQ_1', 'INCH CUBED'), + ('IP', 'INSURANCE POLICY'), + ('ISD', 'INTERNATIONAL SUGAR DEGREE'), + ('IT', 'COUNT PER CENTIMETRE'), + ('IU', 'INCHE PER SECOND'), + ('IU_1', 'INCH PER SECOND (VIBRATION)'), + ('IV', 'INCH PER SECOND SQUARED'), + ('J2', 'JOULE PER KILOGRAM'), + ('JB', 'JUMBO'), + ('JE', 'JOULE PER KELVIN'), + ('JG', 'JUG'), + ('JK', 'MEGAJOULE PER KILOGRAM'), + ('JM', 'MEGAJOULE PER CUBIC METRE'), + ('JO', 'JOINT'), + ('JOU', 'JOULE'), + ('JPS', 'HUNDRED METRE'), + ('JR', 'JAR'), + ('JWL', 'NUMBER OF JEWELS'), + ('K1', 'KILOWATT DEMAND'), + ('K2', 'KILOVOLT AMPERE REACTIVE DEMAND'), + ('K3', 'KILOVOLT AMPERE REACTIVE HOUR'), + ('K5', 'KILOVOLT AMPERE (REACTIVE)'), + ('K6', 'KILOLITRE'), + ('KA', 'CAKE'), + ('KB', 'KILOCHARACTER'), + ('KBA', 'KILOBAR'), + ('KCC', 'KILOGRAM OF CHOLINE CHLORIDE'), + ('KD', 'KILOGRAM DECIMAL'), + ('KEL', 'KELVIN'), + ('KF', 'KILOPACKET'), + ('KG', 'KEG'), + ('KGM', 'KILOGRAM'), + ('KGS', 'KILOGRAM PER SECOND'), + ('KHY', 'KILOGRAM OF HYDROGEN PEROXIDE'), + ('KHZ', 'KILOHERTZ'), + ('KI', 'KILOGRAM PER MILLIMETRE WIDHT'), + ('KIC', 'KILOGRAM, INCLUDING CONTAINER'), + ('KIP', 'KILOGRAM, INCLUDING INNER PACKAGING'), + ('KJ', 'KILOSEGMENT'), + ('KJO', 'KILOJOULE'), + ('KL', 'KILOGRAM PER METRE'), + ('KLK', 'LACTIC DRY MATERIAL PERCENTAGE'), + ('KMA', 'KILOGRAM OF METHYLAMINE'), + ('KMH', 'KILOMETRE PER HOUR'), + ('KMK', 'SQUARE KILOMETRE'), + ('KMQ', 'KILOGRAM PER CUBIC METRE'), + ('KMT', 'KILOMETRE PER HOUR'), + ('KNI', 'KILOGRAM OF NITROGEN'), + ('KNS', 'KILOGRAM NAMED SUBSTANCE'), + ('KNT', 'KNOT'), + ('KO', 'MILLIEQUIVALENCE CAUSTIC POTASH PER GRAM OF PRODUCT'), + ('KPA', 'KILOPASCAL'), + ('KPH', 'KILOGRAM OF POTASSIUM HYDROXIDE (CAUSTIC POTASH)'), + ('KPO', 'KILOGRAM OF POTASSIUM OXIDE'), + ('KPP', 'KILOGRAM OF PHOSPHORUS PENTOXIDE (PHOSPHORIC ANHYDRIDE)'), + ('KR', 'KILOROENTGEN'), + ('KS', 'THOUSAND POUND PER SQUARE INCH'), + ('KSD', 'KILOGRAM OF SUBSTANCE 90% DRY'), + ('KSH', 'KILOGRAM OF SODIUM HYDROXIDE (CAUSTIC SODA)'), + ('KT', 'KIT'), + ('KTM', 'KILOMETRE PER HOUR'), + ('KTN', 'KILOTONNE'), + ('KUR', 'KILOGRAM OF URANIUM'), + ('KVA', 'KILOVOLT-AMPERE'), + ('KVR', 'KILOVAR'), + ('KVT', 'KILOVOLT'), + ('KW', 'KILOGRAMS PER MILLIMETRE'), + ('KWH', 'KILOWATT HOUR'), + ('KWO', 'KILOGRAM OF TUNGSTEN TRIOXIDE'), + ('KWT', 'KILOWATT'), + ('KX', 'MILLILITRE PER KILOGRAM'), + ('L2', 'LITRE PER MINUTE'), + ('LA', 'POUND PER CUBIC INCH'), + ('LAC', 'LACTOSE EXCESS PERCENTAGE'), + ('LBR', 'POUND'), + ('LBR_1', 'POUND DECIMAL'), + ('LBT', 'TROY POUND (US)'), + ('LC', 'LINEAR CENTIMETRE'), + ('LD', 'LITRE PER DAY'), + ('LE', 'LITE'), + ('LEF', 'LEAF'), + ('LF', 'LINEAR FOOT'), + ('LH', 'LABOUR HOUR'), + ('LI', 'LINEAR INCH'), + ('LJ', 'LARGE SPRAY'), + ('LK', 'LINK'), + ('LM', 'LINEAR METRE'), + ('LN', 'LENGTH'), + ('LO', 'LOT [UNIT PROCUREMENT]'), + ('LP', 'LIQUID POUND'), + ('LPA', 'LITRE OF PURE ALCOHOL'), + ('LR', 'LAYER'), + ('LS', 'LUMP SUM'), + ('LTN', 'TON (UK) OR LONG TON (US)'), + ('LTR', 'LITRE'), + ('LUB', 'METRIC TON, LUBRICATING OIL'), + ('LUM', 'LUMEN'), + ('LUX', 'LUX'), + ('LX', 'LINEAR YARD PER POUND'), + ('LY', 'LINAR YARD'), + ('M1', 'MILLIGRAM PER LITRE'), + ('M4', 'MONETARY VALUE'), + ('M5', 'MICROCURIE'), + ('M7', 'MICRO-INCH'), + ('M9', 'MILLION BTU PER 1000 CUBIC FEET'), + ('MA', 'MACHINE PER UNIT'), + ('MAH', 'MEGAVOLT AMPERE REACTIVE HOURS'), + ('MAL', 'MEGA LITRE'), + ('MAM', 'MEGAMETRE'), + ('MAR', 'MEVAVOLT AMPERE REACTIVE'), + ('MAW', 'MEGAWATT'), + ('MBE', 'THOUSAND STANDARD BRICK EQUIVALENT'), + ('MBF', 'THOUSAND BOARD FEET'), + ('MBR', 'MILLIBAR'), + ('MC', 'MICROGRAM'), + ('MCU', 'MILLICURIE'), + ('MD', 'AIR DRY METRIC TONE'), + ('MF', 'MILLIGRAM PER SQUARE FOOT PER SIDE'), + ('MGM', 'MILLIGRAM'), + ('MHZ', 'MEGAHERTZ'), + ('MIK', 'SQUARE MILE'), + ('MIL', 'THOUSAND'), + ('MIN', 'MINUTE [UNIT OF TIME]'), + ('MIO', 'MILLION'), + ('MIU', 'MILLION INTERNATIONAL UNIT'), + ('MK', 'MILLIGRAM PER SQUARE INCH'), + ('MLD', 'BILLION (US)'), + ('MLD_1', 'MILLIARD'), + ('MLT', 'MILLILITRE PER KILOGRAM'), + ('MMK', 'SQUARE MILLIMETRE'), + ('MMQ', 'CUBIC MILLIMETRE'), + ('MMT', 'MILLIMETRE'), + ('MND', 'KILOGRA, DRY WEIGHT'), + ('MO', 'MAGNETIC TAPE'), + ('MON', 'MONTH'), + ('MPA', 'MEGAPASCAL'), + ('MQ', 'THOUSAND METRE'), + ('MQH', 'CUNIC METRE PER HOUR'), + ('MQS', 'CUBIC METRE PER SECOND'), + ('MSK', 'METRE PER SECOND SQUARED'), + ('MT', 'MAT'), + ('MTK', 'SQUARE METRE'), + ('MTQ', 'CUBIC METRE'), + ('MTQ_1', 'METRE CUBED'), + ('MTR', 'METRE'), + ('MTS', 'METRE PER SECOND'), + ('MV', 'NUMBER OF MULTS'), + ('MVA', 'MEGAVOLT-AMPERE'), + ('MWH', 'MEGAWATT HOUR (1000KW.H)'), + ('N1', 'PEN CALORIE'), + ('N2', 'NUMBER OF LINES'), + ('N3', 'PRINT POINT'), + ('NA', 'MILLIGRAM PER KILOGRAM'), + ('NAR', 'NUMBER OF ARTICLES'), + ('NB', 'BARGE'), + ('NBB', 'NUMBER OF BOBBINS'), + ('NC', 'CAR'), + ('NCL', 'NUMBER OF CELLS'), + ('ND', 'NET BARREL'), + ('NE', 'NET LITRE'), + ('NEW', 'NEWTON PER SQUARE CENTIMETRE'), + ('NF', 'MESSAGE'), + ('NG', 'NET GALLON (US)'), + ('NH', 'MESSAGE HOUR'), + ('NI', 'NET IMPERIAL GALLON'), + ('NIU', 'NUMBER OF INTERNATIONAL UNITS'), + ('NJ', 'NUMBER OF SCREENS'), + ('NL', 'LOAD'), + ('NMI', 'NAUTICAL MILE'), + ('NMP', 'NUMBER OF PACKS'), + ('NN', 'TRAIN'), + ('NPL', 'NUMBER OF PARCELS'), + ('NPR', 'NUMBER OF PAIRS'), + ('NPT', 'NUMBER OF PARTS'), + ('NQ', 'MHO'), + ('NR', 'MICROMHO'), + ('NRL', 'NUMBER OF ROLLS'), + ('NT', 'METRIC NET TON'), + ('NT_1', 'NET TON'), + ('NTT', 'NET REGISTER TON'), + ('NV', 'VEHICLE'), + ('NX', 'PART PER THOUSAND'), + ('NY', 'POUND PER AIR DRY METRIC TON'), + ('OA', 'PANEL'), + ('ODE', 'OZONE DEPLETION EQUIVALENT'), + ('OHM', 'OHM'), + ('ON', 'OUNCE PER SQUARE YARD'), + ('ONZ', 'OUNCE PER SQUARE YARD'), + ('OP', 'TWO PACK'), + ('OT', 'OVERTIME HOUR'), + ('OZ', 'OUNCE AV'), + ('OZA', 'FLUID OUNCE (US)'), + ('OZI', 'FLUID OUNCE (UK)'), + ('P0', 'PAGE -ELECTRONIC'), + ('P1', 'PERCENT'), + ('P2', 'POUND PER FOOT'), + ('P3', 'THREE PACK'), + ('P4', 'FOUR PACK'), + ('P5', 'FIVE PACK'), + ('P6', 'SIX PACK'), + ('P7', 'SEVEN PACK'), + ('P8', 'EIGHT PACK'), + ('P9', 'NINE PACK'), + ('PA', 'PACKET'), + ('PAL', 'PASCAL'), + ('PB', 'PAIR INCH'), + ('PD', 'PAD'), + ('PE', 'POUND EQUIVALENT'), + ('PF', 'PALLET (LIFT)'), + ('PFL', 'PROOF LITRE'), + ('PG', 'PLATE'), + ('PGL', 'PROOF GALLON'), + ('PI', 'PITCH'), + ('PK', 'PACK'), + ('PK_1', 'PACKAGE'), + ('PLA', 'PAIL'), + ('PLA_1', 'DEGREE PLATO'), + ('PM', 'POUND PERCENTAGE'), + ('PN', 'POUND NET'), + ('PO', 'POUND PER INCH OF LENGTT'), + ('PQ', 'PAGE PER INCH'), + ('PR', 'PAIR INCH'), + ('PS', 'POUND-FORCE PER SQUARE INCH'), + ('PT', 'PINT (US)'), + ('PTD', 'DRY PINT(US)'), + ('PTI', 'PINT (UK)'), + ('PTL', 'LIQUID PINT (US)'), + ('PU', 'TRAY/TRAY PACK'), + ('PV', 'HALF PINT (US)'), + ('PW', 'POUND PER INCH OF WIDTH'), + ('PY', 'PECK DRY (US)'), + ('PZ', 'PECK DRY (UK)'), + ('Q3', 'MEAL'), + ('QA', 'PAGE-FACSIMILE'), + ('QAN', 'QUARTER (OF A YEAR)'), + ('QB', 'PAGE-HARDCOPY'), + ('QD', 'QUARTER DOZEN'), + ('QH', 'QUARTER HOUR'), + ('QK', 'QUARTES KILOGRAM'), + ('QR', 'QUIRE'), + ('QT', 'QUART (US)'), + ('QTD', 'DRY QUART (US)'), + ('QTI', 'QUART (UK)'), + ('QTL', 'LIQUID QUART (US)'), + ('QTR', 'QUARTER (UK)'), + ('R1', 'PICA'), + ('R4', 'CALORIE'), + ('R9', 'THOUSAND CUBIC METRE'), + ('RA', 'RACK'), + ('RD', 'ROD'), + ('RG', 'RING'), + ('RH', 'RUNNING OR OPERATING HOUR'), + ('RK', 'ROLL METRIC MEASURE'), + ('RL', 'REEL'), + ('RM', 'REAM'), + ('RN', 'REAM METRIC MEASURE'), + ('RO', 'ROLL METRIC MEASURE'), + ('RP', 'POUND PER TEAM'), + ('RPM', 'REVOLUTIONS PER MINUTE'), + ('RPS', 'REVOLUTIONS PER SECOND'), + ('RS', 'RESET'), + ('RT', 'REVENUE TON MILE'), + ('RU', 'RUN'), + ('S3', 'FOOT WQUARE PER SECOND'), + ('S3_1', 'SQUARE FOOT PER SECOND'), + ('S4', 'METRE SQUARED PER SECOND (SQUARE METRES/SECONDS US)'), + ('S4_1', 'SQUARE METRE PER SECOND SIXTY FOURTHS OF AN INCH'), + ('S5', 'SIXTY FOURTHS OF AN INCH'), + ('S6', 'SESSION'), + ('S7', 'STORAGE UNIT'), + ('S8', 'STANDARD ADVERTISING UNIT'), + ('SA', 'SACK'), + ('SAN', 'HALF YEAR (6 MONTHS)'), + ('SCO', 'SCORE'), + ('SCR', 'SCRUPLE'), + ('SD', 'SOLID POUND'), + ('SE', 'SECTION'), + ('SEC', 'SECOND [UNIT OF TIME]'), + ('SET', 'SET'), + ('SG', 'SEGMENT'), + ('SHT', 'SHIPPING TON'), + ('SIE', 'SIEMENS'), + ('SK', 'SPLIT TANK TRUCK'), + ('SL', 'SLIPSHEET'), + ('SMI', 'MILE (STATUTE MILE)'), + ('SN', 'SQUARE ROD'), + ('SO', 'SPOOL'), + ('SP', 'SHELF PACKAGE'), + ('SQ', 'SQUARE'), + ('SQR', 'SQUARE, ROOFING'), + ('SR', 'STRIP'), + ('SS', 'SHEET METRIC MEASURE'), + ('SST', 'SHORT STANDARD (7200 MATCHES)'), + ('ST', 'SHEET'), + ('STI', 'STONE (UK)'), + ('STK', 'STICK, CIGARETTE'), + ('STL', 'STANDARD LITRE'), + ('STN', 'NET TON (2000 LB)'), + ('STN_1', 'TON (US) OR SHORT TON (UK/US)'), + ('SV', 'SKID'), + ('SW', 'SKEIN'), + ('SX', 'SHIPMENT'), + ('T0', 'TELECOMMUNICATION LINE SERVICE'), + ('T1', 'THOUSAND POUND GROSS'), + ('T3', 'THOUSAND PIECE'), + ('T4', 'THOUSAND BAG'), + ('T5', 'THOUSAND CASING'), + ('T6', 'THOUSAND GALLON (US)'), + ('T7', 'THOUSAND IMPRESSION'), + ('T8', 'THOUSAND LINEAR INCH'), + ('TA', 'TENTH CUBIC FOOT'), + ('TAH', 'KILOAMPERE HOUR (THOUSAND AMPERE HOUR'), + ('TC', 'TRUCKLOAD'), + ('TD', 'THERM'), + ('TE', 'TOTE'), + ('TF', 'TEN SQUARE YARD'), + ('TI', 'THOUSAND SQUARE INCH'), + ('TIC', 'METRIC TON, INCLUDING CONTAINER'), + ('TIP', 'METRIC TON, INCLUDING INNER PACKAGING'), + ('TJ', 'THOUSAND SQUARE CENTIMETRE'), + ('TK', 'TANK, RECTANGULAR'), + ('TL', 'THOUSAND FEET (LINEAR)'), + ('TMS', 'KILOGRAM OF IMPORTED META, LESS OFFAL'), + ('TN', 'TIN'), + ('TNE', 'METRIC TON'), + ('TNE_1', 'TONNE (METRIC TON)'), + ('TP', 'TEN PACK'), + ('TPR', 'TEN PAIR'), + ('TQ', 'THOUSAND FEET'), + ('TQD', 'THOUSAND CUBIC METRE PER DAY'), + ('TR', 'TEN SQUARE FEET'), + ('TRL', 'TRILLION (EUR)'), + ('TS', 'TONNE OF SUBSTANCE 90% DRY'), + ('TSD', 'THOUSAND SQUARE FEET'), + ('TSH', 'TON OF STEAM PER HOUR'), + ('TT', 'THOUSAND LINEAR METRE'), + ('TU', 'TUBE'), + ('TV', 'THOUSAND KILOGRAM'), + ('TW', 'THOUSAND SHEET'), + ('TY', 'TANK, CYLINDRICAL'), + ('U1', 'TRATMENT'), + ('U2', 'TABLET'), + ('UA', 'TORR'), + ('UB', 'TELECOMMUNICATION LINE IN SERVICE AVERAGE'), + ('UC', 'TELECOMMUNICATION PORT'), + ('UD', 'TENTH MINUTE'), + ('UE', 'TENTH HOUR'), + ('UF', 'USAGE PER TELECOMMUNICATION LINE AVERAGE'), + ('UH', 'TEN THOUSAND YARD'), + ('UM', 'MILLION UN IT'), + ('UN', 'NEWTON METRE'), + ('VA', 'VOLT AMPERE PER KILOGRAM'), + ('VI', 'VIAL'), + ('VLT', 'VOLT'), + ('VQ', 'BULK'), + ('VS', 'VISIT'), + ('W2', 'WET KILO'), + ('W4', 'TWO WEEK'), + ('WA', 'WATT PER KILOGRAM'), + ('WB', 'WET POUND'), + ('WCD', 'CORD'), + ('WE', 'WET TON'), + ('WE_1', 'WRAP'), + ('WEB', 'WEBER'), + ('WEE', 'WEEK'), + ('WG', 'WINE GALLON'), + ('WH', 'WHEEL'), + ('WHR', 'WATT HOUR'), + ('WI', 'WEIGHT PER SQUARE INCH'), + ('WM', 'WORKING MONTH'), + ('WSD', 'STANDARD'), + ('WTT', 'WATT'), + ('WW', 'MILLILITRE OF WATER'), + ('X1', 'HCHAIN'), + ('YDK', 'SQUARED YARD'), + ('YDQ', 'CUBIC YARD'), + ('YL', 'HUNDRED LINEAR YARD'), + ('YRD', 'YARD'), + ('YT', 'TEN YARD'), + ('Z1', 'LIFT VAN'), + ('Z2', 'CHEST'), + ('Z3', 'CASK'), + ('Z4', 'HOGSHEAD'), + ('Z5', 'LUG'), + ('Z6', 'CONFERENCE POINT'), + ('Z8', 'NEWSPAGE AGATE LINE'), + ('ZP', 'PAGE'), + ('ZZ', 'MUATUALLY DEFINED'), +] \ No newline at end of file diff --git a/frontend/src/lib/api/dashboard/a76/units_of_measure.ts b/frontend/src/lib/api/dashboard/a76/units_of_measure.ts new file mode 100644 index 00000000..cbfce30e --- /dev/null +++ b/frontend/src/lib/api/dashboard/a76/units_of_measure.ts @@ -0,0 +1,101 @@ +/** + * API Client para Units of Measure + * Gestiona las operaciones CRUD para unidades de medida + */ +import { api } from '$lib/api'; + +export interface UnitOfMeasure { + id: number; + code: string; + description: string | null; + description_en: string | null; + customs_code: string | null; + american_code: string | null; + ace_code: string | null; + oma_code: string | null; +} + +export interface UnitOfMeasureListResponse { + items: UnitOfMeasure[]; + total: number; + page: number; + page_size: number; +} + +export interface CreateUnitOfMeasureData { + code: string; + description?: string | null; + description_en?: string | null; + customs_code?: string | null; + american_code?: string | null; + ace_code?: string | null; + oma_code?: string | null; +} + +export interface UpdateUnitOfMeasureData { + code?: string; + description?: string | null; + description_en?: string | null; + customs_code?: string | null; + american_code?: string | null; + ace_code?: string | null; + oma_code?: string | null; +} + +/** + * API para Units of Measure + */ +export const unitsOfMeasureApi = { + /** + * Lista todas las unidades de medida con paginación + * @param companyId - ID de la compañía + * @param page - Número de página (por defecto 1) + * @param pageSize - Tamaño de página (por defecto 50) + */ + list: (companyId: number, page = 1, pageSize = 50) => { + const params = new URLSearchParams({ + company_id: companyId.toString(), + page: page.toString(), + page_size: pageSize.toString() + }); + return api.get( + `/v1/a76/units-of-measure?${params.toString()}` + ); + }, + + /** + * Obtiene una unidad de medida por ID + * @param companyId - ID de la compañía + * @param id - ID de la unidad de medida + */ + get: (companyId: number, id: number) => + api.get(`/v1/a76/units-of-measure/${id}?company_id=${companyId}`), + + /** + * Crea una nueva unidad de medida + * @param companyId - ID de la compañía + * @param data - Datos de la unidad de medida a crear + */ + create: (companyId: number, data: CreateUnitOfMeasureData) => + api.post(`/v1/a76/units-of-measure?company_id=${companyId}`, data), + + /** + * Actualiza una unidad de medida existente + * @param companyId - ID de la compañía + * @param id - ID de la unidad de medida a actualizar + * @param data - Datos a actualizar + */ + update: (companyId: number, id: number, data: UpdateUnitOfMeasureData) => + api.put( + `/v1/a76/units-of-measure/${id}?company_id=${companyId}`, + data + ), + + /** + * Elimina una unidad de medida + * @param companyId - ID de la compañía + * @param id - ID de la unidad de medida a eliminar + */ + delete: (companyId: number, id: number) => + api.delete(`/v1/a76/units-of-measure/${id}?company_id=${companyId}`) +}; diff --git a/frontend/src/lib/api/dashboard/refrence_data/material_types.ts b/frontend/src/lib/api/dashboard/refrence_data/material_types.ts index 3e9e1671..ff140956 100644 --- a/frontend/src/lib/api/dashboard/refrence_data/material_types.ts +++ b/frontend/src/lib/api/dashboard/refrence_data/material_types.ts @@ -48,7 +48,7 @@ export const materialTypesApi = { params.append('type', type); } return api.get( - `/v1/public/refrence_data/material-types?${params.toString()}` + `/v1/public/refrence_data/material-types/?${params.toString()}` ); }, @@ -56,14 +56,14 @@ export const materialTypesApi = { * Obtiene un tipo de material por key * @param key - Clave del tipo de material */ - get: (key: string) => api.get(`/v1/public/refrence_data/material-types/${key}`), + get: (key: string) => api.get(`/v1/public/refrence_data/material-types/${key}/`), /** * Crea un nuevo tipo de material * @param data - Datos del tipo de material a crear */ create: (data: CreateMaterialTypeData) => - api.post('/v1/public/refrence_data/material-types', data), + api.post('/v1/public/refrence_data/material-types/', data), /** * Actualiza un tipo de material existente @@ -71,11 +71,11 @@ export const materialTypesApi = { * @param data - Datos a actualizar */ update: (key: string, data: UpdateMaterialTypeData) => - api.put(`/v1/public/refrence_data/material-types/${key}`, data), + api.put(`/v1/public/refrence_data/material-types/${key}/`, data), /** * Elimina un tipo de material * @param key - Clave del tipo de material a eliminar */ - delete: (key: string) => api.delete(`/v1/public/refrence_data/material-types/${key}`) + delete: (key: string) => api.delete(`/v1/public/refrence_data/material-types/${key}/`) }; diff --git a/frontend/src/lib/components/dashboard/goods/classes/create-edit-dialog.svelte b/frontend/src/lib/components/dashboard/goods/classes/create-edit-dialog.svelte index 15119178..fc4450b9 100644 --- a/frontend/src/lib/components/dashboard/goods/classes/create-edit-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/classes/create-edit-dialog.svelte @@ -7,6 +7,7 @@ import * as Select from "$lib/components/ui/select"; import { classesApi, type A76Class, type A76ClassCreate, type A76ClassUpdate } from "$lib/api/dashboard/a76/classes"; import { materialTypesApi, type MaterialType } from "$lib/api/dashboard/refrence_data/material_types"; + import { unitsOfMeasureApi, type UnitOfMeasure } from "$lib/api/dashboard/a76/units_of_measure"; import { clientsProvidersApi, type ClientProvider } from "$lib/api/dashboard/a76/clients-providers"; import { companyStore } from "$lib/stores/company.svelte"; import { onMount } from 'svelte'; @@ -43,6 +44,8 @@ let error = $state(null); let materialTypes = $state([]); let loadingMaterialTypes = $state(false); + let unitsOfMeasure = $state([]); + let loadingUnitsOfMeasure = $state(false); let clients = $state([]); let loadingClients = $state(false); @@ -51,15 +54,15 @@ let selectedMaterialValue = $state(''); let selectedPhysicalReviewValue = $state(0); - // Cargar tipos de materiales y clientes al montar + // Cargar tipos de materiales, unidades de medida y clientes al montar onMount(async () => { const companyId = companyStore.activeCompany?.id; if (!companyId) return; - // Cargar tipos de materiales + // Cargar tipos de materiales (solo ACTIVO FIJO) loadingMaterialTypes = true; try { - const response = await materialTypesApi.list(1, 100); + const response = await materialTypesApi.list(1, 100, 'ACTIVO FIJO'); if (response.data) { materialTypes = response.data.items; } @@ -69,6 +72,19 @@ loadingMaterialTypes = false; } + // Cargar unidades de medida + loadingUnitsOfMeasure = true; + try { + const response = await unitsOfMeasureApi.list(companyId, 1, 100); + if (response.data) { + unitsOfMeasure = response.data.items; + } + } catch (e) { + console.error('Error loading units of measure:', e); + } finally { + loadingUnitsOfMeasure = false; + } + // Cargar clientes loadingClients = true; try { @@ -216,31 +232,9 @@ } } - // Opciones de unidades de medida (puedes expandir esto) - const unitOptions = [ - { value: 'KG', label: 'Kilogramos (KG)' }, - { value: 'LB', label: 'Libras (LB)' }, - { value: 'MT', label: 'Metros (MT)' }, - { value: 'PZ', label: 'Piezas (PZ)' }, - { value: 'LT', label: 'Litros (LT)' }, - { value: 'M3', label: 'Metros Cúbicos (M3)' }, - { value: 'TON', label: 'Toneladas (TON)' } - ]; - // Funciones para obtener valores seleccionados - function getSelectedMaterialType() { - if (!formData.material_key) return null; - const found = materialTypes.find(mt => mt.key === formData.material_key); - return found ? { value: found.key, label: `${found.key} - ${found.description}` } : null; - } - function getSelectedUnit() { - return unitOptions.find(opt => opt.value === formData.unit_of_measure) || unitOptions[0]; - } - function getSelectedPhysicalReview() { - return { value: formData.physical_review, label: formData.physical_review === 1 ? 'Sí' : 'No' }; - } @@ -409,18 +403,34 @@ - +
- - + + {#if loadingUnitsOfMeasure} +
+
+ Cargando unidades de medida... +
+ {:else if unitsOfMeasure.length > 0} + + {:else} + + {/if}
diff --git a/frontend/src/lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte b/frontend/src/lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte index 16632751..9f410af2 100644 --- a/frontend/src/lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte +++ b/frontend/src/lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte @@ -6,6 +6,7 @@ import { Folder } from 'lucide-svelte'; import { toast } from 'svelte-sonner'; import { materialTypesApi, type MaterialType } from '$lib/api/dashboard/refrence_data/material_types'; + import { unitsOfMeasureApi } from '$lib/api/dashboard/a76/units_of_measure'; import { getTariffFractions, type TariffFraction } from '$lib/api/dashboard/a76/general_catalogs/tariff-fractions'; import { getUSTariffFractions, type USTariffFraction } from '$lib/api/dashboard/a76/general_catalogs/us-tariff-fractions'; import { getDepreciationCatalog, type DepreciationCatalog } from '$lib/api/dashboard/a76/general_catalogs/depreciation-catalog'; @@ -33,14 +34,8 @@ claveOMA: string; } - // Datos de unidades de medida - const unitsOfMeasureData: UnitOfMeasure[] = [ - { code: 'BARR', description: 'BARRIL', descriptionEnglish: 'BARREL', claveMexicana: '8', claveAmericana: 'BBL', claveACE: '', claveOMA: 'BLL' }, - { code: 'BD FT', description: 'PIE TABLA', descriptionEnglish: 'BD FEET', claveMexicana: '5', claveAmericana: 'FT', claveACE: '', claveOMA: 'BFT' }, - { code: 'BOLS', description: 'BOLSA', descriptionEnglish: 'BAG', claveMexicana: '6', claveAmericana: 'PCS', claveACE: '', claveOMA: 'BG' }, - { code: 'KGS', description: 'KILOGRAMOS', descriptionEnglish: 'KGS', claveMexicana: '1', claveAmericana: 'KG2', claveACE: '', claveOMA: 'KGM' }, - { code: 'PZA', description: 'PIEZA', descriptionEnglish: 'PCS', claveMexicana: '6', claveAmericana: 'PCS', claveACE: '', claveOMA: 'C62_1' }, - ]; + // Datos de unidades de medida (se cargan desde el API) + let unitsOfMeasureData: UnitOfMeasure[] = $state([]); // Estado del formulario let formData = $state({ @@ -195,6 +190,28 @@ ); // Funciones + async function loadUnitsOfMeasure() { + if (unitsOfMeasureData.length > 0) return; + try { + const companyId = companyStore.activeCompany?.id; + if (!companyId) return; + const response = await unitsOfMeasureApi.list(companyId, 1, 100); + if (response.data) { + unitsOfMeasureData = response.data.items.map(item => ({ + code: item.code, + description: item.description || '', + descriptionEnglish: item.description_en || '', + claveMexicana: item.customs_code || '', + claveAmericana: item.american_code || '', + claveACE: item.ace_code || '', + claveOMA: item.oma_code || '' + })); + } + } catch (error) { + console.error('Error cargando units of measure:', error); + } + } + async function openMaterialSearch() { showMaterialDialog = true; searchMaterial = ''; @@ -202,7 +219,7 @@ try { const companyId = companyStore.activeCompany?.id; if (!companyId) return; - const response = await materialTypesApi.list(1, 1000); + const response = await materialTypesApi.list(1, 100, 'ACTIVO FIJO'); if (response.data) { materialTypes = response.data.items; } @@ -222,6 +239,7 @@ async function openUnitOfMeasureSearch() { showUnitDialog = true; searchUnit = ''; + await loadUnitsOfMeasure(); } function selectUnit(unit: UnitOfMeasure) { From 27e18c9d0b5f49d930126335e4f3196e757307e6 Mon Sep 17 00:00:00 2001 From: Galindo97 Date: Mon, 12 Jan 2026 11:38:12 -0600 Subject: [PATCH 4/4] feat(database): add deleted_at column to units of measure tables and update DTO field lengths --- ...31bf8cdae06_create_material_types_table.py | 5 ++ .../7937209f9718_seed_initial_data.py | 4 ++ .../general_catalogs/units_of_measure/dto.py | 48 +++++++++---------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/backend/alembic/versions/531bf8cdae06_create_material_types_table.py b/backend/alembic/versions/531bf8cdae06_create_material_types_table.py index 5205a7e2..7e7b4630 100644 --- a/backend/alembic/versions/531bf8cdae06_create_material_types_table.py +++ b/backend/alembic/versions/531bf8cdae06_create_material_types_table.py @@ -178,6 +178,7 @@ def upgrade() -> None: 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' @@ -191,6 +192,7 @@ def upgrade() -> None: 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' @@ -204,6 +206,7 @@ def upgrade() -> None: 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' @@ -218,6 +221,7 @@ def upgrade() -> None: 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' @@ -238,6 +242,7 @@ def upgrade() -> None: 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'], diff --git a/backend/alembic/versions/7937209f9718_seed_initial_data.py b/backend/alembic/versions/7937209f9718_seed_initial_data.py index 46eede98..a3ba52df 100644 --- a/backend/alembic/versions/7937209f9718_seed_initial_data.py +++ b/backend/alembic/versions/7937209f9718_seed_initial_data.py @@ -79,6 +79,10 @@ def upgrade() -> None: 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): diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/dto.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/dto.py index 2864c135..aa75c493 100644 --- a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/dto.py +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/dto.py @@ -21,29 +21,29 @@ class UnitOfMeasureAmericanBase(BaseModel): class UnitOfMeasureCustomsBase(BaseModel): - code: str = Field(..., max_length=2, description="Customs Code") - description: Optional[str] = Field(None, max_length=20) + code: str = Field(..., max_length=10, description="Customs Code") + description: Optional[str] = Field(None, max_length=50) scaii_unit_code: Optional[str] = Field(None, max_length=5) class UnitOfMeasureBase(BaseModel): - code: str = Field(..., max_length=5, description="Unit Code") + code: str = Field(..., max_length=20, description="Unit Code") description: Optional[str] = Field(None, max_length=100) description_en: Optional[str] = Field(None, max_length=100) - customs_code: Optional[str] = Field(None, max_length=2) - american_code: Optional[str] = Field(None, max_length=3) - ace_code: Optional[str] = Field(None, max_length=4) - oma_code: Optional[str] = Field(None, max_length=10) + customs_code: Optional[str] = Field(None, max_length=20) + american_code: Optional[str] = Field(None, max_length=20) + ace_code: Optional[str] = Field(None, max_length=20) + oma_code: Optional[str] = Field(None, max_length=20) class UnitOfMeasureGeneralBase(BaseModel): - code: str = Field(..., max_length=5, description="Unit Code") + code: str = Field(..., max_length=20, description="Unit Code") description: Optional[str] = Field(None, max_length=100) conversion_factor: Optional[Decimal] = None - mexico_unit: Optional[str] = Field(None, max_length=5) - american_unit_code: Optional[str] = Field(None, max_length=5) - customs_code: Optional[str] = Field(None, max_length=2) - ace_code: Optional[str] = Field(None, max_length=4) + mexico_unit: Optional[str] = Field(None, max_length=20) + american_unit_code: Optional[str] = Field(None, max_length=20) + customs_code: Optional[str] = Field(None, max_length=20) + ace_code: Optional[str] = Field(None, max_length=20) # --- Create DTOs --- @@ -90,29 +90,29 @@ class UnitOfMeasureAmericanUpdate(BaseModel): class UnitOfMeasureCustomsUpdate(BaseModel): - code: Optional[str] = Field(None, max_length=2) - description: Optional[str] = Field(None, max_length=20) + code: Optional[str] = Field(None, max_length=10) + description: Optional[str] = Field(None, max_length=50) scaii_unit_code: Optional[str] = Field(None, max_length=5) class UnitOfMeasureUpdate(BaseModel): - code: Optional[str] = Field(None, max_length=5) + code: Optional[str] = Field(None, max_length=20) description: Optional[str] = Field(None, max_length=100) description_en: Optional[str] = Field(None, max_length=100) - customs_code: Optional[str] = Field(None, max_length=2) - american_code: Optional[str] = Field(None, max_length=3) - ace_code: Optional[str] = Field(None, max_length=4) - oma_code: Optional[str] = Field(None, max_length=10) + customs_code: Optional[str] = Field(None, max_length=20) + american_code: Optional[str] = Field(None, max_length=20) + ace_code: Optional[str] = Field(None, max_length=20) + oma_code: Optional[str] = Field(None, max_length=20) class UnitOfMeasureGeneralUpdate(BaseModel): - code: Optional[str] = Field(None, max_length=5) + code: Optional[str] = Field(None, max_length=20) description: Optional[str] = Field(None, max_length=100) conversion_factor: Optional[Decimal] = None - mexico_unit: Optional[str] = Field(None, max_length=5) - american_unit_code: Optional[str] = Field(None, max_length=5) - customs_code: Optional[str] = Field(None, max_length=2) - ace_code: Optional[str] = Field(None, max_length=4) + mexico_unit: Optional[str] = Field(None, max_length=20) + american_unit_code: Optional[str] = Field(None, max_length=20) + customs_code: Optional[str] = Field(None, max_length=20) + ace_code: Optional[str] = Field(None, max_length=20) # --- Response DTOs ---