From e6d7d2332867c95766f45e1721f4623eddf306ae Mon Sep 17 00:00:00 2001 From: acazares Date: Fri, 7 Nov 2025 00:02:35 -0600 Subject: [PATCH 1/2] feat: Add payments, transport, and validation tabs for pedimento editing - Implemented PaymentsTabForm component for managing payment information. - Implemented TransportTabForm component for managing transport details. - Implemented ValidationTabForm component for managing validation documents. - Enhanced the main edit page to include new tabs and handle data saving for each section. - Added alert components for success and error messages during save operations. - Updated server-side logic to handle fetching and saving of pedimento data. --- README.md | 29 +- .../versions/03b786378f94_pedimentos.py | 424 --------------- ...54f2046774d0_create_new_a76_tables_only.py | 195 ------- .../dtos/pedimento_rectification_origin.py | 4 +- .../modules/a76/pedmientos/dtos/pedimentos.py | 4 +- .../models/pedimento_rectification_origin.py | 2 +- .../a76/pedmientos/models/pedimentos.py | 4 +- backend/main.py | 13 +- docker-compose.yml | 2 +- docs/a76.json | 2 +- frontend/src/app.html | 2 +- .../lib/api/dashboard/a76/pedimento-dates.ts | 41 ++ .../api/dashboard/a76/pedimento-payments.ts | 38 ++ .../api/dashboard/a76/pedimento-transport.ts | 44 ++ .../api/dashboard/a76/pedimento-validation.ts | 35 ++ .../src/lib/api/dashboard/a76/pedimentos.ts | 6 +- .../dashboard/pedimentos/columns.ts | 4 +- .../pedimentos/create-edit-dialog.svelte | 425 --------------- .../pedimentos/data-table-actions.svelte | 35 +- .../pedimentos/edit/dates-tab-form.svelte | 122 +++++ .../pedimentos/edit/general-tab-form.svelte | 232 +++++++++ .../pedimentos/edit/payments-tab-form.svelte | 107 ++++ .../pedimentos/edit/transport-tab-form.svelte | 137 +++++ .../edit/validation-tab-form.svelte | 94 ++++ .../ui/alert/alert-description.svelte | 23 + .../components/ui/alert/alert-title.svelte | 20 + .../src/lib/components/ui/alert/alert.svelte | 44 ++ frontend/src/lib/components/ui/alert/index.ts | 14 + frontend/src/lib/components/ui/tabs/index.ts | 16 + .../components/ui/tabs/tabs-content.svelte | 17 + .../lib/components/ui/tabs/tabs-list.svelte | 20 + .../components/ui/tabs/tabs-trigger.svelte | 20 + .../src/lib/components/ui/tabs/tabs.svelte | 19 + frontend/src/routes/+page.svelte | 2 +- frontend/src/routes/dashboard/+page.svelte | 2 +- .../routes/dashboard/pedimentos/+page.svelte | 10 +- .../pedimentos/edit/[id]/+page.server.ts | 72 +++ .../pedimentos/edit/[id]/+page.svelte | 488 ++++++++++++++++++ scripts/postgres-app-entrypoint.sh | 3 +- 39 files changed, 1661 insertions(+), 1110 deletions(-) delete mode 100644 backend/alembic/versions/03b786378f94_pedimentos.py delete mode 100644 backend/alembic/versions/54f2046774d0_create_new_a76_tables_only.py create mode 100644 frontend/src/lib/api/dashboard/a76/pedimento-dates.ts create mode 100644 frontend/src/lib/api/dashboard/a76/pedimento-payments.ts create mode 100644 frontend/src/lib/api/dashboard/a76/pedimento-transport.ts create mode 100644 frontend/src/lib/api/dashboard/a76/pedimento-validation.ts delete mode 100644 frontend/src/lib/components/dashboard/pedimentos/create-edit-dialog.svelte create mode 100644 frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte create mode 100644 frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte create mode 100644 frontend/src/lib/components/dashboard/pedimentos/edit/payments-tab-form.svelte create mode 100644 frontend/src/lib/components/dashboard/pedimentos/edit/transport-tab-form.svelte create mode 100644 frontend/src/lib/components/dashboard/pedimentos/edit/validation-tab-form.svelte create mode 100644 frontend/src/lib/components/ui/alert/alert-description.svelte create mode 100644 frontend/src/lib/components/ui/alert/alert-title.svelte create mode 100644 frontend/src/lib/components/ui/alert/alert.svelte create mode 100644 frontend/src/lib/components/ui/alert/index.ts create mode 100644 frontend/src/lib/components/ui/tabs/index.ts create mode 100644 frontend/src/lib/components/ui/tabs/tabs-content.svelte create mode 100644 frontend/src/lib/components/ui/tabs/tabs-list.svelte create mode 100644 frontend/src/lib/components/ui/tabs/tabs-trigger.svelte create mode 100644 frontend/src/lib/components/ui/tabs/tabs.svelte create mode 100644 frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts create mode 100644 frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte diff --git a/README.md b/README.md index 927f2561..8c54b962 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ # Anexo76 -**Aplicación SaaS para gestión de comercio exterior conforme a Anexos 24, 31 y 22 del SAT** +**Aplicación SaaS para gestión de comercio exterior conforme a Anexos 24, 30 y 22 del SAT** Anexo76 es una plataforma multi-tenant diseñada para maquilas, empresas IMMEX y agentes aduanales, que permite gestionar inventarios, pedimentos y facturas de importación/exportación con control de licencias y cumplimiento normativo. ## 🏗️ Arquitectura ### Backend + - **Framework**: FastAPI 0.110+ - **Autenticación**: Keycloak (OpenID Connect) - **Base de Datos**: PostgreSQL con SQLAlchemy @@ -20,11 +21,13 @@ Anexo76 es una plataforma multi-tenant diseñada para maquilas, empresas IMMEX y - `routes.py`: Endpoints API ### Frontend + - **Framework**: SvelteKit - **Autenticación**: keycloak-js - **UI**: Dashboard moderno y responsivo ### Infraestructura + - **Containerización**: Docker / Docker Compose - **Orquestación**: Kubernetes (futuro) - **Monitoreo**: Prometheus + Grafana @@ -64,6 +67,7 @@ anexo76/ ## 🚀 Inicio Rápido ### Requisitos Previos + - Docker y Docker Compose - Python 3.11+ (para desarrollo local) - Node.js 18+ (para desarrollo frontend) @@ -89,6 +93,7 @@ docker-compose up -d ``` Esto iniciará: + - **PostgreSQL** en `localhost:5432` - **Keycloak** en `localhost:8080` - **Backend API** en `localhost:8000` @@ -150,17 +155,20 @@ npm run dev ## 📦 Módulos Principales ### 1. **Auth** (`/v1/auth`) + - Login con Keycloak - Refresh token - Logout - Información de usuario ### 2. **Tenants** (`/v1/tenants`) + - Creación y gestión de tenants - Upgrade de BD compartida a dedicada - Gestión de realms de Keycloak ### 3. **Licenses** (`/v1/licenses`) + - Control de planes (Free, Basic, Professional, Enterprise) - Validación de licencias activas - Tracking de uso (usuarios, storage, operaciones) @@ -188,11 +196,13 @@ npm run dev ### Modelo Híbrido **BD Compartida** (tenants pequeños/medianos): + - Tabla única con `tenant_id` como foreign key - Row-level security - Más económico para clientes con bajo volumen **BD Dedicada** (tenants enterprise): + - Base de datos PostgreSQL independiente - Máximo aislamiento y performance - Configuración almacenada en `tenants.db_config` @@ -219,16 +229,18 @@ service.upgrade_to_dedicated(tenant_id=123, db_config=db_config) ### Planes Disponibles -| Plan | Usuarios | Storage | Operaciones/mes | Features | -|------|----------|---------|-----------------|----------| -| Free | 5 | 10 GB | 1,000 | API básica | -| Basic | 20 | 50 GB | 10,000 | + Reportes | -| Professional | 100 | 200 GB | 50,000 | + Integraciones | -| Enterprise | Ilimitado | Ilimitado | Ilimitado | + Soporte dedicado + BD dedicada | + +| Plan | Usuarios | Storage | Operaciones/mes | Features | +| ------------ | --------- | --------- | --------------- | -------------------------------- | +| Free | 5 | 10 GB | 1,000 | API básica | +| Basic | 20 | 50 GB | 10,000 | + Reportes | +| Professional | 100 | 200 GB | 50,000 | + Integraciones | +| Enterprise | Ilimitado | Ilimitado | Ilimitado | + Soporte dedicado + BD dedicada | ### Middleware de Validación El `LicenseValidationMiddleware` verifica en cada request: + - ✅ Licencia activa - ✅ No expirada - ✅ Límites no excedidos @@ -254,6 +266,7 @@ npm test ### Prometheus Metrics El backend expone métricas en `/metrics`: + - Request duration - Request count por endpoint - Error rate @@ -262,6 +275,7 @@ El backend expone métricas en `/metrics`: ### Logging Logs estructurados con nivel configurable: + - INFO: Operaciones normales - WARNING: Validaciones fallidas - ERROR: Errores de sistema @@ -282,6 +296,7 @@ Este proyecto es privado y propietario. ## 📞 Soporte Para soporte técnico o consultas: + - Email: soporte@anexo76.com - Documentación: https://docs.anexo76.com diff --git a/backend/alembic/versions/03b786378f94_pedimentos.py b/backend/alembic/versions/03b786378f94_pedimentos.py deleted file mode 100644 index be9283e3..00000000 --- a/backend/alembic/versions/03b786378f94_pedimentos.py +++ /dev/null @@ -1,424 +0,0 @@ -"""Pedimentos - -Revision ID: 03b786378f94 -Revises: 7937209f9718 -Create Date: 2025-11-06 17:07:16.536298 - -""" -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision: str = '03b786378f94' -down_revision: Union[str, Sequence[str], None] = '54f2046774d0' -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - """Upgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('pedimentos', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('year', sa.String(length=2), nullable=True), - sa.Column('customs_office', sa.String(length=2), nullable=True), - sa.Column('license', sa.String(length=4), nullable=True), - sa.Column('pedimento_number', sa.String(length=7), nullable=True), - sa.Column('client_id', sa.Integer(), nullable=True), - sa.Column('operation_type', sa.Integer(), nullable=True), - sa.Column('pedimento_type', sa.Integer(), nullable=True), - sa.Column('pedimento_key', sa.String(length=2), nullable=True), - sa.Column('regime', sa.String(length=3), nullable=True), - sa.Column('status', sa.String(length=30), nullable=True), - sa.Column('usd_value', sa.Numeric(precision=17, scale=6), nullable=True), - sa.Column('paid_price', sa.Numeric(precision=17, scale=6), nullable=True), - sa.Column('gross_weight', sa.Numeric(precision=19, scale=3), nullable=True), - sa.Column('exchange_rate', sa.Numeric(precision=9, scale=5), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimentos_pkey'), - schema='a76' - ) - op.create_index('idx_pedimentos_client_id', 'pedimentos', ['client_id'], unique=False, schema='a76') - op.create_index('idx_pedimentos_created_at', 'pedimentos', ['created_at'], unique=False, schema='a76') - op.create_index('idx_pedimentos_status', 'pedimentos', ['status'], unique=False, schema='a76') - op.create_index(op.f('ix_a76_pedimentos_tenant_id'), 'pedimentos', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_config_additional', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('add_po_identifier', sa.SmallInteger(), nullable=True), - sa.Column('do_not_exempt_norms_complement_x', sa.SmallInteger(), nullable=True), - sa.Column('manual_pedimento_year', sa.String(length=2), nullable=True), - sa.Column('enable_import_invoice_recipient', sa.SmallInteger(), nullable=True), - sa.Column('send_502_validation_file_for_consolidated', sa.SmallInteger(), nullable=True), - sa.Column('add_remove_norms', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_config_additional', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_config_additional_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_config_additional_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_config_additional_tenant_id'), 'pedimento_config_additional', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_config_calculations', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('dta_type', sa.String(length=1), nullable=True), - sa.Column('dta_operation', sa.SmallInteger(), nullable=True), - sa.Column('dta_vehicle_count', sa.SmallInteger(), nullable=True), - sa.Column('dta_mixed_rate_8permil', sa.SmallInteger(), nullable=True), - sa.Column('pays_vat', sa.SmallInteger(), nullable=True), - sa.Column('pays_prevalidation', sa.SmallInteger(), nullable=True), - sa.Column('include_sagar_certificate_fee', sa.SmallInteger(), nullable=True), - sa.Column('fixed_vehicle_dta_fee', sa.SmallInteger(), nullable=True), - sa.Column('additional_fixed_fee', sa.SmallInteger(), nullable=True), - sa.Column('additional_fixed_fee_payment_method', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_config_calculations', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_config_calculations_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_config_calculations_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_config_calculations_tenant_id'), 'pedimento_config_calculations', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_config_parameters', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('is_embassy', sa.SmallInteger(), nullable=True), - sa.Column('embassy_dta', sa.Numeric(precision=11, scale=2), nullable=True), - sa.Column('rule_3121_section_ii', sa.SmallInteger(), nullable=True), - sa.Column('use_previous_tariff', sa.SmallInteger(), nullable=True), - sa.Column('use_payment_date_fi', sa.SmallInteger(), nullable=True), - sa.Column('add_state_supplier_record_505', sa.SmallInteger(), nullable=True), - sa.Column('customs_value_calculation', sa.SmallInteger(), nullable=True), - sa.Column('two_decimals_unit_value', sa.SmallInteger(), nullable=True), - sa.Column('customs_value_per_item', sa.SmallInteger(), nullable=True), - sa.Column('is_national_supplier', sa.SmallInteger(), nullable=True), - sa.Column('is_consolidated', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_config_parameters', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_config_parameters_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_config_parameters_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_config_parameters_tenant_id'), 'pedimento_config_parameters', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_config_surcharges', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('surcharge_igi', sa.SmallInteger(), nullable=True), - sa.Column('surcharge_dta', sa.SmallInteger(), nullable=True), - sa.Column('surcharge_vat', sa.SmallInteger(), nullable=True), - sa.Column('surcharge_isan', sa.SmallInteger(), nullable=True), - sa.Column('surcharge_ieps', sa.SmallInteger(), nullable=True), - sa.Column('surcharge_cc', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_config_surcharges', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_config_surcharges_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_config_surcharges_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_config_surcharges_tenant_id'), 'pedimento_config_surcharges', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_config_update_rectification', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('update_vat', sa.SmallInteger(), nullable=True), - sa.Column('update_advalorem', sa.SmallInteger(), nullable=True), - sa.Column('update_cc', sa.SmallInteger(), nullable=True), - sa.Column('update_ieps', sa.SmallInteger(), nullable=True), - sa.Column('calculate_surcharge', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_config_update_rectification', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_config_update_rectification_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_config_update_rectification_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_config_update_rectification_tenant_id'), 'pedimento_config_update_rectification', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_config_updates', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('update_vat', sa.SmallInteger(), nullable=True), - sa.Column('update_advalorem', sa.SmallInteger(), nullable=True), - sa.Column('update_cc', sa.SmallInteger(), nullable=True), - sa.Column('update_ieps', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_config_updates', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_config_updates_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_config_updates_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_config_updates_tenant_id'), 'pedimento_config_updates', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_customs_offices', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('dispatch_customs', sa.String(length=3), nullable=True), - sa.Column('entry_exit_customs', sa.String(length=3), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_customs_offices', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_customs_offices_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_customs_offices_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_customs_offices_tenant_id'), 'pedimento_customs_offices', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_dates', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('entry_date', sa.DateTime(), nullable=True), - sa.Column('pedimento_date', sa.DateTime(), nullable=True), - sa.Column('payment_date', sa.DateTime(), nullable=True), - sa.Column('rectification_payment_date', sa.DateTime(), nullable=True), - sa.Column('extraction_date', sa.DateTime(), nullable=True), - sa.Column('submission_date', sa.DateTime(), nullable=True), - sa.Column('eucan_date', sa.DateTime(), nullable=True), - sa.Column('original_date', sa.DateTime(), nullable=True), - sa.Column('start_date', sa.DateTime(), nullable=True), - sa.Column('end_date', sa.DateTime(), nullable=True), - sa.Column('capture_date', sa.DateTime(), nullable=True), - sa.Column('capture_time', sa.Time(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_dates', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_dates_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_dates_pedimento_id_key'), - schema='a76' - ) - op.create_index('idx_pedimento_dates_pedimento_id', 'pedimento_dates', ['pedimento_id'], unique=False, schema='a76') - op.create_index(op.f('ix_a76_pedimento_dates_tenant_id'), 'pedimento_dates', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_decrementables', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('freight', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('insurance', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('loading', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('unloading', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('others', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('currency', sa.String(length=3), nullable=True), - sa.Column('currency_factor', sa.Numeric(precision=15, scale=8), nullable=True), - sa.Column('not_affect_usd_value', sa.SmallInteger(), nullable=True), - sa.Column('not_affect_customs_value', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_decrementables', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_decrementables_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_decrementables_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_decrementables_tenant_id'), 'pedimento_decrementables', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_incrementables', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('insured_value', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('freight', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('insurance', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('packaging', sa.Numeric(precision=13, scale=2), nullable=True), - sa.Column('others', sa.Numeric(precision=13, scale=3), nullable=True), - sa.Column('deductibles', sa.Numeric(precision=13, scale=3), nullable=True), - sa.Column('currency', sa.String(length=3), nullable=True), - sa.Column('currency_factor', sa.Numeric(precision=15, scale=8), nullable=True), - sa.Column('not_affect_usd_value', sa.SmallInteger(), nullable=True), - sa.Column('not_affect_customs_value', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_incrementables', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_incrementables_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_incrementables_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_incrementables_tenant_id'), 'pedimento_incrementables', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_indexes', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('update_factor_type', sa.SmallInteger(), nullable=True), - sa.Column('update_factor', sa.Numeric(precision=7, scale=4), nullable=True), - sa.Column('manual_update_factor', sa.SmallInteger(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_indexes', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_indexes_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_indexes_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_indexes_tenant_id'), 'pedimento_indexes', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_payments', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('acknowledgment', sa.String(length=20), nullable=True), - sa.Column('operation_number', sa.String(length=14), nullable=True), - sa.Column('bank_code', sa.Integer(), nullable=True), - sa.Column('cashier', sa.String(length=2), nullable=True), - sa.Column('date', sa.Date(), nullable=True), - sa.Column('time', sa.Time(), nullable=True), - sa.Column('shift', sa.String(length=1), nullable=True), - sa.Column('total_cash_paid', sa.Integer(), nullable=True), - sa.Column('total_contributions', sa.Integer(), nullable=True), - sa.Column('counter_payment', sa.SmallInteger(), nullable=True), - sa.Column('pece_code', sa.String(length=5), nullable=True), - sa.Column('payment_id', sa.Integer(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_payments', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_payments_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_payments_pedimento_id_key'), - schema='a76' - ) - op.create_index('idx_pedimento_payments_pedimento_id', 'pedimento_payments', ['pedimento_id'], unique=False, schema='a76') - op.create_index(op.f('ix_a76_pedimento_payments_tenant_id'), 'pedimento_payments', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_rectification_destination', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('destination_pedimento_year', sa.String(length=2), nullable=True), - sa.Column('destination_customs_office', sa.String(length=3), nullable=True), - sa.Column('destination_license', sa.String(length=4), nullable=True), - sa.Column('destination_pedimento_number', sa.String(length=7), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_rectification_destination', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_rectification_destination_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_rectification_destination_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_rectification_destination_tenant_id'), 'pedimento_rectification_destination', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_rectification_origin', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('original_pedimento_year', sa.String(length=2), nullable=True), - sa.Column('original_customs_office', sa.String(length=3), nullable=True), - sa.Column('original_license', sa.String(length=4), nullable=True), - sa.Column('original_pedimento_number', sa.String(length=7), nullable=True), - sa.Column('original_pedimento_key', sa.String(length=2), nullable=True), - sa.Column('original_payment_date', sa.DateTime(), nullable=True), - sa.Column('total_cash', sa.Integer(), nullable=True), - sa.Column('total_others', sa.Integer(), nullable=True), - sa.Column('reason', sa.String(length=255), nullable=True), - sa.Column('charge_to_client', sa.SmallInteger(), nullable=True), - sa.Column('use_original_payment_date_for_interest_calc', sa.SmallInteger(), nullable=True), - sa.Column('manual_calculation', sa.SmallInteger(), nullable=True), - sa.Column('original_pedimento_norms', sa.SmallInteger(), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_rectification_origin', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_rectification_origin_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_rectification_origin_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_rectification_origin_tenant_id'), 'pedimento_rectification_origin', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_transport_means', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('destination', sa.SmallInteger(), nullable=True), - sa.Column('entry_exit', sa.String(length=2), nullable=True), - sa.Column('arrival', sa.String(length=2), nullable=True), - sa.Column('departure', sa.String(length=2), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_transport_means', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_transport_means_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_transport_means_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_transport_means_tenant_id'), 'pedimento_transport_means', ['tenant_id'], unique=False, schema='a76') - op.create_table('pedimento_validation', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('pedimento_id', sa.Integer(), nullable=False), - sa.Column('tenant_id', sa.Integer(), nullable=False), - sa.Column('validator', sa.String(length=3), nullable=True), - sa.Column('validation_ack', sa.String(length=8), nullable=True), - sa.Column('pre_ack', sa.String(length=8), nullable=True), - sa.Column('line_signature', sa.String(length=50), nullable=True), - sa.Column('electronic_signature', sa.String(length=999), nullable=True), - sa.Column('certificate_number', sa.String(length=99), nullable=True), - sa.Column('validator_id', sa.Integer(), nullable=True), - sa.Column('responsible_id', sa.Integer(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True), - sa.ForeignKeyConstraint(['pedimento_id'], ['a76.pedimentos.id'], name='fk_pedimento_validation', ondelete='CASCADE'), - sa.ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id'], ), - sa.PrimaryKeyConstraint('id', name='pedimento_validation_pkey'), - sa.UniqueConstraint('pedimento_id', name='pedimento_validation_pedimento_id_key'), - schema='a76' - ) - op.create_index(op.f('ix_a76_pedimento_validation_tenant_id'), 'pedimento_validation', ['tenant_id'], unique=False, schema='a76') - op.drop_constraint(op.f('fk_regimenped'), 'code_pedimento_regimens', type_='foreignkey') - op.drop_constraint(op.f('fk_codeped'), 'code_pedimento_regimens', type_='foreignkey') - op.create_foreign_key('fk_codeped', 'code_pedimento_regimens', 'pedimento_codes', ['pedimento_code'], ['code'], source_schema='public', referent_schema='public') - op.create_foreign_key('fk_regimenped', 'code_pedimento_regimens', 'pedimento_regimens', ['regimen_code'], ['code'], source_schema='public', referent_schema='public') - # ### end Alembic commands ### - - -def downgrade() -> None: - """Downgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint('fk_regimenped', 'code_pedimento_regimens', schema='public', type_='foreignkey') - op.drop_constraint('fk_codeped', 'code_pedimento_regimens', schema='public', type_='foreignkey') - op.create_foreign_key(op.f('fk_codeped'), 'code_pedimento_regimens', 'pedimento_codes', ['pedimento_code'], ['code']) - op.create_foreign_key(op.f('fk_regimenped'), 'code_pedimento_regimens', 'pedimento_regimens', ['regimen_code'], ['code']) - op.drop_index(op.f('ix_a76_pedimento_validation_tenant_id'), table_name='pedimento_validation', schema='a76') - op.drop_table('pedimento_validation', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_transport_means_tenant_id'), table_name='pedimento_transport_means', schema='a76') - op.drop_table('pedimento_transport_means', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_rectification_origin_tenant_id'), table_name='pedimento_rectification_origin', schema='a76') - op.drop_table('pedimento_rectification_origin', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_rectification_destination_tenant_id'), table_name='pedimento_rectification_destination', schema='a76') - op.drop_table('pedimento_rectification_destination', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_payments_tenant_id'), table_name='pedimento_payments', schema='a76') - op.drop_index('idx_pedimento_payments_pedimento_id', table_name='pedimento_payments', schema='a76') - op.drop_table('pedimento_payments', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_indexes_tenant_id'), table_name='pedimento_indexes', schema='a76') - op.drop_table('pedimento_indexes', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_incrementables_tenant_id'), table_name='pedimento_incrementables', schema='a76') - op.drop_table('pedimento_incrementables', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_decrementables_tenant_id'), table_name='pedimento_decrementables', schema='a76') - op.drop_table('pedimento_decrementables', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_dates_tenant_id'), table_name='pedimento_dates', schema='a76') - op.drop_index('idx_pedimento_dates_pedimento_id', table_name='pedimento_dates', schema='a76') - op.drop_table('pedimento_dates', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_customs_offices_tenant_id'), table_name='pedimento_customs_offices', schema='a76') - op.drop_table('pedimento_customs_offices', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_config_updates_tenant_id'), table_name='pedimento_config_updates', schema='a76') - op.drop_table('pedimento_config_updates', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_config_update_rectification_tenant_id'), table_name='pedimento_config_update_rectification', schema='a76') - op.drop_table('pedimento_config_update_rectification', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_config_surcharges_tenant_id'), table_name='pedimento_config_surcharges', schema='a76') - op.drop_table('pedimento_config_surcharges', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_config_parameters_tenant_id'), table_name='pedimento_config_parameters', schema='a76') - op.drop_table('pedimento_config_parameters', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_config_calculations_tenant_id'), table_name='pedimento_config_calculations', schema='a76') - op.drop_table('pedimento_config_calculations', schema='a76') - op.drop_index(op.f('ix_a76_pedimento_config_additional_tenant_id'), table_name='pedimento_config_additional', schema='a76') - op.drop_table('pedimento_config_additional', schema='a76') - op.drop_index(op.f('ix_a76_pedimentos_tenant_id'), table_name='pedimentos', schema='a76') - op.drop_index('idx_pedimentos_status', table_name='pedimentos', schema='a76') - op.drop_index('idx_pedimentos_created_at', table_name='pedimentos', schema='a76') - op.drop_index('idx_pedimentos_client_id', table_name='pedimentos', schema='a76') - op.drop_table('pedimentos', schema='a76') - op.drop_index(op.f('ix_a76_licenses_tenant_id'), table_name='licenses', schema='a76') - op.drop_index(op.f('ix_a76_licenses_id'), table_name='licenses', schema='a76') - op.drop_table('licenses', schema='a76') - op.drop_index(op.f('ix_a76_license_usage_tenant_id'), table_name='license_usage', schema='a76') - op.drop_index(op.f('ix_a76_license_usage_id'), table_name='license_usage', schema='a76') - op.drop_table('license_usage', schema='a76') - op.drop_index(op.f('ix_a76_tenants_slug'), table_name='tenants', schema='a76') - op.drop_index(op.f('ix_a76_tenants_name'), table_name='tenants', schema='a76') - op.drop_index(op.f('ix_a76_tenants_id'), table_name='tenants', schema='a76') - op.drop_table('tenants', schema='a76') - # ### end Alembic commands ### diff --git a/backend/alembic/versions/54f2046774d0_create_new_a76_tables_only.py b/backend/alembic/versions/54f2046774d0_create_new_a76_tables_only.py deleted file mode 100644 index 272f1821..00000000 --- a/backend/alembic/versions/54f2046774d0_create_new_a76_tables_only.py +++ /dev/null @@ -1,195 +0,0 @@ -"""Create new A76 tables only - company, clients, parts, classes - -Revision ID: 54f2046774d0 -Revises: 7937209f9718 -Create Date: 2025-11-06 03:38:27.848630 - -""" -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision: str = '54f2046774d0' -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 - Create only new A76 tables.""" - - # Create new A76 tables only (skip existing tenants, licenses, license_usage) - op.create_table('client_provider', - sa.Column('client_id', sa.String(length=8), nullable=False), - sa.Column('type_nat_foreign', sa.String(length=1), nullable=True), - sa.Column('name', sa.String(length=256), nullable=True), - sa.Column('short_name', sa.String(length=10), nullable=True), - sa.Column('rfc', sa.String(length=30), nullable=True), - sa.Column('curp', sa.String(length=19), nullable=True), - sa.Column('client_or_provider', sa.String(length=1), nullable=True), - sa.Column('linking', sa.String(length=1), nullable=True), - sa.Column('transform_subassembly', sa.String(length=1), nullable=True), - sa.Column('extra_information', sa.String(length=399), nullable=True), - sa.Column('web_key', sa.String(length=40), nullable=True), - sa.Column('responsible', sa.String(length=80), nullable=True), - sa.Column('position', sa.String(length=30), nullable=True), - sa.Column('incoterm', sa.String(length=19), nullable=True), - sa.Column('is_national_provider', sa.String(length=2), nullable=True), - sa.Column('enabled_disabled', sa.SmallInteger(), nullable=True), - sa.PrimaryKeyConstraint('client_id'), - schema='a76' - ) - - op.create_table('gcompany', - sa.Column('id', sa.String(length=3), nullable=False), - sa.Column('consecutive', sa.Boolean(), nullable=False), - sa.Column('name', sa.String(length=255), nullable=True), - sa.Column('rfc', sa.String(length=30), nullable=True), - sa.Column('main_activity', sa.String(length=255), nullable=True), - sa.Column('program', sa.String(length=10), nullable=True), - sa.Column('program_number', sa.String(length=40), nullable=True), - sa.Column('prosec', sa.SmallInteger(), nullable=True), - sa.Column('prosec_authorization', sa.String(length=20), nullable=True), - sa.Column('manufacturer_id', sa.String(length=25), nullable=True), - sa.Column('broker_company', sa.String(length=10), nullable=True), - sa.Column('responsible', sa.String(length=80), nullable=True), - sa.Column('responsible_name', sa.String(length=20), nullable=True), - sa.Column('responsible_last_name', sa.String(length=20), nullable=True), - sa.Column('responsible_mother_last_name', sa.String(length=20), nullable=True), - sa.Column('responsible_rfc', sa.String(length=30), nullable=True), - sa.Column('position', sa.String(length=30), nullable=True), - sa.Column('logo', sa.String(length=255), nullable=True), - sa.Column('has_express_line', sa.Boolean(), nullable=True), - sa.Column('order_format_type', sa.String(length=19), nullable=True), - sa.Column('previous_code', sa.SmallInteger(), nullable=True), - sa.Column('is_service_company', sa.Boolean(), nullable=True), - sa.Column('client_name', sa.String(length=300), nullable=True), - sa.Column('subassembly_mode', sa.String(length=7), nullable=True), - sa.Column('curp', sa.String(length=19), nullable=True), - sa.Column('inter_db_name', sa.String(length=100), nullable=True), - sa.Column('ctpat_svi', sa.String(length=100), nullable=True), - sa.Column('trusted_exporter_number', sa.String(length=50), nullable=True), - sa.Column('prevalidator_key', sa.String(length=20), nullable=True), - sa.Column('seventh_amendment', sa.Boolean(), nullable=True), - sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), - sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('consecutive'), - schema='a76' - ) - - op.create_table('classes', - sa.Column('client_key', sa.Integer(), nullable=False), - sa.Column('class_code', sa.String(length=8), nullable=False), - sa.Column('description_spanish', sa.String(length=500), nullable=True), - sa.Column('description_english', sa.String(length=500), nullable=True), - sa.Column('material_key', sa.String(length=10), nullable=True), - sa.Column('unit_of_measure', sa.String(length=5), nullable=True), - sa.Column('fraction', sa.String(length=10), nullable=True), - sa.Column('us_fraction', sa.String(length=16), nullable=True), - sa.Column('sub_key', sa.String(length=5), nullable=True), - sa.Column('physical_review', sa.SmallInteger(), nullable=True), - sa.Column('iva_exempt_fraction', sa.String(length=4), nullable=True), - sa.ForeignKeyConstraint(['material_key'], ['public.material_types.key'], ), - sa.PrimaryKeyConstraint('client_key', 'class_code'), - schema='a76' - ) - - op.create_table('parts', - sa.Column('client_key', sa.Integer(), nullable=False), - sa.Column('part_number', sa.String(length=49), nullable=False), - sa.Column('fraction', sa.String(length=10), nullable=True), - sa.Column('description_spanish', sa.String(length=500), nullable=True), - sa.Column('description_english', sa.String(length=500), nullable=True), - sa.Column('part_class', sa.String(length=8), nullable=True), - sa.Column('unit_of_measure', sa.String(length=5), nullable=True), - sa.Column('commercial_part_number', sa.String(length=70), nullable=True), - sa.Column('country_of_origin', sa.String(length=3), nullable=True), - sa.Column('unit_cost', sa.Numeric(precision=23, scale=8), nullable=True), - sa.Column('currency_type', sa.String(length=2), nullable=True), - sa.Column('currency_key', sa.String(length=3), nullable=True), - sa.Column('unit_weight', sa.Numeric(precision=19, scale=8), nullable=True), - sa.Column('weight_type', sa.String(length=6), nullable=True), - sa.Column('us_fraction', sa.String(length=16), nullable=True), - sa.Column('fda_key', sa.String(length=20), nullable=True), - sa.Column('fcc_key', sa.String(length=30), nullable=True), - sa.Column('license_code', sa.String(length=3), nullable=True), - sa.Column('eccn', sa.String(length=20), nullable=True), - sa.Column('export_code', sa.String(length=2), nullable=True), - sa.Column('exclusion_symbol', sa.String(length=19), nullable=True), - sa.Column('supplier', sa.String(length=14), nullable=True), - sa.Column('alternate_unit_measure', sa.String(length=14), nullable=True), - sa.Column('added_value', sa.Numeric(precision=23, scale=8), nullable=True), - sa.Column('enabled_disabled', sa.SmallInteger(), nullable=True), - sa.Column('creation_date', sa.Integer(), nullable=True), - sa.Column('modification_date', sa.Integer(), nullable=True), - sa.Column('modification_date_iso', sa.DateTime(timezone=True), nullable=True), - sa.Column('part_photo', sa.String(length=255), nullable=True), - sa.ForeignKeyConstraint(['country_of_origin'], ['public.countries.m3_key'], ), - sa.ForeignKeyConstraint(['currency_key'], ['public.currency_types.code'], ), - sa.PrimaryKeyConstraint('client_key', 'part_number'), - schema='a76' - ) - - # Create dependent tables after main tables - op.create_table('gclient_provider_address', - sa.Column('client_id', sa.String(length=8), nullable=False), - sa.Column('municipality', sa.String(length=150), nullable=True), - sa.Column('streets', sa.String(length=100), nullable=True), - sa.Column('neighborhood', sa.String(length=40), nullable=True), - sa.Column('interior_number', sa.String(length=20), nullable=True), - sa.Column('exterior_number', sa.String(length=20), nullable=True), - sa.Column('postal_code', sa.String(length=15), nullable=True), - sa.Column('city', sa.String(length=30), nullable=True), - sa.Column('state', sa.String(length=30), nullable=True), - sa.Column('country', sa.String(length=3), nullable=True), - sa.Column('phone', sa.String(length=30), nullable=True), - sa.Column('fax_number', sa.String(length=30), nullable=True), - sa.Column('email', sa.String(length=100), nullable=True), - sa.Column('contact', sa.String(length=50), nullable=True), - sa.Column('reference', sa.String(length=250), nullable=True), - sa.ForeignKeyConstraint(['client_id'], ['a76.client_provider.client_id'], ondelete='CASCADE'), - sa.PrimaryKeyConstraint('client_id'), - schema='a76' - ) - - op.create_table('gclient_provider_programs', - sa.Column('client_id', sa.String(length=8), nullable=False), - sa.Column('program', sa.String(length=7), nullable=True), - sa.Column('program_number', sa.String(length=40), nullable=True), - sa.Column('prosec', sa.SmallInteger(), nullable=True), - sa.Column('prosec_authorization', sa.String(length=20), nullable=True), - sa.Column('secon_auth_date', sa.Integer(), nullable=True), - sa.Column('manufacturer_id', sa.String(length=25), nullable=True), - sa.Column('tax_id', sa.String(length=30), nullable=True), - sa.Column('broker', sa.String(length=6), nullable=True), - sa.Column('import_broker', sa.String(length=6), nullable=True), - sa.Column('transfer_key', sa.String(length=8), nullable=True), - sa.Column('secon_authorization', sa.String(length=20), nullable=True), - sa.Column('applied_proportion', sa.Numeric(precision=7, scale=2), nullable=True), - sa.Column('is_certified_company', sa.String(length=1), nullable=True), - sa.Column('certified_company_registry', sa.String(length=40), nullable=True), - sa.Column('donation_auth_number', sa.String(length=50), nullable=True), - sa.Column('ctpat_svi', sa.String(length=100), nullable=True), - sa.Column('tax_registry_number', sa.String(length=40), nullable=True), - sa.Column('subassembly_service', sa.SmallInteger(), nullable=True), - sa.Column('autse_dates', sa.Integer(), nullable=True), - sa.Column('autse_number', sa.String(length=300), nullable=True), - sa.ForeignKeyConstraint(['client_id'], ['a76.client_provider.client_id'], ondelete='CASCADE'), - sa.PrimaryKeyConstraint('client_id'), - schema='a76' - ) - - -def downgrade() -> None: - """Downgrade schema - Drop only new A76 tables.""" - # Drop tables in reverse dependency order - op.drop_table('gclient_provider_programs', schema='a76') - op.drop_table('gclient_provider_address', schema='a76') - op.drop_table('parts', schema='a76') - op.drop_table('classes', schema='a76') - op.drop_table('gcompany', schema='a76') - op.drop_table('client_provider', schema='a76') \ No newline at end of file diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_rectification_origin.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_rectification_origin.py index ee8dfeda..ec8464c0 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_rectification_origin.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_rectification_origin.py @@ -11,7 +11,7 @@ class PedimentoRectificationOriginBase(BaseModel): original_customs_office: Optional[str] = Field(None, max_length=3, description="Original customs office") original_license: Optional[str] = Field(None, max_length=4, description="Original license") original_pedimento_number: Optional[str] = Field(None, max_length=7, description="Original pedimento number") - original_pedimento_key: Optional[str] = Field(None, max_length=2, description="Original pedimento key") + original_pedimento_code: Optional[str] = Field(None, max_length=2, description="Original pedimento key") original_payment_date: Optional[datetime] = Field(None, description="Original payment date") total_cash: Optional[int] = Field(None, description="Total cash") total_others: Optional[int] = Field(None, description="Total others") @@ -33,7 +33,7 @@ class PedimentoRectificationOriginUpdate(BaseModel): original_customs_office: Optional[str] = Field(None, max_length=3) original_license: Optional[str] = Field(None, max_length=4) original_pedimento_number: Optional[str] = Field(None, max_length=7) - original_pedimento_key: Optional[str] = Field(None, max_length=2) + original_pedimento_code: Optional[str] = Field(None, max_length=2) original_payment_date: Optional[datetime] = None total_cash: Optional[int] = None total_others: Optional[int] = None diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimentos.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimentos.py index 6ac4c4cf..b9a2e45f 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimentos.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimentos.py @@ -13,7 +13,7 @@ class PedimentosBase(BaseModel): client_id: Optional[int] = Field(None, description="Client ID") operation_type: Optional[int] = Field(None, description="Operation type") pedimento_type: Optional[int] = Field(None, description="Pedimento type") - pedimento_key: Optional[str] = Field(None, max_length=2, description="Pedimento key") + pedimento_code: Optional[str] = Field(None, max_length=2, description="Pedimento key") regime: Optional[str] = Field(None, max_length=3, description="Regime") status: Optional[str] = Field(None, max_length=30, description="Status") usd_value: Optional[Decimal] = Field(None, description="USD value") @@ -36,7 +36,7 @@ class PedimentosUpdate(BaseModel): client_id: Optional[int] = None operation_type: Optional[int] = None pedimento_type: Optional[int] = None - pedimento_key: Optional[str] = Field(None, max_length=2) + pedimento_code: Optional[str] = Field(None, max_length=2) regime: Optional[str] = Field(None, max_length=3) status: Optional[str] = Field(None, max_length=30) usd_value: Optional[Decimal] = None diff --git a/backend/api/v1/modules/a76/pedmientos/models/pedimento_rectification_origin.py b/backend/api/v1/modules/a76/pedmientos/models/pedimento_rectification_origin.py index 9e92068f..951c66b2 100644 --- a/backend/api/v1/modules/a76/pedmientos/models/pedimento_rectification_origin.py +++ b/backend/api/v1/modules/a76/pedmientos/models/pedimento_rectification_origin.py @@ -20,7 +20,7 @@ class PedimentoRectificationOrigin(Base): original_customs_office = mapped_column(String(3)) original_license = mapped_column(String(4)) original_pedimento_number = mapped_column(String(7)) - original_pedimento_key = mapped_column(String(2)) + original_pedimento_code = mapped_column(String(2)) original_payment_date = mapped_column(DateTime) total_cash = mapped_column(Integer) total_others = mapped_column(Integer) diff --git a/backend/api/v1/modules/a76/pedmientos/models/pedimentos.py b/backend/api/v1/modules/a76/pedmientos/models/pedimentos.py index 977003d9..a984364f 100644 --- a/backend/api/v1/modules/a76/pedmientos/models/pedimentos.py +++ b/backend/api/v1/modules/a76/pedmientos/models/pedimentos.py @@ -7,6 +7,8 @@ from core.database import Base class Pedimentos(Base): __tablename__ = 'pedimentos' __table_args__ = ( + ForeignKeyConstraint(['regime'], ['public.pedimento_regimens.code']), + ForeignKeyConstraint(['pedimento_code'], ['public.pedimento_codes.code']), ForeignKeyConstraint(['tenant_id'], ['a76.tenants.id']), PrimaryKeyConstraint('id', name='pedimentos_pkey'), Index('idx_pedimentos_client_id', 'client_id'), @@ -24,7 +26,7 @@ class Pedimentos(Base): client_id = mapped_column(Integer) operation_type = mapped_column(Integer) pedimento_type = mapped_column(Integer) - pedimento_key = mapped_column(String(2)) + pedimento_code = mapped_column(String(2)) regime = mapped_column(String(3)) status = mapped_column(String(30)) usd_value = mapped_column(Numeric(17, 6)) diff --git a/backend/main.py b/backend/main.py index a11f226f..fb95f89c 100644 --- a/backend/main.py +++ b/backend/main.py @@ -12,6 +12,7 @@ from core.middleware import ( LicenseValidationMiddleware, RequestLoggingMiddleware ) +from core.database import init_db from api.v1.router import router as api_v1_router # Configurar logging @@ -26,12 +27,20 @@ logger = logging.getLogger(__name__) app = FastAPI( title="Anexo76 API", version=settings.APP_VERSION, - description="Aplicación SaaS para gestión de comercio exterior conforme a Anexos 24, 31 y 22 del SAT", + description="Aplicación SaaS para gestión de comercio exterior conforme a Anexos 24, 30 y 22 del SAT", docs_url="/api/docs" if settings.DEBUG else None, redoc_url="/api/redoc" if settings.DEBUG else None, openapi_url="/api/openapi.json" if settings.DEBUG else None, ) +# Inicializar la base de datos +@app.on_event("startup") +async def on_startup(): + """Evento de inicio de la aplicación""" + logger.info("Iniciando la aplicación Anexo76...") + init_db() + logger.info("Base de datos inicializada correctamente.") + # Configurar CORS app.add_middleware( CORSMiddleware, @@ -41,6 +50,8 @@ app.add_middleware( allow_headers=["*"], ) +logger.info(f"CORS configurado para orígenes: {settings.cors_origins_list}") + # Agregar middlewares personalizados app.add_middleware(RequestLoggingMiddleware) app.add_middleware(LicenseValidationMiddleware) diff --git a/docker-compose.yml b/docker-compose.yml index 3d54d692..d3423ec7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -162,7 +162,7 @@ services: - KEYCLOAK_REALM=${KEYCLOAK_REALM:-master} - KEYCLOAK_CLIENT_ID=${KEYCLOAK_CLIENT_ID:-anexo76-backend} - KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-dev-secret} - - CORS_ORIGINS=http://localhost:5180,http://localhost:3000 + - CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:5180,http://localhost:3000} ports: - "8000:8000" depends_on: diff --git a/docs/a76.json b/docs/a76.json index 331f38fc..9d62e2bf 100644 --- a/docs/a76.json +++ b/docs/a76.json @@ -1,7 +1,7 @@ { "context": { "project_name": "Anexo76", - "description": "Aplicación SaaS para gestión de comercio exterior conforme a Anexos 24, 31 y 22 del SAT.", + "description": "Aplicación SaaS para gestión de comercio exterior conforme a Anexos 24, 30 y 22 del SAT.", "business_goal": "Ofrecer una plataforma multi-tenant para maquilas, IMMEX y agentes aduanales que permita manejar inventarios, pedimentos y facturas de importación/exportación con control de licencias y cumplimiento normativo." }, "architecture": { diff --git a/frontend/src/app.html b/frontend/src/app.html index 608bad89..26eb1a95 100644 --- a/frontend/src/app.html +++ b/frontend/src/app.html @@ -4,7 +4,7 @@ Anexo76 - Gestión de Comercio Exterior - + - - - - - - {isEditing ? "Editar" : "Nuevo"} Pedimento - - - {isEditing - ? "Modifica los datos del pedimento." - : "Completa los datos para crear un nuevo pedimento."} - - - -
- {#if error} -
- {error} -
- {/if} - - -
-

Información del Pedimento

- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
- -
-
- - -
- -
- - -
-
-
- - -
-

Cliente y Operación

- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
- - -
-

Información Financiera

- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
- - - - - -
-
-
diff --git a/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte b/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte index 9df58ec8..01f9bba9 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte +++ b/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte @@ -11,8 +11,6 @@ onSuccess?: () => void; } = $props(); - let showEditDialog = $state(false); - let showDeleteDialog = $state(false); let loading = $state(false); let error = $state(null); @@ -54,12 +52,8 @@ } function handleEdit() { - showEditDialog = true; - } - - function handleView() { - // Navegar a la vista de detalles - window.location.href = `/dashboard/pedimentos/${item.id}`; + // Navegar a la página de edición + window.location.href = `/dashboard/pedimentos/edit/${item.id}`; } @@ -89,24 +83,6 @@ Acciones - - - - - - Ver detalles - - -{#if showEditDialog} - - {#await import('./create-edit-dialog.svelte') then { default: CreateEditDialog }} - - {/await} -{/if} diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte new file mode 100644 index 00000000..fc1f9ca5 --- /dev/null +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte @@ -0,0 +1,122 @@ + + + + + Fechas del Pedimento + + Gestiona las fechas importantes del pedimento + + + + {#if loading} +
+ + + +
+ {:else} +
+
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+
+ {/if} +
+
diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte new file mode 100644 index 00000000..4466f18d --- /dev/null +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte @@ -0,0 +1,232 @@ + + + + + Información General + + Edita los datos principales del pedimento + + + +
+ +
+ +
+ + +
+ + +
-
+ + +
+ + +
+ + +
-
+ + +
+ + +
+ + +
-
+ + +
+ + +
+
+ +
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+
+
+
diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/payments-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/payments-tab-form.svelte new file mode 100644 index 00000000..b137c64e --- /dev/null +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/payments-tab-form.svelte @@ -0,0 +1,107 @@ + + + + + Información de Pagos + + Gestiona la información de pagos del pedimento + + + + {#if loading} +
+ + +
+ {:else} +
+
+ +
+ + +
+ + +
+ + +
+
+
+ {/if} +
+
diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/transport-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/transport-tab-form.svelte new file mode 100644 index 00000000..896cac37 --- /dev/null +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/transport-tab-form.svelte @@ -0,0 +1,137 @@ + + + + + Medios de Transporte + + Gestiona la información de transporte del pedimento + + + + {#if loading} +
+ + + + +
+ {:else} +
+
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+
+ {/if} +
+
diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/validation-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/validation-tab-form.svelte new file mode 100644 index 00000000..eabfc447 --- /dev/null +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/validation-tab-form.svelte @@ -0,0 +1,94 @@ + + + + + Validación del Pedimento + + Gestiona la documentación de validación del pedimento + + + + {#if loading} +
+ +
+ {:else} +
+
+ +